feat(display): OLED dims a few seconds after last activity

Splash holds bright for 10 s on (re-)entry, then drops to dim while
LearnMore/Info keep alternating. The dashboard stays bright for 3 s
after the last packet or mode change, then dims in place without
disturbing the Listening/Transmitting state or the 1 s sparkline
timer. Cross-leaf TX↔RX hops stay bright throughout — `set_dim` is
fired by the 3 s timer handler as an action rather than as a sibling
`exit:` action, so mode-change leaf-crossings no longer flash
dim→bright on every swap.

Two driver families (`ssd1306::Ssd1306Async` and the in-tree
`Sh1106`) wrapped behind a single `DisplayBrightness` trait in
`src/driver/mod.rs`; the board trait's `DisplayDriver` associated
type now requires it. Dim/bright contrast values centralized as
`CONTRAST_BRIGHT` / `CONTRAST_DIM` constants — tune in one place.

`On.on(CmdReset)` now targets `LearnMore` directly rather than the
ancestor `Splash`. Under hsmc 0.2 up-transition semantics, targeting
an already-active ancestor unwinds only below it without re-descent;
the USB-disconnect reset path was previously relying on the old
re-enter-and-descend behavior and would have parked at `Splash`
with a dead alternation timer.

Bumps `hsmc` 0.1.0 → 0.2 for the up-transition semantic fix.
This commit is contained in:
swaits committed 2026-04-22 19:38:42 -06:00
1 parent fa1eeceb7c
commit 42a6b1142d
6 files changed
+185 -14

No files matched your search

+5 -2
View File
@@ -9,6 +9,8 @@
use embedded_graphics::draw_target::DrawTarget;
use embedded_graphics::pixelcolor::BinaryColor;
use crate::driver::DisplayBrightness;
/// Async RGB LED control. Boards without an LED use `()` which is a no-op.
pub trait RgbLed {
fn set_rgb(&mut self, r: u8, g: u8, b: u8) -> impl core::future::Future<Output = ()>;
@@ -35,8 +37,9 @@ pub trait LoRaBoard: Sized {
/// Display peripheral bundle (I2C bus for display init).
type DisplayParts;
/// Concrete display driver type (must implement DrawTarget for rendering).
type DisplayDriver: DrawTarget<Color = BinaryColor>;
/// Concrete display driver type (must implement DrawTarget for rendering
/// and DisplayBrightness for the two-level dim control).
type DisplayDriver: DrawTarget<Color = BinaryColor> + DisplayBrightness;
/// RGB LED driver. Boards without an LED use `()`.
type LedDriver: RgbLed;