diff --git a/src/bin/main.rs b/src/bin/main.rs index 934c4fb..2efc3a9 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -18,7 +18,6 @@ use creaturedex::drivers::tertiary_lcd::{ 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; @@ -68,32 +67,40 @@ async fn main(spawner: Spawner) { 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(); + let (primary, mut secondaries) = retry( + 5, + 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, + }, + spi_bus::DisplayPinConfiguration::build, + ); // Initialize the shared I2C bus using the refactored i2c_bus module. let shared_i2c = { - let config = I2cBusPinConfiguration { + use alloc::boxed::Box; + let bus = retry(5, I2cBusPinConfiguration { i2c_peripheral: peripherals.I2C0, scl: peripherals.GPIO18, sda: peripherals.GPIO17, - }; - config.build() + }, I2cBusPinConfiguration::build); + Box::leak(Box::new(bus)) }; - let mut lcd: TertiaryDisplay = TertiaryDisplayPinConfiguration { i2c: shared_i2c }.build(); + let mut lcd: TertiaryDisplay = retry( + 5, + TertiaryDisplayPinConfiguration { i2c: shared_i2c }, + TertiaryDisplayPinConfiguration::build, + ); lcd.load_charset(EXAMPLE).unwrap(); let h = EXAMPLE[HEART]; let e = EXAMPLE[EMPTY]; @@ -150,6 +157,7 @@ async fn main(spawner: Spawner) { spawner.spawn( background_tasks::nfc_scanner(nfc_driver, cardstore, rtc).expect("nfc scanner task failed"), ); + core::future::pending::<()>().await } fn display_shit(oled: &mut SecondaryDisplay<'static>, text: &str) { @@ -161,3 +169,17 @@ fn display_shit(oled: &mut SecondaryDisplay<'static>, text: &str) { .unwrap(); oled.flush().unwrap(); } + +fn retry Result>(repetitions: u32, input: T, mut action: F) -> U { + let mut initial_state = input; + for iteration in 0..repetitions { + log::debug!("Trying to initialize. Retries: {iteration}"); + + match action(initial_state) { + Ok(success) => return success, + Err(recovered_input) => initial_state = recovered_input, + } + } + + panic!("Init failed after {repetitions} retries.") +} diff --git a/src/drivers/i2c_bus.rs b/src/drivers/i2c_bus.rs index 23500ed..db4bec2 100644 --- a/src/drivers/i2c_bus.rs +++ b/src/drivers/i2c_bus.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use embedded_hal_bus::i2c::AtomicDevice; use embedded_hal_bus::util::AtomicCell; use esp_hal::gpio::interconnect::PeripheralInput; @@ -21,18 +20,19 @@ where SCL: PeripheralOutput<'a> + PeripheralInput<'a>, SDA: PeripheralOutput<'a> + PeripheralInput<'a>, { - pub fn build(self) -> I2cBus<'a> { + pub fn build(self) -> Result>, Self> { let config = Config::default().with_frequency(esp_hal::time::Rate::from_khz(400)); - let i2c = match I2c::new(self.i2c_peripheral, config) { - Ok(bus) => bus.with_sda(self.sda).with_scl(self.scl), + match I2c::new(self.i2c_peripheral, config) { + Ok(bus) => { + let i2c = bus.with_sda(self.sda).with_scl(self.scl); + log::info!("Shared I2C bus ready on GPIO17 (SDA) and GPIO18 (SCL)"); + Ok(AtomicCell::new(i2c)) + } Err(e) => { log::error!("Shared I2C bus initialization failed for GPIO17/GPIO18: {e:?}"); - panic!("Shared I2C bus initialization failed"); + unimplemented!("Partial move makes it impossible to retry."); + // Err(self) } - }; - let shared_i2c = Box::leak(Box::new(AtomicCell::new(i2c))); - log::info!("Shared I2C bus ready on GPIO17 (SDA) and GPIO18 (SCL)"); - - shared_i2c + } } } diff --git a/src/drivers/spi_bus.rs b/src/drivers/spi_bus.rs index 036b1a5..89ec939 100644 --- a/src/drivers/spi_bus.rs +++ b/src/drivers/spi_bus.rs @@ -135,7 +135,7 @@ where RES2: OutputPin + 'static, DC: OutputPin + 'static, { - pub fn build(self) -> (PrimaryDisplay<'static>, [SecondaryDisplay<'static>; 3]) { + pub fn build(self) -> Result<(PrimaryDisplay<'static>, [SecondaryDisplay<'static>; 3]), Self> { let spi = Spi::new( self.spi_peripheral, SpiConfig::default() @@ -178,7 +178,7 @@ where } .build(); - (primary, secondaries) + Ok((primary, secondaries)) } } diff --git a/src/drivers/tertiary_lcd.rs b/src/drivers/tertiary_lcd.rs index 36213f5..3c3df68 100644 --- a/src/drivers/tertiary_lcd.rs +++ b/src/drivers/tertiary_lcd.rs @@ -15,19 +15,20 @@ pub struct TertiaryDisplayPinConfiguration<'a> { } impl<'a> TertiaryDisplayPinConfiguration<'a> { - pub fn build(self) -> TertiaryDisplay<'a> { + pub fn build(self) -> Result, Self> { let device = AtomicDevice::new(self.i2c); let mut lcd = CharacterDisplayPCF8574T::new(device, LcdDisplayType::Lcd16x2, Delay::new()); match lcd.init() { Ok(()) => { log::info!("I2C tertiary LCD initialized on PCF8574T at address 0x27"); - TertiaryDisplay { + Ok(TertiaryDisplay { display: lcd, charset: create_custom_char_set!(), - } + }) } Err(e) => { - panic!("I2C tertiary LCD init failed on PCF8574T at address 0x27: {e}"); + log::error!("I2C tertiary LCD init failed on PCF8574T at address 0x27: {e}"); + Err(self) } } } @@ -407,4 +408,3 @@ pub const BOX: CharMap = [ ]; pub const EXAMPLE: CustomCharset = create_custom_char_set!(HEART, BOX, EMPTY); -