From 421cb5840e2fc755d923f30be206dd6bef9279da Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 5 Apr 2026 21:04:56 +0900 Subject: [PATCH] Split into main/net/tusb_config, extract ring_buffer and usb_cdc headers --- CMakeLists.txt | 5 +- include/net.h | 3 + include/ring_buffer.h | 44 ++++++++++++++ include/usb_cdc.h | 31 ++++++++++ main.cpp | 59 ++++++++++++++++++ net.cpp | 24 ++++++++ picomap.cpp | 120 ------------------------------------- usb.cpp => tusb_config.cpp | 0 8 files changed, 164 insertions(+), 122 deletions(-) create mode 100644 include/net.h create mode 100644 include/ring_buffer.h create mode 100644 include/usb_cdc.h create mode 100644 main.cpp create mode 100644 net.cpp delete mode 100644 picomap.cpp rename usb.cpp => tusb_config.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b72355d..aaf615f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,9 @@ set(CMAKE_CXX_STANDARD 23) pico_sdk_init() add_executable(picomap - picomap.cpp - usb.cpp + main.cpp + net.cpp + tusb_config.cpp w6300/w6300.cpp ) diff --git a/include/net.h b/include/net.h new file mode 100644 index 0000000..c688261 --- /dev/null +++ b/include/net.h @@ -0,0 +1,3 @@ +#pragma once + +bool net_init(); diff --git a/include/ring_buffer.h b/include/ring_buffer.h new file mode 100644 index 0000000..2b10957 --- /dev/null +++ b/include/ring_buffer.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include +#include + +template +struct ring_buffer { + std::array data = {}; + uint16_t head = 0; + uint16_t tail = 0; + + uint16_t used() const { return tail - head; } + uint16_t free() const { return N - used(); } + bool empty() const { return head == tail; } + + void push(std::span src) { + if (src.size() > free()) return; + for (auto b : src) + data[(tail++) % N] = b; + } + + uint16_t peek(std::span dst) const { + uint16_t len = dst.size() < used() ? dst.size() : used(); + for (uint16_t i = 0; i < len; i++) + dst[i] = data[(head + i) % N]; + return len; + } + + void consume(uint16_t len) { + head += len; + if (head >= N) { + head -= N; + tail -= N; + } + } + + std::span read_contiguous() const { + uint16_t offset = head % N; + uint16_t contig = N - offset; + uint16_t pending = used(); + uint16_t len = pending < contig ? pending : contig; + return {data.data() + offset, len}; + } +}; diff --git a/include/usb_cdc.h b/include/usb_cdc.h new file mode 100644 index 0000000..5f52cd4 --- /dev/null +++ b/include/usb_cdc.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include +#include "tusb.h" +#include "ring_buffer.h" + +struct usb_cdc { + ring_buffer<512> tx; + + void send(std::span data) { + tx.push(data); + drain(); + } + + void send(const std::vector& data) { + send(std::span{data}); + } + + void drain() { + while (!tx.empty()) { + uint32_t avail = tud_cdc_write_available(); + if (avail == 0) break; + auto chunk = tx.read_contiguous(); + if (chunk.size() > avail) chunk = chunk.first(avail); + tud_cdc_write(chunk.data(), chunk.size()); + tx.consume(chunk.size()); + } + tud_cdc_write_flush(); + } +}; diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..1f58e2c --- /dev/null +++ b/main.cpp @@ -0,0 +1,59 @@ +#include "pico/stdlib.h" +#include "pico/bootrom.h" +#include "pico/unique_id.h" +#include "tusb.h" +#include "wire.h" +#include "usb_cdc.h" +#include "net.h" +#include "w6300.h" + +static usb_cdc usb; + +int main() { + tusb_init(); + + net_init(); + + static static_vector rx_buf; + + while (true) { + tud_task(); + + usb.drain(); + + while (tud_cdc_available()) { + uint8_t byte; + if (tud_cdc_read(&byte, 1) != 1) break; + + rx_buf.push_back(byte); + + auto msg = try_decode(rx_buf); + if (!msg) { + if (rx_buf.full()) rx_buf.clear(); + continue; + } + + rx_buf.clear(); + + switch (msg->type_id) { + case RequestPICOBOOT::ext_id: + usb.send(encode_response(msg->message_id, ResponsePICOBOOT{})); + sleep_ms(100); + reset_usb_boot(0, 1); + break; + case RequestInfo::ext_id: { + ResponseInfo resp; + pico_unique_board_id_t uid; + pico_get_unique_board_id(&uid); + std::copy(uid.id, uid.id + 8, resp.board_id.begin()); + auto ninfo = w6300::get_net_info(); + resp.mac = ninfo.mac; + usb.send(encode_response(msg->message_id, resp)); + break; + } + } + } + + __wfi(); + } +} diff --git a/net.cpp b/net.cpp new file mode 100644 index 0000000..94415e0 --- /dev/null +++ b/net.cpp @@ -0,0 +1,24 @@ +#include "net.h" +#include "pico/unique_id.h" +#include "w6300.h" + +bool net_init() { + w6300::init_spi(); + w6300::init_critical_section(); + w6300::reset(); + w6300::init(); + if (!w6300::check()) return false; + + pico_unique_board_id_t uid; + pico_get_unique_board_id(&uid); + w6300::net_info info = {}; + info.mac[0] = (uid.id[0] & 0xFC) | 0x02; + info.mac[1] = uid.id[1]; + info.mac[2] = uid.id[2]; + info.mac[3] = uid.id[3]; + info.mac[4] = uid.id[4]; + info.mac[5] = uid.id[5]; + w6300::init_net(info); + + return true; +} diff --git a/picomap.cpp b/picomap.cpp deleted file mode 100644 index d32693a..0000000 --- a/picomap.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "pico/stdlib.h" -#include "pico/bootrom.h" -#include "pico/unique_id.h" -#include "tusb.h" -#include "wire.h" - -#include "w6300.h" - -struct tx_buf { - uint8_t data[512]; - uint16_t head = 0; - uint16_t tail = 0; - - 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() { - w6300::init_spi(); - w6300::init_critical_section(); - w6300::reset(); - w6300::init(); - if (!w6300::check()) return false; - - pico_unique_board_id_t uid; - pico_get_unique_board_id(&uid); - w6300::net_info info = {}; - info.mac[0] = (uid.id[0] & 0xFC) | 0x02; - info.mac[1] = uid.id[1]; - info.mac[2] = uid.id[2]; - info.mac[3] = uid.id[3]; - info.mac[4] = uid.id[4]; - info.mac[5] = uid.id[5]; - w6300::init_net(info); - - return true; -} - -int main() { - tusb_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; - - rx_buf.push_back(byte); - - auto msg = try_decode(rx_buf); - if (!msg) { - if (rx_buf.full()) rx_buf.clear(); - continue; - } - - rx_buf.clear(); - - switch (msg->type_id) { - case RequestPICOBOOT::ext_id: - send_bytes(encode_response(msg->message_id, ResponsePICOBOOT{})); - sleep_ms(100); - reset_usb_boot(0, 1); - break; - case RequestInfo::ext_id: { - ResponseInfo resp; - pico_unique_board_id_t uid; - pico_get_unique_board_id(&uid); - std::copy(uid.id, uid.id + 8, resp.board_id.begin()); - auto ninfo = w6300::get_net_info(); - resp.mac = ninfo.mac; - send_bytes(encode_response(msg->message_id, resp)); - break; - } - } - } - - __wfi(); - } -} diff --git a/usb.cpp b/tusb_config.cpp similarity index 100% rename from usb.cpp rename to tusb_config.cpp