diff --git a/F0:F030,F042,F072/usbcan_gpio/Readme.md b/F0:F030,F042,F072/usbcan_gpio/Readme.md index f5a8006..f0291a7 100644 --- a/F0:F030,F042,F072/usbcan_gpio/Readme.md +++ b/F0:F030,F042,F072/usbcan_gpio/Readme.md @@ -10,3 +10,6 @@ The old USB-CAN is available as earlier by /dev/USB-CANx, also you can see new d New interface allows you to configure GPIO and use it's base functions: in/out/ADC. +## DMA channels + +DMA1 channel1: ADC. \ No newline at end of file diff --git a/F0:F030,F042,F072/usbcan_gpio/adc.c b/F0:F030,F042,F072/usbcan_gpio/adc.c new file mode 100644 index 0000000..3c25fe7 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_gpio/adc.c @@ -0,0 +1,158 @@ +/* + * 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 + +#include "adc.h" + +/** + * @brief ADC_array - array for ADC channels with median filtering: + * 0..3 - external channels + * 4 - internal Tsens + * 5 - Vref + */ +#define TSENS_CHAN (NUM_EXT_ADC_CH) +#define VREF_CHAN (NUM_EXT_ADC_CH + 1) +static uint16_t ADC_array[MAX_ADC_CHANNELS*9]; + +/* + * ADC channels: + * IN0 - V12 + * IN1 - V5 + * IN16- temperature sensor + * IN17- vref + */ +void adc_setup(){ + uint16_t ctr = 0; // 0xfff0 - more than 1.3ms + // Enable clocking + /* (1) Enable the peripheral clock of the ADC */ + /* (2) Start HSI14 RC oscillator */ + /* (3) Wait HSI14 is ready */ + RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* (1) */ + RCC->CR2 |= RCC_CR2_HSI14ON; /* (2) */ + while ((RCC->CR2 & RCC_CR2_HSI14RDY) == 0 && ++ctr < 0xfff0){}; /* (3) */ + // calibration + /* (1) Ensure that ADEN = 0 */ + /* (2) Clear ADEN */ + /* (3) Launch the calibration by setting ADCAL */ + /* (4) Wait until ADCAL=0 */ + if ((ADC1->CR & ADC_CR_ADEN) != 0){ /* (1) */ + ADC1->CR &= (uint32_t)(~ADC_CR_ADEN); /* (2) */ + } + ADC1->CR |= ADC_CR_ADCAL; /* (3) */ + ctr = 0; // ADC calibration time is 5.9us + while ((ADC1->CR & ADC_CR_ADCAL) != 0 && ++ctr < 0xfff0){}; /* (4) */ + // enable ADC + ctr = 0; + do{ + ADC1->CR |= ADC_CR_ADEN; + }while ((ADC1->ISR & ADC_ISR_ADRDY) == 0 && ++ctr < 0xfff0); + // configure ADC + /* (1) Select HSI14 by writing 00 in CKMODE (reset value) */ + /* (2) Select the continuous mode */ + /* (3) Select CHSEL0-9 - all ADC inputs, 16,17 - t. sensor and vref */ + /* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */ + /* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */ + // ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */ + ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/ + ADC1->CHSELR = (0x3FF << 0) | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17; /* (3)*/ + ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* (4) */ + ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; /* (5) */ + // configure DMA for ADC + // DMA for AIN + /* (1) Enable the peripheral clock on DMA */ + /* (2) Enable DMA transfer on ADC and circular mode */ + /* (3) Configure the peripheral data register address */ + /* (4) Configure the memory address */ + /* (5) Configure the number of DMA tranfer to be performs on DMA channel 1 */ + /* (6) Configure increment, size, interrupts and circular mode */ + /* (7) Enable DMA Channel 1 */ + RCC->AHBENR |= RCC_AHBENR_DMA1EN; /* (1) */ + ADC1->CFGR1 |= ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG; /* (2) */ + DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR)); /* (3) */ + DMA1_Channel1->CMAR = (uint32_t)(ADC_array); /* (4) */ + DMA1_Channel1->CNDTR = MAX_ADC_CHANNELS * 9; /* (5) */ + DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_CIRC; /* (6) */ + DMA1_Channel1->CCR |= DMA_CCR_EN; /* (7) */ + ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversions */ +} + + +/** + * @brief getADCval - calculate median value for `nch` channel + * @param nch - number of channel + * @return + */ +uint16_t getADCval(int nch){ + int i, addr = nch; + register uint16_t temp; +#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); } +#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; } + uint16_t p[9]; + for(i = 0; i < 9; ++i, addr += MAX_ADC_CHANNELS) // first we should prepare array for optmed + p[i] = ADC_array[addr]; + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ; + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ; + PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ; + PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ; + PIX_SORT(p[4], p[2]) ; + return p[4]; +#undef PIX_SORT +#undef PIX_SWAP +} + +// return MCU temperature (degrees of celsius * 10) +int32_t getMCUtemp(){ + int32_t ADval = getADCval(TSENS_CHAN); + int32_t temperature = (int32_t) *TEMP30_CAL_ADDR - ADval; + temperature *= (int32_t)(1100 - 300); + temperature /= (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR); + temperature += 300; + return(temperature); +} + +// return Vdd * 100 (V) +uint32_t getVdd(){ + uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330; // 3.3V + vdd /= getADCval(VREF_CHAN); + return vdd; +} + +static inline uint32_t Ufromadu(uint8_t nch, uint32_t vdd){ + uint32_t ADU = getADCval(nch); + ADU *= vdd; + ADU >>= 12; // /4096 + return ADU; +} + +/** + * @brief getUval - calculate U12/U5 + * @return array with members: + * 0 - V12 * 100V (U12 = 12Vin/4.93) + * 1 - V5 * 100V (U5 = 5Vin /2) + */ +uint16_t *getUval(){ + static uint16_t Uval[4]; + uint32_t vdd = getVdd(); + uint32_t val = Ufromadu(0, vdd) * 493; + Uval[0] = (uint16_t)(val / 100); + Uval[1] = (uint16_t)(Ufromadu(1, vdd) << 1); + return Uval; +} diff --git a/F0:F030,F042,F072/usbcan_gpio/adc.h b/F0:F030,F042,F072/usbcan_gpio/adc.h new file mode 100644 index 0000000..11ecbe4 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_gpio/adc.h @@ -0,0 +1,30 @@ +/* + * 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 +#include + +// 10 ADC ins + VDD + MCUt +#define NUM_EXT_ADC_CH 10 +#define MAX_ADC_CHANNELS (NUM_EXT_ADC_CH+2) + +int32_t getMCUtemp(); +uint32_t getVdd(); +uint16_t getADCval(int nch); +void adc_setup(); +uint16_t *getUval(); diff --git a/F0:F030,F042,F072/usbcan_gpio/canproto.c b/F0:F030,F042,F072/usbcan_gpio/canproto.c index 2f6da31..cacfe94 100644 --- a/F0:F030,F042,F072/usbcan_gpio/canproto.c +++ b/F0:F030,F042,F072/usbcan_gpio/canproto.c @@ -337,11 +337,11 @@ TRUE_INLINE void getcanstat(){ } /** - * @brief cmd_parser - command parsing + * @brief CommandParser - command parsing * @param txt - buffer with commands & data * @param isUSB - == 1 if data got from USB */ -static void cmd_parser(char *txt){ +static void CommandParser(char *txt){ char _1st = txt[0]; ++txt; /* @@ -479,5 +479,5 @@ void CANUSB_process(){ } int l = RECV(inbuff, MAXSTRLEN); if(l < 0) SEND("ERROR: USB buffer overflow or string was too long\n"); - else if(l) cmd_parser(inbuff); + else if(l) CommandParser(inbuff); } diff --git a/F0:F030,F042,F072/usbcan_gpio/gpio.c b/F0:F030,F042,F072/usbcan_gpio/gpio.c index 5b222c9..8df5540 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpio.c +++ b/F0:F030,F042,F072/usbcan_gpio/gpio.c @@ -19,10 +19,11 @@ #include #include +#include "adc.h" #include "flash.h" #include "gpio.h" -static uint16_t monitor_mask[2] = {0}; // pins to monitor == 1 (ONLY GPIO!!!) +static uint16_t monitor_mask[2] = {0}; // pins to monitor == 1 (ONLY GPIO and ADC) static uint16_t oldstates[2][16] = {0}; // previous state (16 bits - as some pins could be analog) // strings for keywords @@ -134,6 +135,22 @@ int set_pinfunc(uint8_t port, uint8_t pin, pinconfig_t *pcfg){ return TRUE; } +/** + * @brief get_adc_channel - get ADC channel number for given pin + * @param port - 0/1 (GPIOA/GPIOB) + * @param pin - 0..16 + * @return ADC channel number or -1 + */ +TRUE_INLINE int8_t get_adc_channel(uint8_t port, uint8_t pin){ + if(port == 0){ // GPIOA + if (pin <= 7) return pin; // PA0..PA7 -> IN0..IN7 + }else{ // GPIOB + if(pin == 0) return 8; // PB0 -> IN8 + if(pin == 1) return 9; // PB1 -> IN9 + } + return -1; // No ADC channel on this pin +} + // reinit all GPIO registers due to config; also configure (if need) USART1/2, SPI1 and I2C1 int gpio_reinit(){ bzero(monitor_mask, sizeof(monitor_mask)); @@ -167,7 +184,19 @@ int gpio_reinit(){ int shift4 = (pin - 8) << 4; gpio->AFR[1] = (gpio->AFR[1] & ~(0xf << shift4)) | (cfg->afno << shift4); } - if(cfg->monitor && cfg->mode != MODE_AF) monitor_mask[port] |= (1 << pin); + if(cfg->monitor && cfg->mode != MODE_AF){ + monitor_mask[port] |= (1 << pin); + if(cfg->mode == MODE_ANALOG){ + if(cfg->threshold > 4095) cfg->threshold = 4095; // no threshold + int8_t chan = get_adc_channel(port, pin); + if(chan >= 0){ + oldstates[port][pin] = getADCval(chan); + } + }else{ + // цифровой режим  сохраняем текущее состояние IDR + oldstates[port][pin] = (gpio->IDR >> pin) & 1; + } + } } } // TODO: configure USART, SPI etc @@ -216,8 +245,14 @@ int16_t pin_in(uint8_t port, uint8_t pin){ if(GPIOx->IDR & (1<= 0){ + return (int16_t)getADCval(chan); // getADCval возвращает uint16_t + } + } + break; + default: break; } return val; @@ -241,11 +276,22 @@ uint16_t gpio_alert(uint8_t port){ uint8_t curm = moder & 3; if((curm == MODE_AF) || 0 == (monitor_mask[port] & curpinbit)) continue; // monitor also OUT (if OD) // TODO: add AIN - if(curm == MODE_ANALOG) continue; - uint16_t curval = (GPIOx->IDR & curpinbit) ? 1 : 0; - if(oldstate[pin] != curval){ - oldstate[pin] = curval; - alert |= curpinbit; + if(curm == MODE_ANALOG){ + int8_t chan = get_adc_channel(port, pin); + if(chan < 0) continue; // can't be in normal case + uint16_t cur = getADCval(chan); + uint16_t thresh = the_conf.pinconfig[port][pin].threshold; + uint16_t diff = (cur > oldstate[pin]) ? (cur - oldstate[pin]) : (oldstate[pin] - cur); + if(diff > thresh){ + oldstate[pin] = cur; + alert |= curpinbit; + } + }else{ + uint16_t curval = (GPIOx->IDR & curpinbit) ? 1 : 0; + if(oldstate[pin] != curval){ + oldstate[pin] = curval; + alert |= curpinbit; + } } } return alert; diff --git a/F0:F030,F042,F072/usbcan_gpio/gpio.h b/F0:F030,F042,F072/usbcan_gpio/gpio.h index a35c602..10ce618 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpio.h +++ b/F0:F030,F042,F072/usbcan_gpio/gpio.h @@ -78,14 +78,15 @@ typedef union{ } funcvalues_t; */ typedef struct{ - uint8_t enable : 1; // [immutable!] pin config avialable (==1 for PA0-PA3, PA5-PA7, PA9, PA10, PB0-PB7, PB10, PB11, ==0 for rest) + uint8_t enable : 1; // [immutable!] pin config avialable (==1 for PA0-PA3, PA5-PA7, PA9, PA10, PB0-PB7, PB10, PB11, ==0 for rest) pinmode_t mode : 2; pinpull_t pull : 2; pinout_t otype : 1; pinspeed_t speed : 2; - uint8_t afno : 3; // alternate function number (only if mode == MODE_AF) - uint8_t af : 3; // alternate function name (`FuncNames`) - uint8_t monitor : 1; // monitor changes + uint8_t afno : 3; // alternate function number (only if mode == MODE_AF) + uint8_t af : 3; // alternate function name (`FuncNames`) + uint8_t monitor : 1; // monitor changes + uint16_t threshold; // threshold for ADC measurement } pinconfig_t; typedef struct{ @@ -119,7 +120,8 @@ KW(OD) \ KW(USART) \ KW(SPI) \ KW(I2C) \ -KW(MONITOR) +KW(MONITOR) \ +KW(THRESHOLD) enum{ // indexes of string keywords #define KW(k) STR_ ## k, diff --git a/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp b/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp index 8f6d180..26763bf 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp +++ b/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp @@ -22,6 +22,7 @@ extern "C"{ #include +#include "adc.h" #include "can.h" #include "flash.h" #include "gpioproto.h" @@ -43,6 +44,7 @@ extern volatile uint32_t Tms; COMMAND(dumpconf, "dump current configuration") \ COMMAND(eraseflash, "erase full flash storage") \ COMMAND(help, "show this help") \ + COMMAND(mcutemp, "get MCU temperature (degC*10)") \ COMMAND(mcureset, "reset MCU") \ COMMAND(PA, "GPIOA setter/getter (type PA0=help for further info)") \ COMMAND(PB, "GPIOB setter/getter") \ @@ -52,7 +54,8 @@ extern volatile uint32_t Tms; COMMAND(sendcan, "send all after '=' to CAN USB interface") \ COMMAND(setiface, "set/get name of interface x (0 - CAN, 1 - GPIO)") \ COMMAND(storeconf, "save config to flash") \ - COMMAND(time, "show current time (ms)") + COMMAND(time, "show current time (ms)") \ + COMMAND(vdd, "get approx Vdd value (V*100)") // COMMAND(USART, "Read USART data or send (USART=hex)") // COMMAND(usartconf, "set USART params (e.g. usartconf=115200 8N1)") @@ -93,6 +96,7 @@ enum KeywordGroup { enum MiscValues{ MISC_MONITOR = 1, + MISC_THRESHOLD }; static const Keyword keywords[] = { @@ -110,6 +114,7 @@ static const Keyword keywords[] = { KEY(SPI, GROUP_FUNC, FUNC_SPI) KEY(I2C, GROUP_FUNC, FUNC_I2C) KEY(MONITOR, GROUP_MISC, MISC_MONITOR) + KEY(THRESHOLD, GROUP_MISC, MISC_THRESHOLD) #undef K }; #define NUM_KEYWORDS (sizeof(keywords)/sizeof(keywords[0])) @@ -129,11 +134,18 @@ static const char *pinhelp = " PULL: PU, PD or FL (pullup, pulldown, no pull - floating)\n" " OTYPE: PP or OD (push-pull or open-drain)\n" " FUNC: USART or SPI (enable alternate function and configure peripheal)\n" - " MISC: MONITOR (send data by USB as only state changed)\n\n" + " MISC: MONITOR - send data by USB as only state changed\n" + " THRESHOLD (ADC only) - monitoring threshold, ADU\n" + "\n" ; static const char *EQ = " = "; // equal sign for getters +// send `command = ` +#define CMDEQ() do{SEND(cmd); SEND(EQ);}while(0) +// send `commandXXX = ` +#define CMDEQP(x) do{SEND(cmd); SEND(u2str((uint32_t)x)); SEND(EQ);}while(0) + /** * @brief splitargs - get command parameter and setter from `args` * @param args (i) - rest of string after command (like `1 = PU OD OUT`) @@ -201,8 +213,19 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){ // complex setter: parse properties uint8_t mode_set = 0xFF, pull_set = 0xFF, otype_set = 0xFF, func_set = 0xFF; bool monitor = false; + uint16_t *pending_num = NULL; // pointer to UINT16 value, if !NULL, next token should be a number + pinconfig_t curconf = the_conf.pinconfig[port][pin]; // copy old config char *saveptr, *token = strtok_r(setter, " ,", &saveptr); while(token){ + if(pending_num){ + int32_t val; + char *end = getint(token, &val); + if(end == token || val < 0 || val > 0xFFFF) return ERR_BADVAL; + *pending_num = (uint16_t)val; + pending_num = NULL; // reset + token = strtok_r(NULL, " ,", &saveptr); + continue; + } size_t i = 0; for(; i < NUM_KEYWORDS; i++){ if(strcmp(token, str_keywords[keywords[i].index]) == 0){ @@ -229,8 +252,14 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){ break; case GROUP_MISC: DBG("GROUP_MISC\n"); - if(keywords[i].value == MISC_MONITOR) monitor = true; - break; + switch(keywords[i].value){ + case MISC_MONITOR: + monitor = true; + break; + case MISC_THRESHOLD: + pending_num = &curconf.threshold; + break; + } } break; } @@ -238,6 +267,7 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){ if(i == NUM_KEYWORDS) return ERR_BADVAL; // not found token = strtok_r(NULL, " ,", &saveptr); } + if(pending_num) return ERR_BADVAL; // no number that we waiting for if(func_set != 0xFF) mode_set = MODE_AF; if(mode_set == 0xFF) return ERR_BADVAL; // user forgot to set mode // set defaults @@ -245,7 +275,6 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){ if(otype_set == 0xFF) otype_set = OUTPUT_PP; // can also do something with `speed_set`, then remove SPEED_MEDIUM from `curconfig` // check that current parameters combination is acceptable for current pin - pinconfig_t curconf; curconf.mode = static_cast (mode_set); curconf.pull = static_cast (pull_set); curconf.otype = static_cast (otype_set); @@ -301,12 +330,14 @@ static errcodes_t cmd_canspeed(const char *cmd, char *args){ if(S < CAN_MIN_SPEED || S > CAN_MAX_SPEED) return ERR_BADVAL; the_conf.CANspeed = S; } - SEND(cmd); PUTCHAR('='); SENDn(u2str(the_conf.CANspeed)); + CMDEQ(); + SENDn(u2str(the_conf.CANspeed)); return ERR_AMOUNT; } static errcodes_t cmd_curcanspeed(const char *cmd, char _U_ *args){ - SEND(cmd); PUTCHAR('='); SENDn(u2str(CAN_getspeed())); + CMDEQ(); + SENDn(u2str(CAN_getspeed())); return ERR_AMOUNT; } @@ -350,6 +381,11 @@ static errcodes_t cmd_dumpconf(const char _U_ *cmd, char _U_ *args){ break; case MODE_ANALOG: S(AIN); + if(p->threshold){ + SP(THRESHOLD); + PUTCHAR(' '); + SEND(u2str(p->threshold)); + } break; case MODE_AF: switch(p->af){ @@ -430,7 +466,7 @@ static errcodes_t cmd_setiface(const char* cmd, char *args){ } } // getter - SEND(cmd); PUTCHAR('='); + CMDEQP(N); char *ptr = (char*) the_conf.iInterface[N]; int l = the_conf.iIlengths[N] / 2; for(int j = 0; j < l; ++j){ @@ -446,11 +482,13 @@ static errcodes_t cmd_sendcan(const char _U_ *cmd, char *args){ char *setter = splitargs(args, NULL); if(!setter) return ERR_BADVAL; if(USB_sendstr(ICAN, setter)) return ERR_OK; + USB_putbyte(ICAN, '\n'); return ERR_CANTRUN; } static errcodes_t cmd_time(const char *cmd, char _U_ *args){ - SEND(cmd); PUTCHAR('='); SENDn(u2str(Tms)); + CMDEQ(); + SENDn(u2str(Tms)); return ERR_AMOUNT; } @@ -474,6 +512,18 @@ static errcodes_t cmd_eraseflash(const char _U_ *cmd, char _U_ *args){ return ERR_OK; } +static errcodes_t cmd_mcutemp(const char *cmd, char _U_ *args){ + CMDEQ(); + SENDn(i2str(getMCUtemp())); + return ERR_AMOUNT; +} + +static errcodes_t cmd_vdd(const char *cmd, char _U_ *args){ + CMDEQ(); + SENDn(u2str(getVdd())); + return ERR_AMOUNT; +} + static errcodes_t cmd_help(const char _U_ *cmd, char _U_ *args){ SEND(REPOURL); for(size_t i = 0; i < sizeof(cmdInfo)/sizeof(cmdInfo[0]); i++){ @@ -490,7 +540,7 @@ constexpr uint32_t hash(const char* str, uint32_t h = 0){ // TODO: add checking real command length! -static const char *cmd_parser(char *str){ +static const char *CommandParser(char *str){ char command[CMD_MAXLEN+1]; int i = 0; while(*str > '@' && i < CMD_MAXLEN){ command[i++] = *str++; } @@ -524,7 +574,7 @@ void GPIO_process(){ if(l == 0) return; if(l < 0) SEND("ERROR: USB buffer overflow or string was too long\n"); else{ - const char *ans = cmd_parser(inbuff); + const char *ans = CommandParser(inbuff); if(ans) SENDn(ans); } } diff --git a/F0:F030,F042,F072/usbcan_gpio/gpioproto.h b/F0:F030,F042,F072/usbcan_gpio/gpioproto.h index ff5390c..6f5478e 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpioproto.h +++ b/F0:F030,F042,F072/usbcan_gpio/gpioproto.h @@ -34,4 +34,7 @@ typedef enum{ // maximal available parameter number #define MAXPARNO 255 +// default threshold for monitoring +#define ADC_THRES_DEFAULT 100 + void GPIO_process(); diff --git a/F0:F030,F042,F072/usbcan_gpio/hardware.c b/F0:F030,F042,F072/usbcan_gpio/hardware.c index a64c064..eae568c 100644 --- a/F0:F030,F042,F072/usbcan_gpio/hardware.c +++ b/F0:F030,F042,F072/usbcan_gpio/hardware.c @@ -16,22 +16,30 @@ * along with this program. If not, see . */ +#include "adc.h" +#include "gpio.h" #include "hardware.h" uint8_t ledsON = 0; -void gpio_setup(void){ - // enable all active GPIO clocking - RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; +TRUE_INLINE void gpio_setup(){ // setup some common GPIO // Set LEDS (PB15/PA8) as output pin_set(LED0_port, LED0_pin); // clear LEDs pin_set(LED1_port, LED1_pin); GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER15)) | - GPIO_MODER_MODER15_O; + GPIO_MODER_MODER15_O; GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER8)) | GPIO_MODER_MODER8_O; } +void hardware_setup(){ + // enable all active GPIO clocking + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; + gpio_setup(); + //gpio_reinit(); + adc_setup(); +} + void iwdg_setup(){ uint32_t tmout = 16000000; /* Enable the peripheral clock RTC */ diff --git a/F0:F030,F042,F072/usbcan_gpio/hardware.h b/F0:F030,F042,F072/usbcan_gpio/hardware.h index d93dccc..d70d44d 100644 --- a/F0:F030,F042,F072/usbcan_gpio/hardware.h +++ b/F0:F030,F042,F072/usbcan_gpio/hardware.h @@ -44,7 +44,7 @@ extern volatile uint32_t Tms; extern uint8_t ledsON; -void gpio_setup(void); +void hardware_setup(); void iwdg_setup(); #ifdef STM32F072xB void Jump2Boot(); diff --git a/F0:F030,F042,F072/usbcan_gpio/main.c b/F0:F030,F042,F072/usbcan_gpio/main.c index 9c6a9e2..e9ce141 100644 --- a/F0:F030,F042,F072/usbcan_gpio/main.c +++ b/F0:F030,F042,F072/usbcan_gpio/main.c @@ -33,7 +33,7 @@ int main(void){ sysreset(); SysTick_Config(6000, 1); flashstorage_init(); - gpio_setup(); + hardware_setup(); USB_setup(); CAN_setup(the_conf.CANspeed); RCC->CSR |= RCC_CSR_RMVF; // remove reset flags diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin index 0dab055..3e42d37 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 3ba89ad..407bc5f 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 5101e54..a18589b 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files +++ b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files @@ -1,3 +1,5 @@ +adc.c +adc.h can.c can.h canproto.c diff --git a/F0:F030,F042,F072/usbcan_gpio/version.inc b/F0:F030,F042,F072/usbcan_gpio/version.inc index d504585..e4c8082 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 "125" +#define BUILD_NUMBER "132" #define BUILD_DATE "2026-03-10"