From 5ac8fe96102147d677c2bf684db9cb54fad58e9c Mon Sep 17 00:00:00 2001 From: rhetenor Date: Sat, 29 Aug 2026 21:13:21 +0000 Subject: [PATCH 1/6] error view: clear display --- src/views/error_view.rs | 13 +++++++++++-- src/views/settings_menu.rs | 6 ++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/views/error_view.rs b/src/views/error_view.rs index 14711a9..cac0274 100644 --- a/src/views/error_view.rs +++ b/src/views/error_view.rs @@ -34,6 +34,15 @@ impl Navigable for ErrorView { _: &Peripherals, ) -> impl core::future::Future>> + Send { async move { + outputs + .primary_display + .clear(Rgb565::BLACK) + .unwrap_or_else(|error| { + panic!( + "Error: {error:?}\nDraw error while rendering ErrorView: {}", + self.error + ) + }); let style = MonoTextStyle::new(&FONT_10X20, Rgb565::RED); let display_area = outputs.primary_display.bounding_box(); Text::new( @@ -44,7 +53,7 @@ impl Navigable for ErrorView { .draw(&mut outputs.primary_display) .unwrap_or_else(|error| { panic!( - "Error: {error:?}\nDraw error while rendering error: {}", + "Error: {error:?}\nDraw error while rendering ErrorView: {}", self.error ) }); @@ -61,7 +70,7 @@ impl Navigable for ErrorView { .draw(&mut outputs.primary_display) .unwrap_or_else(|error| { panic!( - "Error: {error:?}\nDraw error while rendering error: {}", + "Error: {error:?}\nDraw error while rendering ErrorView: {}", self.error ) }); diff --git a/src/views/settings_menu.rs b/src/views/settings_menu.rs index 47ceee1..c0f3fc9 100644 --- a/src/views/settings_menu.rs +++ b/src/views/settings_menu.rs @@ -12,7 +12,7 @@ use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::RgbColor; use embedded_graphics_core::draw_target::DrawTarget; -pub const MAX_SELECTED: i32 = 2; +pub const MAX_SELECTED: i32 = 3; #[derive(Debug, Clone)] pub struct SettingsMenu { @@ -27,7 +27,9 @@ impl Navigable for SettingsMenu { ) -> impl core::future::Future>> + Send { async move { let display = &mut outputs.primary_display; - display.clear(Rgb565::BLACK).unwrap(); + display + .clear(Rgb565::BLACK) + .map_err(PrimaryDisplayError::from)?; menu_item::show(display, "System Inforation", 0, self.selected) .map_err(PrimaryDisplayError::from)?; menu_item::show(display, "Wifi Information", 1, self.selected) -- 2.39.5 From ccf16522bb87032f20f9ec16bea946b7e94eab60 Mon Sep 17 00:00:00 2001 From: rhetenor Date: Sun, 30 Aug 2026 08:13:34 +0000 Subject: [PATCH 2/6] flash_store: forgot to add offset when erasing before write --- src/peripherals/storage/flash_store.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/peripherals/storage/flash_store.rs b/src/peripherals/storage/flash_store.rs index 76f45a1..e99d99f 100644 --- a/src/peripherals/storage/flash_store.rs +++ b/src/peripherals/storage/flash_store.rs @@ -75,7 +75,10 @@ impl FlashStore { bytes.len() ); let mut lock = self.storage.lock().await; - lock.erase(FLASH_ADDR + offset, FLASH_ADDR + bytes.len() as u32)?; + lock.erase( + FLASH_ADDR + offset, + FLASH_ADDR + offset + bytes.len() as u32, + )?; lock.write(FLASH_ADDR + offset, bytes)?; Ok(()) } -- 2.39.5 From af964bcc3734756d9d90ec06521f652a714175f9 Mon Sep 17 00:00:00 2001 From: rhetenor Date: Sun, 30 Aug 2026 08:14:20 +0000 Subject: [PATCH 3/6] default to debug log for now --- .cargo/config.toml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index a1297d5..aa24b04 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -2,13 +2,11 @@ runner = "espflash flash --monitor --chip esp32s3" [env] -ESP_LOG="info" +ESP_LOG = "debug" WM_CONN = '{"ssid": "Wokwi-GUEST", "psk": "", "data": {}}' [build] -rustflags = [ - "-C", "link-arg=-nostartfiles", -] +rustflags = ["-C", "link-arg=-nostartfiles"] target = "xtensa-esp32s3-none-elf" -- 2.39.5 From 3d36885e118f9cb1cce7af34646a67378d2a2039 Mon Sep 17 00:00:00 2001 From: rhetenor Date: Sun, 30 Aug 2026 08:14:54 +0000 Subject: [PATCH 4/6] flash_info_view: align content justified --- src/views/flash_info_view.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/views/flash_info_view.rs b/src/views/flash_info_view.rs index 54a0bc6..cb407b0 100644 --- a/src/views/flash_info_view.rs +++ b/src/views/flash_info_view.rs @@ -16,6 +16,7 @@ use embedded_graphics::{ pixelcolor::Rgb565, prelude::*, primitives::Rectangle, + text::Text, }; use alloc::format; @@ -34,7 +35,11 @@ impl Navigable for FlashInfoView { peripherals: &Peripherals, ) -> impl core::future::Future>> + Send { async move { - let _style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); + outputs + .primary_display + .clear(Rgb565::BLACK) + .map_err(PrimaryDisplayError::from)?; + let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); let mut magic_bytes: [u8; MAGIC_REGION.size] = [0; MAGIC_REGION.size]; peripherals .store @@ -55,7 +60,7 @@ impl Navigable for FlashInfoView { let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); let textbox_style = TextBoxStyleBuilder::new() .height_mode(HeightMode::FitToText) - .alignment(HorizontalAlignment::Center) + .alignment(HorizontalAlignment::Justified) .build(); let display_area = outputs.primary_display.bounding_box(); -- 2.39.5 From 3c657045caa26f5c88f5610eb9e0e29341da0302 Mon Sep 17 00:00:00 2001 From: rhetenor Date: Sun, 30 Aug 2026 08:53:37 +0000 Subject: [PATCH 5/6] pass outputs and state to nfc task so that they can show errors on their own --- src/background_tasks/nfc.rs | 18 +++++- src/bin/main.rs | 11 ++-- src/navigation/navigation.rs | 86 ++++++++++++++++---------- src/peripherals/storage/flash_store.rs | 5 +- src/views/error_view.rs | 2 +- 5 files changed, 79 insertions(+), 43 deletions(-) diff --git a/src/background_tasks/nfc.rs b/src/background_tasks/nfc.rs index e659aaf..5aed664 100644 --- a/src/background_tasks/nfc.rs +++ b/src/background_tasks/nfc.rs @@ -1,4 +1,9 @@ -use crate::peripherals::Peripherals; +use crate::navigation::navigation::display_error; +use crate::{ + navigation::{navigation::Mutex, outputs::Outputs, state::NavigationState}, + peripherals::Peripherals, +}; +use alloc::string::ToString; use embedded_hal_bus::i2c::AtomicDevice; use esp_hal::{Blocking, i2c::master::I2c, time::Instant}; @@ -15,7 +20,9 @@ use crate::{ )] pub async fn nfc_scanner( mut nfc_driver: NfcPn532Driver>>, + outputs: &'static Mutex, peripherals: &'static Peripherals, + navigation_state: &'static Mutex, ) { loop { while CARD_DATA.lock().await.is_none() { @@ -45,7 +52,14 @@ pub async fn nfc_scanner( { Ok(()) => {} Err(error) => { - log::error!("Error storing card in flash: {:?}", error) + log::error!("Error storing card in flash: {:?}", error); + display_error( + error.to_string(), + navigation_state, + outputs, + peripherals, + ) + .await; } } diff --git a/src/bin/main.rs b/src/bin/main.rs index f001eee..e833a09 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -20,6 +20,7 @@ use creaturedex::drivers::tertiary_lcd::{ use creaturedex::navigation::navigation::Mutex; use creaturedex::navigation::inputs::Inputs; use creaturedex::navigation::navigation::{self}; +use creaturedex::navigation::state::NavigationState; use creaturedex::navigation::outputs::Outputs; use creaturedex::peripherals::Peripherals; use creaturedex::peripherals::storage::cardstore::CardStore; @@ -163,7 +164,7 @@ async fn main(spawner: Spawner) { display_shit(&mut secondaries[2], "baz 1"); display_shit_prim(&mut primary, "Hello World"); - let outputs = { + let outputs = Box::leak(Box::new(Mutex::new({ let [sec_1, sec_2, sec_3] = secondaries; Outputs { primary_display: primary, @@ -173,12 +174,14 @@ async fn main(spawner: Spawner) { tertiary_display: lcd, _led_a: (), } - }; + }))); + + let navigation_state = Box::leak(Box::new(Mutex::new(NavigationState::new()))); log::info!("Setup complete, entering main loop"); - spawner.spawn(navigation::run(inputs, outputs, peripherals).expect("run task failed")); + spawner.spawn(navigation::run(inputs, outputs, peripherals, navigation_state).expect("run task failed")); spawner.spawn( - background_tasks::nfc_scanner(nfc_driver, peripherals).expect("nfc scanner task failed"), + background_tasks::nfc_scanner(nfc_driver, outputs, peripherals, navigation_state).expect("nfc scanner task failed"), ); core::future::pending::<()>().await } diff --git a/src/navigation/navigation.rs b/src/navigation/navigation.rs index b7aa9e0..f05febf 100644 --- a/src/navigation/navigation.rs +++ b/src/navigation/navigation.rs @@ -41,43 +41,56 @@ pub trait Navigable { fn handle_input(&self, input: Action) -> impl core::future::Future + Send; } -#[embassy_executor::task] -pub async fn run(mut inputs: Inputs, mut outputs: Outputs, peripherals: &'static Peripherals) { - async fn display_error( - error: String, - state: &mut NavigationState, - outputs: &mut Outputs, - peripherals: &Peripherals, - ) -> () { - let error_view = ErrorView { - error: error.to_string(), - }; - state.screens.push(View::Error(error_view)); - state - .screens - .last() - // Unwrap: we just pushed the state - .unwrap() - .display(outputs, peripherals) - .await - // Unwrap: display will panic on error in error view - .unwrap(); - } - - log::info!("starting navigation"); - - let mut state = NavigationState::new(); - if let Err(error) = state +pub async fn display_error( + error: String, + navigation_state: &Mutex, + outputs: &Mutex, + peripherals: &Peripherals, +) -> () { + let error_view = ErrorView { + error: error.to_string(), + }; + let mut state = navigation_state.lock().await; + state.screens.push(View::Error(error_view)); + let mut outs = outputs.lock().await; + state .screens .last() + // Unwrap: we just pushed the state .unwrap() - .display(&mut outputs, peripherals) + .display(&mut outs, peripherals) .await + // Unwrap: display will panic on error in error view + .unwrap(); +} + +#[embassy_executor::task] +pub async fn run( + mut inputs: Inputs, + mut outputs: &'static Mutex, + peripherals: &'static Peripherals, + navigation_state: &'static Mutex, +) { + log::info!("starting navigation"); + { - display_error(error.to_string(), &mut state, &mut outputs, peripherals).await; - }; + let mut outs = outputs.lock().await; + if let Err(error) = navigation_state + .lock() + .await + .screens + .last() + .unwrap() + .display(&mut outs, peripherals) + .await + { + display_error(error.to_string(), &navigation_state, &outputs, peripherals).await; + }; + } loop { + Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)).await; + let mut state = navigation_state.lock().await; let selection = select( inputs.wait_for_press(), Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)), @@ -120,17 +133,22 @@ pub async fn run(mut inputs: Inputs, mut outputs: Outputs, peripherals: &'static } state.screens.push(new_state.view); + let mut outs = outputs.lock().await; if (action != Action::Timer || new_state.redraw) && let Err(error) = state .screens .last() .unwrap() - .display(&mut outputs, peripherals) + .display(&mut outs, peripherals) .await { - display_error(error.to_string(), &mut state, &mut outputs, peripherals).await; + display_error( + error.to_string(), + &navigation_state, + &mut outputs, + peripherals, + ) + .await; } - - Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)).await; } } diff --git a/src/peripherals/storage/flash_store.rs b/src/peripherals/storage/flash_store.rs index e99d99f..1bbb564 100644 --- a/src/peripherals/storage/flash_store.rs +++ b/src/peripherals/storage/flash_store.rs @@ -21,8 +21,9 @@ impl Error for FlashStoreError {} impl Display for FlashStoreError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - use core::fmt::Debug; - self.0.fmt(f) + match self { + err => write!(f, "FlashStoreError:\n{:?}", err.0), + } } } diff --git a/src/views/error_view.rs b/src/views/error_view.rs index cac0274..2524f69 100644 --- a/src/views/error_view.rs +++ b/src/views/error_view.rs @@ -64,7 +64,7 @@ impl Navigable for ErrorView { .alignment(HorizontalAlignment::Center) .build(); - let bounds = Rectangle::new(Point::new(0, 30), display_area.size); + let bounds = Rectangle::new(Point::new(0, 50), display_area.size); TextBox::with_textbox_style(&self.error.to_string(), bounds, style, textbox_style) .draw(&mut outputs.primary_display) -- 2.39.5 From 91948bdcf5aae9d372e9f49d117831cc6ee4b72c Mon Sep 17 00:00:00 2001 From: rhetenor Date: Sun, 30 Aug 2026 09:25:49 +0000 Subject: [PATCH 6/6] fix clippy warnings --- Cargo.toml | 3 +++ src/navigation/navigation.rs | 12 +++--------- src/peripherals/storage/flash_store.rs | 4 +--- src/views/flash_info_view.rs | 3 +-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2e4a06e..b2f26eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,3 +83,6 @@ opt-level = 's' [features] default = [] wokwi = [] + +[lints.clippy] +manual_async_fn = "allow" diff --git a/src/navigation/navigation.rs b/src/navigation/navigation.rs index f05febf..583719f 100644 --- a/src/navigation/navigation.rs +++ b/src/navigation/navigation.rs @@ -67,7 +67,7 @@ pub async fn display_error( #[embassy_executor::task] pub async fn run( mut inputs: Inputs, - mut outputs: &'static Mutex, + outputs: &'static Mutex, peripherals: &'static Peripherals, navigation_state: &'static Mutex, ) { @@ -84,7 +84,7 @@ pub async fn run( .display(&mut outs, peripherals) .await { - display_error(error.to_string(), &navigation_state, &outputs, peripherals).await; + display_error(error.to_string(), navigation_state, outputs, peripherals).await; }; } @@ -142,13 +142,7 @@ pub async fn run( .display(&mut outs, peripherals) .await { - display_error( - error.to_string(), - &navigation_state, - &mut outputs, - peripherals, - ) - .await; + display_error(error.to_string(), navigation_state, outputs, peripherals).await; } } } diff --git a/src/peripherals/storage/flash_store.rs b/src/peripherals/storage/flash_store.rs index 1bbb564..031afad 100644 --- a/src/peripherals/storage/flash_store.rs +++ b/src/peripherals/storage/flash_store.rs @@ -21,9 +21,7 @@ impl Error for FlashStoreError {} impl Display for FlashStoreError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - err => write!(f, "FlashStoreError:\n{:?}", err.0), - } + write!(f, "FlashStoreError:\n{:?}", self.0) } } diff --git a/src/views/flash_info_view.rs b/src/views/flash_info_view.rs index cb407b0..ee7b4f9 100644 --- a/src/views/flash_info_view.rs +++ b/src/views/flash_info_view.rs @@ -16,7 +16,6 @@ use embedded_graphics::{ pixelcolor::Rgb565, prelude::*, primitives::Rectangle, - text::Text, }; use alloc::format; @@ -39,7 +38,7 @@ impl Navigable for FlashInfoView { .primary_display .clear(Rgb565::BLACK) .map_err(PrimaryDisplayError::from)?; - let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); + let _style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); let mut magic_bytes: [u8; MAGIC_REGION.size] = [0; MAGIC_REGION.size]; peripherals .store -- 2.39.5