diff --git a/F3:F303/PL2303/pl2303.creator.user.7bd84e3 b/F3:F303/PL2303/pl2303.creator.user.7bd84e3
new file mode 100644
index 0000000..aa79e75
--- /dev/null
+++ b/F3:F303/PL2303/pl2303.creator.user.7bd84e3
@@ -0,0 +1,171 @@
+
+
+
+
+
+ EnvironmentId
+ {7bd84e39-ca37-46d3-be9d-99ebea85bc0d}
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ KOI8-R
+ false
+ 4
+ false
+ 80
+ true
+ true
+ 1
+ false
+ true
+ false
+ 0
+ true
+ true
+ 0
+ 8
+ true
+ false
+ 1
+ true
+ false
+ true
+ *.md, *.MD, Makefile
+ false
+ true
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+ true
+ false
+ true
+ true
+ true
+ true
+
+
+ 0
+ true
+
+ true
+ true
+ Builtin.DefaultTidyAndClazy
+ 2
+
+
+
+ true
+
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ Desktop
+ Desktop
+ {65a14f9e-e008-4c1b-89df-4eaa4774b6e3}
+ 0
+ 0
+ 0
+
+ /Big/Data/00__Electronics/STM32/F303-nolib/blink
+
+
+
+ all
+
+ true
+ GenericProjectManager.GenericMakeStep
+
+ 1
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+
+ clean
+
+ true
+ GenericProjectManager.GenericMakeStep
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ false
+
+ Default
+ GenericProjectManager.GenericBuildConfiguration
+
+ 1
+
+
+ 0
+ Развёртывание
+ Развёртывание
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+
+ 2
+
+ ProjectExplorer.CustomExecutableRunConfiguration
+
+ false
+ true
+ false
+ true
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 22
+
+
+ Version
+ 22
+
+
diff --git a/F3:F303/Seven_CDCs/7CDCs.files b/F3:F303/Seven_CDCs/7CDCs.files
index 3d78e2d..a912955 100644
--- a/F3:F303/Seven_CDCs/7CDCs.files
+++ b/F3:F303/Seven_CDCs/7CDCs.files
@@ -1,10 +1,13 @@
cmdproto.c
cmdproto.h
+debug.h
hardware.c
hardware.h
main.c
ringbuffer.c
ringbuffer.h
+strfunc.c
+strfunc.h
usart.c
usart.h
usb.c
diff --git a/F3:F303/Seven_CDCs/cmdproto.c b/F3:F303/Seven_CDCs/cmdproto.c
index bcd5aba..72387cc 100644
--- a/F3:F303/Seven_CDCs/cmdproto.c
+++ b/F3:F303/Seven_CDCs/cmdproto.c
@@ -1,6 +1,6 @@
/*
* This file is part of the SevenCDCs project.
- * Copyright 2022 Edward V. Emelianov .
+ * Copyright 202 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
@@ -17,6 +17,8 @@
*/
#include "cmdproto.h"
+#include "debug.h"
+#include "strfunc.h"
#include "usb.h"
#include "version.inc"
@@ -24,136 +26,7 @@
#define SENDN(str) do{USB_sendstr(CMD_IDX, str); USB_putbyte(CMD_IDX, '\n');}while(0)
extern volatile uint32_t Tms;
-
-char *omit_spaces(const char *buf){
- while(*buf){
- if(*buf > ' ') break;
- ++buf;
- }
- return (char*)buf;
-}
-
-// In case of overflow return `buf` and N==0xffffffff
-// read decimal number & return pointer to next non-number symbol
-static char *getdec(const char *buf, uint32_t *N){
- char *start = (char*)buf;
- uint32_t num = 0;
- while(*buf){
- char c = *buf;
- if(c < '0' || c > '9'){
- break;
- }
- if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
- *N = 0xffffff;
- return start;
- }
- num *= 10;
- num += c - '0';
- ++buf;
- }
- *N = num;
- return (char*)buf;
-}
-// read hexadecimal number (without 0x prefix!)
-static char *gethex(const char *buf, uint32_t *N){
- char *start = (char*)buf;
- uint32_t num = 0;
- while(*buf){
- char c = *buf;
- uint8_t M = 0;
- if(c >= '0' && c <= '9'){
- M = '0';
- }else if(c >= 'A' && c <= 'F'){
- M = 'A' - 10;
- }else if(c >= 'a' && c <= 'f'){
- M = 'a' - 10;
- }
- if(M){
- if(num & 0xf0000000){ // overflow
- *N = 0xffffff;
- return start;
- }
- num <<= 4;
- num += c - M;
- }else{
- break;
- }
- ++buf;
- }
- *N = num;
- return (char*)buf;
-}
-// read octal number (without 0 prefix!)
-static char *getoct(const char *buf, uint32_t *N){
- char *start = (char*)buf;
- uint32_t num = 0;
- while(*buf){
- char c = *buf;
- if(c < '0' || c > '7'){
- break;
- }
- if(num & 0xe0000000){ // overflow
- *N = 0xffffff;
- return start;
- }
- num <<= 3;
- num += c - '0';
- ++buf;
- }
- *N = num;
- return (char*)buf;
-}
-// read binary number (without b prefix!)
-static char *getbin(const char *buf, uint32_t *N){
- char *start = (char*)buf;
- uint32_t num = 0;
- while(*buf){
- char c = *buf;
- if(c < '0' || c > '1'){
- break;
- }
- if(num & 0x80000000){ // overflow
- *N = 0xffffff;
- return start;
- }
- num <<= 1;
- if(c == '1') num |= 1;
- ++buf;
- }
- *N = num;
- return (char*)buf;
-}
-
-/**
- * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
- * @param buf - buffer with number and so on
- * @param N - the number read
- * @return pointer to first non-number symbol in buf
- * (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
- */
-char *getnum(const char *txt, uint32_t *N){
- char *nxt = NULL;
- char *s = omit_spaces(txt);
- if(*s == '0'){ // hex, oct or 0
- if(s[1] == 'x' || s[1] == 'X'){ // hex
- nxt = gethex(s+2, N);
- if(nxt == s+2) nxt = (char*)txt;
- }else if(s[1] > '0'-1 && s[1] < '8'){ // oct
- nxt = getoct(s+1, N);
- if(nxt == s+1) nxt = (char*)txt;
- }else{ // 0
- nxt = s+1;
- *N = 0;
- }
- }else if(*s == 'b' || *s == 'B'){
- nxt = getbin(s+1, N);
- if(nxt == s+1) nxt = (char*)txt;
- }else{
- nxt = getdec(s, N);
- if(nxt == s) nxt = (char*)txt;
- }
- return nxt;
-}
+extern uint8_t usbON;
const char* helpmsg =
"https://github.com/eddyem/stm32samples/tree/master/F3:F303/PL2303 build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
@@ -164,16 +37,14 @@ const char* helpmsg =
"'W' - test watchdog\n"
;
-
-extern uint8_t usbON;
void parse_cmd(const char *buf){
if(buf[1] == '\n' || !buf[1]){ // one symbol commands
switch(*buf){
case 'i':
SEND("USB->ISTR=");
- SEND(u2hexstr(USB->ISTR));
+ SEND(uhex2str(USB->ISTR));
SEND(", USB->CNTR=");
- SENDN(u2hexstr(USB->CNTR));
+ SENDN(uhex2str(USB->CNTR));
break;
case 'R':
SENDN("Soft reset");
@@ -196,7 +67,7 @@ void parse_cmd(const char *buf){
return;
}
uint32_t Num = 0;
- char *nxt;
+ const char *nxt;
switch(*buf){ // long messages
case 'N':
++buf;
@@ -217,41 +88,3 @@ void parse_cmd(const char *buf){
return;
}
}
-
-
-// return string with number `val`
-char *u2str(uint32_t val){
- static char strbuf[11];
- char *bufptr = &strbuf[10];
- *bufptr = 0;
- if(!val){
- *(--bufptr) = '0';
- }else{
- while(val){
- *(--bufptr) = val % 10 + '0';
- val /= 10;
- }
- }
- return bufptr;
-}
-
-char *u2hexstr(uint32_t val){
- static char strbuf[11] = "0x";
- char *sptr = strbuf + 2;
- uint8_t *ptr = (uint8_t*)&val + 3;
- int8_t i, j, z=1;
- for(i = 0; i < 4; ++i, --ptr){
- if(*ptr == 0){ // omit leading zeros
- if(i == 3) z = 0;
- if(z) continue;
- }
- else z = 0;
- for(j = 1; j > -1; --j){
- uint8_t half = (*ptr >> (4*j)) & 0x0f;
- if(half < 10) *sptr++ = half + '0';
- else *sptr++ = half - 10 + 'a';
- }
- }
- *sptr = 0;
- return strbuf;
-}
diff --git a/F3:F303/Seven_CDCs/cmdproto.h b/F3:F303/Seven_CDCs/cmdproto.h
index f41a242..c58ffad 100644
--- a/F3:F303/Seven_CDCs/cmdproto.h
+++ b/F3:F303/Seven_CDCs/cmdproto.h
@@ -1,6 +1,6 @@
/*
* This file is part of the SevenCDCs project.
- * Copyright 2022 Edward V. Emelianov .
+ * Copyright 2023 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
@@ -17,17 +17,7 @@
*/
#pragma once
-#ifndef PROTO_H__
-#define PROTO_H__
#include
-extern uint8_t starttest;
-
void parse_cmd(const char *buf);
-char *omit_spaces(const char *buf);
-char *getnum(const char *buf, uint32_t *N);
-char *u2str(uint32_t val);
-char *u2hexstr(uint32_t val);
-
-#endif // PROTO_H__
diff --git a/F3:F303/Seven_CDCs/debug.h b/F3:F303/Seven_CDCs/debug.h
new file mode 100644
index 0000000..793ff6b
--- /dev/null
+++ b/F3:F303/Seven_CDCs/debug.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the 7CDCs project.
+ * Copyright 2023 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 "usb.h"
+
+#ifdef EBUG
+#define DBG(str) do{USB_sendstr(DBG_IDX, __FILE__ " (L" STR(__LINE__) "): " str); newline(DBG_IDX);}while(0)
+#define DBGmesg(str) do{USB_sendstr(DBG_IDX, str);}while(0)
+#define DBGnl() newline(DBG_IDX)
+#else
+#define DBG(str)
+#define DBGmesg(str)
+#define DBGnl()
+#endif
+
+#define MSG(str) do{USB_sendstr(DBG_IDX, str); newline(DBG_IDX);}while(0)
+
diff --git a/F3:F303/Seven_CDCs/main.c b/F3:F303/Seven_CDCs/main.c
index e9bdfb4..3cf3ff1 100644
--- a/F3:F303/Seven_CDCs/main.c
+++ b/F3:F303/Seven_CDCs/main.c
@@ -16,8 +16,9 @@
* along with this program. If not, see .
*/
-#include "hardware.h"
#include "cmdproto.h"
+#include "debug.h"
+#include "hardware.h"
#include "usart.h"
#include "usb.h"
@@ -48,11 +49,14 @@ int main(void){
if(Tms - ctr > 499){
ctr = Tms;
pin_toggle(GPIOB, 1 << 1 | 1 << 0); // toggle LED @ PB0
+ //DBG("blink\n");
}
int l = USB_receivestr(CMD_IDX, inbuff, MAXSTRLEN);
if(l < 0) USB_sendstr(CMD_IDX, "ERROR: USB buffer overflow or string was too long\n");
else if(l){
parse_cmd(inbuff);
}
+ l = USB_receivestr(DBG_IDX, inbuff, MAXSTRLEN);
+ if(l) USB_sendstr(DBG_IDX, inbuff); // just echo back all from USB-DBG interface
}
}
diff --git a/F3:F303/Seven_CDCs/sevenCDCs.bin b/F3:F303/Seven_CDCs/sevenCDCs.bin
index d2324ac..202f361 100755
Binary files a/F3:F303/Seven_CDCs/sevenCDCs.bin and b/F3:F303/Seven_CDCs/sevenCDCs.bin differ
diff --git a/F3:F303/Seven_CDCs/strfunc.c b/F3:F303/Seven_CDCs/strfunc.c
new file mode 100644
index 0000000..d599669
--- /dev/null
+++ b/F3:F303/Seven_CDCs/strfunc.c
@@ -0,0 +1,343 @@
+/*
+ * This file is part of the 7CDCs project.
+ * Copyright 2023 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
+#include
+/**
+ * @brief hexdump - dump hex array by 16 bytes in string
+ * @param sendfun - function to send data
+ * @param arr - array to dump
+ * @param len - length of `arr`
+ */
+void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){
+ char buf[52], *bptr = buf;
+ for(uint16_t l = 0; l < len; ++l, ++arr){
+ for(int16_t j = 1; j > -1; --j){
+ register uint8_t half = (*arr >> (4*j)) & 0x0f;
+ if(half < 10) *bptr++ = half + '0';
+ else *bptr++ = half - 10 + 'a';
+ }
+ if(l % 16 == 15){
+ *bptr++ = '\n';
+ *bptr = 0;
+ sendfun(buf);
+ bptr = buf;
+ }else *bptr++ = ' ';
+ }
+ if(bptr != buf){
+ *bptr++ = '\n';
+ *bptr = 0;
+ sendfun(buf);
+ }
+}
+
+/**
+ * @brief _2str - convert value into string buffer
+ * @param val - |value|
+ * @param minus - ==0 if value > 0
+ * @return buffer with number
+ */
+static char *_2str(uint32_t val, uint8_t minus){
+ static char strbuf[12];
+ char *bufptr = &strbuf[11];
+ *bufptr = 0;
+ if(!val){
+ *(--bufptr) = '0';
+ }else{
+ while(val){
+ uint32_t x = val / 10;
+ *(--bufptr) = (val - 10*x) + '0';
+ val = x;
+ //*(--bufptr) = val % 10 + '0';
+ //val /= 10;
+ }
+ }
+ if(minus) *(--bufptr) = '-';
+ return bufptr;
+}
+
+// return string with number `val`
+char *u2str(uint32_t val){
+ return _2str(val, 0);
+}
+char *i2str(int32_t i){
+ uint8_t minus = 0;
+ uint32_t val;
+ if(i < 0){
+ minus = 1;
+ val = -i;
+ }else val = i;
+ return _2str(val, minus);
+}
+
+/**
+ * @brief uhex2str - print 32bit unsigned int as hex
+ * @param val - value
+ * @return string with number
+ */
+char *uhex2str(uint32_t val){
+ static char buf[12] = "0x";
+ int npos = 2;
+ uint8_t *ptr = (uint8_t*)&val + 3;
+ int8_t i, j, z=1;
+ for(i = 0; i < 4; ++i, --ptr){
+ if(*ptr == 0){ // omit leading zeros
+ if(i == 3) z = 0;
+ if(z) continue;
+ }
+ else z = 0;
+ for(j = 1; j > -1; --j){
+ uint8_t half = (*ptr >> (4*j)) & 0x0f;
+ if(half < 10) buf[npos++] = half + '0';
+ else buf[npos++] = half - 10 + 'a';
+ }
+ }
+ buf[npos] = 0;
+ return buf;
+}
+
+/**
+ * @brief omit_spaces - eliminate leading spaces and other trash in string
+ * @param buf - string
+ * @return - pointer to first character in `buf` > ' '
+ */
+const char *omit_spaces(const char *buf){
+ while(*buf){
+ if(*buf > ' ') break;
+ ++buf;
+ }
+ return buf;
+}
+
+/**
+ * @brief getdec - read decimal number & return pointer to next non-number symbol
+ * @param buf - string
+ * @param N - number read
+ * @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff
+ */
+static const char *getdec(const char *buf, uint32_t *N){
+ char *start = (char*)buf;
+ uint32_t num = 0;
+ while(*buf){
+ char c = *buf;
+ if(c < '0' || c > '9'){
+ break;
+ }
+ if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
+ *N = 0xffffff;
+ return start;
+ }
+ num *= 10;
+ num += c - '0';
+ ++buf;
+ }
+ *N = num;
+ return buf;
+}
+// read hexadecimal number (without 0x prefix!)
+static const char *gethex(const char *buf, uint32_t *N){
+ const char *start = buf;
+ uint32_t num = 0;
+ while(*buf){
+ char c = *buf;
+ uint8_t M = 0;
+ if(c >= '0' && c <= '9'){
+ M = '0';
+ }else if(c >= 'A' && c <= 'F'){
+ M = 'A' - 10;
+ }else if(c >= 'a' && c <= 'f'){
+ M = 'a' - 10;
+ }
+ if(M){
+ if(num & 0xf0000000){ // overflow
+ *N = 0xffffff;
+ return start;
+ }
+ num <<= 4;
+ num += c - M;
+ }else{
+ break;
+ }
+ ++buf;
+ }
+ *N = num;
+ return buf;
+}
+// read octal number (without 0 prefix!)
+static const char *getoct(const char *buf, uint32_t *N){
+ const char *start = (char*)buf;
+ uint32_t num = 0;
+ while(*buf){
+ char c = *buf;
+ if(c < '0' || c > '7'){
+ break;
+ }
+ if(num & 0xe0000000){ // overflow
+ *N = 0xffffff;
+ return start;
+ }
+ num <<= 3;
+ num += c - '0';
+ ++buf;
+ }
+ *N = num;
+ return buf;
+}
+// read binary number (without b prefix!)
+static const char *getbin(const char *buf, uint32_t *N){
+ const char *start = (char*)buf;
+ uint32_t num = 0;
+ while(*buf){
+ char c = *buf;
+ if(c < '0' || c > '1'){
+ break;
+ }
+ if(num & 0x80000000){ // overflow
+ *N = 0xffffff;
+ return start;
+ }
+ num <<= 1;
+ if(c == '1') num |= 1;
+ ++buf;
+ }
+ *N = num;
+ return buf;
+}
+
+/**
+ * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
+ * @param buf - buffer with number and so on
+ * @param N - the number read
+ * @return pointer to first non-number symbol in buf
+ * (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
+ */
+const char *getnum(const char *txt, uint32_t *N){
+ const char *nxt = NULL;
+ const char *s = omit_spaces(txt);
+ if(*s == '0'){ // hex, oct or 0
+ if(s[1] == 'x' || s[1] == 'X'){ // hex
+ nxt = gethex(s+2, N);
+ if(nxt == s+2) nxt = (char*)txt;
+ }else if(s[1] > '0'-1 && s[1] < '8'){ // oct
+ nxt = getoct(s+1, N);
+ if(nxt == s+1) nxt = (char*)txt;
+ }else{ // 0
+ nxt = s+1;
+ *N = 0;
+ }
+ }else if(*s == 'b' || *s == 'B'){
+ nxt = getbin(s+1, N);
+ if(nxt == s+1) nxt = (char*)txt;
+ }else{
+ nxt = getdec(s, N);
+ if(nxt == s) nxt = (char*)txt;
+ }
+ return nxt;
+}
+
+// get signed integer
+const char *getint(const char *txt, int32_t *I){
+ const char *s = omit_spaces(txt);
+ int32_t sign = 1;
+ uint32_t U;
+ if(*s == '-'){
+ sign = -1;
+ ++s;
+ }
+ const char *nxt = getnum(s, &U);
+ if(nxt == s) return txt;
+ if(U & 0x80000000) return txt; // overfull
+ *I = sign * (int32_t)U;
+ return nxt;
+}
+
+/*
+void mymemcpy(char *dest, const char *src, int len){
+ if(len < 1) return;
+ while(len--) *dest++ = *src++;
+}
+*/
+
+// be careful: if pow10 would be bigger you should change str[] size!
+static const float pwr10[] = {1.f, 10.f, 100.f, 1000.f, 10000.f};
+static const float rounds[] = {0.5f, 0.05f, 0.005f, 0.0005f, 0.00005f};
+#define P10L (sizeof(pwr10)/sizeof(uint32_t) - 1)
+char * float2str(float x, uint8_t prec){
+ static char str[16] = {0}; // -117.5494E-36\0 - 14 symbols max!
+ if(prec > P10L) prec = P10L;
+ if(isnan(x)){ memcpy(str, "NAN", 4); return str;}
+ else{
+ int i = isinf(x);
+ if(i){memcpy(str, "-INF", 5); if(i == 1) return str+1; else return str;}
+ }
+ char *s = str + 14; // go to end of buffer
+ uint8_t minus = 0;
+ if(x < 0){
+ x = -x;
+ minus = 1;
+ }
+ int pow = 0; // xxxEpow
+ // now convert float to 1.xxxE3y
+ while(x > 1000.f){
+ x /= 1000.f;
+ pow += 3;
+ }
+ if(x > 0.) while(x < 1.){
+ x *= 1000.f;
+ pow -= 3;
+ }
+ // print Eyy
+ if(pow){
+ uint8_t m = 0;
+ if(pow < 0){pow = -pow; m = 1;}
+ while(pow){
+ register int p10 = pow/10;
+ *s-- = '0' + (pow - 10*p10);
+ pow = p10;
+ }
+ if(m) *s-- = '-';
+ *s-- = 'E';
+ }
+ // now our number is in [1, 1000]
+ uint32_t units;
+ if(prec){
+ units = (uint32_t) x;
+ uint32_t decimals = (uint32_t)((x-units+rounds[prec])*pwr10[prec]);
+ // print decimals
+ while(prec){
+ register int d10 = decimals / 10;
+ *s-- = '0' + (decimals - 10*d10);
+ decimals = d10;
+ --prec;
+ }
+ // decimal point
+ *s-- = '.';
+ }else{ // without decimal part
+ units = (uint32_t) (x + 0.5);
+ }
+ // print main units
+ if(units == 0) *s-- = '0';
+ else while(units){
+ register uint32_t u10 = units / 10;
+ *s-- = '0' + (units - 10*u10);
+ units = u10;
+ }
+ if(minus) *s-- = '-';
+ return s+1;
+}
diff --git a/F3:F303/Seven_CDCs/strfunc.h b/F3:F303/Seven_CDCs/strfunc.h
new file mode 100644
index 0000000..a63ac4b
--- /dev/null
+++ b/F3:F303/Seven_CDCs/strfunc.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the 7CDCs project.
+ * Copyright 2023 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
+#include
+
+void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
+const char *u2str(uint32_t val);
+const char *i2str(int32_t i);
+const char *uhex2str(uint32_t val);
+const char *getnum(const char *txt, uint32_t *N);
+const char *omit_spaces(const char *buf);
+const char *getint(const char *txt, int32_t *I);
+//void mymemcpy(char *dest, const char *src, int len);
+char * float2str(float x, uint8_t prec);
diff --git a/F3:F303/Seven_CDCs/usart.c b/F3:F303/Seven_CDCs/usart.c
index 1da5114..447290a 100644
--- a/F3:F303/Seven_CDCs/usart.c
+++ b/F3:F303/Seven_CDCs/usart.c
@@ -30,17 +30,18 @@ volatile int linerdy = 0, // received data ready
dlen = 0, // length of data (including '\n') in current buffer
bufovr = 0; // input buffer overfull
// USARTs speeds
-static int speeds[USARTSNO+1] = {0};
+static usb_LineCoding lineCodings[USARTSNO+1] = {
+ {115200, USB_CDC_1_STOP_BITS, USB_CDC_NO_PARITY, 8}, {0}};
-usb_LineCoding *getLineCoding(int usartNo){
- static usb_LineCoding lineCoding; // `static` - to return pointer to it
- if(usartNo < 1 || usartNo > USARTSNO) return NULL;
-// TODO: fixme
- lineCoding.dwDTERate = speeds[usartNo];
- lineCoding.bCharFormat = USB_CDC_1_STOP_BITS;
- lineCoding.bParityType = USB_CDC_NO_PARITY;
- lineCoding.bDataBits = 8;
- return &lineCoding;
+usb_LineCoding *getLineCoding(int ifNo){
+ int usartNo = ifNo - USART1_EPNO + 1;
+ if(usartNo < 1 || usartNo > USARTSNO) return lineCodings;
+ return & lineCodings[usartNo];
+// TODO: fixme for different settings
+ //lineCoding.dwDTERate = speeds[usartNo];
+ //lineCoding.bCharFormat = USB_CDC_1_STOP_BITS;
+ //lineCoding.bParityType = USB_CDC_NO_PARITY;
+ //lineCoding.bDataBits = 8;
}
void usart_putchar(uint8_t ch){
@@ -64,9 +65,11 @@ void usarts_setup(){
NVIC_EnableIRQ(USART3_IRQn);
}
-void usart_config(uint8_t usartNo, usb_LineCoding *lc){
- if(!usartNo || usartNo > USARTSNO) return;
- speeds[usartNo] = lc->dwDTERate;
+void usart_config(uint8_t ifNo, usb_LineCoding *lc){
+ int usartNo = ifNo - USART1_EPNO + 1;
+ if(usartNo < 1 || usartNo > USARTSNO) return;
+ lineCodings[usartNo] = *lc;
+ // FIXME: change also parity and so on
volatile USART_TypeDef *U = USARTx[usartNo];
U->ICR = 0xffffffff; // clear all flags
U->BRR = SysFreq / lc->dwDTERate;
diff --git a/F3:F303/Seven_CDCs/usart.h b/F3:F303/Seven_CDCs/usart.h
index 64bacfd..2d40ee7 100644
--- a/F3:F303/Seven_CDCs/usart.h
+++ b/F3:F303/Seven_CDCs/usart.h
@@ -29,8 +29,8 @@
extern volatile int linerdy, bufovr;
void usarts_setup();
-void usart_config(uint8_t usartNo, usb_LineCoding *lc);
+void usart_config(uint8_t ifNo, usb_LineCoding *lc);
void usart_sendn(const uint8_t *str, int L);
-usb_LineCoding *getLineCoding(int usartNo);
+usb_LineCoding *getLineCoding(int ifNo);
#endif // __USART_H__
diff --git a/F3:F303/Seven_CDCs/usb.c b/F3:F303/Seven_CDCs/usb.c
index a2bae45..04edb91 100644
--- a/F3:F303/Seven_CDCs/usb.c
+++ b/F3:F303/Seven_CDCs/usb.c
@@ -30,7 +30,7 @@ volatile ringbuffer rbout[WORK_EPs] = {OBUF(0), OBUF(1), OBUF(2), OBUF(3), OBUF(
#define IBUF(N) {.data = ibuf[N], .length = RBOUTSZ, .head = 0, .tail = 0}
volatile ringbuffer rbin[WORK_EPs] = {IBUF(0), IBUF(1), IBUF(2), IBUF(3), IBUF(4), IBUF(5), IBUF(6)};
// transmission is succesfull
-volatile uint8_t bufisempty[WORK_EPs] = {1,1,1,1,1,1};
+volatile uint8_t bufisempty[WORK_EPs] = {1,1,1,1,1,1,1};
volatile uint8_t bufovrfl[WORK_EPs] = {0};
// here and later: ifNo is index of buffers, i.e. ifNo = epno-1 !!!
@@ -39,12 +39,12 @@ void send_next(int ifNo){
static int lastdsz = 0;
int buflen = RB_read((ringbuffer*)&rbout[ifNo], (uint8_t*)usbbuff, USB_TRBUFSZ);
if(!buflen){
- if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send
+ if(lastdsz == 64) EP_Write(ifNo+1, NULL, 0); // send ZLP after 64 bits packet when nothing more to send
lastdsz = 0;
bufisempty[ifNo] = 1;
return;
}
- EP_Write(3, (uint8_t*)usbbuff, buflen);
+ EP_Write(ifNo+1, (uint8_t*)usbbuff, buflen);
lastdsz = buflen;
}
@@ -59,8 +59,10 @@ int USB_sendall(int ifNo){
// put `buf` into queue to send
int USB_send(int ifNo, const uint8_t *buf, int len){
if(!buf || !usbON || !len) return 0;
+ uint32_t T = Tms;
while(len){
int a = RB_write((ringbuffer*)&rbout[ifNo], buf, len);
+ if(a == 0 && Tms - T > 5) return 0; // timeout
len -= a;
buf += a;
if(bufisempty[ifNo]){
@@ -126,4 +128,3 @@ int USB_receivestr(int ifNo, char *buf, int len){
}
return l;
}
-
diff --git a/F3:F303/Seven_CDCs/usb.h b/F3:F303/Seven_CDCs/usb.h
index af1d699..1daba82 100644
--- a/F3:F303/Seven_CDCs/usb.h
+++ b/F3:F303/Seven_CDCs/usb.h
@@ -31,12 +31,6 @@
#define STR_HELPER(s) #s
#define STR(s) STR_HELPER(s)
-#ifdef EBUG
-#define DBG(str) do{USB_sendstr(__FILE__ " (L" STR(__LINE__) "): " str); newline();}while(0)
-#else
-#define DBG(str)
-#endif
-
// total amount of working EPs
#define WORK_EPs 7
// functional EPs
@@ -45,10 +39,12 @@
#define USART2_EPNO 3
#define USART3_EPNO 4
#define CAN_EPNO 6
+#define DBG_EPNO 7
#define USARTMAX_EPNO USART3_EPNO
// functional indexes
#define CMD_IDX (CMD_EPNO-1)
#define CAN_IDX (CAN_EPNO-1)
+#define DBG_IDX (DBG_EPNO-1)
extern volatile ringbuffer rbout[], rbin[];
extern volatile uint8_t bufisempty[], bufovrfl[];
diff --git a/F3:F303/Seven_CDCs/usb_lib.c b/F3:F303/Seven_CDCs/usb_lib.c
index ee41396..48756b7 100644
--- a/F3:F303/Seven_CDCs/usb_lib.c
+++ b/F3:F303/Seven_CDCs/usb_lib.c
@@ -17,6 +17,10 @@
*/
#include
+#include "debug.h"
+#ifdef EBUG
+#include "strfunc.h"
+#endif
#include "usart.h"
#include "usb.h"
#include "usb_lib.h"
@@ -48,8 +52,8 @@ static const uint8_t USB_DeviceDescriptor[] = {
bDeviceSubClass, // bDeviceSubClass
bDeviceProtocol, // bDeviceProtocol
USB_EP0_BUFSZ, // bMaxPacketSize
- // 0483:5740 (VID:PID) - stm32 VCP
- 0x83, 0x04, 0x40, 0x57,
+ // 0483:5740 (VID:PID) - stm32 VCP
+ 0x83, 0x04, 0x40, 0x57,
0x00, // bcdDevice_Ver_L
0x02, // bcdDevice_Ver_H
iMANUFACTURER_DESCR, // iManufacturer
@@ -768,6 +772,8 @@ static void rxtx_Handler(uint8_t epno){
uint8_t buf[USB_TRBUFSZ];
int idx = epno - 1;
uint16_t epstatus = KEEP_DTOG(USB->EPnR[epno]);
+ DBGmesg("RxTx="); DBGmesg(u2str(epno));
+ DBGmesg(", epst="); DBGmesg(u2str(epstatus)); DBGnl();
if(RX_FLAG(epstatus)){
uint8_t sz = EP_Read(epno, (uint8_t*)buf);
if(sz){
@@ -793,6 +799,7 @@ static inline void std_h2d_req(){
for(uint8_t i = 1; i <= WORK_EPs; ++i){
EP_Init(i, EP_TYPE_BULK, USB_TRBUFSZ, USB_TRBUFSZ, rxtx_Handler);
}
+ usbON = 1;
break;
default:
break;
@@ -814,6 +821,8 @@ void EP0_Handler(uint8_t __attribute__((unused)) epno){
uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0;
int rxflag = RX_FLAG(epstatus);
usb_LineCoding *lc;
+ // calculate iFno (EP number minus 1) by setup_packet->wIndex (bInterfaceNumber): iFno = wIndex >> 1
+ int iFno = setup_packet->wIndex >> 1;
if(rxflag && SETUP_FLAG(epstatus)){
switch(reqtype){
case STANDARD_DEVICE_REQUEST_TYPE: // standard device request
@@ -832,17 +841,20 @@ void EP0_Handler(uint8_t __attribute__((unused)) epno){
case CONTROL_REQUEST_TYPE:
switch(setup_packet->bRequest){
case GET_LINE_CODING:
- lc = getLineCoding(1); // TODO: HOW can we change number of interface???
+ DBG("GET_LINE_CODING from"); DBGmesg(u2str(iFno)); DBGnl();
+ lc = getLineCoding(iFno);
if(!lc) EP_WriteIRQ(0, (uint8_t *)0, 0);
else EP_WriteIRQ(0, (uint8_t*)&lc, sizeof(usb_LineCoding));
break;
case SET_LINE_CODING: // omit this for next stage, when data will come
break;
case SET_CONTROL_LINE_STATE:
- clstate_handler(1, setup_packet->wValue); // TODO: how can we check iface number???
+ DBG("SET_CONTROL_LINE_STATE from"); DBGmesg(u2str(iFno)); DBGnl();
+ clstate_handler(iFno, setup_packet->wValue);
break;
case SEND_BREAK:
- break_handler(1); // TODO: how can we check iface number???
+ DBG("SEND_BREAK from"); DBGmesg(u2str(iFno)); DBGnl();
+ break_handler(iFno);
break;
default:
break;
@@ -855,8 +867,8 @@ void EP0_Handler(uint8_t __attribute__((unused)) epno){
}else if(rxflag){ // got data over EP0 or host acknowlegement
if(endpoints[0].rx_cnt){
if(setup_packet->bRequest == SET_LINE_CODING){
- // TODO: how can we check iface number???
- linecoding_handler(1, (usb_LineCoding*)ep0databuf);
+ DBG("SET_LINE_CODING from"); DBGmesg(u2str(iFno)); DBGnl();
+ linecoding_handler(iFno, (usb_LineCoding*)ep0databuf);
}
}
} else if(TX_FLAG(epstatus)){ // package transmitted
diff --git a/F3:F303/Seven_CDCs/usb_lib.h b/F3:F303/Seven_CDCs/usb_lib.h
index 3bead86..e0cd1c2 100644
--- a/F3:F303/Seven_CDCs/usb_lib.h
+++ b/F3:F303/Seven_CDCs/usb_lib.h
@@ -98,16 +98,6 @@ enum{
#define LANG_US (uint16_t)0x0409
-#if 0
-typedef struct{
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint16_t *bString;
-} string_descriptor_t;
-
-#define _USB_STRING_(name, str) string_descriptor_t name = {(sizeof(str) + 2), STRING_DESCRIPTOR, str}
-#endif
-
#define _USB_STRING_(name, str) \
static const struct name \
{ \
@@ -162,14 +152,6 @@ typedef struct {
uint8_t bDataBits;
} __attribute__ ((packed)) usb_LineCoding;
-typedef struct {
- uint8_t bmRequestType;
- uint8_t bNotificationType;
- uint16_t wValue;
- uint16_t wIndex;
- uint16_t wLength;
-} __attribute__ ((packed)) usb_cdc_notification;
-
extern ep_t endpoints[];
extern volatile uint8_t usbON;
extern config_pack_t *setup_packet;
diff --git a/F3:F303/Seven_CDCs/usbhw.c b/F3:F303/Seven_CDCs/usbhw.c
index 3414927..d00efb8 100644
--- a/F3:F303/Seven_CDCs/usbhw.c
+++ b/F3:F303/Seven_CDCs/usbhw.c
@@ -118,6 +118,7 @@ void usb_lp_isr(){
if(USB->ISTR & USB_ISTR_WKUP){ // wakeup
USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE); // clear suspend flags
USB->ISTR = ~USB_ISTR_WKUP;
+ usbON = 1;
}
}
diff --git a/F3:F303/Seven_CDCs/version.inc b/F3:F303/Seven_CDCs/version.inc
index bb6dca5..70e8760 100644
--- a/F3:F303/Seven_CDCs/version.inc
+++ b/F3:F303/Seven_CDCs/version.inc
@@ -1,2 +1,2 @@
-#define BUILD_NUMBER "47"
-#define BUILD_DATE "2023-04-18"
+#define BUILD_NUMBER "56"
+#define BUILD_DATE "2023-04-23"