#![no_std] #![no_main] #![deny( clippy::mem_forget, reason = "mem::forget is generally not safe to do with esp_hal types, especially those \ holding buffers for the duration of a data transfer." )] #![deny(clippy::large_stack_frames)] use creaturedex::background_tasks; use creaturedex::drivers::i2c_bus::I2cBusPinConfiguration; use creaturedex::drivers::nfc_pn532::NfcPn532Driver; use creaturedex::drivers::secondary_oled::SecondaryDisplay; use creaturedex::drivers::spi_bus; use creaturedex::drivers::tertiary_lcd::{ BOX, EMPTY, EXAMPLE, HEART, TertiaryDisplay, TertiaryDisplayPinConfiguration, }; use creaturedex::navigation::inputs::Inputs; use creaturedex::navigation::navigation::{self}; use creaturedex::navigation::outputs::Outputs; use creaturedex::network::wifi::setup_wifi; use creaturedex::storage::cardstore::CardStore; use creaturedex::storage::store::Store; use embassy_executor::Spawner; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::{ mono_font::{MonoTextStyle, ascii::FONT_6X10}, prelude::*, text::Text, }; use embedded_hal_bus::i2c::AtomicDevice; 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); loop {} } extern crate alloc; const HEAP_SIZE: usize = 73744; // This creates a default app-descriptor required by the esp-idf bootloader. // For more information see: esp_bootloader_esp_idf::esp_app_desc!(); #[allow( clippy::large_stack_frames, reason = "it's not unusual to allocate larger buffers etc. in main" )] #[esp_rtos::main] async fn main(spawner: Spawner) { creaturedex::logging::init(); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: HEAP_SIZE); let sw_interrupt = esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); let timg0 = TimerGroup::new(peripherals.TIMG0); esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0); let (primary, mut secondaries) = spi_bus::DisplayPinConfiguration { spi_peripheral: peripherals.SPI2, sck: peripherals.GPIO36, mosi: peripherals.GPIO35, miso: peripherals.GPIO37, cs_primary: peripherals.GPIO11, cs_secondary_1: peripherals.GPIO13, cs_secondary_2: peripherals.GPIO14, cs_secondary_3: peripherals.GPIO21, reset_primary: peripherals.GPIO10, reset_secondary: peripherals.GPIO47, dc_pin: peripherals.GPIO12, } .build(); // Initialize the shared I2C bus using the refactored i2c_bus module. let shared_i2c = { let config = I2cBusPinConfiguration { i2c_peripheral: peripherals.I2C0, scl: peripherals.GPIO18, sda: peripherals.GPIO17, }; config.build() }; let mut lcd: TertiaryDisplay = TertiaryDisplayPinConfiguration { i2c: shared_i2c }.build(); lcd.load_charset(EXAMPLE).unwrap(); let h = EXAMPLE[HEART]; let e = EXAMPLE[EMPTY]; let b = EXAMPLE[BOX]; if let Err(e) = lcd.write(&alloc::format!( "Custom symbols: {h}{e}{b} And more stuff to wrap and cut off please." )) { log::error!( "Tertiary LCD startup text write failed over shared I2C bus; check the shared bus, wiring, and device responses: {e}" ); } let store = Store::new(peripherals.FLASH).expect("Could not initialize Flash 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; let mut nfc_driver = NfcPn532Driver::new(AtomicDevice::new(shared_i2c)); if nfc_driver.configure_sam().await.is_ok() { log::info!("NFC SAM configuration successful on the shared I2C bus"); } else { log::error!("NFC SAM configuration failed on the shared I2C bus"); } let button_config = InputConfig::default().with_pull(Pull::Up); let inputs = Inputs { up: Input::new(peripherals.GPIO38, button_config), down: Input::new(peripherals.GPIO39, button_config), left: Input::new(peripherals.GPIO40, button_config), right: Input::new(peripherals.GPIO41, button_config), back: Input::new(peripherals.GPIO8, button_config), ok: Input::new(peripherals.GPIO0, button_config), }; display_shit(&mut secondaries[0], "foo 1"); display_shit(&mut secondaries[1], "bar 1"); display_shit(&mut secondaries[2], "baz 1"); let outputs = { let [sec_1, sec_2, sec_3] = secondaries; Outputs { primary_display: primary, secondary_display_1: sec_1, secondary_display_2: sec_2, secondary_display_3: sec_3, tertiary_display: lcd, _led_a: (), } }; 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, cardstore, rtc).expect("nfc scanner task failed"), ); } fn display_shit(oled: &mut SecondaryDisplay<'static>, text: &str) { oled.clear().unwrap(); let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On); Text::new(text, Point::new(10, 20), text_style) .draw(oled) .unwrap(); oled.flush().unwrap(); }