ringbuffer and device detection to USB-CAN-relay

This commit is contained in:
2024-08-02 11:58:40 +03:00
parent 9470b22c88
commit 0cb9b5f3c8
30 changed files with 1440 additions and 733 deletions

View File

@@ -22,6 +22,7 @@
#include "hardware.h"
#include "proto.h"
#include "usb.h"
#include "version.inc"
#include <string.h> // strlen
@@ -30,30 +31,6 @@ extern volatile uint8_t canerror;
uint8_t ShowMsgs = 0;
uint16_t Ignore_IDs[IGN_SIZE];
uint8_t IgnSz = 0;
static char buff[BUFSZ+1], *bptr = buff;
static uint8_t blen = 0;
void sendbuf(){
IWDG->KR = IWDG_REFRESH;
if(blen == 0) return;
*bptr = 0;
USB_sendstr(buff);
bptr = buff;
blen = 0;
}
void bufputchar(char ch){
if(blen > BUFSZ-1){
sendbuf();
}
*bptr++ = ch;
++blen;
}
void addtobuf(const char *txt){
IWDG->KR = IWDG_REFRESH;
while(*txt) bufputchar(*txt++);
}
char *omit_spaces(const char *buf){
while(*buf){
@@ -148,7 +125,7 @@ static CAN_message *parseCANmsg(char *txt){
txt = n;
if(ctr == -1){
if(N > 0x7ff){
SEND("ID should be 11-bit number!\n");
USND("ID should be 11-bit number!");
return NULL;
}
canmsg.ID = (uint16_t)(N&0x7ff);
@@ -157,21 +134,20 @@ static CAN_message *parseCANmsg(char *txt){
continue;
}
if(ctr > 7){
SEND("ONLY 8 data bytes allowed!\n");
USND("ONLY 8 data bytes allowed!");
return NULL;
}
if(N > 0xff){
SEND("Every data portion is a byte!\n");
USND("Every data portion is a byte!");
return NULL;
}
canmsg.data[ctr++] = (uint8_t)(N&0xff);
}while(1);
if(canmsg.ID == 0xffff){
SEND("NO ID given, send nothing!\n");
USND("NO ID given, send nothing!");
return NULL;
}
SEND("Message parsed OK\n");
sendbuf();
USND("Message parsed OK");
canmsg.length = (uint8_t) ctr;
return &canmsg;
}
@@ -191,55 +167,55 @@ TRUE_INLINE void CANini(char *txt){
uint32_t N;
char *n = getnum(txt, &N);
if(txt == n){
SEND("No speed given");
USND("No speed given");
return;
}
if(N < 50){
SEND("Lowest speed is 50kbps");
USND("Lowest speed is 50kbps");
return;
}else if(N > 3000){
SEND("Highest speed is 3000kbps");
USND("Highest speed is 3000kbps");
return;
}
CAN_reinit((uint16_t)N);
SEND("Reinit CAN bus with speed ");
printu(N); SEND("kbps");
USB_sendstr("Reinit CAN bus with speed ");
printu(N); USND("kbps");
}
TRUE_INLINE void addIGN(char *txt){
if(IgnSz == IGN_SIZE){
MSG("Ignore buffer is full");
DBG("Ignore buffer is full");
return;
}
txt = omit_spaces(txt);
uint32_t N;
char *n = getnum(txt, &N);
if(txt == n){
SEND("No ID given");
USND("No ID given");
return;
}
if(N == CANID){
SEND("You can't ignore self ID!");
USND("You can't ignore self ID!");
return;
}
if(N > 0x7ff){
SEND("ID should be 11-bit number!");
USND("ID should be 11-bit number!");
return;
}
Ignore_IDs[IgnSz++] = (uint16_t)(N & 0x7ff);
SEND("Added ID "); printu(N);
SEND("\nIgn buffer size: "); printu(IgnSz);
USB_sendstr("Added ID "); printu(N);
USB_sendstr("\nIgn buffer size: "); printu(IgnSz); newline();
}
TRUE_INLINE void print_ign_buf(){
if(IgnSz == 0){
SEND("Ignore buffer is empty");
USND("Ignore buffer is empty");
return;
}
SEND("Ignored IDs:\n");
USND("Ignored IDs:");
for(int i = 0; i < IgnSz; ++i){
printu(i);
SEND(": ");
USB_sendstr(": ");
printuhex(Ignore_IDs[i]);
newline();
}
@@ -267,29 +243,29 @@ TRUE_INLINE void list_filters(){
uint32_t fa = CAN->FA1R, ctr = 0, mask = 1;
while(fa){
if(fa & 1){
SEND("Filter "); printu(ctr); SEND(", FIFO");
if(CAN->FFA1R & mask) SEND("1");
else SEND("0");
SEND(" in ");
USB_sendstr("Filter "); printu(ctr); USB_sendstr(", FIFO");
if(CAN->FFA1R & mask) USB_putbyte('1');
else USB_putbyte('0');
USB_sendstr(" in ");
if(CAN->FM1R & mask){ // up to 4 filters in LIST mode
SEND("LIST mode, IDs: ");
USB_sendstr("LIST mode, IDs: ");
printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
SEND(" ");
USB_sendstr(" ");
printID(CAN->sFilterRegister[ctr].FR1 >> 16);
SEND(" ");
USB_sendstr(" ");
printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
SEND(" ");
USB_sendstr(" ");
printID(CAN->sFilterRegister[ctr].FR2 >> 16);
}else{ // up to 2 filters in MASK mode
SEND("MASK mode: ");
USB_sendstr("MASK mode: ");
if(!(CAN->sFilterRegister[ctr].FR1&0x1f)){
SEND("ID="); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR1 >> 16);
SEND(" ");
USB_sendstr("ID="); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
USB_sendstr(", MASK="); printID(CAN->sFilterRegister[ctr].FR1 >> 16);
USB_sendstr(" ");
}
if(!(CAN->sFilterRegister[ctr].FR2&0x1f)){
SEND("ID="); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR2 >> 16);
USB_sendstr("ID="); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
USB_sendstr(", MASK="); printID(CAN->sFilterRegister[ctr].FR2 >> 16);
}
}
newline();
@@ -298,7 +274,6 @@ TRUE_INLINE void list_filters(){
++ctr;
mask <<= 1;
}
sendbuf();
}
/**
@@ -315,18 +290,19 @@ static void add_filter(char *str){
str = omit_spaces(str);
char *n = getnum(str, &N);
if(n == str){
SEND("No bank# given");
USND("No bank# given");
return;
}
if(N == 0 || N > STM32F0FBANKNO-1){
SEND("0 (reserved for self) < bank# < 28 (max bank# is 27)!!!");
USND("0 (reserved for self) < bank# < 28 (max bank# is 27)!!!");
return;
}
uint8_t bankno = (uint8_t)N;
str = omit_spaces(n);
if(!*str){ // deactivate filter
SEND("Deactivate filters in bank ");
USB_sendstr("Deactivate filters in bank ");
printu(bankno);
newline();
CAN->FMR = CAN_FMR_FINIT;
CAN->FA1R &= ~(1<<bankno);
CAN->FMR &=~ CAN_FMR_FINIT;
@@ -335,7 +311,7 @@ static void add_filter(char *str){
uint8_t fifono = 0;
if(*str == '1') fifono = 1;
else if(*str != '0'){
SEND("FIFO# is 0 or 1");
USND("FIFO# is 0 or 1");
return;
}
str = omit_spaces(str + 1);
@@ -343,7 +319,7 @@ static void add_filter(char *str){
uint8_t mode = 0; // ID
if(c == 'M' || c == 'm') mode = 1;
else if(c != 'I' && c != 'i'){
SEND("mode is 'M/m' for MASK and 'I/i' for IDLIST");
USND("mode is 'M/m' for MASK and 'I/i' for IDLIST");
return;
}
str = omit_spaces(str + 1);
@@ -356,11 +332,11 @@ static void add_filter(char *str){
str = omit_spaces(n);
}
if(nfilt == 0){
SEND("You should add at least one filter!");
USND("You should add at least one filter!");
return;
}
if(mode && (nfilt&1)){
SEND("In MASK mode you should point pairs of ID/MASK");
USND("In MASK mode you should point pairs of ID/MASK");
return;
}
CAN->FMR = CAN_FMR_FINIT;
@@ -389,8 +365,8 @@ static void add_filter(char *str){
CAN->sFilterRegister[bankno].FR1 = (F1 & 0xffff0000) | (filters[0] << 5);
}
CAN->FMR &=~ CAN_FMR_FINIT;
SEND("Added filter with ");
printu(nfilt); SEND(" parameters");
USB_sendstr("Added filter with ");
printu(nfilt); USND(" parameters");
}
/**
@@ -402,13 +378,13 @@ static void ledsOp(const char *str, uint8_t state){
uint32_t N;
char *x = getnum(str, &N);
if(!x || x == str || N > LEDSNO - 1){
SEND("Wrong LED number\n");
USND("Wrong LED number\n");
return;
}
if(state) LED_on(N);
else LED_off(N);
SEND("LED"); printu(N); SEND(" is ");
if(state) SEND("on"); else SEND("off");
USB_sendstr("LED"); printu(N); USB_sendstr(" is ");
if(state) USND("on"); else USND("off");
}
// print current buttons state
@@ -418,9 +394,9 @@ TRUE_INLINE void getBtnState(){
uint32_t T;
keyevent e = keystate(i, &T);
if(e != EVT_NONE){
SEND("The key "); printu(i);
SEND(" is "); addtobuf(states[e]); SEND(" at ");
printu(T); NL();
USB_sendstr("The key "); printu(i);
USB_sendstr(" is "); USB_sendstr(states[e]); USB_sendstr(" at ");
printu(T); newline();
}
}
}
@@ -428,13 +404,12 @@ TRUE_INLINE void getBtnState(){
TRUE_INLINE void getPWM(){
volatile uint32_t *reg = &TIM1->CCR1;
for(int n = 0; n < 3; ++n){
SEND("PWM");
bufputchar('0' + n);
bufputchar('=');
USB_sendstr("PWM");
USB_putbyte('0' + n);
USB_putbyte('=');
printu(*reg++);
bufputchar('\n');
newline();
}
sendbuf();
}
TRUE_INLINE void changePWM(char *str){
@@ -442,34 +417,33 @@ TRUE_INLINE void changePWM(char *str){
uint32_t N, pwm;
char *nxt = getnum(str, &N);
if(nxt == str || N > 2){
SEND("Nch = 0..2");
USND("Nch = 0..2");
return;
}
str = omit_spaces(nxt);
nxt = getnum(str, &pwm);
if(nxt == str || pwm > 255){
SEND("PWM should be from 0 to 255");
USND("PWM should be from 0 to 255");
return;
}
volatile uint32_t *reg = &TIM1->CCR1;
reg[N] = pwm;
SEND("OK, changed");
USND("OK, changed");
}
TRUE_INLINE void printADC(){ // show all 4 channels ADC
for(int i = 0; i < NUMBER_OF_ADC_CHANNELS; ++i){
SEND("ADC"); bufputchar('0' + i); bufputchar('=');
printu(getADCval(i)); bufputchar('\n');
USB_sendstr("ADC"); USB_putbyte('0' + i); USB_putbyte('=');
printu(getADCval(i)); newline();
}
sendbuf();
}
TRUE_INLINE void printVT(){ // show T and Vdd
int32_t t = getMCUtemp();
SEND("T=");
if(t < 0){ bufputchar('-'); t = -t; }
printu(t); SEND("/10degC\nVDD=");
printu(getVdd()); SEND("/100V");
USB_sendstr("T=");
if(t < 0){ USB_putbyte('-'); t = -t; }
printu(t); USB_sendstr("/10degC\nVDD=");
printu(getVdd()); USND("/100V");
}
// set or check relay(N) state
@@ -481,10 +455,36 @@ TRUE_INLINE void relayX(uint8_t N, const char *txt){
if(b && b != txt && sr < 2){
if(sr) Relay_ON(N); else Relay_OFF(N);
}
SEND("Relay"); bufputchar('0'+N); bufputchar('=');
bufputchar('0' + Relay_chk(N));
USB_sendstr("Relay"); USB_putbyte('0'+N); USB_putbyte('=');
USB_putbyte('0' + Relay_chk(N)); newline();
}
static const char *helpmsg =
"https://github.com/eddyem/stm32samples/tree/master/F0-nolib/usbcan_relay build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
"'0' - turn relay0 on(1) or off(0)\n"
"'1' - turn relay1 on(1) or off(0)\n"
"'a' - add ID to ignore list (max 10 IDs)\n"
"'A' - get ADC values @ all 4 channels\n"
"'b' - get buttons' state\n"
"'C' - reinit CAN with given baudrate\n"
"'d' - delete ignore list\n"
"'D' - activate DFU mode\n"
"'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n"
"'F' - send/clear flood message: F ID byte0 ... byteN\n"
"'I' - read CAN ID\n"
"'l' - list all active filters\n"
"'m' - get MCU temp & Vdd\n"
"'o' - turn nth LED OFF\n"
"'O' - turn nth LED ON\n"
"'p' - print ignore buffer\n"
"'P' - pause/resume in packets displaying\n"
"'R' - software reset\n"
"'s/S' - send data over CAN: s ID byte0 .. byteN\n"
"'T' - get time from start (ms)\n"
"'w' - get PWM settings\n"
"'W' - set PWM @nth channel (ch: 0..2, PWM: 0..255)\n"
;
/**
* @brief cmd_parser - command parsing
* @param txt - buffer with commands & data
@@ -550,15 +550,13 @@ void cmd_parser(char *txt){
case 'd':
IgnSz = 0;
break;
#ifdef EBUG
case 'D':
SEND("Go into DFU mode\n");
sendbuf();
USND("Go into DFU mode\n");
USB_sendall();
Jump2Boot();
break;
#endif
case 'I':
SEND("CAN ID: "); printuhex(CANID);
USB_sendstr("CAN ID: "); printuhex(CANID);
break;
case 'l':
list_filters();
@@ -571,17 +569,17 @@ void cmd_parser(char *txt){
break;
case 'P':
ShowMsgs = !ShowMsgs;
if(ShowMsgs) SEND("Resume\n");
else SEND("Pause\n");
if(ShowMsgs) USND("Resume");
else USND("Pause");
break;
case 'R':
SEND("Soft reset\n");
sendbuf();
USND("Soft reset");
USB_sendall();
pause_ms(5); // a little pause to transmit data
NVIC_SystemReset();
break;
case 'T':
SEND("Time (ms): ");
USB_sendstr("Time (ms): ");
printu(Tms);
break;
case 'w':
@@ -589,37 +587,11 @@ void cmd_parser(char *txt){
return;
break;
default: // help
SEND(
"'0' - turn relay0 on(1) or off(0)\n"
"'1' - turn relay1 on(1) or off(0)\n"
"'a' - add ID to ignore list (max 10 IDs)\n"
"'A' - get ADC values @ all 4 channels\n"
"'b' - get buttons' state\n"
"'C' - reinit CAN with given baudrate\n"
"'d' - delete ignore list\n"
#ifdef EBUG
"'D' - activate DFU mode\n"
#endif
"'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n"
"'F' - send/clear flood message: F ID byte0 ... byteN\n"
"'I' - read CAN ID\n"
"'l' - list all active filters\n"
"'m' - get MCU temp & Vdd\n"
"'o' - turn nth LED OFF\n"
"'O' - turn nth LED ON\n"
"'p' - print ignore buffer\n"
"'P' - pause/resume in packets displaying\n"
"'R' - software reset\n"
"'s/S' - send data over CAN: s ID byte0 .. byteN\n"
"'T' - get time from start (ms)\n"
"'w' - get PWM settings\n"
"'W' - set PWM @nth channel (ch: 0..2, PWM: 0..255)\n"
);
USND(helpmsg);
break;
}
eof:
newline();
sendbuf();
}
// print 32bit unsigned int
@@ -634,12 +606,12 @@ void printu(uint32_t val){
val /= 10;
}
}
addtobuf(bufptr);
USB_sendstr(bufptr);
}
// print 32bit unsigned int as hex
void printuhex(uint32_t val){
addtobuf("0x");
USB_sendstr("0x");
uint8_t *ptr = (uint8_t*)&val + 3;
int8_t i, j, z=1;
for(i = 0; i < 4; ++i, --ptr){
@@ -650,8 +622,8 @@ void printuhex(uint32_t val){
else z = 0;
for(j = 1; j > -1; --j){
uint8_t half = (*ptr >> (4*j)) & 0x0f;
if(half < 10) bufputchar(half + '0');
else bufputchar(half - 10 + 'a');
if(half < 10) USB_putbyte(half + '0');
else USB_putbyte(half - 10 + 'a');
}
}
}