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:
17624 files changed
+4564928
-38
No files matched your search
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
use crate::Region;
|
||||
|
||||
/// Iterator producing block-region pairs, where each memory block maps to each
|
||||
/// region.
|
||||
pub struct OverlapIterator<'a, R, I>
|
||||
where
|
||||
R: Region,
|
||||
I: Iterator<Item = R>,
|
||||
{
|
||||
memory: &'a [u8],
|
||||
regions: I,
|
||||
base_address: u32,
|
||||
}
|
||||
|
||||
/// Trait allowing us to automatically add an `overlaps` function to all iterators over [`Region`]
|
||||
pub trait IterableByOverlaps<'a, R, I>
|
||||
where
|
||||
R: Region,
|
||||
I: Iterator<Item = R>,
|
||||
{
|
||||
/// Obtain an [`OverlapIterator`] over a subslice of `memory` that overlaps with the region in `self`
|
||||
fn overlaps(self, memory: &'a [u8], base_address: u32) -> OverlapIterator<R, I>;
|
||||
}
|
||||
|
||||
impl<'a, R, I> Iterator for OverlapIterator<'a, R, I>
|
||||
where
|
||||
R: Region,
|
||||
I: Iterator<Item = R>,
|
||||
{
|
||||
type Item = (&'a [u8], R, u32);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(region) = self.regions.next() {
|
||||
// TODO: This might be possible to do in a smarter way?
|
||||
let mut block_range = (0..self.memory.len())
|
||||
.skip_while(|index| !region.contains(self.base_address + *index as u32))
|
||||
.take_while(|index| region.contains(self.base_address + *index as u32));
|
||||
if let Some(start) = block_range.next() {
|
||||
let end = block_range.last().unwrap_or(start) + 1;
|
||||
return Some((
|
||||
&self.memory[start..end],
|
||||
region,
|
||||
self.base_address + start as u32,
|
||||
));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Blanket implementation for all types implementing [`Iterator`] over [`Regions`]
|
||||
impl<'a, R, I> IterableByOverlaps<'a, R, I> for I
|
||||
where
|
||||
R: Region,
|
||||
I: Iterator<Item = R>,
|
||||
{
|
||||
fn overlaps(self, memory: &'a [u8], base_address: u32) -> OverlapIterator<R, I> {
|
||||
OverlapIterator {
|
||||
memory,
|
||||
regions: self,
|
||||
base_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user