From 9fc79408dc97ba23dbd0ef2d71931f0aa2275c97 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 5 Apr 2026 20:47:48 +0900 Subject: [PATCH] Non-blocking USB TX with ring buffer and immediate drain --- picomap.cpp | 61 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/picomap.cpp b/picomap.cpp index 16f73f3..d32693a 100644 --- a/picomap.cpp +++ b/picomap.cpp @@ -6,23 +6,47 @@ #include "w6300.h" -static void usb_write(const uint8_t* data, uint32_t len) { - while (len > 0) { - uint32_t avail = tud_cdc_write_available(); - if (avail == 0) { - tud_task(); - continue; - } - uint32_t chunk = len < avail ? len : avail; - tud_cdc_write(data, chunk); - tud_cdc_write_flush(); - data += chunk; - len -= chunk; - } -} +struct tx_buf { + uint8_t data[512]; + uint16_t head = 0; + uint16_t tail = 0; -static void send_bytes(const std::vector &data) { - usb_write(data.data(), data.size()); + uint16_t used() const { return tail - head; } + uint16_t free() const { return sizeof(data) - used(); } + bool empty() const { return head == tail; } + + void push(const uint8_t* src, uint16_t len) { + if (len > free()) return; + for (uint16_t i = 0; i < len; i++) + data[(tail + i) % sizeof(data)] = src[i]; + tail += len; + } + + void drain() { + while (!empty()) { + uint32_t avail = tud_cdc_write_available(); + if (avail == 0) break; + uint16_t offset = head % sizeof(data); + uint16_t contig = sizeof(data) - offset; + uint16_t pending = used(); + uint16_t chunk = pending < contig ? pending : contig; + if (chunk > avail) chunk = avail; + tud_cdc_write(data + offset, chunk); + head += chunk; + } + tud_cdc_write_flush(); + if (head >= sizeof(data)) { + head -= sizeof(data); + tail -= sizeof(data); + } + } +}; + +static tx_buf usb_tx; + +static void send_bytes(const std::vector& data) { + usb_tx.push(data.data(), data.size()); + usb_tx.drain(); } static bool w6300_init() { @@ -49,14 +73,15 @@ static bool w6300_init() { int main() { tusb_init(); - if (!w6300_init()) { - } + w6300_init(); static static_vector rx_buf; while (true) { tud_task(); + usb_tx.drain(); + while (tud_cdc_available()) { uint8_t byte; if (tud_cdc_read(&byte, 1) != 1) break;