diff --git a/src/background_tasks/nfc.rs b/src/background_tasks/nfc.rs index 1e50d02..04a2fe3 100644 --- a/src/background_tasks/nfc.rs +++ b/src/background_tasks/nfc.rs @@ -1,4 +1,6 @@ +use crate::storage::cardstore::CardStore; use embedded_hal_bus::i2c::AtomicDevice; +use esp_hal::rtc_cntl::Rtc; use esp_hal::{Blocking, i2c::master::I2c, time::Instant}; use crate::{ @@ -14,6 +16,8 @@ use crate::{ )] pub async fn nfc_scanner( mut nfc_driver: NfcPn532Driver>>, + mut card_store: CardStore, + rtc: Rtc<'static>, ) { loop { while CARD_DATA.lock().await.is_none() { @@ -24,10 +28,22 @@ pub async fn nfc_scanner( log::error!("Failed to split NFC card data"); continue; }; - CARD_DATA - .lock() - .await - .replace(Card::try_from(split_data).unwrap()); + let card = match Card::try_from(split_data) { + Ok(card) => card, + Err(err) => { + log::error!("Invalid card data: {err}"); + continue; + } + }; + CARD_DATA.lock().await.replace(card); + + match card_store.save_raw_card(split_data, rtc.current_time_us()) { + Ok(()) => {} + Err(error) => { + log::error!("Error storing card in flash: {:?}", error) + } + } + let elapsed_ms = start.elapsed().as_millis(); log::info!( "NFC read duration: {} ms, card data length: {}", @@ -35,8 +51,8 @@ pub async fn nfc_scanner( card_data.len() ); } - Err(e) => { - log::error!("NFC read failed: {e}"); + Err(_) => { + log::info!("No NFC card found"); } } } diff --git a/src/bin/main.rs b/src/bin/main.rs index 0570d85..934c4fb 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -22,7 +22,6 @@ use creaturedex::network::wifi::setup_wifi; use creaturedex::storage::cardstore::CardStore; use creaturedex::storage::store::Store; use embassy_executor::Spawner; -use embassy_time::Instant; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::{ mono_font::{MonoTextStyle, ascii::FONT_6X10}, @@ -30,13 +29,13 @@ use embedded_graphics::{ text::Text, }; use embedded_hal_bus::i2c::AtomicDevice; -use embedded_hal_bus::util::AtomicCell; -use esp_hal::Blocking; use esp_hal::clock::CpuClock; use esp_hal::gpio::{Input, InputConfig, Pull}; use esp_hal::timer::timg::TimerGroup; use log::error; +use esp_hal::rtc_cntl::Rtc; + #[panic_handler] fn panic(panic_info: &core::panic::PanicInfo) -> ! { error!("{}", panic_info); @@ -108,7 +107,7 @@ async fn main(spawner: Spawner) { } let store = Store::new(peripherals.FLASH).expect("Could not initialize Flash Store"); - let card_store = CardStore::new(store).expect("Could not initialize Card Store"); + let cardstore = CardStore::new(store).expect("Could not initialize Card Store"); let rtc = Rtc::new(peripherals.LPWR); //setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await; @@ -148,7 +147,9 @@ async fn main(spawner: Spawner) { log::info!("Setup complete, entering main loop"); spawner.spawn(navigation::run(inputs, outputs).expect("run task failed")); - spawner.spawn(background_tasks::nfc_scanner(nfc_driver).expect("nfc scanner task failed")); + spawner.spawn( + background_tasks::nfc_scanner(nfc_driver, cardstore, rtc).expect("nfc scanner task failed"), + ); } fn display_shit(oled: &mut SecondaryDisplay<'static>, text: &str) { diff --git a/src/views.rs b/src/views.rs index 4d465b2..08094c2 100644 --- a/src/views.rs +++ b/src/views.rs @@ -1,4 +1,5 @@ pub mod card_view; +pub mod flash_info_view; pub mod journal_view; pub mod main_menu; pub mod menu_item; diff --git a/src/views/flash_info_view.rs b/src/views/flash_info_view.rs new file mode 100644 index 0000000..7e2ee5d --- /dev/null +++ b/src/views/flash_info_view.rs @@ -0,0 +1,49 @@ +use crate::navigation::inputs::ButtonAction; +use crate::navigation::navigation::Action; +use crate::navigation::navigation::Navigable; +use crate::navigation::navigation::NewState; +use crate::navigation::outputs::Outputs; +use crate::views::view::View; +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; + +#[derive(Debug, Clone)] +pub struct FlashInfoView {} + +impl Navigable for FlashInfoView { + fn display(&self, outputs: &mut Outputs) -> impl core::future::Future + Send { + let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); + Text::new("Flash Initialized: {:?}", Point::new(40, 40), style); + + core::future::ready(()) + } + + fn handle_input(&self, input: Action) -> impl core::future::Future + Send { + async move { + let Action::Button(input) = input else { + // Skip timer inputs + return NewState { + view: View::FlashInfo(self.clone()), + replace_view: true, + redraw: false, + }; + }; + + let new_menu = match input { + _ => View::FlashInfo(self.clone()), + }; + + NewState { + replace_view: matches!(new_menu, View::FlashInfo(_)), + view: new_menu, + redraw: true, + } + } + } +} diff --git a/src/views/settings_menu.rs b/src/views/settings_menu.rs index f855e91..1b12b7b 100644 --- a/src/views/settings_menu.rs +++ b/src/views/settings_menu.rs @@ -1,11 +1,14 @@ use crate::navigation::navigation::{Action, Navigable, NewState}; use crate::navigation::outputs::Outputs; -use crate::views::{menu_item, view::View}; +use crate::views::{flash_info_view::FlashInfoView, menu_item, view::View}; + +use crate::navigation::inputs::ButtonAction; use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::RgbColor; use embedded_graphics_core::draw_target::DrawTarget; -pub const MAX_SELECTED: i8 = 2; + +pub const MAX_SELECTED: i32 = 2; #[derive(Debug, Clone)] pub struct SettingsMenu { @@ -18,16 +21,50 @@ impl Navigable for SettingsMenu { 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); core::future::ready(()) } fn handle_input(&self, input: Action) -> impl core::future::Future + Send { async move { + let Action::Button(input) = input else { + // Skip timer inputs + return NewState { + view: View::Settings(self.clone()), + replace_view: true, + redraw: false, + }; + }; + + let new_menu = match input { + ButtonAction::Up => { + let new_selected = if (self.selected - 1) < 0 { + MAX_SELECTED - 1 + } else { + self.selected - 1 + }; + View::Settings(SettingsMenu { + selected: new_selected, + }) + } + ButtonAction::Down => { + let new_selected = self.selected.wrapping_add(1) % MAX_SELECTED; + View::Settings(SettingsMenu { + selected: new_selected, + }) + } + ButtonAction::Ok => match self.selected { + 2 => View::FlashInfo(FlashInfoView {}), + _ => View::Settings(self.clone()), + }, + _ => View::Settings(self.clone()), + }; + NewState { - view: View::Settings(SettingsMenu { selected: 0 }), - replace_view: true, - redraw: !matches!(input, Action::Timer), + replace_view: matches!(new_menu, View::Settings(_)), + view: new_menu, + redraw: true, } } } diff --git a/src/views/view.rs b/src/views/view.rs index f3da7c9..bd2e1c2 100644 --- a/src/views/view.rs +++ b/src/views/view.rs @@ -1,8 +1,8 @@ use crate::navigation::outputs::Outputs; use crate::views::card_view::CardView; use crate::views::{ - journal_view::JournalView, main_menu::MainMenu, scan_menu::ScanMenu, - settings_menu::SettingsMenu, + flash_info_view::FlashInfoView, journal_view::JournalView, main_menu::MainMenu, + scan_menu::ScanMenu, settings_menu::SettingsMenu, }; use crate::navigation::navigation::{Navigable, NewState}; @@ -14,6 +14,7 @@ pub enum View { Settings(SettingsMenu), Journal(JournalView), Card(CardView), + FlashInfo(FlashInfoView), } impl Navigable for View { @@ -25,6 +26,7 @@ impl Navigable for View { View::Settings(settings_menu) => settings_menu.display(outputs).await, View::Journal(journal_view) => journal_view.display(outputs).await, View::Card(card_view) => card_view.display(outputs).await, + View::FlashInfo(flash_info_view) => flash_info_view.display(outputs).await, } } } @@ -40,6 +42,7 @@ impl Navigable for View { View::Settings(settings_menu) => settings_menu.handle_input(input).await, View::Journal(journal_view) => journal_view.handle_input(input).await, View::Card(card_view) => card_view.handle_input(input).await, + View::FlashInfo(flash_info_view) => flash_info_view.handle_input(input).await, } } }