use alloc::boxed::Box; use core::cell::RefCell; use embedded_hal::digital::{ErrorType, OutputPin as EhOutputPin, PinState}; use esp_hal::delay::Delay; use esp_hal::gpio::interconnect::{PeripheralInput, PeripheralOutput}; use esp_hal::gpio::{Level, Output, OutputConfig, OutputPin}; use esp_hal::spi::master::{Config as SpiConfig, Spi}; use esp_hal::spi::Mode; use esp_hal::time::Rate; use crate::display::primary_lcd::{init_primary_lcd_on_bus, PrimaryLcdDisplay}; use crate::display::secondary_oled::{init_secondary_oled_on_bus, SecondaryOledDisplay}; pub struct SharedPin<'a>(pub &'a RefCell>); impl<'a> ErrorType for SharedPin<'a> { type Error = core::convert::Infallible; } impl<'a> EhOutputPin for SharedPin<'a> { fn set_low(&mut self) -> Result<(), Self::Error> { self.0.borrow_mut().set_low(); Ok(()) } fn set_high(&mut self) -> Result<(), Self::Error> { self.0.borrow_mut().set_high(); Ok(()) } fn set_state(&mut self, state: PinState) -> Result<(), Self::Error> { self.0.borrow_mut().set_state(state); Ok(()) } } pub type DisplaySpiBus = Spi<'static, esp_hal::Blocking>; pub type DualPrimaryDisplay<'a> = PrimaryLcdDisplay<'a, DisplaySpiBus, SharedPin<'a>, SharedPin<'a>>; pub type DualSecondaryDisplay<'a> = SecondaryOledDisplay<'a, DisplaySpiBus, SharedPin<'a>>; pub fn init_dual_displays( spi_peripheral: SPI, sck: SCK, mosi: MOSI, miso: MISO, cs_primary: CS1, cs_secondary: CS2, reset_pin: RES, dc_pin: DC, delay: &mut Delay, ) -> (DualPrimaryDisplay<'static>, DualSecondaryDisplay<'static>) where SPI: esp_hal::spi::master::Instance + 'static, SCK: PeripheralOutput<'static>, MOSI: PeripheralOutput<'static>, MISO: PeripheralInput<'static>, CS1: OutputPin + 'static, CS2: OutputPin + 'static, RES: OutputPin + 'static, DC: OutputPin + 'static, { let spi = Spi::new( spi_peripheral, SpiConfig::default().with_frequency(Rate::from_khz(20_000)).with_mode(Mode::_0), ) .unwrap() .with_sck(sck) .with_mosi(mosi) .with_miso(miso); let bus_static: &'static RefCell = Box::leak(Box::new(RefCell::new(spi))); let reset_static: &'static RefCell> = Box::leak(Box::new(RefCell::new( Output::new(reset_pin, Level::High, OutputConfig::default()), ))); let dc_static: &'static RefCell> = Box::leak(Box::new(RefCell::new( Output::new(dc_pin, Level::High, OutputConfig::default()), ))); let primary = init_primary_lcd_on_bus( bus_static, cs_primary, SharedPin(reset_static), SharedPin(dc_static), delay, ); let secondary = init_secondary_oled_on_bus( bus_static, cs_secondary, SharedPin(reset_static), SharedPin(dc_static), delay, ); (primary, secondary) }