lilkaoxide 0.1.1

Rust support library for Lilka console
use crate::spi::{InnerDelay, SpiBusWrapper, SpiDev, SpiInitError, make_device};
use esp_hal::gpio::{DriveMode, Level, Output, OutputConfig, Pull};
#[cfg(feature = "blocking")]
use mipidsi::{
    interface::SpiInterface,
    models::ST7789,
    options::{ColorInversion, Orientation, RefreshOrder, Rotation, TearingEffect},
    Builder,
    Display,
    NoResetPin
};
#[cfg(feature = "async")]
use lcd_async::{
    interface::SpiInterface,
    models::ST7789,
    options::{ColorInversion, Orientation, RefreshOrder, Rotation, TearingEffect},
    Builder,
    Display,
    NoResetPin
};
use static_cell::StaticCell;
#[cfg(feature = "display_buffer_512")]
static DISPLAY_BUFFER_CELL: StaticCell<[u8; 512]> = StaticCell::new();
#[cfg(feature = "display_buffer_1024")]
static DISPLAY_BUFFER_CELL: StaticCell<[u8; 1024]> = StaticCell::new();
#[cfg(feature = "display_buffer_8192")]
static DISPLAY_BUFFER_CELL: StaticCell<[u8; 8192]> = StaticCell::new();
#[cfg(feature = "blocking")]
pub type LilkaDisplay =
    Display<SpiInterface<'static, SpiDev<'static>, Output<'static>>, ST7789, NoResetPin>;
#[cfg(feature = "async")]
pub type LilkaDisplay =
    Display<SpiInterface<SpiDev<'static>, Output<'static>>, ST7789, NoResetPin>;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DisplayInitError {
    SpiDevice(SpiInitError),
    ControllerInitFailed,
    TearingConfigFailed,
}

impl DisplayInitError {
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::SpiDevice(err) => err.as_str(),
            Self::ControllerInitFailed => "Display init failed",
            Self::TearingConfigFailed => "Display tearing config failed",
        }
    }
}

#[cfg(feature = "blocking")]
pub fn init_display(
    dp: esp_hal::peripherals::GPIO46<'static>,
    dc: esp_hal::peripherals::GPIO15<'static>,
    cs: esp_hal::peripherals::GPIO7<'static>,
    spi_bus: &'static SpiBusWrapper,
    mut delay: InnerDelay,
    refresh_order: RefreshOrder,
    rotation: Rotation,
    tearing: TearingEffect,
) -> Result<LilkaDisplay, DisplayInitError> {
    let mut display_power = Output::new(
        dp,
        Level::High,
        OutputConfig::default()
            .with_drive_mode(DriveMode::PushPull)
            .with_pull(Pull::Down),
    );
    display_power.set_high();
    let dc: Output<'static> = Output::new(
        dc,
        Level::Low,
        OutputConfig::default().with_drive_mode(DriveMode::PushPull),
    );
    let disp_cs: Output<'static> = Output::new(
        cs,
        Level::Low,
        OutputConfig::default().with_drive_mode(DriveMode::PushPull),
    );
    let spi_dev =
        make_device(spi_bus, disp_cs, delay.clone()).map_err(DisplayInitError::SpiDevice)?;
    #[cfg(feature = "blocking")]
    {
        cfg_if::cfg_if! {
            if #[cfg(feature = "display_buffer_512")] {
                let di = SpiInterface::new(spi_dev, dc, DISPLAY_BUFFER_CELL.init([0_u8; 512]));
            } else if #[cfg(feature = "display_buffer_1024")] {
                let di = SpiInterface::new(spi_dev, dc, DISPLAY_BUFFER_CELL.init([0_u8; 1024]));
            } else if #[cfg(feature = "display_buffer_8192")] {
                let di = SpiInterface::new(spi_dev, dc, DISPLAY_BUFFER_CELL.init([0_u8; 8192]));
            } else {
                compile_error!("Один з display_buffer_512, display_buffer_1024, або display_buffer_8192 має бути активний");
            }
        }
        let mut display = Builder::new(ST7789, di)
            .refresh_order(refresh_order)
            .invert_colors(ColorInversion::Inverted)
            .display_size(240, 280)
            .orientation(Orientation::new().rotate(rotation))
            .display_offset(0, 20)
            .color_order(mipidsi::options::ColorOrder::Rgb)
            .init(&mut delay)
            .map_err(|_| DisplayInitError::ControllerInitFailed)?;
        display
            .set_tearing_effect(tearing)
            .map_err(|_| DisplayInitError::TearingConfigFailed)?;
        return Ok(display);
    }
}

#[cfg(feature = "async")]
pub async fn init_display(
    dp: esp_hal::peripherals::GPIO46<'static>,
    dc: esp_hal::peripherals::GPIO15<'static>,
    cs: esp_hal::peripherals::GPIO7<'static>,
    spi_bus: &'static SpiBusWrapper,
    mut delay: InnerDelay,
    refresh_order: RefreshOrder,
    rotation: Rotation,
    tearing: TearingEffect,
) -> Result<LilkaDisplay, DisplayInitError> {
    let mut display_power = Output::new(
        dp,
        Level::High,
        OutputConfig::default()
            .with_drive_mode(DriveMode::PushPull)
            .with_pull(Pull::Down),
    );
    display_power.set_high();
    let dc: Output<'static> = Output::new(
        dc,
        Level::Low,
        OutputConfig::default().with_drive_mode(DriveMode::PushPull),
    );
    let disp_cs: Output<'static> = Output::new(
        cs,
        Level::Low,
        OutputConfig::default().with_drive_mode(DriveMode::PushPull),
    );
    let spi_dev =
        make_device(spi_bus, disp_cs, delay.clone()).map_err(DisplayInitError::SpiDevice)?;
    let di = SpiInterface::new(spi_dev, dc);
    let mut display = Builder::new(ST7789, di)
        .refresh_order(refresh_order)
        .invert_colors(ColorInversion::Inverted)
        .display_size(240, 280)
        .orientation(Orientation::new().rotate(rotation))
        .display_offset(0, 20)
        .color_order(lcd_async::options::ColorOrder::Rgb)
        .init(&mut delay)
        .await
        .map_err(|_| DisplayInitError::ControllerInitFailed)?;
    display
        .set_tearing_effect(tearing)
        .await
        .map_err(|_| DisplayInitError::TearingConfigFailed)?;

    Ok(display)
}