diff --git a/F3:F303/CANbus4BTA/BTA_CAN.bin b/F3:F303/CANbus4BTA/BTA_CAN.bin index c030ba8..1f55b85 100755 Binary files a/F3:F303/CANbus4BTA/BTA_CAN.bin and b/F3:F303/CANbus4BTA/BTA_CAN.bin differ diff --git a/F3:F303/CANbus4BTA/can.c b/F3:F303/CANbus4BTA/can.c index 3be9089..94cec5e 100644 --- a/F3:F303/CANbus4BTA/can.c +++ b/F3:F303/CANbus4BTA/can.c @@ -32,6 +32,15 @@ #include // memcpy +// CAN bus oscillator frequency: 36MHz +#define CAN_F_OSC (36000000UL) +// timing values TBS1 and TBS2 (in BTR [TBS1-1] and [TBS2-1]) +// use 3 and 2 to get 6MHz +#define CAN_TBS1 (3) +#define CAN_TBS2 (2) +// bitrate oscillator frequency +#define CAN_BIT_OSC (CAN_F_OSC / (1+CAN_TBS1+CAN_TBS2)) + uint8_t cansniffer = 0; // 0 - receive only 0 and myID, 1 - receive all // circular buffer for received messages @@ -143,7 +152,7 @@ void CAN_setup(uint32_t speed){ /* (1) Enter CAN init mode to write the configuration */ /* (2) Wait the init mode entering */ /* (3) Exit sleep mode */ - /* (4) Normal mode, set timing to 100kb/s: TBS1 = 4, TBS2 = 3, prescaler = 60 */ + /* (4) Normal mode, set timing : TBS1 = 4, TBS2 = 3 */ /* (5) Leave init mode */ /* (6) Wait the init mode leaving */ /* (7) Enter filter init mode, (16-bit + mask, bank 0 for FIFO 0) */ @@ -158,8 +167,8 @@ void CAN_setup(uint32_t speed){ if(tmout==0){ DBG("timeout!\n");} CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */ CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */ - CAN->BTR = 2 << 20 | 3 << 16 | (((uint32_t)4500000UL)/speed - 1); //| CAN_BTR_SILM | CAN_BTR_LBKM; /* (4) */ - oldspeed = ((uint32_t)4500000UL)/(uint32_t)((CAN->BTR & CAN_BTR_BRP) + 1); + CAN->BTR = (CAN_TBS2-1) << 20 | (CAN_TBS1-1) << 16 | (CAN_BIT_OSC/speed - 1); //| CAN_BTR_SILM | CAN_BTR_LBKM; /* (4) */ + oldspeed = CAN_BIT_OSC/(uint32_t)((CAN->BTR & CAN_BTR_BRP) + 1); CAN->MCR &= ~CAN_MCR_INRQ; /* (5) */ tmout = 10000; while(CAN->MSR & CAN_MSR_INAK) /* (6) */ diff --git a/F3:F303/CANbus4BTA/canbus4bta.creator.user b/F3:F303/CANbus4BTA/canbus4bta.creator.user index 332da69..b114d45 100644 --- a/F3:F303/CANbus4BTA/canbus4bta.creator.user +++ b/F3:F303/CANbus4BTA/canbus4bta.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F3:F303/CANbus4BTA/canbus4bta.files b/F3:F303/CANbus4BTA/canbus4bta.files index 9930bb6..4478816 100644 --- a/F3:F303/CANbus4BTA/canbus4bta.files +++ b/F3:F303/CANbus4BTA/canbus4bta.files @@ -6,6 +6,8 @@ commonfunctions.c commonfunctions.h flash.c flash.h +gpio.c +gpio.h hardware.c hardware.h main.c diff --git a/F3:F303/CANbus4BTA/commonfunctions.c b/F3:F303/CANbus4BTA/commonfunctions.c index 46dd599..f4a828c 100644 --- a/F3:F303/CANbus4BTA/commonfunctions.c +++ b/F3:F303/CANbus4BTA/commonfunctions.c @@ -20,6 +20,7 @@ #include "can.h" #include "commonfunctions.h" #include "flash.h" +#include "gpio.h" #include "proto.h" #include "usb.h" @@ -102,7 +103,39 @@ static errcodes erasestor(CAN_message _U_ *msg){ if(0 == erase_storage(-1)) return ERR_OK; return ERR_CANTRUN; } - +// relay management +static errcodes relay(CAN_message *msg){ + if(ISSETTER(msg->data)){ + if(msg->data[4] == 1) RELAY_ON(); + else RELAY_OFF(); + }else FIXDL(msg); + *(uint32_t*)&msg->data[4] = RELAY_GET(); + return ERR_OK; +} +// blocking ESW get status +static errcodes eswblk(CAN_message *msg){ + uint8_t no = msg->data[2] & ~SETTER_FLAG; + if(no > 1) return ERR_BADPAR; + FIXDL(msg); + *(uint32_t*)&msg->data[4] = getSwitches(no); + return ERR_OK; +} +// bounce-free ESW get status +static errcodes esw(CAN_message *msg){ + uint8_t no = msg->data[2] & ~SETTER_FLAG; + if(no > 1) return ERR_BADPAR; + FIXDL(msg); + *(uint32_t*)&msg->data[4] = getESW(no); + return ERR_OK; +} +// bounce constant, ms +static errcodes bounce(CAN_message *msg){ + if(ISSETTER(msg->data)){ + the_conf.bounce_ms = *(uint32_t*)&msg->data[4]; + }else FIXDL(msg); + *(uint32_t*)&msg->data[4] = the_conf.bounce_ms; + return ERR_OK; +} /************ END of all common functions list (for `funclist`) ************/ @@ -126,6 +159,10 @@ static const commonfunction funclist[CMD_AMOUNT] = { [CMD_ADCMUL] = {adcmul, 0, 0, 3}, // at least parno [CMD_SAVECONF] = {saveconf, 0, 0, 0}, [CMD_ERASESTOR] = {erasestor, 0, 0, 0}, + [CMD_RELAY] = {relay, 0, 1, 0}, + [CMD_GETESW_BLK] = {eswblk, 0, 0, 3}, + [CMD_GETESW] = {esw, 0, 0, 3}, + [CMD_BOUNCE] = {bounce, 0, 300, 0}, }; diff --git a/F3:F303/CANbus4BTA/flash.c b/F3:F303/CANbus4BTA/flash.c index d4366f8..5976917 100644 --- a/F3:F303/CANbus4BTA/flash.c +++ b/F3:F303/CANbus4BTA/flash.c @@ -35,6 +35,7 @@ static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here .userconf_sz = sizeof(user_conf) \ ,.CANspeed = 100000 \ ,.CANID = 0xaa \ + ,.bounce = 50 \ ,.adcmul[0] = 10.930f \ ,.adcmul[1] = 2.028f \ ,.adcmul[2] = 1.f \ diff --git a/F3:F303/CANbus4BTA/flash.h b/F3:F303/CANbus4BTA/flash.h index 5e1b871..4f5730f 100644 --- a/F3:F303/CANbus4BTA/flash.h +++ b/F3:F303/CANbus4BTA/flash.h @@ -35,6 +35,7 @@ typedef struct __attribute__((packed, aligned(4))){ uint16_t userconf_sz; // "magick number" uint16_t CANID; // identifier uint32_t CANspeed; // default CAN speed + uint32_t bounce_ms; // a float adcmul[ADC_TSENS]; // ADC voltage multipliers } user_conf; diff --git a/F3:F303/CANbus4BTA/gpio.c b/F3:F303/CANbus4BTA/gpio.c new file mode 100644 index 0000000..acc15a0 --- /dev/null +++ b/F3:F303/CANbus4BTA/gpio.c @@ -0,0 +1,102 @@ +/* + * This file is part of the canbus4bta project. + * Copyright 2024 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 "flash.h" +#include "gpio.h" +#include "hardware.h" + +// GPIO IN management by two 74HC4051 + +static uint8_t eswitches[2] = {0}; +static uint8_t stage = 0; +static uint32_t lastT[8][2] = {0}; // last time of ESW changed + +uint8_t getESW(uint8_t nch){ + return eswitches[nch]; +} + +// update `eswitches`, anti-bounce +TRUE_INLINE void updesw(uint8_t nch, uint8_t newval){ + uint8_t mask = eswitches[nch] ^ newval, newmask = 0; + if(mask == 0) return; + for(uint8_t bit = 0; bit < 8; ++bit){ // check all bits of mask + newmask >>= 1; + if((mask & 1) && Tms - lastT[bit][nch] >= the_conf.bounce_ms){ // OK, change this value + newmask |= 0x80; + lastT[bit][nch] = Tms; + } + mask >>= 1; + } + if(newmask == 0) return; + // now change only allowable bits + eswitches[nch] = (eswitches[nch] & ~newmask) | (newval & newmask); +} + +/** + * @brief ESW_process - process multiplexer 1 + */ +void ESW_process(){ + static uint8_t curch = 0; + static int curaddr = 7; + static uint8_t ESW = 0; + switch(stage){ + case 0: // stage 0: change address and turn on multiplexer + stage = 1; + MULADDR_set(curaddr); + MUL_ON(curch); + break; + case 1: // stage 1: read data and turn off mul + default: + stage = 0; + ESW <<= 1; + ESW |= ESW_GET(); + MUL_OFF(curch); + if(--curaddr < 0){ + updesw(curch, ESW); + curch = !curch; + curaddr = 7; + } + break; + } +} + +static void NeverDoThisFuckingShit(){ + uint32_t ctr = 3; + while(ctr--) nop(); +} + +/** + * @brief getSwitches - blocking read of all switches of given channel + * @param chno - number of multiplexer: 0 (board switches) or 1 (external ESW) + */ +uint8_t getSwitches(uint8_t chno){ + if(chno > 1) return 0; + MUL_OFF(0); MUL_OFF(1); + uint8_t state = 0; + for(int i = 7; i > -1; --i){ + MULADDR_set(i); + MUL_ON(chno); + state <<= 1; + NeverDoThisFuckingShit(); + state |= ESW_GET(); + MUL_OFF(chno); + NeverDoThisFuckingShit(); + } + stage = 0; // prevent interference with `ESW_process()` + return state; +} diff --git a/F3:F303/CANbus4BTA/gpio.h b/F3:F303/CANbus4BTA/gpio.h new file mode 100644 index 0000000..2b63608 --- /dev/null +++ b/F3:F303/CANbus4BTA/gpio.h @@ -0,0 +1,24 @@ +/* + * This file is part of the canbus4bta project. + * Copyright 2024 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 + +uint8_t getESW(uint8_t nch); +void ESW_process(); +uint8_t getSwitches(uint8_t chno); diff --git a/F3:F303/CANbus4BTA/hardware.c b/F3:F303/CANbus4BTA/hardware.c index fa04be3..2836d52 100644 --- a/F3:F303/CANbus4BTA/hardware.c +++ b/F3:F303/CANbus4BTA/hardware.c @@ -47,6 +47,7 @@ TRUE_INLINE void iwdg_setup(){ #endif static inline void gpio_setup(){ + RELAY_OFF(); MUL_OFF(0); MUL_OFF(1); RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN; // PWM - AF1 @PA7; USB - alternate function 14 @ pins PA11/PA12; USART1 = AF7 @PA9/10; SWD - AF0 @PA13/14 GPIOA->AFR[0] = AFRf(1, 7); @@ -57,7 +58,8 @@ static inline void gpio_setup(){ GPIOA->MODER = MODER_AI(0) | MODER_AI(1) | MODER_AI(2) | MODER_AI(3) | MODER_I(4) | MODER_O(5) | MODER_O(6) | MODER_AF(7) | MODER_I(8) | MODER_AF(9) | MODER_AF(10) | MODER_AF(11) | MODER_AF(12) | MODER_AF(13) | MODER_AF(14) | MODER_I(15); - GPIOA->OSPEEDR = OSPEED_MED(7) | OSPEED_MED(9) | OSPEED_MED(10) | OSPEED_HI(11) | OSPEED_HI(12) | OSPEED_HI(13) | OSPEED_HI(14); + GPIOA->OSPEEDR = OSPEED_HI(4) | OSPEED_MED(7) | OSPEED_MED(9) | OSPEED_MED(10) | OSPEED_HI(11) | + OSPEED_HI(12) | OSPEED_HI(13) | OSPEED_HI(14); // SPI for SSI: AF5 @PB3, PB4; I2C1: AF4 @PB6, PB7; CAN: AF9 @PB8, PB9; SPI2: AF5 @PB12..PB15 GPIOB->AFR[0] = AFRf(5, 3) | AFRf(5, 4) | AFRf(4, 6) | AFRf(4, 7); GPIOB->AFR[1] = AFRf(9, 8) | AFRf(9, 9) | AFRf(5, 12) | AFRf(5, 13) | AFRf(5, 14) | AFRf(5, 15); diff --git a/F3:F303/CANbus4BTA/hardware.h b/F3:F303/CANbus4BTA/hardware.h index a623393..c1138cf 100644 --- a/F3:F303/CANbus4BTA/hardware.h +++ b/F3:F303/CANbus4BTA/hardware.h @@ -20,11 +20,25 @@ #include +// USB pullup #define USBPU_port GPIOC #define USBPU_pin (1<<15) #define USBPU_ON() pin_set(USBPU_port, USBPU_pin) #define USBPU_OFF() pin_clear(USBPU_port, USBPU_pin) +// relay +#define RELAY_port GPIOC +#define RELAY_pin (1<<14) +#define RELAY_ON() pin_set(RELAY_port, RELAY_pin) +#define RELAY_OFF() pin_clear(RELAY_port, RELAY_pin) +#define RELAY_GET() pin_read(RELAY_port, RELAY_pin) + +// GPIO end-switches multiplexer (addr - PB0..2, ~DEN0 - PA5, ~DEN1 - PA6) and input (PA4) +#define ESW_GET() (GPIOA->IDR & (1<<4) ? 0 : 1) +#define MULADDR_set(x) do{GPIOB->BSRR = (x&7) | (((~x)&7) << 16);}while(0) +#define MUL_ON(x) pin_clear(GPIOA, 1<<(5+x)) +#define MUL_OFF(x) pin_set(GPIOA, 1<<(5+x)) + extern volatile uint32_t Tms; void hw_setup(); diff --git a/F3:F303/CANbus4BTA/main.c b/F3:F303/CANbus4BTA/main.c index 4263c36..91aaeb8 100644 --- a/F3:F303/CANbus4BTA/main.c +++ b/F3:F303/CANbus4BTA/main.c @@ -18,6 +18,7 @@ #include "can.h" #include "flash.h" +#include "gpio.h" #include "hardware.h" #include "textfunctions.h" #include "usart.h" @@ -57,6 +58,7 @@ int main(void){ } flashstorage_init(); hw_setup(); + // getSwitches() and set module role & CAN ID CAN_setup(the_conf.CANspeed); USBPU_ON(); while(1){ @@ -86,5 +88,15 @@ int main(void){ const char *ans = run_text_cmd(inbuff); if(ans) USB_sendstr(ans); } + ESW_process(); + static uint8_t oldswitches[2] = {0}; + for(int i = 0; i < 2; ++i){ + uint8_t new = getESW(i); + if(oldswitches[i] != new){ + oldswitches[i] = new; + USB_sendstr("ESW changed @"); printu(Tms); + USB_sendstr(" to "); printuhex(new); newline(); + } + } } } diff --git a/F3:F303/CANbus4BTA/proto.h b/F3:F303/CANbus4BTA/proto.h index 5981ff8..677c4f9 100644 --- a/F3:F303/CANbus4BTA/proto.h +++ b/F3:F303/CANbus4BTA/proto.h @@ -60,6 +60,10 @@ typedef enum{ CMD_ADCMUL, // 7 - get/set ADC multipliers 0..4 CMD_SAVECONF, // 8 - save configuration CMD_ERASESTOR, // 9 - erase all flash storage + CMD_RELAY, // 10 - switch relay ON/OFF + CMD_GETESW_BLK, // 11 - blocking read of ESW + CMD_GETESW, // 12 - current ESW state, bounce-free + CMD_BOUNCE, // 13 - get/set bounce constant (ms) CMD_AMOUNT // amount of CAN commands } can_cmd; diff --git a/F3:F303/CANbus4BTA/textfunctions.c b/F3:F303/CANbus4BTA/textfunctions.c index aff6ac3..d1615e4 100644 --- a/F3:F303/CANbus4BTA/textfunctions.c +++ b/F3:F303/CANbus4BTA/textfunctions.c @@ -53,12 +53,16 @@ static const funcdescr funclist[] = { {"adcmul", CMD_ADCMUL, "get/set ADC multipliers 0..3 (*1000)"}, {"adcraw", CMD_ADCRAW, "get raw ADC values of channel 0..4"}, {"adcv", CMD_ADCV, "get ADC voltage of channel 0..3 (*100V)"}, + {"bounce", CMD_BOUNCE, "get/set bounce constant (ms)"}, {"canid", CMD_CANID, "get/set CAN ID"}, {"cansnif", -TCMD_CANSNIF, "get/change sniffer state (0 - normal, 1 - sniffer)"}, {"canspeed", CMD_CANSPEED, "get/set CAN speed (bps)"}, {"dumpconf", -TCMD_DUMPCONF, "dump current configuration"}, + {"esw", CMD_GETESW, "anti-bounce read ESW of channel 0 or 1"}, + {"eswblk", CMD_GETESW_BLK, "blocking read ESW of channel 0 or 1"}, {"eraseflash", CMD_ERASESTOR, "erase all flash storage"}, {"mcutemp", CMD_MCUTEMP, "get MCU temperature (*10degrC)"}, + {"relay", CMD_RELAY, "get/set relay state (0 - off, 1 - on)"}, {"reset", CMD_RESET, "reset MCU"}, {"s", -TCMD_CANSEND, "send CAN message: ID 0..8 data bytes"}, {"saveconf", CMD_SAVECONF, "save configuration"}, @@ -144,7 +148,7 @@ static errcodes cansend(const char *txt){ uint32_t Tstart = Tms; while(Tms - Tstart < SEND_TIMEOUT_MS){ if(CAN_OK == CAN_send(&canmsg)){ - USB_sendstr("OK\n"); + //USB_sendstr("OK\n"); - don't send OK, as after sending might be an error return ERR_OK; } } diff --git a/F3:F303/CANbus4BTA/version.inc b/F3:F303/CANbus4BTA/version.inc index c14b316..7893c4b 100644 --- a/F3:F303/CANbus4BTA/version.inc +++ b/F3:F303/CANbus4BTA/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "56" +#define BUILD_NUMBER "68" #define BUILD_DATE "2024-01-08"