Skip to content

Commit

Permalink
Display error screen
Browse files Browse the repository at this point in the history
  • Loading branch information
zargony committed Sep 24, 2024
1 parent c04907e commit 095561d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 47 deletions.
11 changes: 7 additions & 4 deletions firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use esp_hal::system::SystemControl;
use esp_hal::timer::systimer::{SystemTimer, Target};
use esp_hal::timer::timg::TimerGroup;
use esp_println::println;
use log::info;
use log::{error, info};

static VERSION_STR: &str = concat!("v", env!("CARGO_PKG_VERSION"));
static GIT_SHA_STR: &str = env!("GIT_SHORT_SHA");
Expand Down Expand Up @@ -179,7 +179,7 @@ async fn main(spawner: Spawner) {
let mut ui = ui::Ui::new(display, keypad, nfc, buzzer, wifi);

// Show splash screen for a while, ignore any error
let _ = ui.show_splash_screen().await;
let _ = ui.show_splash().await;

// Wait for network to become available (if not already), ignore any error
let _ = ui.wait_network_up().await;
Expand All @@ -192,8 +192,11 @@ async fn main(spawner: Spawner) {
Err(error::Error::Cancel) => info!("User cancelled, starting over..."),
// Timeout: start over again
Err(error::Error::UserTimeout) => info!("Timeout waiting for user, starting over..."),
// TODO: Display error to user and start over again
Err(err) => panic!("Unhandled Error: {:?}", err),
// Display error to user and start over again
Err(err) => {
error!("Unhandled Error: {:?}", err);
let _ = ui.show_error(&err).await;
}
}
}
}
77 changes: 39 additions & 38 deletions firmware/src/screen.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{GIT_SHA_STR, VERSION_STR};
use core::fmt;
use embedded_graphics::draw_target::DrawTarget;
use embedded_graphics::image::{Image, ImageRaw};
use embedded_graphics::pixelcolor::BinaryColor;
Expand Down Expand Up @@ -76,6 +77,43 @@ impl Screen for Splash {
}
}

/// Failure screen
pub struct Failure<M> {
message: M,
}

impl<M: fmt::Display> Failure<M> {
pub fn new(message: M) -> Self {
Self { message }
}
}

impl<M: fmt::Display> Screen for Failure<M> {
fn draw<D: DrawTarget<Color = BinaryColor>>(
&self,
target: &mut D,
) -> Result<(), Error<D::Error>> {
TITLE_FONT.render_aligned(
"FEHLER!",
Point::new(63, 27),
VerticalPosition::Baseline,
HorizontalAlignment::Center,
FontColor::Transparent(BinaryColor::On),
target,
)?;
SMALL_FONT.render_aligned(
format_args!("{}", self.message),
Point::new(63, 27 + 12),
VerticalPosition::Baseline,
HorizontalAlignment::Center,
FontColor::Transparent(BinaryColor::On),
target,
)?;
Footer::new("* Abbruch", "").draw(target)?;
Ok(())
}
}

/// Wait while a lengthy action is in progress
pub enum PleaseWait {
WifiConnecting,
Expand Down Expand Up @@ -224,7 +262,7 @@ impl Screen for Success {
target,
)?;
SMALL_FONT.render_aligned(
format_args!("{} Getränke entnehmen", self.num_drinks),
format_args!("{} Getränke genehmigt", self.num_drinks),
Point::new(63, 27 + 12),
VerticalPosition::Baseline,
HorizontalAlignment::Center,
Expand All @@ -236,43 +274,6 @@ impl Screen for Success {
}
}

/// Error screen
pub struct Failure<'a> {
message: &'a str,
}

impl<'a> Failure<'a> {
pub fn new(message: &'a str) -> Self {
Self { message }
}
}

impl<'a> Screen for Failure<'a> {
fn draw<D: DrawTarget<Color = BinaryColor>>(
&self,
target: &mut D,
) -> Result<(), Error<D::Error>> {
TITLE_FONT.render_aligned(
"FEHLER!",
Point::new(63, 27),
VerticalPosition::Baseline,
HorizontalAlignment::Center,
FontColor::Transparent(BinaryColor::On),
target,
)?;
SMALL_FONT.render_aligned(
self.message,
Point::new(63, 27 + 12),
VerticalPosition::Baseline,
HorizontalAlignment::Center,
FontColor::Transparent(BinaryColor::On),
target,
)?;
Footer::new("* Abbruch", "").draw(target)?;
Ok(())
}
}

/// Common footer (bottom 7 lines 57..64)
struct Footer<'a> {
left: &'a str,
Expand Down
29 changes: 24 additions & 5 deletions firmware/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::nfc::{Nfc, Uid};
use crate::screen;
use crate::wifi::Wifi;
use core::convert::Infallible;
use core::fmt;
use embassy_futures::select::{select, Either};
use embassy_time::{with_timeout, Duration, TimeoutError};
use embedded_hal_async::digital::Wait;
Expand Down Expand Up @@ -69,8 +70,11 @@ impl<'a, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, I2C, IRQ> {
}

/// Show splash screen and wait for keypress or timeout
pub async fn show_splash_screen(&mut self) -> Result<(), Error> {
pub async fn show_splash(&mut self) -> Result<(), Error> {
info!("UI: Displaying splash screen");

self.display.screen(&screen::Splash).await?;

match with_timeout(SPLASH_TIMEOUT, self.keypad.read()).await {
// Key pressed
Ok(_key) => Ok(()),
Expand All @@ -79,13 +83,31 @@ impl<'a, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, I2C, IRQ> {
}
}

/// Show error screen and wait for keypress or timeout
pub async fn show_error<M: fmt::Display>(&mut self, message: M) -> Result<(), Error> {
info!("UI: Displaying error: {}", message);

self.display.screen(&screen::Failure::new(message)).await?;
let _ = self.buzzer.error().await;

let wait_cancel = async { while self.keypad.read().await != Key::Cancel {} };
match with_timeout(USER_TIMEOUT, wait_cancel).await {
// Cancel key cancels
Ok(()) => Ok(()),
// User interaction timeout
Err(TimeoutError) => Err(Error::UserTimeout),
}
}

/// Wait for network to become available (if not already). Show a waiting screen and allow to
/// cancel
pub async fn wait_network_up(&mut self) -> Result<(), Error> {
if self.wifi.is_up() {
return Ok(());
}

info!("UI: Waiting for network to become available...");

self.display
.screen(&screen::PleaseWait::WifiConnecting)
.await?;
Expand Down Expand Up @@ -117,10 +139,7 @@ impl<'a, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, I2C, IRQ> {

// TODO: Process payment
let _ = screen::Success::new(num_drinks);
self.display
.screen(&screen::Failure::new("Not implemented yet"))
.await?;
let _ = self.buzzer.error().await;
let _ = self.show_error("Not implemented yet").await;
let _key = self.keypad.read().await;
Ok(())
}
Expand Down

0 comments on commit 095561d

Please sign in to comment.