From ba6fb7522c7333b3a9081a823f2b93a425b36022 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Thu, 4 Sep 2025 19:05:46 -0400 Subject: fw: usb --- fw/usb.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 fw/usb.c (limited to 'fw/usb.c') diff --git a/fw/usb.c b/fw/usb.c new file mode 100644 index 0000000..2992888 --- /dev/null +++ b/fw/usb.c @@ -0,0 +1,170 @@ +#include + +#include +#include + +#include +#include +#include + +#include "usb.h" + +// Line coding +// See struct USB_CDC_LINE_CODING +enum { + DATA_RATE = 9600, // bps + CHAR_FORMAT = NUM_STOP_BITS_1, + PARITY_TYPE = PARITY_NONE, + DATA_BITS = 8, +}; + +// State +typedef enum { + IDLE, // waiting for command + CMD_START, // received opcode + ECHO, + WRITE_EEPROM, + READ_EEPROM, +} State; + +static uint8_t readBuf[CDC_DATA_OUT_EP_SIZE]; +static uint8_t writeBuf[CDC_DATA_IN_EP_SIZE]; +static State state = IDLE; + +// Handle "e" echo command. +static void +echo(void) { + static uint8_t readLen = 0u; + static uint8_t ri, wi; + + if (!USBUSARTIsTxTrfReady()) { + return; + } + + if (readLen == 0u) { + readLen = getsUSBUSART(readBuf, sizeof(readBuf)); + ri = 0u; + wi = 0u; + } + + while (readLen--) { + if (wi > sizeof(writeBuf)) { + // Overflow; flush + putUSBUSART(writeBuf, sizeof(writeBuf)); + wi = 0u; + return; // continue on next call + } + + writeBuf[wi] = readBuf[ri]; + if (readBuf[ri] == '\n') { + // End of command + putUSBUSART(writeBuf, wi); + readLen = 0u; + state = IDLE; + return; + } + + ri++; + wi++; + } +} + +// Handle "w" write eeprom command. +static void +writeEeprom(void) { + // TODO +} + +// Handle "r" read eeprom command. +static void readEeprom(void) { + // TODO +} + +static void +setCmdState(uint8_t opcode) { + switch (opcode) { + case 'e': // echo + state = ECHO; + break; + case 'w': + state = WRITE_EEPROM; + break; + case 'r': + state = READ_EEPROM; + break; + } +} + +void +usbTask(void) { + static uint8_t opcode = 0u; + + USBDeviceTasks(); + + if (USBGetDeviceState() < CONFIGURED_STATE) { + return; + } + if (USBIsDeviceSuspended()) { + return; + } + + switch (state) { + case IDLE: + if (getsUSBUSART(&opcode, 1u) > 0) { + state = CMD_START; + } + break; + case CMD_START: + // Skip space char + if (getsUSBUSART(readBuf, 1u) > 0) { + setCmdState(opcode); + } + case ECHO: echo(); + break; + case WRITE_EEPROM: writeEeprom(); + break; + case READ_EEPROM: readEeprom(); + break; + } + + CDCTxService(); +} + +static void +configure(void) { + line_coding.dwDTERate = DATA_RATE; + line_coding.bCharFormat = CHAR_FORMAT; + line_coding.bParityType = PARITY_TYPE; + line_coding.bDataBits = DATA_BITS; +} + +bool +USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, uint16_t size) { + switch ((int)event) { + case EVENT_TRANSFER: + break; + case EVENT_SOF: + break; + case EVENT_SUSPEND: + break; + case EVENT_RESUME: + break; + case EVENT_CONFIGURED: + CDCInitEP(); + configure(); + break; + case EVENT_SET_DESCRIPTOR: + break; + case EVENT_EP0_REQUEST: + USBCheckCDCRequest(); + break; + case EVENT_BUS_ERROR: + break; + case EVENT_TRANSFER_TERMINATED: + break; + default: + break; + } + + return true; +} -- cgit v1.2.3