display views: return error instead of unwrapping #49

Merged
rhetenor merged 1 commits from rhetenor/errorview-remove-unwraps AGit into main 2026-08-29 23:09:42 +02:00
9 changed files with 114 additions and 40 deletions
+21 -1
View File
@@ -1,3 +1,6 @@
use core::error::Error;
use core::fmt::Debug;
use core::fmt::Display;
use display_interface_spi::SPIInterface;
use embedded_graphics::draw_target::DrawTarget;
use embedded_graphics::pixelcolor::Rgb565;
@@ -6,10 +9,27 @@ use embedded_hal_bus::spi::AtomicDevice;
use embedded_hal_bus::util::AtomicCell;
use esp_hal::delay::Delay;
use esp_hal::gpio::Output;
use ili9341::{DisplaySize240x320, Ili9341, Orientation};
use ili9341::{DisplayError, DisplaySize240x320, Ili9341, Orientation};
use crate::drivers::spi_bus::{DisplaySpiBus, SharedOutput};
#[derive(Debug)]
pub struct PrimaryDisplayError(DisplayError);
impl Display for PrimaryDisplayError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.fmt(f)
}
}
impl Error for PrimaryDisplayError {}
impl From<DisplayError> for PrimaryDisplayError {
fn from(value: DisplayError) -> Self {
Self(value)
}
}
type GenericPrimaryDisplay<'a, BUS, DC, RES> =
Ili9341<SPIInterface<AtomicDevice<'a, BUS, Output<'a>, Delay>, DC>, RES>;
pub type PrimaryDisplay<'a> =
+12 -9
View File
@@ -1,4 +1,5 @@
use crate::display::sprite::render_sprite_onto_ili9341;
use crate::drivers::primary_lcd::PrimaryDisplayError;
use crate::navigation::navigation::NewState;
use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals;
@@ -35,7 +36,9 @@ impl Navigable for CardView {
) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move {
let display = &mut outputs.primary_display;
display.clear(Rgb565::BLACK).unwrap();
display
.clear(Rgb565::BLACK)
.map_err(PrimaryDisplayError::from)?;
let background = Rectangle::new(Point::new(0, 0), Size::new(240, 320));
let bg_color = self.card.cardtype.clone().into();
@@ -49,56 +52,56 @@ impl Navigable for CardView {
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Text::new(
&format!("Type: {}", self.card.cardtype),
Point::new(20, 250),
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Text::new(
&format!("Event: {}", self.card.event),
Point::new(20, 260),
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Text::new(
&format!("UUID: {}", self.card.uuid),
Point::new(20, 270),
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Text::new(
&format!("Trait1: {}", self.card.trait1),
Point::new(20, 280),
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Text::new(
&format!("Trait2: {}", self.card.trait2),
Point::new(20, 290),
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Text::new(
&format!("Trait3: {}", self.card.trait3),
Point::new(20, 300),
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Text::new(
&format!("Secret: {}", self.card.secret),
Point::new(20, 310),
style,
)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
let palette: Palette = self.card.cardtype.clone().into();
render_sprite_onto_ili9341(display, self.card.sprite.data.as_slice(), &palette);
+49 -8
View File
@@ -1,21 +1,30 @@
use crate::drivers::primary_lcd::PrimaryDisplayError;
use crate::navigation::navigation::Action;
use crate::navigation::navigation::Navigable;
use crate::navigation::navigation::NewState;
use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals;
use crate::peripherals::storage::MAGIC_REGION;
use crate::peripherals::storage::cardstore::COUNT_REGION;
use crate::views::view::View;
use alloc::boxed::Box;
use core::error;
use embedded_graphics::mono_font::MonoTextStyle;
use embedded_graphics::mono_font::ascii::FONT_10X20;
use embedded_graphics::pixelcolor::Rgb565;
use embedded_graphics::prelude::DrawTarget;
use embedded_graphics::prelude::RgbColor;
use embedded_graphics::text::Text;
use embedded_graphics::prelude::Point;
use embedded_graphics::{
Drawable,
mono_font::{MonoTextStyle, ascii::FONT_10X20},
pixelcolor::Rgb565,
prelude::*,
primitives::Rectangle,
text::Text,
};
use alloc::format;
use embedded_text::{
TextBox,
alignment::HorizontalAlignment,
style::{HeightMode, TextBoxStyleBuilder},
};
#[derive(Debug, Clone)]
pub struct FlashInfoView {}
@@ -35,7 +44,39 @@ impl Navigable for FlashInfoView {
.flash_store
.read(MAGIC_REGION.offset, &mut magic_bytes)
.await?;
Text::new("Flash Initialized: {:?}", Point::new(40, 40), style);
let mut card_count_bytes: [u8; COUNT_REGION.size] = [0; COUNT_REGION.size];
peripherals
.store
.lock()
.await
.flash_store
.read(COUNT_REGION.offset, &mut card_count_bytes)
.await?;
let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
let textbox_style = TextBoxStyleBuilder::new()
.height_mode(HeightMode::FitToText)
.alignment(HorizontalAlignment::Center)
.build();
let display_area = outputs.primary_display.bounding_box();
let bounds = Rectangle::new(Point::new(0, 30), display_area.size);
TextBox::with_textbox_style(
&format!(
"
Flash Init Magic: 0x{:x}\n
Card Count: {}\n
",
u32::from_le_bytes(magic_bytes),
u32::from_le_bytes(card_count_bytes)
),
bounds,
style,
textbox_style,
)
.draw(&mut outputs.primary_display)
.map_err(PrimaryDisplayError::from)?;
Ok(())
}
}
+6 -2
View File
@@ -1,6 +1,7 @@
use crate::drivers::primary_lcd::PrimaryDisplayError;
use crate::peripherals::Peripherals;
use alloc::boxed::Box;
use core::error;
use crate::peripherals::Peripherals;
use core::future;
use alloc::vec::Vec;
@@ -31,7 +32,10 @@ impl Navigable for JournalView {
_: &Peripherals,
) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move {
outputs.primary_display.clear(Rgb565::BLACK).unwrap();
outputs
.primary_display
.clear(Rgb565::BLACK)
.map_err(PrimaryDisplayError::from)?;
Ok(())
}
}
+9 -5
View File
@@ -1,3 +1,4 @@
use crate::drivers::primary_lcd::PrimaryDisplayError;
use crate::peripherals::Peripherals;
use alloc::boxed::Box;
use alloc::vec;
@@ -17,7 +18,6 @@ use embedded_graphics::pixelcolor::Rgb565;
use embedded_graphics::prelude::RgbColor;
use embedded_graphics_core::draw_target::DrawTarget;
use crate::peripherals::storage::cardstore::CardStoreError;
pub const MAX_SELECTED: i32 = 4;
#[derive(Debug, Clone)]
@@ -35,10 +35,14 @@ impl Navigable for MainMenu {
let display = &mut outputs.primary_display;
display.clear(Rgb565::BLACK).unwrap();
menu_item::show(display, "Scan card", 0, self.selected);
menu_item::show(display, "Last card", 1, self.selected);
menu_item::show(display, "Journal", 2, self.selected);
menu_item::show(display, "Settings", 3, self.selected);
menu_item::show(display, "Scan card", 0, self.selected)
.map_err(PrimaryDisplayError::from)?;
menu_item::show(display, "Last card", 1, self.selected)
.map_err(PrimaryDisplayError::from)?;
menu_item::show(display, "Journal", 2, self.selected)
.map_err(PrimaryDisplayError::from)?;
menu_item::show(display, "Settings", 3, self.selected)
.map_err(PrimaryDisplayError::from)?;
Ok(())
}
+3 -6
View File
@@ -1,6 +1,3 @@
use alloc::boxed::Box;
use core::error;
use crate::peripherals::Peripherals;
use embedded_graphics::Drawable;
use embedded_graphics::draw_target::DrawTarget;
use embedded_graphics::mono_font::MonoTextStyle;
@@ -10,7 +7,7 @@ use embedded_graphics::prelude::Point;
use embedded_graphics::prelude::RgbColor;
use embedded_graphics::text::Text;
pub fn show<D>(display: &mut D, name: &str, position: i32, selected: i32)
pub fn show<D>(display: &mut D, name: &str, position: i32, selected: i32) -> Result<(), D::Error>
where
D: DrawTarget<Color = Rgb565>,
D::Error: core::fmt::Debug,
@@ -27,6 +24,6 @@ where
style
},
)
.draw(display)
.unwrap();
.draw(display)?;
Ok(())
}
+7 -4
View File
@@ -1,3 +1,4 @@
use crate::drivers::primary_lcd::PrimaryDisplayError;
use crate::navigation::inputs::ButtonAction;
use crate::navigation::navigation::CARD_DATA;
use crate::navigation::navigation::NewState;
@@ -44,13 +45,15 @@ impl Navigable for ScanMenu {
async move {
let display = &mut outputs.primary_display;
let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
display.clear(Rgb565::BLACK).unwrap();
display
.clear(Rgb565::BLACK)
.map_err(PrimaryDisplayError::from)?;
let display_area = display.bounding_box();
Text::new("Scanning...", Point::new(20, 30), style)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
// Create styles used by the drawing operations.
let arc_stroke = PrimitiveStyleBuilder::new()
@@ -80,13 +83,13 @@ impl Navigable for ScanMenu {
)
.into_styled(arc_stroke)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
// Draw centered text.
let text = format!("{:.2}%", 100. * (self.progress as f32) / 255.);
Text::with_text_style(&text, display_area.center(), character_style, text_style)
.draw(display)
.unwrap();
.map_err(PrimaryDisplayError::from)?;
Ok(())
}
}
+7 -3
View File
@@ -1,3 +1,4 @@
use crate::drivers::primary_lcd::PrimaryDisplayError;
use crate::navigation::navigation::{Action, Navigable, NewState};
use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals;
@@ -27,9 +28,12 @@ impl Navigable for SettingsMenu {
async move {
let display = &mut outputs.primary_display;
display.clear(Rgb565::BLACK).unwrap();
menu_item::show(display, "System Inforation", 0, self.selected);
menu_item::show(display, "Wifi Information", 1, self.selected);
menu_item::show(display, "Flash Information", 2, self.selected);
menu_item::show(display, "System Inforation", 0, self.selected)
.map_err(PrimaryDisplayError::from)?;
menu_item::show(display, "Wifi Information", 1, self.selected)
.map_err(PrimaryDisplayError::from)?;
menu_item::show(display, "Flash Information", 2, self.selected)
.map_err(PrimaryDisplayError::from)?;
Ok(())
}
}
-2
View File
@@ -1,3 +1 @@
use alloc::boxed::Box;
use core::error;
// Status bar view module