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

+92
View File
@@ -0,0 +1,92 @@
#[doc = "Register `FLASH` reader"]
pub struct R(crate::R<FLASH_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<FLASH_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<FLASH_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<FLASH_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `FLASH` reader - Flash variant"]
pub type FLASH_R = crate::FieldReader<u32, FLASH_A>;
#[doc = "Flash variant\n\nValue on reset: 512"]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum FLASH_A {
#[doc = "128: 128 kByte FLASH"]
K128 = 128,
#[doc = "256: 256 kByte FLASH"]
K256 = 256,
#[doc = "512: 512 kByte FLASH"]
K512 = 512,
#[doc = "4294967295: Unspecified"]
UNSPECIFIED = 4294967295,
}
impl From<FLASH_A> for u32 {
#[inline(always)]
fn from(variant: FLASH_A) -> Self {
variant as _
}
}
impl FLASH_R {
#[doc = "Get enumerated values variant"]
#[inline(always)]
pub fn variant(&self) -> Option<FLASH_A> {
match self.bits {
128 => Some(FLASH_A::K128),
256 => Some(FLASH_A::K256),
512 => Some(FLASH_A::K512),
4294967295 => Some(FLASH_A::UNSPECIFIED),
_ => None,
}
}
#[doc = "Checks if the value of the field is `K128`"]
#[inline(always)]
pub fn is_k128(&self) -> bool {
*self == FLASH_A::K128
}
#[doc = "Checks if the value of the field is `K256`"]
#[inline(always)]
pub fn is_k256(&self) -> bool {
*self == FLASH_A::K256
}
#[doc = "Checks if the value of the field is `K512`"]
#[inline(always)]
pub fn is_k512(&self) -> bool {
*self == FLASH_A::K512
}
#[doc = "Checks if the value of the field is `UNSPECIFIED`"]
#[inline(always)]
pub fn is_unspecified(&self) -> bool {
*self == FLASH_A::UNSPECIFIED
}
}
impl R {
#[doc = "Bits 0:31 - Flash variant"]
#[inline(always)]
pub fn flash(&self) -> FLASH_R {
FLASH_R::new(self.bits)
}
}
#[doc = "Flash variant\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 [flash](index.html) module"]
pub struct FLASH_SPEC;
impl crate::RegisterSpec for FLASH_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [flash::R](R) reader structure"]
impl crate::Readable for FLASH_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets FLASH to value 0x0200"]
impl crate::Resettable for FLASH_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0x0200
}
}
+100
View File
@@ -0,0 +1,100 @@
#[doc = "Register `PACKAGE` reader"]
pub struct R(crate::R<PACKAGE_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<PACKAGE_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<PACKAGE_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<PACKAGE_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `PACKAGE` reader - Package option"]
pub type PACKAGE_R = crate::FieldReader<u32, PACKAGE_A>;
#[doc = "Package option\n\nValue on reset: 8192"]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum PACKAGE_A {
#[doc = "8192: QFxx - 48-pin QFN"]
QF = 8192,
#[doc = "8193: CHxx - 7x8 WLCSP 56 balls"]
CH = 8193,
#[doc = "8194: CIxx - 7x8 WLCSP 56 balls"]
CI = 8194,
#[doc = "8197: CKxx - 7x8 WLCSP 56 balls with backside coating for light protection"]
CK = 8197,
#[doc = "4294967295: Unspecified"]
UNSPECIFIED = 4294967295,
}
impl From<PACKAGE_A> for u32 {
#[inline(always)]
fn from(variant: PACKAGE_A) -> Self {
variant as _
}
}
impl PACKAGE_R {
#[doc = "Get enumerated values variant"]
#[inline(always)]
pub fn variant(&self) -> Option<PACKAGE_A> {
match self.bits {
8192 => Some(PACKAGE_A::QF),
8193 => Some(PACKAGE_A::CH),
8194 => Some(PACKAGE_A::CI),
8197 => Some(PACKAGE_A::CK),
4294967295 => Some(PACKAGE_A::UNSPECIFIED),
_ => None,
}
}
#[doc = "Checks if the value of the field is `QF`"]
#[inline(always)]
pub fn is_qf(&self) -> bool {
*self == PACKAGE_A::QF
}
#[doc = "Checks if the value of the field is `CH`"]
#[inline(always)]
pub fn is_ch(&self) -> bool {
*self == PACKAGE_A::CH
}
#[doc = "Checks if the value of the field is `CI`"]
#[inline(always)]
pub fn is_ci(&self) -> bool {
*self == PACKAGE_A::CI
}
#[doc = "Checks if the value of the field is `CK`"]
#[inline(always)]
pub fn is_ck(&self) -> bool {
*self == PACKAGE_A::CK
}
#[doc = "Checks if the value of the field is `UNSPECIFIED`"]
#[inline(always)]
pub fn is_unspecified(&self) -> bool {
*self == PACKAGE_A::UNSPECIFIED
}
}
impl R {
#[doc = "Bits 0:31 - Package option"]
#[inline(always)]
pub fn package(&self) -> PACKAGE_R {
PACKAGE_R::new(self.bits)
}
}
#[doc = "Package option\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 [package](index.html) module"]
pub struct PACKAGE_SPEC;
impl crate::RegisterSpec for PACKAGE_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [package::R](R) reader structure"]
impl crate::Readable for PACKAGE_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets PACKAGE to value 0x2000"]
impl crate::Resettable for PACKAGE_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0x2000
}
}
+76
View File
@@ -0,0 +1,76 @@
#[doc = "Register `PART` reader"]
pub struct R(crate::R<PART_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<PART_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<PART_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<PART_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `PART` reader - Part code"]
pub type PART_R = crate::FieldReader<u32, PART_A>;
#[doc = "Part code\n\nValue on reset: 337970"]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum PART_A {
#[doc = "337970: nRF52832"]
N52832 = 337970,
#[doc = "4294967295: Unspecified"]
UNSPECIFIED = 4294967295,
}
impl From<PART_A> for u32 {
#[inline(always)]
fn from(variant: PART_A) -> Self {
variant as _
}
}
impl PART_R {
#[doc = "Get enumerated values variant"]
#[inline(always)]
pub fn variant(&self) -> Option<PART_A> {
match self.bits {
337970 => Some(PART_A::N52832),
4294967295 => Some(PART_A::UNSPECIFIED),
_ => None,
}
}
#[doc = "Checks if the value of the field is `N52832`"]
#[inline(always)]
pub fn is_n52832(&self) -> bool {
*self == PART_A::N52832
}
#[doc = "Checks if the value of the field is `UNSPECIFIED`"]
#[inline(always)]
pub fn is_unspecified(&self) -> bool {
*self == PART_A::UNSPECIFIED
}
}
impl R {
#[doc = "Bits 0:31 - Part code"]
#[inline(always)]
pub fn part(&self) -> PART_R {
PART_R::new(self.bits)
}
}
#[doc = "Part code\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 [part](index.html) module"]
pub struct PART_SPEC;
impl crate::RegisterSpec for PART_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [part::R](R) reader structure"]
impl crate::Readable for PART_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets PART to value 0x0005_2832"]
impl crate::Resettable for PART_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0x0005_2832
}
}
+92
View File
@@ -0,0 +1,92 @@
#[doc = "Register `RAM` reader"]
pub struct R(crate::R<RAM_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<RAM_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<RAM_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<RAM_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `RAM` reader - RAM variant"]
pub type RAM_R = crate::FieldReader<u32, RAM_A>;
#[doc = "RAM variant\n\nValue on reset: 64"]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum RAM_A {
#[doc = "16: 16 kByte RAM"]
K16 = 16,
#[doc = "32: 32 kByte RAM"]
K32 = 32,
#[doc = "64: 64 kByte RAM"]
K64 = 64,
#[doc = "4294967295: Unspecified"]
UNSPECIFIED = 4294967295,
}
impl From<RAM_A> for u32 {
#[inline(always)]
fn from(variant: RAM_A) -> Self {
variant as _
}
}
impl RAM_R {
#[doc = "Get enumerated values variant"]
#[inline(always)]
pub fn variant(&self) -> Option<RAM_A> {
match self.bits {
16 => Some(RAM_A::K16),
32 => Some(RAM_A::K32),
64 => Some(RAM_A::K64),
4294967295 => Some(RAM_A::UNSPECIFIED),
_ => None,
}
}
#[doc = "Checks if the value of the field is `K16`"]
#[inline(always)]
pub fn is_k16(&self) -> bool {
*self == RAM_A::K16
}
#[doc = "Checks if the value of the field is `K32`"]
#[inline(always)]
pub fn is_k32(&self) -> bool {
*self == RAM_A::K32
}
#[doc = "Checks if the value of the field is `K64`"]
#[inline(always)]
pub fn is_k64(&self) -> bool {
*self == RAM_A::K64
}
#[doc = "Checks if the value of the field is `UNSPECIFIED`"]
#[inline(always)]
pub fn is_unspecified(&self) -> bool {
*self == RAM_A::UNSPECIFIED
}
}
impl R {
#[doc = "Bits 0:31 - RAM variant"]
#[inline(always)]
pub fn ram(&self) -> RAM_R {
RAM_R::new(self.bits)
}
}
#[doc = "RAM variant\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 [ram](index.html) module"]
pub struct RAM_SPEC;
impl crate::RegisterSpec for RAM_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [ram::R](R) reader structure"]
impl crate::Readable for RAM_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets RAM to value 0x40"]
impl crate::Resettable for RAM_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0x40
}
}
+65
View File
@@ -0,0 +1,65 @@
#[doc = "Register `UNUSED0[%s]` reader"]
pub struct R(crate::R<UNUSED0_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<UNUSED0_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<UNUSED0_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<UNUSED0_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Register `UNUSED0[%s]` writer"]
pub struct W(crate::W<UNUSED0_SPEC>);
impl core::ops::Deref for W {
type Target = crate::W<UNUSED0_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl core::ops::DerefMut for W {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl From<crate::W<UNUSED0_SPEC>> for W {
#[inline(always)]
fn from(writer: crate::W<UNUSED0_SPEC>) -> Self {
W(writer)
}
}
impl W {
#[doc = "Writes raw bits to the register."]
#[inline(always)]
pub unsafe fn bits(&mut self, bits: u32) -> &mut Self {
self.0.bits(bits);
self
}
}
#[doc = "Description collection\\[0\\]: Unspecified\n\nThis register you can [`read`](crate::generic::Reg::read), [`write_with_zero`](crate::generic::Reg::write_with_zero), [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`modify`](crate::generic::Reg::modify). See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [unused0](index.html) module"]
pub struct UNUSED0_SPEC;
impl crate::RegisterSpec for UNUSED0_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [unused0::R](R) reader structure"]
impl crate::Readable for UNUSED0_SPEC {
type Reader = R;
}
#[doc = "`write(|w| ..)` method takes [unused0::W](W) writer structure"]
impl crate::Writable for UNUSED0_SPEC {
type Writer = W;
}
#[doc = "`reset()` method sets UNUSED0[%s]
to value 0"]
impl crate::Resettable for UNUSED0_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0
}
}
+116
View File
@@ -0,0 +1,116 @@
#[doc = "Register `VARIANT` reader"]
pub struct R(crate::R<VARIANT_SPEC>);
impl core::ops::Deref for R {
type Target = crate::R<VARIANT_SPEC>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<crate::R<VARIANT_SPEC>> for R {
#[inline(always)]
fn from(reader: crate::R<VARIANT_SPEC>) -> Self {
R(reader)
}
}
#[doc = "Field `VARIANT` reader - Part Variant, Hardware version and Production configuration, encoded as ASCII"]
pub type VARIANT_R = crate::FieldReader<u32, VARIANT_A>;
#[doc = "Part Variant, Hardware version and Production configuration, encoded as ASCII\n\nValue on reset: 1094795586"]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum VARIANT_A {
#[doc = "1094795585: AAAA"]
AAAA = 1094795585,
#[doc = "1094795586: AAAB"]
AAAB = 1094795586,
#[doc = "1094795841: AABA"]
AABA = 1094795841,
#[doc = "1094795842: AABB"]
AABB = 1094795842,
#[doc = "1094795824: AAB0"]
AAB0 = 1094795824,
#[doc = "1094796592: AAE0"]
AAE0 = 1094796592,
#[doc = "4294967295: Unspecified"]
UNSPECIFIED = 4294967295,
}
impl From<VARIANT_A> for u32 {
#[inline(always)]
fn from(variant: VARIANT_A) -> Self {
variant as _
}
}
impl VARIANT_R {
#[doc = "Get enumerated values variant"]
#[inline(always)]
pub fn variant(&self) -> Option<VARIANT_A> {
match self.bits {
1094795585 => Some(VARIANT_A::AAAA),
1094795586 => Some(VARIANT_A::AAAB),
1094795841 => Some(VARIANT_A::AABA),
1094795842 => Some(VARIANT_A::AABB),
1094795824 => Some(VARIANT_A::AAB0),
1094796592 => Some(VARIANT_A::AAE0),
4294967295 => Some(VARIANT_A::UNSPECIFIED),
_ => None,
}
}
#[doc = "Checks if the value of the field is `AAAA`"]
#[inline(always)]
pub fn is_aaaa(&self) -> bool {
*self == VARIANT_A::AAAA
}
#[doc = "Checks if the value of the field is `AAAB`"]
#[inline(always)]
pub fn is_aaab(&self) -> bool {
*self == VARIANT_A::AAAB
}
#[doc = "Checks if the value of the field is `AABA`"]
#[inline(always)]
pub fn is_aaba(&self) -> bool {
*self == VARIANT_A::AABA
}
#[doc = "Checks if the value of the field is `AABB`"]
#[inline(always)]
pub fn is_aabb(&self) -> bool {
*self == VARIANT_A::AABB
}
#[doc = "Checks if the value of the field is `AAB0`"]
#[inline(always)]
pub fn is_aab0(&self) -> bool {
*self == VARIANT_A::AAB0
}
#[doc = "Checks if the value of the field is `AAE0`"]
#[inline(always)]
pub fn is_aae0(&self) -> bool {
*self == VARIANT_A::AAE0
}
#[doc = "Checks if the value of the field is `UNSPECIFIED`"]
#[inline(always)]
pub fn is_unspecified(&self) -> bool {
*self == VARIANT_A::UNSPECIFIED
}
}
impl R {
#[doc = "Bits 0:31 - Part Variant, Hardware version and Production configuration, encoded as ASCII"]
#[inline(always)]
pub fn variant(&self) -> VARIANT_R {
VARIANT_R::new(self.bits)
}
}
#[doc = "Part Variant, Hardware version and Production configuration\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 [variant](index.html) module"]
pub struct VARIANT_SPEC;
impl crate::RegisterSpec for VARIANT_SPEC {
type Ux = u32;
}
#[doc = "`read()` method returns [variant::R](R) reader structure"]
impl crate::Readable for VARIANT_SPEC {
type Reader = R;
}
#[doc = "`reset()` method sets VARIANT to value 0x4141_4142"]
impl crate::Resettable for VARIANT_SPEC {
#[inline(always)]
fn reset_value() -> Self::Ux {
0x4141_4142
}
}