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

+61
View File
@@ -0,0 +1,61 @@
#[doc = "Register `TAGHEADER0` reader"]
pub struct R(crate::R<TAGHEADER0_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<TAGHEADER0_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<TAGHEADER0_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<TAGHEADER0_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `MFGID` reader - Default Manufacturer ID: Nordic Semiconductor ASA has ICM 0x5F"]
pub type MFGID_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD1` reader - Unique identifier byte 1"]
pub type UD1_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD2` reader - Unique identifier byte 2"]
pub type UD2_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD3` reader - Unique identifier byte 3"]
pub type UD3_R = crate::FieldReader<u8, u8>;
impl R {
#[doc = "Bits 0:7 - Default Manufacturer ID: Nordic Semiconductor ASA has ICM 0x5F"]
#[inline(always)]
pub fn mfgid(&self) -> MFGID_R {
MFGID_R::new((self.bits & 0xff) as u8)
}
#[doc = "Bits 8:15 - Unique identifier byte 1"]
#[inline(always)]
pub fn ud1(&self) -> UD1_R {
UD1_R::new(((self.bits >> 8) & 0xff) as u8)
}
#[doc = "Bits 16:23 - Unique identifier byte 2"]
#[inline(always)]
pub fn ud2(&self) -> UD2_R {
UD2_R::new(((self.bits >> 16) & 0xff) as u8)
}
#[doc = "Bits 24:31 - Unique identifier byte 3"]
#[inline(always)]
pub fn ud3(&self) -> UD3_R {
UD3_R::new(((self.bits >> 24) & 0xff) as u8)
}
}
#[doc = "Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.\n\nThis register you can [`read`](crate::generic::Reg::read). See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [tagheader0](index.html) module"]
pub struct TAGHEADER0_SPEC;
impl crate::RegisterSpec for TAGHEADER0_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [tagheader0::R](R) reader structure"]
impl crate::Readable for TAGHEADER0_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets TAGHEADER0 to value 0xffff_ff5f"]
impl crate::Resettable for TAGHEADER0_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0xffff_ff5f
}
}
+61
View File
@@ -0,0 +1,61 @@
#[doc = "Register `TAGHEADER1` reader"]
pub struct R(crate::R<TAGHEADER1_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<TAGHEADER1_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<TAGHEADER1_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<TAGHEADER1_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `UD4` reader - Unique identifier byte 4"]
pub type UD4_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD5` reader - Unique identifier byte 5"]
pub type UD5_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD6` reader - Unique identifier byte 6"]
pub type UD6_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD7` reader - Unique identifier byte 7"]
pub type UD7_R = crate::FieldReader<u8, u8>;
impl R {
#[doc = "Bits 0:7 - Unique identifier byte 4"]
#[inline(always)]
pub fn ud4(&self) -> UD4_R {
UD4_R::new((self.bits & 0xff) as u8)
}
#[doc = "Bits 8:15 - Unique identifier byte 5"]
#[inline(always)]
pub fn ud5(&self) -> UD5_R {
UD5_R::new(((self.bits >> 8) & 0xff) as u8)
}
#[doc = "Bits 16:23 - Unique identifier byte 6"]
#[inline(always)]
pub fn ud6(&self) -> UD6_R {
UD6_R::new(((self.bits >> 16) & 0xff) as u8)
}
#[doc = "Bits 24:31 - Unique identifier byte 7"]
#[inline(always)]
pub fn ud7(&self) -> UD7_R {
UD7_R::new(((self.bits >> 24) & 0xff) as u8)
}
}
#[doc = "Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.\n\nThis register you can [`read`](crate::generic::Reg::read). See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [tagheader1](index.html) module"]
pub struct TAGHEADER1_SPEC;
impl crate::RegisterSpec for TAGHEADER1_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [tagheader1::R](R) reader structure"]
impl crate::Readable for TAGHEADER1_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets TAGHEADER1 to value 0xffff_ffff"]
impl crate::Resettable for TAGHEADER1_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0xffff_ffff
}
}
+61
View File
@@ -0,0 +1,61 @@
#[doc = "Register `TAGHEADER2` reader"]
pub struct R(crate::R<TAGHEADER2_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<TAGHEADER2_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<TAGHEADER2_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<TAGHEADER2_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `UD8` reader - Unique identifier byte 8"]
pub type UD8_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD9` reader - Unique identifier byte 9"]
pub type UD9_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD10` reader - Unique identifier byte 10"]
pub type UD10_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD11` reader - Unique identifier byte 11"]
pub type UD11_R = crate::FieldReader<u8, u8>;
impl R {
#[doc = "Bits 0:7 - Unique identifier byte 8"]
#[inline(always)]
pub fn ud8(&self) -> UD8_R {
UD8_R::new((self.bits & 0xff) as u8)
}
#[doc = "Bits 8:15 - Unique identifier byte 9"]
#[inline(always)]
pub fn ud9(&self) -> UD9_R {
UD9_R::new(((self.bits >> 8) & 0xff) as u8)
}
#[doc = "Bits 16:23 - Unique identifier byte 10"]
#[inline(always)]
pub fn ud10(&self) -> UD10_R {
UD10_R::new(((self.bits >> 16) & 0xff) as u8)
}
#[doc = "Bits 24:31 - Unique identifier byte 11"]
#[inline(always)]
pub fn ud11(&self) -> UD11_R {
UD11_R::new(((self.bits >> 24) & 0xff) as u8)
}
}
#[doc = "Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.\n\nThis register you can [`read`](crate::generic::Reg::read). See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [tagheader2](index.html) module"]
pub struct TAGHEADER2_SPEC;
impl crate::RegisterSpec for TAGHEADER2_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [tagheader2::R](R) reader structure"]
impl crate::Readable for TAGHEADER2_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets TAGHEADER2 to value 0xffff_ffff"]
impl crate::Resettable for TAGHEADER2_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0xffff_ffff
}
}
+61
View File
@@ -0,0 +1,61 @@
#[doc = "Register `TAGHEADER3` reader"]
pub struct R(crate::R<TAGHEADER3_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<TAGHEADER3_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<TAGHEADER3_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<TAGHEADER3_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `UD12` reader - Unique identifier byte 12"]
pub type UD12_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD13` reader - Unique identifier byte 13"]
pub type UD13_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD14` reader - Unique identifier byte 14"]
pub type UD14_R = crate::FieldReader<u8, u8>;
#[doc = "Field `UD15` reader - Unique identifier byte 15"]
pub type UD15_R = crate::FieldReader<u8, u8>;
impl R {
#[doc = "Bits 0:7 - Unique identifier byte 12"]
#[inline(always)]
pub fn ud12(&self) -> UD12_R {
UD12_R::new((self.bits & 0xff) as u8)
}
#[doc = "Bits 8:15 - Unique identifier byte 13"]
#[inline(always)]
pub fn ud13(&self) -> UD13_R {
UD13_R::new(((self.bits >> 8) & 0xff) as u8)
}
#[doc = "Bits 16:23 - Unique identifier byte 14"]
#[inline(always)]
pub fn ud14(&self) -> UD14_R {
UD14_R::new(((self.bits >> 16) & 0xff) as u8)
}
#[doc = "Bits 24:31 - Unique identifier byte 15"]
#[inline(always)]
pub fn ud15(&self) -> UD15_R {
UD15_R::new(((self.bits >> 24) & 0xff) as u8)
}
}
#[doc = "Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.\n\nThis register you can [`read`](crate::generic::Reg::read). See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [tagheader3](index.html) module"]
pub struct TAGHEADER3_SPEC;
impl crate::RegisterSpec for TAGHEADER3_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [tagheader3::R](R) reader structure"]
impl crate::Readable for TAGHEADER3_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets TAGHEADER3 to value 0xffff_ffff"]
impl crate::Resettable for TAGHEADER3_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0xffff_ffff
}
}