feat: add display UI with splash screen, dashboard, and RSSI sparkline

Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
swaitsandClaude Opus 4.6 committed 2026-03-29 20:42:54 -06:00
1 parent 7064110293
commit 3102fc747a
17624 files changed
+4564928 -38

No files matched your search

+6 -3
View File
@@ -10,7 +10,7 @@ mod usb;
use embassy_executor::Spawner;
use crate::channel::{CommandChannel, ResponseChannel, StatusWatch};
use crate::channel::{CommandChannel, DisplayCommandChannel, ResponseChannel, StatusWatch};
cfg_if::cfg_if! {
if #[cfg(feature = "rak_4631")] {
@@ -23,16 +23,19 @@ cfg_if::cfg_if! {
static COMMANDS: CommandChannel = CommandChannel::new();
static RESPONSES: ResponseChannel = ResponseChannel::new();
static STATUS: StatusWatch = StatusWatch::new();
static DISPLAY_COMMANDS: DisplayCommandChannel = DisplayCommandChannel::new();
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let board = board::Board::init();
let (radio, usb, display) = board.into_parts();
let has_display = display.is_some();
spawner.spawn(radio::radio_task(radio, &COMMANDS, &RESPONSES, &STATUS)).unwrap();
spawner.spawn(usb::usb_task(usb, &COMMANDS, &RESPONSES)).unwrap();
spawner.spawn(usb::usb_task(usb, &COMMANDS, &RESPONSES, &DISPLAY_COMMANDS, has_display)).unwrap();
if let Some(dp) = display {
spawner.spawn(display::display_task(dp, &STATUS)).unwrap();
spawner.spawn(display::display_task(dp, &STATUS, &DISPLAY_COMMANDS)).unwrap();
}
}