diff --git a/F0:F030,F042,F072/usbcan_gpio/gpio.c b/F0:F030,F042,F072/usbcan_gpio/gpio.c index ff86226..ad1edf9 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpio.c +++ b/F0:F030,F042,F072/usbcan_gpio/gpio.c @@ -42,41 +42,93 @@ typedef struct{ #define CANUSART(x) ((x) & (1< need to set up timers / channels +TIM1 / 2 3 +TIM2 / 2 3 4 +TIM3 / 1 2 3 4 +TIM14 / 1 +TIM16 / 1 +#endif + +#define PT(t, ch) {.tim = t, .chidx = ch} +#define PTC(t, ch, P, p) {.tim = t, .chidx = ch, .collision = 1, .collport = P, .collpin = p} +static const pwmtimer_t timer_map[2][16] = { + [0] = { + [1] = PTC(TIM2, 1, 1, 3), + [2] = PTC(TIM2, 2, 1, 10), + [3] = PTC(TIM2, 3, 1, 11), + [6] = PT(TIM16, 0), + [7] = PT(TIM14, 0), + [9] = PT(TIM1, 1), + [10] = PT(TIM1, 2) + }, + [1] = { + [0] = PT(TIM3, 2), + [1] = PT(TIM3, 3), + [3] = PTC(TIM2, 1, 0, 1), + [4] = PT(TIM3, 0), + [5] = PT(TIM3, 1), + [10] = PTC(TIM2, 2, 0, 2), + [11] = PTC(TIM2, 3, 0, 3) + } +}; +#undef PT +#undef PTC typedef struct{ uint8_t isrx : 1; @@ -434,3 +486,17 @@ uint16_t gpio_alert(uint8_t port){ } return alert; } + +/** + * @brief canPWM - check if pin have PWM ability + * @param port - port (0/1 for GPIOA/GPIOB) + * @param pin - pin (0..15) + * @param t (o) - struct for pin's PWM timer + * @return TRUE if can, FALSE if no + */ +int canPWM(uint8_t port, uint8_t pin, pwmtimer_t *t){ + if(port > 1 || pin > 15) return 0; + if(t) *t = timer_map[port][pin]; + if(timer_map[port][pin].tim) return TRUE; + return FALSE; +} diff --git a/F0:F030,F042,F072/usbcan_gpio/gpio.h b/F0:F030,F042,F072/usbcan_gpio/gpio.h index 4d5992d..826471e 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpio.h +++ b/F0:F030,F042,F072/usbcan_gpio/gpio.h @@ -19,6 +19,7 @@ #pragma once #include +#include #ifdef EBUG #define USBIF IGPIO @@ -90,6 +91,15 @@ typedef struct{ uint16_t threshold; // threshold for ADC measurement } pinconfig_t; +// Timers for PWM +typedef struct{ + volatile TIM_TypeDef *tim; // timer + uint8_t chidx : 2; // channel index (0..3) + uint8_t collision : 1; // have collision with other channel (1) + uint8_t collport : 1; // collision port index (0 - GPIOA, 1 - GPIOB) + uint8_t collpin : 4; // collision pin index (0..15) +} pwmtimer_t; + /* typedef struct{ uint32_t speed; @@ -111,3 +121,5 @@ int gpio_reinit(); int pin_out(uint8_t port, uint8_t pin, uint8_t newval); int16_t pin_in(uint8_t port, uint8_t pin); uint16_t gpio_alert(uint8_t port); + +int canPWM(uint8_t port, uint8_t pin, pwmtimer_t *t); diff --git a/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp b/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp index 3b52601..9cde6ca 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp +++ b/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp @@ -54,7 +54,8 @@ static uint8_t hex_input_mode = 0; // ==0 for text input, 1 for HEX + text in qu COMMAND(mcureset, "reset MCU") \ COMMAND(PA, "GPIOA setter/getter (type PA0=help for further info)") \ COMMAND(PB, "GPIOB setter/getter") \ - COMMAND(readconf, "re-read config from flash") \ + COMMAND(pwmmap, "show pins with PWM ability") \ + COMMAND(readconf, "re-read config from flash") \ COMMAND(reinit, "apply pin config") \ COMMAND(saveconf, "save current user configuration into flash") \ COMMAND(sendcan, "send all after '=' to CAN USB interface") \ @@ -679,7 +680,7 @@ static errcodes_t cmd_help(const char _U_ *cmd, char _U_ *args){ return ERR_AMOUNT; } -static errcodes_t cmd_hexinput(const char *cmd, char *args) { +static errcodes_t cmd_hexinput(const char *cmd, char *args){ int32_t val; if(argsvals(args, NULL, &val)){ if(val == 0 || val == 1) hex_input_mode = (uint8_t)val; @@ -690,6 +691,25 @@ static errcodes_t cmd_hexinput(const char *cmd, char *args) { return ERR_AMOUNT; } +static errcodes_t cmd_pwmmap(const char _U_ *cmd, char _U_ *args){ + pwmtimer_t t; + SEND("PWM pins:\n"); + for(int port = 0; port < 2; ++port){ + for(int pin = 0; pin < 16; ++pin){ + if(!canPWM(port, pin, &t)) continue; + SEND((port == 0) ? "PA" : "PB"); + SEND(u2str(pin)); + if(t.collision){ + SEND(" conflicts with "); + SEND((t.collport == 0) ? "PA" : "PB"); + SEND(u2str(t.collpin)); + } + NL(); + } + } + return ERR_AMOUNT; +} + static int sendfun(const char *s){ if(!s) return 0; return USB_sendstr(IGPIO, s); diff --git a/F0:F030,F042,F072/usbcan_gpio/pwm.c b/F0:F030,F042,F072/usbcan_gpio/pwm.c new file mode 100644 index 0000000..4e45470 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_gpio/pwm.c @@ -0,0 +1,32 @@ +/* + * This file is part of the usbcangpio project. + * Copyright 2026 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "pwm.h" + +/* + * initial setup of all available PWM timers / channels: + * TIM1 / 2 3 + * TIM2 / 2 3 4 + * TIM3 / 1 2 3 4 + * TIM14 / 1 + * TIM16 / 1 + */ + +void pwm_setup(){ + ; +} diff --git a/F0:F030,F042,F072/usbcan_gpio/pwm.h b/F0:F030,F042,F072/usbcan_gpio/pwm.h new file mode 100644 index 0000000..1a04315 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_gpio/pwm.h @@ -0,0 +1,21 @@ +/* + * This file is part of the usbcangpio project. + * Copyright 2026 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +void pwm_setup(); diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin index f5500fe..25457cc 100755 Binary files a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin and b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin differ diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user index aa40037..765e6fb 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user +++ b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files index 1df8100..7e44667 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files +++ b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files @@ -16,6 +16,8 @@ hashgen/Readme hashgen/hashgen.c hashgen/mktestdic main.c +pwm.c +pwm.h ringbuffer.c ringbuffer.h strfunc.c diff --git a/F0:F030,F042,F072/usbcan_gpio/version.inc b/F0:F030,F042,F072/usbcan_gpio/version.inc index 4d56d69..951c9c1 100644 --- a/F0:F030,F042,F072/usbcan_gpio/version.inc +++ b/F0:F030,F042,F072/usbcan_gpio/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "190" -#define BUILD_DATE "2026-03-14" +#define BUILD_NUMBER "192" +#define BUILD_DATE "2026-03-15"