#![no_std] #![no_main] #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_assoc_type)] use alloc::rc::Rc; use embassy_executor::Spawner; use embassy_net::Stack; use embassy_sync::{ blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}, mutex::Mutex, pubsub::{ PubSubChannel, Publisher, Subscriber, WaitResult::{Lagged, Message}, }, signal::Signal, }; use embassy_time::{Duration, Timer}; use esp_hal::gpio::Input; use esp_hal::{gpio::InputConfig, peripherals}; use log::{debug, info}; use static_cell::make_static; extern crate alloc; use crate::{ init::sd_card::SDCardPersistence, store::{IDStore, day::Day, tally_id::TallyID}, webserver::start_webserver, }; mod drivers; mod feedback; mod init; mod store; mod webserver; static FEEDBACK_STATE: Signal = Signal::new(); type TallyChannel = PubSubChannel; type TallyPublisher = Publisher<'static, NoopRawMutex, TallyID, 8, 2, 1>; type TallySubscriber = Subscriber<'static, NoopRawMutex, TallyID, 8, 2, 1>; type UsedStore = IDStore; #[esp_hal_embassy::main] async fn main(mut spawner: Spawner) { let (uart_device, stack, i2c, led, buzzer_gpio, sd_det_gpio, persistence_layer) = init::hardware::hardware_init(&mut spawner).await; info!("Starting up..."); let mut rtc = drivers::rtc::RTCClock::new(i2c).await; let store: UsedStore = IDStore::new_from_storage(persistence_layer).await; let shared_store = Rc::new(Mutex::new(store)); let chan: &'static mut TallyChannel = make_static!(PubSubChannel::new()); let publisher: TallyPublisher = chan.publisher().unwrap(); let mut sub: TallySubscriber = chan.subscriber().unwrap(); wait_for_stack_up(stack).await; start_webserver(&mut spawner, stack, shared_store.clone(), chan); /****************************** Spawning tasks ***********************************/ debug!("spawing NFC reader task..."); spawner.must_spawn(drivers::nfc_reader::rfid_reader_task( uart_device, publisher, )); debug!("spawing feedback task.."); spawner.must_spawn(feedback::feedback_task(led, buzzer_gpio)); debug!("spawn sd detect task"); spawner.must_spawn(sd_detect_task(sd_det_gpio)); /******************************************************************************/ debug!("everything spawned"); FEEDBACK_STATE.signal(feedback::FeedbackState::Startup); loop { let wait_result = sub.next_message().await; match wait_result { Lagged(_) => debug!("Lagged"), Message(msg) => { debug!("Got message: {msg:?}"); let day: Day = rtc.get_time().await.into(); let added = shared_store.lock().await.add_id(msg, day).await; if added { FEEDBACK_STATE.signal(feedback::FeedbackState::Ack); } } } } } #[embassy_executor::task] async fn sd_detect_task(sd_det_gpio: peripherals::GPIO0<'static>) { let mut sd_det = Input::new(sd_det_gpio, InputConfig::default()); sd_det.wait_for(esp_hal::gpio::Event::AnyEdge).await; loop { sd_det.wait_for_any_edge().await; { if sd_det.is_high() { FEEDBACK_STATE.signal(feedback::FeedbackState::Ack); debug!("card insert"); } //card is not insert on low else { FEEDBACK_STATE.signal(feedback::FeedbackState::Nack); debug!("card removed"); } } //debounce time Timer::after(Duration::from_millis(100)).await; } } async fn wait_for_stack_up(stack: Stack<'static>) { loop { if stack.is_link_up() { break; } Timer::after(Duration::from_millis(500)).await; if stack.is_config_up() { break; } Timer::after(Duration::from_millis(500)).await; } }