refactor: complete hsmc conversion and add debug-checkpoint feature
Finishes the hsmc migration that was staged across the prior two commits: - Radio task is now a single `machine.run().await`; all I/O lives in state-scoped `during:` activities (`next_command`, `next_packet`, `perform_tx`). The old `push/drain` helpers, the imperative top-level `select`, `handle_cmd`, `handle_rx_result`, and `execute_transmit` are gone. `StartingRx` / `ResumingRx` intermediate states model the host-visible difference between a responding and a silent RX re-arm. - Host/USB task is now an hsmc statechart (Disconnected/Connected) with entry/exit actions handling display wake, radio StopRx, and display reset — replacing the open-coded `was_connected` edge detector. The `protocol_loop` keeps its imperative read path because `read_packet` blocks. - New `debug-checkpoint` cargo feature ships a dedicated `debug_blink.rs` task and a shared atomic counter that code along the boot/dispatch/TX path bumps at notable points. A ladder-latching write policy preserves the deepest TX phase reached on the first attempt until reboot — diagnostic output for UART-only boards where defmt would corrupt the host protocol. Zero footprint when the feature is off. - Silence a stray `clippy::unit_arg` on `led_off` / `led_blip` in the display task for boards with `LedDriver = ()`.
This commit is contained in:
7 files changed
+902
-438
No files matched your search
+63
-75
@@ -37,9 +37,7 @@ use embassy_time::Timer;
|
||||
use hsmc::statechart;
|
||||
|
||||
use crate::board::{self, Board, DisplayDriver, DisplayParts, LedDriver, LoRaBoard, RgbLed};
|
||||
use crate::channel::{
|
||||
DisplayCommand, DisplayCommandChannel, RadioEvent, RadioEventChannel,
|
||||
};
|
||||
use crate::channel::{DisplayCommand, DisplayCommandChannel, RadioEvent, RadioEventChannel};
|
||||
use crate::protocol::RadioConfig;
|
||||
|
||||
use render::{BoardInfo, RSSI_HISTORY_LEN};
|
||||
@@ -71,7 +69,10 @@ pub enum DisplayEvent {
|
||||
/// Radio returned to Idle.
|
||||
RadioIdle,
|
||||
/// A packet was received (data only — does not imply a mode change).
|
||||
PacketRx { rssi: i16, snr: Option<i16> },
|
||||
PacketRx {
|
||||
rssi: i16,
|
||||
snr: Option<i16>,
|
||||
},
|
||||
/// A packet was transmitted (data only — does not imply a mode change).
|
||||
PacketTx,
|
||||
ConfigChanged(RadioConfig),
|
||||
@@ -154,8 +155,14 @@ pub struct DisplayContext {
|
||||
|
||||
impl DisplayContext {
|
||||
async fn flush_info(&mut self) {
|
||||
let Peripherals { display, mac_str, .. } = &mut self.peripherals;
|
||||
let info = BoardInfo { name: BOARD_NAME, version: VERSION, mac: mac_str };
|
||||
let Peripherals {
|
||||
display, mac_str, ..
|
||||
} = &mut self.peripherals;
|
||||
let info = BoardInfo {
|
||||
name: BOARD_NAME,
|
||||
version: VERSION,
|
||||
mac: mac_str,
|
||||
};
|
||||
render::info(display, &info);
|
||||
let _ = display.flush().await;
|
||||
}
|
||||
@@ -167,8 +174,14 @@ impl DisplayContext {
|
||||
}
|
||||
|
||||
async fn flush_dashboard(&mut self, badge: Badge) {
|
||||
let Peripherals { display, mac_str, .. } = &mut self.peripherals;
|
||||
let info = BoardInfo { name: BOARD_NAME, version: VERSION, mac: mac_str };
|
||||
let Peripherals {
|
||||
display, mac_str, ..
|
||||
} = &mut self.peripherals;
|
||||
let info = BoardInfo {
|
||||
name: BOARD_NAME,
|
||||
version: VERSION,
|
||||
mac: mac_str,
|
||||
};
|
||||
render::dashboard(
|
||||
display,
|
||||
badge,
|
||||
@@ -192,10 +205,16 @@ impl DisplayContext {
|
||||
let _ = self.peripherals.display.flush().await;
|
||||
}
|
||||
|
||||
// Boards without an LED use `LedDriver = ()`; the `RgbLed for ()` impl
|
||||
// makes `set_rgb` a noop returning `()`. Clippy's unit_arg lint
|
||||
// misreads method calls on unit values as "passing a unit value to a
|
||||
// function" — silence it here where the noop is intentional.
|
||||
#[allow(clippy::unit_arg)]
|
||||
async fn led_off(&mut self) {
|
||||
self.peripherals.led.set_rgb(0, 0, 0).await;
|
||||
}
|
||||
|
||||
#[allow(clippy::unit_arg)]
|
||||
async fn led_blip(&mut self, r: u8, g: u8, b: u8) {
|
||||
self.peripherals.led.set_rgb(r, g, b).await;
|
||||
Timer::after_millis(50).await;
|
||||
@@ -439,70 +458,41 @@ mod render {
|
||||
/// traditional dark-on-light look including a proper quiet zone.
|
||||
const QR_WIDTH_PX: u32 = 64;
|
||||
const QR_BITMAP: [u8; 512] = [
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x00, 0x07, 0x9F, 0xFE, 0x60, 0x00, 0x7F,
|
||||
0xFE, 0x00, 0x07, 0x9F, 0xFE, 0x60, 0x00, 0x7F,
|
||||
0xFE, 0x7F, 0xE6, 0x18, 0x19, 0xE7, 0xFE, 0x7F,
|
||||
0xFE, 0x7F, 0xE6, 0x18, 0x19, 0xE7, 0xFE, 0x7F,
|
||||
0xFE, 0x60, 0x67, 0x81, 0xE6, 0x66, 0x06, 0x7F,
|
||||
0xFE, 0x60, 0x67, 0x81, 0xE6, 0x66, 0x06, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x19, 0x87, 0xE6, 0x06, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x19, 0x87, 0xE6, 0x06, 0x7F,
|
||||
0xFE, 0x60, 0x67, 0xE6, 0x1F, 0xE6, 0x06, 0x7F,
|
||||
0xFE, 0x60, 0x67, 0xE6, 0x1F, 0xE6, 0x06, 0x7F,
|
||||
0xFE, 0x7F, 0xE6, 0x67, 0x80, 0x67, 0xFE, 0x7F,
|
||||
0xFE, 0x7F, 0xE6, 0x67, 0x80, 0x67, 0xFE, 0x7F,
|
||||
0xFE, 0x00, 0x06, 0x66, 0x66, 0x60, 0x00, 0x7F,
|
||||
0xFE, 0x00, 0x06, 0x66, 0x66, 0x60, 0x00, 0x7F,
|
||||
0xFF, 0xFF, 0xFF, 0xFE, 0x61, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFE, 0x61, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x00, 0x60, 0x06, 0x01, 0x99, 0x99, 0xFF,
|
||||
0xFE, 0x00, 0x60, 0x06, 0x01, 0x99, 0x99, 0xFF,
|
||||
0xFE, 0x01, 0x98, 0x1F, 0x9E, 0x79, 0xF9, 0xFF,
|
||||
0xFE, 0x01, 0x98, 0x1F, 0x9E, 0x79, 0xF9, 0xFF,
|
||||
0xFF, 0xE0, 0x66, 0x18, 0x61, 0x9F, 0x98, 0x7F,
|
||||
0xFF, 0xE0, 0x66, 0x18, 0x61, 0x9F, 0x98, 0x7F,
|
||||
0xFF, 0x98, 0x1E, 0x01, 0xE7, 0x99, 0xFE, 0x7F,
|
||||
0xFF, 0x98, 0x1E, 0x01, 0xE7, 0x99, 0xFE, 0x7F,
|
||||
0xFF, 0xE1, 0xE6, 0x19, 0xF8, 0x06, 0x60, 0x7F,
|
||||
0xFF, 0xE1, 0xE6, 0x19, 0xF8, 0x06, 0x60, 0x7F,
|
||||
0xFE, 0x19, 0xF8, 0x06, 0x1E, 0x79, 0x99, 0xFF,
|
||||
0xFE, 0x19, 0xF8, 0x06, 0x1E, 0x79, 0x99, 0xFF,
|
||||
0xFE, 0x7E, 0x01, 0xFF, 0x80, 0x18, 0x18, 0x7F,
|
||||
0xFE, 0x7E, 0x01, 0xFF, 0x80, 0x18, 0x18, 0x7F,
|
||||
0xFE, 0x7E, 0x19, 0x9E, 0x1E, 0x78, 0x7E, 0x7F,
|
||||
0xFE, 0x7E, 0x19, 0x9E, 0x1E, 0x78, 0x7E, 0x7F,
|
||||
0xFE, 0x60, 0x06, 0x66, 0x66, 0x00, 0x67, 0xFF,
|
||||
0xFE, 0x60, 0x06, 0x66, 0x66, 0x00, 0x67, 0xFF,
|
||||
0xFF, 0xFF, 0xFE, 0x67, 0xF8, 0x7E, 0x1F, 0xFF,
|
||||
0xFF, 0xFF, 0xFE, 0x67, 0xF8, 0x7E, 0x1F, 0xFF,
|
||||
0xFE, 0x00, 0x06, 0x00, 0x7E, 0x66, 0x60, 0x7F,
|
||||
0xFE, 0x00, 0x06, 0x00, 0x7E, 0x66, 0x60, 0x7F,
|
||||
0xFE, 0x7F, 0xE7, 0x99, 0xE6, 0x7E, 0x1E, 0x7F,
|
||||
0xFE, 0x7F, 0xE7, 0x99, 0xE6, 0x7E, 0x1E, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x61, 0xF8, 0x00, 0x60, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x61, 0xF8, 0x00, 0x60, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x06, 0x01, 0x86, 0x00, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x06, 0x01, 0x86, 0x00, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x67, 0x86, 0x7F, 0x86, 0x7F,
|
||||
0xFE, 0x60, 0x66, 0x67, 0x86, 0x7F, 0x86, 0x7F,
|
||||
0xFE, 0x7F, 0xE6, 0x66, 0x18, 0x00, 0x1E, 0x7F,
|
||||
0xFE, 0x7F, 0xE6, 0x66, 0x18, 0x00, 0x1E, 0x7F,
|
||||
0xFE, 0x00, 0x06, 0x66, 0x67, 0x98, 0x00, 0x7F,
|
||||
0xFE, 0x00, 0x06, 0x66, 0x67, 0x98, 0x00, 0x7F,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0x9F,
|
||||
0xFE, 0x60, 0x00, 0x7F, 0xFE, 0x00, 0x07, 0x9F, 0xFE, 0x60, 0x00, 0x7F, 0xFE, 0x7F, 0xE6,
|
||||
0x18, 0x19, 0xE7, 0xFE, 0x7F, 0xFE, 0x7F, 0xE6, 0x18, 0x19, 0xE7, 0xFE, 0x7F, 0xFE, 0x60,
|
||||
0x67, 0x81, 0xE6, 0x66, 0x06, 0x7F, 0xFE, 0x60, 0x67, 0x81, 0xE6, 0x66, 0x06, 0x7F, 0xFE,
|
||||
0x60, 0x66, 0x19, 0x87, 0xE6, 0x06, 0x7F, 0xFE, 0x60, 0x66, 0x19, 0x87, 0xE6, 0x06, 0x7F,
|
||||
0xFE, 0x60, 0x67, 0xE6, 0x1F, 0xE6, 0x06, 0x7F, 0xFE, 0x60, 0x67, 0xE6, 0x1F, 0xE6, 0x06,
|
||||
0x7F, 0xFE, 0x7F, 0xE6, 0x67, 0x80, 0x67, 0xFE, 0x7F, 0xFE, 0x7F, 0xE6, 0x67, 0x80, 0x67,
|
||||
0xFE, 0x7F, 0xFE, 0x00, 0x06, 0x66, 0x66, 0x60, 0x00, 0x7F, 0xFE, 0x00, 0x06, 0x66, 0x66,
|
||||
0x60, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x61, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
||||
0x61, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x60, 0x06, 0x01, 0x99, 0x99, 0xFF, 0xFE, 0x00, 0x60,
|
||||
0x06, 0x01, 0x99, 0x99, 0xFF, 0xFE, 0x01, 0x98, 0x1F, 0x9E, 0x79, 0xF9, 0xFF, 0xFE, 0x01,
|
||||
0x98, 0x1F, 0x9E, 0x79, 0xF9, 0xFF, 0xFF, 0xE0, 0x66, 0x18, 0x61, 0x9F, 0x98, 0x7F, 0xFF,
|
||||
0xE0, 0x66, 0x18, 0x61, 0x9F, 0x98, 0x7F, 0xFF, 0x98, 0x1E, 0x01, 0xE7, 0x99, 0xFE, 0x7F,
|
||||
0xFF, 0x98, 0x1E, 0x01, 0xE7, 0x99, 0xFE, 0x7F, 0xFF, 0xE1, 0xE6, 0x19, 0xF8, 0x06, 0x60,
|
||||
0x7F, 0xFF, 0xE1, 0xE6, 0x19, 0xF8, 0x06, 0x60, 0x7F, 0xFE, 0x19, 0xF8, 0x06, 0x1E, 0x79,
|
||||
0x99, 0xFF, 0xFE, 0x19, 0xF8, 0x06, 0x1E, 0x79, 0x99, 0xFF, 0xFE, 0x7E, 0x01, 0xFF, 0x80,
|
||||
0x18, 0x18, 0x7F, 0xFE, 0x7E, 0x01, 0xFF, 0x80, 0x18, 0x18, 0x7F, 0xFE, 0x7E, 0x19, 0x9E,
|
||||
0x1E, 0x78, 0x7E, 0x7F, 0xFE, 0x7E, 0x19, 0x9E, 0x1E, 0x78, 0x7E, 0x7F, 0xFE, 0x60, 0x06,
|
||||
0x66, 0x66, 0x00, 0x67, 0xFF, 0xFE, 0x60, 0x06, 0x66, 0x66, 0x00, 0x67, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x67, 0xF8, 0x7E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, 0x67, 0xF8, 0x7E, 0x1F, 0xFF, 0xFE,
|
||||
0x00, 0x06, 0x00, 0x7E, 0x66, 0x60, 0x7F, 0xFE, 0x00, 0x06, 0x00, 0x7E, 0x66, 0x60, 0x7F,
|
||||
0xFE, 0x7F, 0xE7, 0x99, 0xE6, 0x7E, 0x1E, 0x7F, 0xFE, 0x7F, 0xE7, 0x99, 0xE6, 0x7E, 0x1E,
|
||||
0x7F, 0xFE, 0x60, 0x66, 0x61, 0xF8, 0x00, 0x60, 0x7F, 0xFE, 0x60, 0x66, 0x61, 0xF8, 0x00,
|
||||
0x60, 0x7F, 0xFE, 0x60, 0x66, 0x06, 0x01, 0x86, 0x00, 0x7F, 0xFE, 0x60, 0x66, 0x06, 0x01,
|
||||
0x86, 0x00, 0x7F, 0xFE, 0x60, 0x66, 0x67, 0x86, 0x7F, 0x86, 0x7F, 0xFE, 0x60, 0x66, 0x67,
|
||||
0x86, 0x7F, 0x86, 0x7F, 0xFE, 0x7F, 0xE6, 0x66, 0x18, 0x00, 0x1E, 0x7F, 0xFE, 0x7F, 0xE6,
|
||||
0x66, 0x18, 0x00, 0x1E, 0x7F, 0xFE, 0x00, 0x06, 0x66, 0x67, 0x98, 0x00, 0x7F, 0xFE, 0x00,
|
||||
0x06, 0x66, 0x67, 0x98, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF,
|
||||
];
|
||||
|
||||
pub struct BoardInfo<'a> {
|
||||
@@ -751,9 +741,7 @@ mod render {
|
||||
// ── QR code: flush to the right edge, 1:1 pixel rendering ───
|
||||
let qr_x = w - QR_WIDTH_PX as i32;
|
||||
let qr_raw: ImageRaw<BinaryColor> = ImageRaw::new(&QR_BITMAP, QR_WIDTH_PX);
|
||||
Image::new(&qr_raw, Point::new(qr_x, 0))
|
||||
.draw(target)
|
||||
.ok();
|
||||
Image::new(&qr_raw, Point::new(qr_x, 0)).draw(target).ok();
|
||||
|
||||
// ── Text column (everything left of the QR) ─────────────────
|
||||
let col_w = qr_x;
|
||||
|
||||
Reference in new issue
Block a user