aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2025-09-06 10:50:59 -0400
committerSam Anthony <sam@samanthony.xyz>2025-09-06 10:50:59 -0400
commitdf3ed451bf11d40e6369b0333fef92c536c57b4d (patch)
tree777fd2fbb0d941bd8587ecb7b75a6e34870837c0
parentd58635fd5cfedab133f8f25001289c77a3c874b1 (diff)
downloadcan-gauge-interface-df3ed451bf11d40e6369b0333fef92c536c57b4d.zip
usb getchar()
-rw-r--r--doc/protocol8
-rw-r--r--fw/usb.c80
2 files changed, 55 insertions, 33 deletions
diff --git a/doc/protocol b/doc/protocol
index 5d2cb65..59e807d 100644
--- a/doc/protocol
+++ b/doc/protocol
@@ -8,12 +8,12 @@ Echo:
Write EEPROM:
<opcode> ::= "w"
-<args> ::= <addr> <bytes>{:pagesize}
-<retval> ::= ""
+<args> ::= <addr> " " <size> " " <bytes>
+<retval> ::= "ok"
Read EEPROM:
<opcode> ::= "r"
-<args> ::= <addr> <size>
+<args> ::= <addr> " " <size>
<retval> ::= <bytes>{size}
<addr> ::= "0"--"2047"
@@ -22,4 +22,4 @@ Read EEPROM:
<byte> ::= "0"--"FF"
<size> ::= "0"--"2048"
-pagesize := 16
+Messages must not contain NUL ('\0').
diff --git a/fw/usb.c b/fw/usb.c
index 532bafd..0b03250 100644
--- a/fw/usb.c
+++ b/fw/usb.c
@@ -28,6 +28,12 @@ typedef struct State {
struct State* (*next)(void);
} State;
+// Input buffer
+typedef struct {
+ uint8_t data[CDC_DATA_OUT_EP_SIZE];
+ uint8_t len, head;
+} RxQueue;
+
/***** Function Declarations *****/
// States
@@ -38,12 +44,27 @@ static State *readEepromState(void);
/***** Global Variables *****/
-static uint8_t readBuf[CDC_DATA_OUT_EP_SIZE];
-static uint8_t writeBuf[CDC_DATA_IN_EP_SIZE];
-static uint8_t readLen = 0u;
+static uint8_t txBuf[CDC_DATA_IN_EP_SIZE];
+static RxQueue rxBuf = {.len = 0u, .head = 0u};
/***** Function Definitions *****/
+// Return the next Rx'd char, or '\0' if no data.
+static char
+getchar(void) {
+ if (rxBuf.len <= 0u) {
+ rxBuf.len = getsUSBUSART(rxBuf.data, sizeof(rxBuf.data));
+ rxBuf.head = 0u;
+ }
+
+ if (rxBuf.len > 0u) {
+ rxBuf.len--;
+ return rxBuf.data[rxBuf.head++];
+ } else {
+ return '\0';
+ }
+}
+
void
usbTask(void) {
static State state = {idleState};
@@ -66,30 +87,36 @@ usbTask(void) {
}
// Read (the start of) a command from USB.
-// Leaves <args> at the beginning of the read buffer.
static State *
idleState(void) {
static State state;
- uint8_t opcode;
+ char opcode;
state.next = idleState;
- readLen = getsUSBUSART(readBuf, sizeof(readBuf));
- if (readLen >= 2u) { // <opcode> <space> ...
- opcode = readBuf[0u];
+ // Read opcode
+ opcode = getchar();
+ if (!opcode) {
+ // No data
+ return &state;
+ }
- // skip <opcode> <space>
- memmove(readBuf, readBuf+2u, readLen-2u);
- readLen -= 2u;
+ // Skip space
+ if (!getchar()) {
+ // Incomplete command
+ putsUSBUSART("nack\n");
+ return &state;
+ }
- switch (opcode) {
- case 'e': state.next = echoState; break;
- case 'w': state.next = writeEepromState; break;
- case 'r': state.next = readEepromState; break;
- default: putsUSBUSART("nack\n"); break; // invalid command
- }
- } else if (readLen > 0) {
+ // State transition
+ switch (opcode) {
+ case 'e': state.next = echoState; break;
+ case 'w': state.next = writeEepromState; break;
+ case 'r': state.next = readEepromState; break;
+ default: // invalid command
+ rxBuf.len = 0u; // discard input
putsUSBUSART("nack\n");
+ break;
}
return &state;
@@ -103,24 +130,19 @@ echoState(void) {
state.next = echoState;
- if (readLen == 0u) {
- readLen = getsUSBUSART(readBuf, sizeof(readBuf));
- }
-
- for (i = 0u; i < readLen; i++) {
- writeBuf[i] = readBuf[i];
- if (readBuf[i] == '\n') {
+ i = 0u;
+ while (i < sizeof(txBuf)) {
+ txBuf[i] = getchar();
+ if (txBuf[i++] == '\n') {
// End of command
state.next = idleState;
- i++;
break;
}
}
- if (readLen > 0u) {
- putUSBUSART(writeBuf, i);
+ if (i > 0u) {
+ putUSBUSART(txBuf, i);
}
- readLen = 0u;
return &state;
}