From df3ed451bf11d40e6369b0333fef92c536c57b4d Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 6 Sep 2025 10:50:59 -0400 Subject: usb getchar() --- doc/protocol | 8 +++--- fw/usb.c | 80 ++++++++++++++++++++++++++++++++++++++---------------------- 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: ::= "w" - ::= {:pagesize} - ::= "" + ::= " " " " + ::= "ok" Read EEPROM: ::= "r" - ::= + ::= " " ::= {size} ::= "0"--"2047" @@ -22,4 +22,4 @@ Read EEPROM: ::= "0"--"FF" ::= "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 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 = readBuf[0u]; + // Read opcode + opcode = getchar(); + if (!opcode) { + // No data + return &state; + } - // skip - 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; } -- cgit v1.2.3