#include "dispatch.h" #include #include "pico/stdlib.h" #include "tusb.h" #include "wire.h" #include "usb_cdc.h" #include "timer_queue.h" #include "net.h" #include "debug_log.h" #include "hardware/sync.h" static timer_queue timers; void dispatch_init() { tusb_init(); net_init(); dlog("dispatch_init complete"); } void dispatch_schedule_ms(uint32_t ms, std::function fn) { timers.schedule_ms(ms, std::move(fn)); } [[noreturn]] void dispatch_run(std::span handlers) { std::unordered_map> (*)(uint32_t, std::span)> handler_map; for (auto& entry : handlers) { handler_map[entry.type_id] = entry.handle; } static usb_cdc usb; static static_vector usb_rx_buf; net_set_handler([&](std::span payload) -> std::vector> { auto msg = try_decode(payload.data(), payload.size()); if (!msg) return {}; auto it = handler_map.find(msg->type_id); if (it == handler_map.end()) return {}; return it->second(msg->message_id, msg->payload); }); while (true) { uint32_t save = save_and_disable_interrupts(); dlog_if_slow("tud_task", 1000, [&]{ tud_task(); }); dlog_if_slow("drain", 1000, [&]{ usb.drain(); }); dlog_if_slow("timers", 1000, [&]{ timers.run(); }); dlog_if_slow("net_poll", 1000, [&]{ net_poll(); }); while (tud_cdc_available()) { uint8_t byte; if (tud_cdc_read(&byte, 1) != 1) break; usb_rx_buf.push_back(byte); auto msg = try_decode(usb_rx_buf); if (!msg) { if (usb_rx_buf.full()) usb_rx_buf.clear(); continue; } usb_rx_buf.clear(); auto it = handler_map.find(msg->type_id); if (it != handler_map.end()) { for (auto& response : it->second(msg->message_id, msg->payload)) { if (response.size() > usb.tx.free()) { auto err = encode_response(msg->message_id, DeviceError{2, "response too large: " + std::to_string(response.size())}); usb.send(err); } else { usb.send(response); } } } } __wfi(); restore_interrupts(save); } }