lilkaoxide 0.1.0

Rust support library for Lilka console
use crate::spi::{InnerDelay, SpiBusWrapper, SpiDev, SpiInitError, make_device};
use esp_hal::gpio::{DriveMode, Level, Output, OutputConfig, Pull};
use mipidsi::interface::SpiInterface;
use mipidsi::models::ST7789;
use mipidsi::options::{ColorInversion, Orientation, RefreshOrder, Rotation, TearingEffect};
use mipidsi::{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();
pub type LilkaDisplay =
    Display<SpiInterface<'static, 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",
        }
    }
}

pub fn init_display(
    dp: esp_hal::peripherals::GPIO46,
    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_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)?;

    Ok(display)
}