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

+1
View File
@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"c9790623db19b1e9e9cbdd8109c0194d5d092e622b786b1936716c39c661d1f8","Cargo.toml":"91f70a1e787f22685f48fb2303a1b98cdc8f7c67fddf152d23ebe3a2ea4be958","Cargo.toml.orig":"4761497eb82802da966f42a90e6d67f9cea08980647815d6c5f70910538a8448","src/lib.rs":"2baa70dc5b9239259256f59f1da614519707f3510acd5577bc64941cf0fc4f2f"},"package":"0eee54712c5d778d2fb2da43b1ce5a7b5060886ef7b09891baeb4bf36910a3ed"}
+6
View File
@@ -0,0 +1,6 @@
{
"git": {
"sha1": "e7e7f4bff575d30ea7c73e2e65c93a91a7d3c7f9"
},
"path_in_vcs": "descriptors"
}
+29
View File
@@ -0,0 +1,29 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
name = "usbd-hid-descriptors"
version = "0.8.2"
authors = ["twitchyliquid64"]
description = "Low-level, wire-format enums/bitfields used in HID descriptors"
keywords = [
"no-std",
"hid",
]
categories = [
"embedded",
"no-std",
]
license = "MIT OR Apache-2.0"
[dependencies.bitfield]
version = "~0.14"
+125
View File
@@ -0,0 +1,125 @@
#![no_std]
use bitfield::bitfield;
/// GlobalItemKind describes global item tags as described in section 6.2.2.7
/// 'Report Descriptor' of the spec, version 1.11.
#[repr(u8)]
#[allow(unused)]
#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub enum GlobalItemKind {
UsagePage = 0,
LogicalMin = 1,
LogicalMax = 2,
PhysicalMin = 3,
PhysicalMax = 4,
UnitExponent = 5,
Unit = 6,
ReportSize = 7,
ReportID = 8,
ReportCount = 9,
}
impl From<GlobalItemKind> for u8 {
fn from(kind: GlobalItemKind) -> u8 {
kind as u8
}
}
/// LocalItemKind describes local item tags as described in section 6.2.2.8
/// 'Local Items' of the spec, version 1.11.
#[repr(u8)]
#[allow(unused)]
#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub enum LocalItemKind {
Usage = 0,
UsageMin = 1,
UsageMax = 2,
DesignatorIdx = 3,
DesignatorMin = 4,
DesignatorMax = 5,
StringIdx = 7,
StringMin = 8,
StringMax = 9,
Delimiter = 10,
}
impl From<LocalItemKind> for u8 {
fn from(kind: LocalItemKind) -> u8 {
kind as u8
}
}
/// MainItemKind describes main item tags as described in section 6.2.2.4
/// 'Report Descriptor' of the spec, version 1.11.
#[repr(u8)]
#[allow(unused)]
#[derive(Copy, Debug, Default, Clone, Eq, PartialEq)]
pub enum MainItemKind {
#[default]
Input = 0b1000,
Output = 0b1001,
Feature = 0b1011,
Collection = 0b1010,
EndCollection = 0b1100,
}
impl From<MainItemKind> for u8 {
fn from(kind: MainItemKind) -> u8 {
kind as u8
}
}
impl From<&str> for MainItemKind {
fn from(s: &str) -> Self {
match s {
"feature" => MainItemKind::Feature,
"output" => MainItemKind::Output,
"collection" => MainItemKind::Collection,
"ecollection" => MainItemKind::EndCollection,
"input" => MainItemKind::Input,
_ => MainItemKind::Input,
}
}
}
/// ItemType describes types of items as described in section 6.2.2.7
/// 'Report Descriptor' of the spec, version 1.11.
#[repr(u8)]
#[allow(unused)]
#[derive(Copy, Debug, Default, Clone, Eq, PartialEq)]
pub enum ItemType {
#[default]
Main = 0,
Global = 1,
Local = 2,
}
impl From<ItemType> for u8 {
fn from(kind: ItemType) -> u8 {
kind as u8
}
}
bitfield! {
/// MainItemSetting describes the bits which configure invariants on a MainItem.
#[derive(Clone,Debug)]
pub struct MainItemSetting(u8);
pub is_constant, set_constant: 0;
pub is_variable, set_variable: 1;
pub is_relative, set_relative: 2;
pub is_wrap, set_wrap: 3;
pub is_non_linear, set_non_linear: 4;
pub has_no_preferred_state, set_no_preferred_state: 5;
pub has_null_state, set_has_null_state: 6;
pub volatile, set_volatile: 7;
}
bitfield! {
/// ItemPrefix describes the 1 byte prefix describing an item in a descriptor.
pub struct ItemPrefix(u8);
impl Debug;
pub byte_count, set_byte_count: 1, 0;
pub typ, set_type: 3, 2;
pub tag, set_tag: 7, 4;
}