From f46185feaf03bee150d3cfec20f89efa71688c6f Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Fri, 4 Apr 2025 11:56:37 +0300 Subject: [PATCH] encoders works fine --- F1:F103/BISS_C_encoders/Readme.md | 121 ++++++++++- F1:F103/BISS_C_encoders/bissC.c | 17 +- F1:F103/BISS_C_encoders/bissC.h | 5 + F1:F103/BISS_C_encoders/encoders.bin | Bin 12524 -> 13336 bytes F1:F103/BISS_C_encoders/encoders.creator.user | 2 +- F1:F103/BISS_C_encoders/flash.c | 6 +- F1:F103/BISS_C_encoders/flash.h | 13 +- F1:F103/BISS_C_encoders/main.c | 44 ++-- F1:F103/BISS_C_encoders/openocd.cfg | 92 +-------- F1:F103/BISS_C_encoders/openocd.cfg_ | 4 - F1:F103/BISS_C_encoders/proto.c | 190 +++++++++++------- F1:F103/BISS_C_encoders/spi.c | 27 +-- F1:F103/BISS_C_encoders/spi.h | 10 +- F1:F103/BISS_C_encoders/usart.c | 100 --------- F1:F103/BISS_C_encoders/version.inc | 4 +- .../USB_NEW_concept_7inone/usb_dev.c | 28 ++- .../USB_NEW_concept_CDC/usb_dev.c | 27 ++- .../USB_NEW_concept_PL2303/usb_dev.c | 30 ++- 18 files changed, 359 insertions(+), 361 deletions(-) delete mode 100644 F1:F103/BISS_C_encoders/openocd.cfg_ delete mode 100644 F1:F103/BISS_C_encoders/usart.c diff --git a/F1:F103/BISS_C_encoders/Readme.md b/F1:F103/BISS_C_encoders/Readme.md index 37a3b12..992452f 100644 --- a/F1:F103/BISS_C_encoders/Readme.md +++ b/F1:F103/BISS_C_encoders/Readme.md @@ -1,5 +1,124 @@ Get data from 2 encoders by BISS-C protocol =========================================== +This device works with two BISS-C encoders (resolution from 8 to 32 bit). + +If you want to test readout from device, run `./testDev /dev/encoder_X0` or `./testDev /dev/encoder_X0`. + +** Encoder cable pinout: + +* 1 - NC or shield +* 2 - CLK_A - positive of SSI clock out +* 3 - CLC_B - negative of SSI clock out +* 4 - NC or shield +* 5 - +5V - 5V power for sensor (at least 250mA) +* 6 - DATA_A - positive of data in +* 7 - DATA_B - negative of data in +* 8 - NC +* 9 - Gnd - common ground + + +** Device interfaces + +After connection you will see device 0483:5740 with three CDC interfaces. Each interface +have its own `iInterface` field, by default they are: + +* encoder_cmd - configure/command/debugging interface +* encoder_X - X sensor output +* encoder_Y - Y sensor output + +Add to udev-rules file `99-myHW.rules` which will create symlinks to each interface in `/dev/` directory. +You can change all three `iInterface` values and store them in device' flash memory. + +The readout of encoders depends on settings. If you save in flash `autom=1`, readout of both encoders +will repeat each `amperiod` milliseconds. Also you always can ask for readout sending any '\n'-terminated +data into encoder's interface or running commands `readenc`, `readX` or `readY` in command interface. + + +** Protocol + +The device have simple text protocol, each text string should be closed by '\n'. +Base format is 'param [ = value]', where 'param' could be command to run some procedure +or getter, 'value' is setter. + +Answer for all getters is 'param=value'. Here are answers for setters and procedures: + +* OK - all OK +* FAIL - procedure failed to run +* BADCMD - your entered wrong command +* BADPAR - parameter of setter is out of allowable range + +Some procedures (like 'help' or 'readenc') returns a lot of data after calling. + + +*** Base commands on command interface + +These are commands for directrly work with SPI interfaces: + +* readenc - read both encoders once +* readX - read X encoder once +* readY - read Y encoder once +* help - show full help +* reset - reset MCU +* spideinit - deinit SPI +* spiinit - init SPI +* spistat - get status of both SPI interfaces + + +*** Configuration commands + +This set of commands allows to change current configuration (remember: each time SPI configuration changes +you need to run `spiinit`) and store it into flash memory. + +* autom - turn on or off automonitoring +* amperiod - period of monitoring, 1..255 milliseconds +* BR - change SPI BR register (1 - 18MHz ... 7 - 281kHz) +* CPHA - change CPHA value (0/1) +* CPOL - change CPOL value (0/1) +* dumpconf - dump current configuration +* encbits - set encoder data bits amount (26/32) +* encbufsz - change encoder auxiliary buffer size (8..32 bytes) +* erasestorage - erase full storage or current page (=n) +* maxzeros - maximal amount of zeros in preamble +* minzeros - minimal amount of zeros in preamble +* setiface1 - set name of first (command) interface +* setiface2 - set name of second (axis X) interface +* setiface3 - set name of third (axis Y) interface +* storeconf - store configuration in flash memory + +Here is example of default configuration ouput (`dumpconf`): + +``` +userconf_sz=108 +currentconfidx=-1 +setiface1= +setiface2= +setiface3= +autom=0 +amperiod=1 +BR=4 +CPHA=0 +CPOL=1 +encbits=26 +encbufsz=12 +maxzeros=50 +minzeros=4 +``` + +`userconf_sz` is some type of "magick sequence" to find start of last record in flash memory. +`currentconfidx` shows number of record (-1 means that the storage is empty and you see default values). +Empty field of `setifaceX` means default interface name. + + +*** Debugging commands + +Some of these commands could be usefull when you're trying to play with settings or want to measure maximal +readout speed for encoders (when each reading starts immediately after parsing previous result). + +* dummy - dummy integer setter/getter +* fin - reinit flash (e.g. to restore last configuration) +* sendx - send text string to X encoder's terminal +* sendy - send text string to Y encoder's terminal +* testx - test X-axis throughput +* testy - test Y-axis throughput -tl;dr diff --git a/F1:F103/BISS_C_encoders/bissC.c b/F1:F103/BISS_C_encoders/bissC.c index 78f03f1..e158458 100644 --- a/F1:F103/BISS_C_encoders/bissC.c +++ b/F1:F103/BISS_C_encoders/bissC.c @@ -17,16 +17,14 @@ */ #include "bissC.h" -#include "usb_dev.h" +#include "flash.h" #ifdef EBUG #include "strfunc.h" #endif -#include "flash.h" +#include "spi.h" +#include "usb_dev.h" -#define MAX_BITSTREAM_UINTS 4 // 4 * 32 = 128 bits capacity -// min/max zeros before preambule -#define MINZEROS 4 -#define MAXZEROS 40 +#define MAX_BITSTREAM_UINTS (ENCODER_BUFSZ_MAX / 4) // ENCODER_BUFSZ_MAX bits capacity static uint32_t bitstream[MAX_BITSTREAM_UINTS] = {0}; @@ -50,11 +48,6 @@ static void bytes_to_bitstream(const uint8_t *bytes, uint32_t num_bytes, uint32_ } } } - /* Store remaining bits if any - if(*num_bits % 32 != 0){ - current <<= (32 - (*num_bits % 32)); - bitstream[pos] = current; - }*/ } // Compute CRC-6 using polynomial x^6 + x + 1 @@ -102,7 +95,7 @@ BiSS_Frame parse_biss_frame(const uint8_t *bytes, uint32_t num_bytes){ if(!curbit){ zero_count++; }else{ - if(zero_count >= MINZEROS && zero_count <= MAXZEROS){ + if(zero_count >= the_conf.minzeros && zero_count <= the_conf.maxzeros){ if((i + 1) < num_bits && !get_bit(i + 1)){ data_start = i + 2; found = 1; diff --git a/F1:F103/BISS_C_encoders/bissC.h b/F1:F103/BISS_C_encoders/bissC.h index b7816eb..d1de0d5 100644 --- a/F1:F103/BISS_C_encoders/bissC.h +++ b/F1:F103/BISS_C_encoders/bissC.h @@ -20,6 +20,11 @@ #include +#include "spi.h" +#if ENCRESOL_MAX > 32 +#error "Change full code. Current don't support more than 32 bits of encoder resolution." +#endif + typedef struct { uint32_t data; // 26/32/36-bit data uint8_t error : 1; // error flag (0 - error: bad value or high temperature) diff --git a/F1:F103/BISS_C_encoders/encoders.bin b/F1:F103/BISS_C_encoders/encoders.bin index 660b8d127ec30f1eeedb86a6fcda2bc583fd6a47..41a4e130bd4bf7b6bf212566d1d6e9cffe7ef8e2 100755 GIT binary patch delta 7572 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 delta 6652 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 V`2!iWxJZ1ySdRzkQ`}bU{0ID&Kmq^& diff --git a/F1:F103/BISS_C_encoders/encoders.creator.user b/F1:F103/BISS_C_encoders/encoders.creator.user index 1de570b..f99097b 100644 --- a/F1:F103/BISS_C_encoders/encoders.creator.user +++ b/F1:F103/BISS_C_encoders/encoders.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F1:F103/BISS_C_encoders/flash.c b/F1:F103/BISS_C_encoders/flash.c index 5b23653..8e8f9e4 100644 --- a/F1:F103/BISS_C_encoders/flash.c +++ b/F1:F103/BISS_C_encoders/flash.c @@ -33,7 +33,11 @@ user_conf the_conf = { .userconf_sz = sizeof(user_conf), .flags.CPOL = 1, .flags.BR = 4, - .encbits = 26 + .encbits = 26, + .encbufsz = 12, + .minzeros = 4, + .maxzeros = 50, + .monittime = 1, }; int currentconfidx = -1; // index of current configuration diff --git a/F1:F103/BISS_C_encoders/flash.h b/F1:F103/BISS_C_encoders/flash.h index ae80899..cf4b5ff 100644 --- a/F1:F103/BISS_C_encoders/flash.h +++ b/F1:F103/BISS_C_encoders/flash.h @@ -27,10 +27,17 @@ // maximal size (in letters) of iInterface for settings #define MAX_IINTERFACE_SZ (16) +// min/max zeros before preambule +#define MINZEROS_MIN 2 +#define MINZEROS_MAX 60 +#define MAXZEROS_MIN 4 +#define MAXZEROS_MAX 120 + typedef struct{ uint8_t CPOL : 1; uint8_t CPHA : 1; uint8_t BR : 3; + uint8_t monit: 1; // auto monitoring of encoder each `monittime` milliseconds } flags_t; /* @@ -40,8 +47,12 @@ typedef struct __attribute__((packed, aligned(4))){ uint16_t userconf_sz; // "magick number" uint16_t iInterface[bTotNumEndpoints][MAX_IINTERFACE_SZ]; // hryunikod! uint8_t iIlengths[bTotNumEndpoints]; - flags_t flags; // flags: CPOL, CPHA etc uint8_t encbits; // encoder bits: 26 or 32 + uint8_t encbufsz; // encoder buffer size (up to ENCODER_BUFSZ_MAX) + uint8_t minzeros; // min/max zeros in preamble when searching start of record + uint8_t maxzeros; + uint8_t monittime; // auto monitoring period (ms) + flags_t flags; // flags: CPOL, CPHA etc } user_conf; extern user_conf the_conf; diff --git a/F1:F103/BISS_C_encoders/main.c b/F1:F103/BISS_C_encoders/main.c index 3d0633d..d3f43bc 100644 --- a/F1:F103/BISS_C_encoders/main.c +++ b/F1:F103/BISS_C_encoders/main.c @@ -27,6 +27,7 @@ volatile uint32_t Tms = 0; static char inbuff[RBINSZ]; +static uint32_t monitT[2] = {0}; /* Called when systick fires */ void sys_tick_handler(void){ @@ -47,7 +48,6 @@ static void printResult(BiSS_Frame *result){ } static void proc_enc(uint8_t idx){ - uint8_t encbuf[ENCODER_BUFSZ]; static uint32_t lastMSG[2], gotgood[2], gotwrong[2]; int iface = idx ? I_Y : I_X; char ifacechr = idx ? 'Y' : 'X'; @@ -65,9 +65,11 @@ static void proc_enc(uint8_t idx){ CMDWR("'\n"); } } + if(l > 0) spi_start_enc(idx); // start encoder reading on each request from given interface } - if(!spi_read_enc(idx, encbuf)) return; - BiSS_Frame result = parse_biss_frame(encbuf, ENCODER_BUFSZ); + uint8_t *encbuf = spi_read_enc(idx); + if(!encbuf) return; + BiSS_Frame result = parse_biss_frame(encbuf, the_conf.encbufsz); char *str = result.crc_valid ? u2str(result.data) : NULL; uint8_t testflag = (idx) ? user_pars.testy : user_pars.testx; if(CDCready[I_CMD]){ @@ -86,11 +88,11 @@ static void proc_enc(uint8_t idx){ if(str) ++gotgood[idx]; else ++gotwrong[idx]; } - }else{ + }else if(!the_conf.flags.monit){ printResult(&result); CMDWR("ENC"); USB_putbyte(I_CMD, ifacechr); USB_putbyte(I_CMD, '='); - hexdump(I_CMD, encbuf, ENCODER_BUFSZ); + hexdump(I_CMD, encbuf, the_conf.encbufsz); CMDWR(" ("); if(str) CMDWR(str); else CMDWR("wrong"); @@ -102,22 +104,17 @@ static void proc_enc(uint8_t idx){ USB_putbyte(iface, '\n'); } if(result.error) spi_setup(1+idx); // reinit SPI in case of error - if(testflag) spi_start_enc(idx); + if(the_conf.flags.monit) monitT[idx] = Tms; + else if(testflag) spi_start_enc(idx); } int main(){ - uint32_t lastT = 0;//, lastS = 0; + uint32_t lastT = 0; StartHSE(); flashstorage_init(); hw_setup(); USBPU_OFF(); SysTick_Config(72000); -/* -#ifdef EBUG - usart_setup(); - uint32_t tt = 0; -#endif -*/ USB_setup(); #ifndef EBUG iwdg_setup(); @@ -129,29 +126,18 @@ int main(){ LED_blink(LED0); lastT = Tms; } -/* -#ifdef EBUG - if(Tms != tt){ - __disable_irq(); - usart_transmit(); - tt = Tms; - __enable_irq(); - } -#endif -*/ if(CDCready[I_CMD]){ - /*if(Tms - lastS > 9999){ - USB_sendstr(I_CMD, "Tms="); - USB_sendstr(I_CMD, u2str(Tms)); - CMDn(); - lastS = Tms; - }*/ int l = USB_receivestr(I_CMD, inbuff, RBINSZ); if(l < 0) CMDWRn("ERROR: CMD USB buffer overflow or string was too long"); else if(l) parse_cmd(inbuff); } proc_enc(0); proc_enc(1); + if(the_conf.flags.monit){ + for(int i = 0; i < 2; ++i){ + if(Tms - monitT[i] >= the_conf.monittime) spi_start_enc(i); + } + } } return 0; } diff --git a/F1:F103/BISS_C_encoders/openocd.cfg b/F1:F103/BISS_C_encoders/openocd.cfg index a43a499..7533dd1 100644 --- a/F1:F103/BISS_C_encoders/openocd.cfg +++ b/F1:F103/BISS_C_encoders/openocd.cfg @@ -1,94 +1,4 @@ set FLASH_SIZE 0x10000 source [find interface/stlink.cfg] - - -# script for stm32f1x family - -# -# stm32 devices support both JTAG and SWD transports. -# -source [find target/swj-dp.tcl] -source [find mem_helper.tcl] - -if { [info exists CHIPNAME] } { - set _CHIPNAME $CHIPNAME -} else { - set _CHIPNAME stm32f1x -} - -set _ENDIAN little - -# Work-area is a space in RAM used for flash programming -# By default use 4kB (as found on some STM32F100s) -if { [info exists WORKAREASIZE] } { - set _WORKAREASIZE $WORKAREASIZE -} else { - set _WORKAREASIZE 0x1000 -} - -# Allow overriding the Flash bank size -if { [info exists FLASH_SIZE] } { - set _FLASH_SIZE $FLASH_SIZE -} else { - # autodetect size - set _FLASH_SIZE 0 -} - -#jtag scan chain -if { [info exists CPUTAPID] } { - set _CPUTAPID $CPUTAPID -} else { - if { [using_jtag] } { - # See STM Document RM0008 Section 26.6.3 - set _CPUTAPID 0x2ba01477 - } { - # this is the SW-DP tap id not the jtag tap id - set _CPUTAPID 0x2ba01477 - } -} - -swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu - -if {[using_jtag]} { - jtag newtap $_CHIPNAME bs -irlen 5 -} - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap - -$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 - -# flash size will be probed -set _FLASHNAME $_CHIPNAME.flash -flash bank $_FLASHNAME stm32f1x 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME - -# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz -adapter_khz 1000 - -adapter_nsrst_delay 100 -if {[using_jtag]} { - jtag_ntrst_delay 100 -} - -reset_config srst_nogate - -if {![using_hla]} { - # if srst is not fitted use SYSRESETREQ to - # perform a soft reset - cortex_m reset_config sysresetreq -} - -$_TARGETNAME configure -event examine-end { - # DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP | - # DBG_STANDBY | DBG_STOP | DBG_SLEEP - mmw 0xE0042004 0x00000307 0 -} - -$_TARGETNAME configure -event trace-config { - # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync - # change this value accordingly to configure trace pins - # assignment - mmw 0xE0042004 0x00000020 0 -} +source [find target/stm32f1x.cfg] diff --git a/F1:F103/BISS_C_encoders/openocd.cfg_ b/F1:F103/BISS_C_encoders/openocd.cfg_ deleted file mode 100644 index 7533dd1..0000000 --- a/F1:F103/BISS_C_encoders/openocd.cfg_ +++ /dev/null @@ -1,4 +0,0 @@ -set FLASH_SIZE 0x10000 - -source [find interface/stlink.cfg] -source [find target/stm32f1x.cfg] diff --git a/F1:F103/BISS_C_encoders/proto.c b/F1:F103/BISS_C_encoders/proto.c index 8001187..b99ac90 100644 --- a/F1:F103/BISS_C_encoders/proto.c +++ b/F1:F103/BISS_C_encoders/proto.c @@ -72,6 +72,11 @@ typedef enum{ C_encbits, C_testX, C_testY, + C_encbufsz, + C_minzeros, + C_maxzeros, + C_autom, + C_amperiod, C_AMOUNT } cmd_e; @@ -223,58 +228,64 @@ static errcode_e spideinit(_U_ cmd_e idx, _U_ char *par){ return ERR_SILENCE; } -static errcode_e setflags(cmd_e idx, char *par){ +static errcode_e setuintpar(cmd_e idx, char *par){ + uint32_t val; if(par){ - if(*par < '0' || *par > '9') return ERR_BADPAR; - uint8_t val = *par - '0'; + if(par == getnum(par, &val)) return ERR_BADPAR; switch(idx){ - case C_cpha: - if(val > 1) return ERR_BADPAR; - the_conf.flags.CPHA = val; - break; - case C_cpol: - if(val > 1) return ERR_BADPAR; - the_conf.flags.CPOL = val; - break; + case C_br: + if(val == 0 || val > 7) return ERR_BADPAR; + the_conf.flags.BR = val; + break; + case C_encbits: + if(val < ENCRESOL_MIN || val > ENCRESOL_MAX) return ERR_BADPAR; // don't support less than 8 of more than 32 + the_conf.encbits = val; + break; + case C_encbufsz: + if(val < 8 || val > ENCODER_BUFSZ_MAX) return ERR_BADPAR; + the_conf.encbufsz = val; + break; + case C_minzeros: + if(val < MINZEROS_MIN || val > MINZEROS_MAX) return ERR_BADPAR; + the_conf.minzeros = val; + break; + case C_maxzeros: + if(val < MAXZEROS_MIN || val > MAXZEROS_MAX) return ERR_BADPAR; + the_conf.maxzeros = val; + break; + case C_amperiod: + if(val > 255 || val == 0) return ERR_BADPAR; + the_conf.monittime = val; + break; + default: + return ERR_BADCMD; + } + } + CMDWR(commands[idx].cmd); + USB_putbyte(I_CMD, '='); + switch(idx){ case C_br: - if(val == 0 || val > 7) return ERR_BADPAR; - the_conf.flags.BR = val; + val = the_conf.flags.BR; + break; + case C_encbits: + val = the_conf.encbits; + break; + case C_encbufsz: + val = the_conf.encbufsz; + break; + case C_minzeros: + val = the_conf.minzeros; + break; + case C_maxzeros: + val = the_conf.maxzeros; + break; + case C_amperiod: + val = the_conf.monittime; break; default: return ERR_BADCMD; - } } - uint8_t val = 0; - switch(idx){ - case C_cpha: - val = the_conf.flags.CPHA; - break; - case C_cpol: - val = the_conf.flags.CPOL; - break; - case C_br: - val = the_conf.flags.BR; - break; - default: - return ERR_BADCMD; - } - CMDWR(commands[idx].cmd); - USB_putbyte(I_CMD, '='); - USB_putbyte(I_CMD, '0' + val); - CMDn(); - return ERR_SILENCE; -} - -static errcode_e encbits(cmd_e idx, char *par){ - if(par){ - uint32_t N; - if(par == getnum(par, &N)) return ERR_BADPAR; - if(N < 26 || N > 32) return ERR_BADPAR; // don't support less than 26 of more than 32 - the_conf.encbits = N; - } - CMDWR(commands[idx].cmd); - USB_putbyte(I_CMD, '='); - CMDWR(u2str(the_conf.encbits)); + CMDWR(u2str(val)); CMDn(); return ERR_SILENCE; } @@ -285,25 +296,43 @@ static errcode_e setboolpar(cmd_e idx, char *par){ if(*par != '0' && *par != '1') return ERR_BADPAR; val = *par - '0'; switch(idx){ + case C_cpha: + the_conf.flags.CPHA = val; + break; + case C_cpol: + the_conf.flags.CPOL = val; + break; case C_testX: user_pars.testx = val; - break; + if(val) spi_start_enc(0); + break; case C_testY: user_pars.testy = val; - break; + if(val) spi_start_enc(1); + break; + case C_autom: + the_conf.flags.monit = val; + break; default: return ERR_BADCMD; } } switch(idx){ + case C_cpha: + val = the_conf.flags.CPHA; + break; + case C_cpol: + val = the_conf.flags.CPOL; + break; case C_testX: val = user_pars.testx; - if(val) spi_start_enc(0); - break; + break; case C_testY: val = user_pars.testy; - if(val) spi_start_enc(1); - break; + break; + case C_autom: + val = the_conf.flags.monit; + break; default: return ERR_BADCMD; } @@ -320,10 +349,15 @@ static errcode_e dumpconf(cmd_e _U_ idx, char _U_ *par){ CMDn(); for(int i = 0; i < bTotNumEndpoints; ++i) setiface(C_setiface1 + i, NULL); - setflags(C_br, NULL); - setflags(C_cpha, NULL); - setflags(C_cpol, NULL); - encbits(C_encbits, NULL); + setboolpar(C_autom, NULL); + setuintpar(C_amperiod, NULL); + setuintpar(C_br, NULL); + setboolpar(C_cpha, NULL); + setboolpar(C_cpol, NULL); + setuintpar(C_encbits, NULL); + setuintpar(C_encbufsz, NULL); + setuintpar(C_maxzeros, NULL); + setuintpar(C_minzeros, NULL); return ERR_SILENCE; } @@ -347,12 +381,17 @@ static const funcdescr_t commands[C_AMOUNT] = { [C_spistat] = {"spistat", spistat}, [C_spiinit] = {"spiinit", spiinit}, [C_spideinit] = {"spideinit", spideinit}, - [C_cpol] = {"CPOL", setflags}, - [C_cpha] = {"CPHA", setflags}, - [C_br] = {"BR", setflags}, - [C_encbits] = {"encbits", encbits}, + [C_cpol] = {"CPOL", setboolpar}, + [C_cpha] = {"CPHA", setboolpar}, + [C_br] = {"BR", setuintpar}, + [C_encbits] = {"encbits", setuintpar}, [C_testX] = {"testx", setboolpar}, [C_testY] = {"testy", setboolpar}, + [C_encbufsz] = {"encbufsz", setuintpar}, + [C_minzeros] = {"minzeros", setuintpar}, + [C_maxzeros] = {"maxzeros", setuintpar}, + [C_autom] = {"autom", setboolpar}, + [C_amperiod] = {"amperiod", setuintpar}, }; typedef struct{ @@ -362,28 +401,33 @@ typedef struct{ // SHOUL be sorted and grouped static const help_t helpmessages[] = { - {-1, "Configuration"}, - {C_dumpconf, "dump current configuration"}, - {C_erasestorage, "erase full storage or current page (=n)"}, - {C_setiface1, "set name of first (command) interface"}, - {C_setiface2, "set name of second (axis X) interface"}, - {C_setiface3, "set name of third (axis Y) interface"}, - {C_storeconf, "store configuration in flash memory"}, - {-1, "Different commands"}, - {C_dummy, "dummy integer setter/getter"}, - {C_encstart, "start reading encoders"}, - {C_encX, "read only X encoder"}, - {C_encY, "read only Y encoder"}, + {-1, "Base commands"}, + {C_encstart, "read both encoders once"}, + {C_encX, "read X encoder once"}, + {C_encY, "read Y encoder once"}, {C_help, "show this help"}, {C_reset, "reset MCU"}, {C_spideinit, "deinit SPI"}, {C_spiinit, "init SPI"}, {C_spistat, "get status of both SPI interfaces"}, - {-1, "Debug"}, + {-1, "Configuration"}, + {C_autom, "turn on or off automonitoring"}, + {C_amperiod, "period (ms) of monitoring, 1..255"}, {C_br, "change SPI BR register (1 - 18MHz ... 7 - 281kHz)"}, {C_cpha, "change CPHA value (0/1)"}, {C_cpol, "change CPOL value (0/1)"}, - {C_encbits, "set encoder data bits amount"}, + {C_dumpconf, "dump current configuration"}, + {C_encbits, "set encoder data bits amount (26/32)"}, + {C_encbufsz, "change encoder auxiliary buffer size (8..32 bytes)"}, + {C_erasestorage, "erase full storage or current page (=n)"}, + {C_maxzeros, "maximal amount of zeros in preamble"}, + {C_minzeros, "minimal amount of zeros in preamble"}, + {C_setiface1, "set name of first (command) interface"}, + {C_setiface2, "set name of second (axis X) interface"}, + {C_setiface3, "set name of third (axis Y) interface"}, + {C_storeconf, "store configuration in flash memory"}, + {-1, "Debug commands"}, + {C_dummy, "dummy integer setter/getter"}, {C_fin, "reinit flash"}, {C_sendX, "send text string to X encoder's terminal"}, {C_sendY, "send text string to Y encoder's terminal"}, diff --git a/F1:F103/BISS_C_encoders/spi.c b/F1:F103/BISS_C_encoders/spi.c index 06bfb0f..0a5ba10 100644 --- a/F1:F103/BISS_C_encoders/spi.c +++ b/F1:F103/BISS_C_encoders/spi.c @@ -34,7 +34,7 @@ static volatile SPI_TypeDef* const SPIs[AMOUNT_OF_SPI+1] = {NULL, SPI1, SPI2}; static volatile DMA_Channel_TypeDef * const DMAs[AMOUNT_OF_SPI+1] = {NULL, DMA1_Channel2, DMA1_Channel4}; #define WAITX(x) do{volatile uint32_t wctr = 0; while((x) && (++wctr < 3600)) IWDG->KR = IWDG_REFRESH; if(wctr==3600){ DBG("timeout"); return 0;}}while(0) -static uint8_t encoderbuf[AMOUNT_OF_SPI][ENCODER_BUFSZ] = {0}; +static uint8_t encoderbuf[AMOUNT_OF_SPI][ENCODER_BUFSZ_MAX] = {0}; static uint8_t freshdata[AMOUNT_OF_SPI] = {0}; // init SPI to work RX-only with DMA @@ -81,8 +81,6 @@ void spi_onoff(uint8_t idx, uint8_t on){ CHKIDX(idx); volatile SPI_TypeDef *SPI = SPIs[idx]; if(on){ - //DBGs(u2str(idx)); - //DBG("turn on SPI"); SPI->CR1 |= SPI_CR1_SPE; spi_status[idx] = SPI_BUSY; }else{ @@ -114,20 +112,15 @@ static int spi_waitbsy(uint8_t idx){ DBG("Busy - turn off"); spi_onoff(idx, 0); // turn off SPI if it's busy } - //DBGs(u2str(idx)); - //DBG("wait busy"); - //WAITX(SPIs[idx]->SR & SPI_SR_BSY); return 1; } // just copy last read encoder value into `buf` -// @return TRUE if got fresh data -int spi_read_enc(uint8_t encno, uint8_t buf[ENCODER_BUFSZ]){ - if(encno > 1 || !freshdata[encno]) return FALSE; - //DBGs(u2str(encno)); DBG("Read encoder data"); - memcpy(buf, encoderbuf[encno], ENCODER_BUFSZ); +// @return pointer to buffer if got fresh data +uint8_t *spi_read_enc(uint8_t encno){ + if(encno > 1 || !freshdata[encno]) return NULL; freshdata[encno] = 0; // clear fresh status - return TRUE; + return encoderbuf[encno]; } // start encoder reading over DMA @@ -135,16 +128,12 @@ int spi_read_enc(uint8_t encno, uint8_t buf[ENCODER_BUFSZ]){ // here `encodernum` is 0 (SPI1) or 1 (SPI2), not 1/2 as SPI index! int spi_start_enc(int encodernum){ int spiidx = encodernum + 1; - //DBG("start enc"); if(spiidx < 1 || spiidx > AMOUNT_OF_SPI) return FALSE; if(spi_status[spiidx] != SPI_READY) return FALSE; if(!spi_waitbsy(spiidx)) return FALSE; - if(SPI1->CR1 & SPI_CR1_SPE){ DBG("spi1 works!");} - if(SPI2->CR1 & SPI_CR1_SPE){ DBG("spi2 works!");} volatile DMA_Channel_TypeDef *DMA = DMAs[spiidx]; DMA->CMAR = (uint32_t) encoderbuf[encodernum]; - DMA->CNDTR = ENCODER_BUFSZ; - //DBG("turn on spi"); + DMA->CNDTR = the_conf.encbufsz; spi_onoff(spiidx, 1); DMA->CCR |= DMA_CCR_EN; return TRUE; @@ -159,12 +148,8 @@ void dma1_channel2_isr(){ DMA1->IFCR = DMA_IFCR_CTEIF2; } if(DMA1->ISR & DMA_ISR_TCIF2){ - //uint32_t ctr = TIM2->CNT; DMA1->IFCR = DMA_IFCR_CTCIF2; freshdata[0] = 1; - //encoderbuf[5] = (ctr >> 16) & 0xff; - //encoderbuf[6] = (ctr >> 8 ) & 0xff; - //encoderbuf[7] = (ctr >> 0 ) & 0xff; } spi_status[1] = SPI_READY; } diff --git a/F1:F103/BISS_C_encoders/spi.h b/F1:F103/BISS_C_encoders/spi.h index f5a4f84..e4e630f 100644 --- a/F1:F103/BISS_C_encoders/spi.h +++ b/F1:F103/BISS_C_encoders/spi.h @@ -2,9 +2,13 @@ #pragma once #include +// two SPI interfaces for two sensors #define AMOUNT_OF_SPI (2) - -#define ENCODER_BUFSZ (12) +// static buffer size +#define ENCODER_BUFSZ_MAX (32) +// encoder resolution +#define ENCRESOL_MIN (8) +#define ENCRESOL_MAX (32) typedef enum{ SPI_NOTREADY, @@ -18,4 +22,4 @@ void spi_onoff(uint8_t idx, uint8_t on); void spi_deinit(uint8_t idx); void spi_setup(uint8_t idx); int spi_start_enc(int encodernum); -int spi_read_enc(uint8_t encno, uint8_t buf[ENCODER_BUFSZ]); +uint8_t *spi_read_enc(uint8_t encno); diff --git a/F1:F103/BISS_C_encoders/usart.c b/F1:F103/BISS_C_encoders/usart.c deleted file mode 100644 index 5722fb0..0000000 --- a/F1:F103/BISS_C_encoders/usart.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * usart.c - * - * Copyright 2018 Edward V. Emelianoff - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include - -#include "stm32f1.h" -#include "usart.h" -#include "ringbuffer.h" - -extern volatile uint32_t Tms; -// buffers for out ringbuffer and DMA send -static uint8_t buf[UARTBUFSZ], txbuf[UARTBUFSZ]; -static ringbuffer ringbuf = {.data = buf, .length = UARTBUFSZ}; - -static volatile int usart_txrdy = 1; // transmission done - -// transmit current tbuf -void usart_transmit(){ - if(RB_hasbyte(&ringbuf, '\n') < 0 || !usart_txrdy) return; - int L = 0, l = 0; - do{ - l = RB_readto(&ringbuf, '\n', txbuf + L, UARTBUFSZ - L); - if(l > 0) L += l; - }while(l > 0 && L < UARTBUFSZ); - if(L < 1) return; - usart_txrdy = 0; - if(L < UARTBUFSZ-1){ - txbuf[L++] = '$'; txbuf[L++] = '\n'; - } - DMA1_Channel4->CCR &= ~DMA_CCR_EN; - DMA1_Channel4->CMAR = (uint32_t) txbuf; // mem - DMA1_Channel4->CNDTR = L; - DMA1_Channel4->CCR |= DMA_CCR_EN; -} - -void usart_putchar(const char ch){ - RB_write(&ringbuf, (const uint8_t*)&ch, 1); -} - -void usart_send(const char *str){ - int l = strlen(str); - if(RB_datalen(&ringbuf) > UARTBUFSZ/2) usart_transmit(); - RB_write(&ringbuf, (const uint8_t*)str, l); -} - -/* - * USART speed: baudrate = Fck/(USARTDIV) - * USARTDIV stored in USART->BRR - * - * for 72MHz USARTDIV=72000/f(kboud); so for 115200 USARTDIV=72000/115.2=625 -> BRR=0x271 - * 9600: BRR = 7500 (0x1D4C) - */ - -void usart_setup(){ - uint32_t tmout = 16000000; - // PA9 - Tx, PA10 - Rx - RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN; - RCC->AHBENR |= RCC_AHBENR_DMA1EN; - GPIOA->CRH |= CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT); - - // USART1 Tx DMA - Channel4 (Rx - channel 5) - DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; // periph - DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq - // Tx CNDTR set @ each transmission due to data size - NVIC_SetPriority(DMA1_Channel4_IRQn, 3); - NVIC_EnableIRQ(DMA1_Channel4_IRQn); - NVIC_SetPriority(USART1_IRQn, 0); - // setup usart1 - USART1->BRR = 72000000 / 4000000; - USART1->CR1 = USART_CR1_TE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART - while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission - USART1->SR = 0; // clear flags - USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ - USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx -} - -void dma1_channel4_isr(){ - if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx - DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag - usart_txrdy = 1; - } -} diff --git a/F1:F103/BISS_C_encoders/version.inc b/F1:F103/BISS_C_encoders/version.inc index 2bcb422..aebe739 100644 --- a/F1:F103/BISS_C_encoders/version.inc +++ b/F1:F103/BISS_C_encoders/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "91" -#define BUILD_DATE "2025-04-02" +#define BUILD_NUMBER "96" +#define BUILD_DATE "2025-04-04" diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_7inone/usb_dev.c b/F1:F103/USB_New_concept/USB_NEW_concept_7inone/usb_dev.c index 7122e2d..0791a90 100644 --- a/F1:F103/USB_New_concept/USB_NEW_concept_7inone/usb_dev.c +++ b/F1:F103/USB_New_concept/USB_NEW_concept_7inone/usb_dev.c @@ -78,13 +78,19 @@ static void chkin(uint8_t ifno){ static void send_next(uint8_t ifno){ uint8_t usbbuff[USB_TXBUFSZ]; int buflen = RB_read((ringbuffer*)&rbout[ifno], (uint8_t*)usbbuff, USB_TXBUFSZ); + if(!CDCready[ifno]){ + lastdsz[ifno] = -1; + return; + } if(buflen == 0){ - if(lastdsz[ifno] == 64) EP_Write(1+ifno, NULL, 0); // send ZLP after 64 bits packet when nothing more to send - lastdsz[ifno] = 0; + if(lastdsz[ifno] == USB_TXBUFSZ){ + EP_Write(1+ifno, NULL, 0); // send ZLP after 64 bits packet when nothing more to send + lastdsz[ifno] = 0; + }else lastdsz[ifno] = -1; // OK. User can start sending data return; }else if(buflen < 0){ DBG("Buff busy"); - lastdsz[ifno] = 0; + lastdsz[ifno] = -1; return; } DBG("Got data in buf"); @@ -221,14 +227,17 @@ int USB_send(uint8_t ifno, const uint8_t *buf, int len){ if(!buf || !CDCready[ifno] || !len) return FALSE; DBG("USB_send"); while(len){ + if(!CDCready[ifno]) return FALSE; IWDG->KR = IWDG_REFRESH; int a = RB_write((ringbuffer*)&rbout[ifno], buf, len); - if(lastdsz[ifno] == 0) send_next(ifno); // need to run manually - all data sent, so no IRQ on IN if(a > 0){ len -= a; buf += a; - } else if (a < 0) continue; // do nothing if buffer is in reading state + }else if(a == 0){ // overfull + if(lastdsz[ifno] < 0) send_next(ifno); + } } + if(buf[len-1] == '\n' && lastdsz[ifno] < 0) send_next(ifno); return TRUE; } @@ -236,10 +245,15 @@ int USB_putbyte(uint8_t ifno, uint8_t byte){ if(!CDCready[ifno]) return FALSE; int l = 0; while((l = RB_write((ringbuffer*)&rbout[ifno], &byte, 1)) != 1){ + if(!CDCready[ifno]) return FALSE; IWDG->KR = IWDG_REFRESH; - if(lastdsz[ifno] == 0) send_next(ifno); // need to run manually - all data sent, so no IRQ on IN - if(l < 0) continue; + if(l == 0){ // overfull + if(lastdsz[ifno] < 0) send_next(ifno); + continue; + } } + // send line if got EOL + if(byte == '\n' && lastdsz[ifno] < 0) send_next(ifno); return TRUE; } diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_CDC/usb_dev.c b/F1:F103/USB_New_concept/USB_NEW_concept_CDC/usb_dev.c index 942694c..da97f94 100644 --- a/F1:F103/USB_New_concept/USB_NEW_concept_CDC/usb_dev.c +++ b/F1:F103/USB_New_concept/USB_NEW_concept_CDC/usb_dev.c @@ -75,13 +75,19 @@ static void chkin(){ static void send_next(){ uint8_t usbbuff[USB_TXBUFSZ]; int buflen = RB_read((ringbuffer*)&rbout, (uint8_t*)usbbuff, USB_TXBUFSZ); + if(!CDCready){ + lastdsz = -1; + return; + } if(buflen == 0){ - if(lastdsz == 64) EP_Write(1, NULL, 0); // send ZLP after 64 bits packet when nothing more to send - lastdsz = 0; + if(lastdsz == USB_TXBUFSZ){ + EP_Write(1, NULL, 0); // send ZLP after 64 bits packet when nothing more to send + lastdsz = 0; + }else lastdsz = -1; return; }else if(buflen < 0){ DBG("Buff busy"); - lastdsz = 0; + lastdsz = -1; return; } DBG("Got data in buf"); @@ -193,14 +199,17 @@ int USB_send(const uint8_t *buf, int len){ if(!buf || !CDCready || !len) return FALSE; DBG("USB_send"); while(len){ + if(!CDCready) return FALSE; IWDG->KR = IWDG_REFRESH; int a = RB_write((ringbuffer*)&rbout, buf, len); - if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN if(a > 0){ len -= a; buf += a; - } else if (a < 0) continue; // do nothing if buffer is in reading state + }else if(a == 0){ // overfull + if(lastdsz < 0) send_next(); + } } + if(buf[len-1] == '\n' && lastdsz < 0) send_next(); return TRUE; } @@ -208,10 +217,14 @@ int USB_putbyte(uint8_t byte){ if(!CDCready) return FALSE; int l = 0; while((l = RB_write((ringbuffer*)&rbout, &byte, 1)) != 1){ + if(!CDCready) return FALSE; IWDG->KR = IWDG_REFRESH; - if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN - if(l < 0) continue; + if(l == 0){ // overfull + if(lastdsz < 0) send_next(); + continue; + } } + if(byte == '\n' && lastdsz < 0) send_next(); return TRUE; } diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.c index 5b3fd40..4949d00 100644 --- a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.c +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.c @@ -81,12 +81,18 @@ static void chkin(){ static void send_next(){ uint8_t usbbuff[USB_TXBUFSZ]; int buflen = RB_read((ringbuffer*)&rbout, (uint8_t*)usbbuff, USB_TXBUFSZ); + if(!CDCready){ + lastdsz = -1; + return; + } if(buflen == 0){ - if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send - lastdsz = 0; + if(lastdsz == 64){ + EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send + lastdsz = 0; + } else lastdsz = -1; // OK. User can start sending data return; }else if(buflen < 0){ - lastdsz = 0; + lastdsz = -1; return; } EP_Write(3, (uint8_t*)usbbuff, buflen); @@ -231,16 +237,19 @@ int USB_sendall(){ // put `buf` into queue to send int USB_send(const uint8_t *buf, int len){ if(!buf || !CDCready || !len) return FALSE; - DBG("send"); + DBG("USB_send"); while(len){ + if(!CDCready) return FALSE; IWDG->KR = IWDG_REFRESH; int a = RB_write((ringbuffer*)&rbout, buf, len); - if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN if(a > 0){ len -= a; buf += a; - } else if (a < 0) continue; // do nothing if buffer is in reading state + }else if(a == 0){ // overfull + if(lastdsz < 0) send_next(); } + } + if(buf[len-1] == '\n' && lastdsz < 0) send_next(); return TRUE; } @@ -248,10 +257,15 @@ int USB_putbyte(uint8_t byte){ if(!CDCready) return FALSE; int l = 0; while((l = RB_write((ringbuffer*)&rbout, &byte, 1)) != 1){ + if(!CDCready) return FALSE; IWDG->KR = IWDG_REFRESH; - if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN - if(l < 0) continue; + if(l == 0){ // overfull + if(lastdsz < 0) send_next(); + continue; + } } + // send line if got EOL + if(byte == '\n' && lastdsz < 0) send_next(); return TRUE; }