lilkaoxide 0.1.0

Rust support library for Lilka console
use crate::spi::{InnerDelay, SpiBusWrapper, SpiDev, SpiInitError, make_device};
use embedded_sdmmc::{SdCard, TimeSource, Timestamp, VolumeManager};
use esp_hal::gpio::{Level, Output, OutputConfig};
use esp_hal::peripherals::GPIO16;

pub type SDC<'a> = SdCard<SpiDev<'a>, InnerDelay>;
#[derive(Default)]
pub struct Timesource();
impl TimeSource for Timesource {
    fn get_timestamp(&self) -> Timestamp {
        Timestamp {
            year_since_1970: 0,
            zero_indexed_month: 0,
            zero_indexed_day: 0,
            hours: 0,
            minutes: 0,
            seconds: 0,
        }
    }
}

pub type SdVolMgr<'a> = VolumeManager<SDC<'a>, Timesource>;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SdInitError {
    SpiDevice(SpiInitError),
    CardReadFailed,
}

impl SdInitError {
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::SpiDevice(err) => err.as_str(),
            Self::CardReadFailed => "SD card read failed",
        }
    }
}

pub fn init_sd<'a>(
    spi_bus: &'a SpiBusWrapper,
    sd_cs: GPIO16<'a>,
    delay: InnerDelay,
) -> Result<SDC<'a>, SdInitError> {
    let sd_cs = Output::new(sd_cs, Level::Low, OutputConfig::default());
    let spi_dev = make_device(spi_bus, sd_cs, delay.clone()).map_err(SdInitError::SpiDevice)?;
    let sdcard = SdCard::new(spi_dev, delay);

    let mut card_size = None;
    for attempt in 1..=5 {
        match sdcard.num_bytes() {
            Ok(size) => {
                card_size = Some(size);
                defmt::info!("SD: Detected on attempt {}", attempt);
                break;
            }
            Err(_e) => {
                defmt::debug!("SD: num_bytes attempt {} failed", attempt);
                if attempt < 5 {
                    delay.delay_millis(50);
                }
            }
        }
    }

    match card_size {
        Some(size) => {
            let size_mb = size / (1024 * 1024);
            let size_gb = size / (1024 * 1024 * 1024);
            if size_gb > 0 {
                defmt::info!(
                    "SD: {}.{} GB detected",
                    size_gb,
                    (size % (1024 * 1024 * 1024)) / (100 * 1024 * 1024)
                );
            } else {
                defmt::info!("SD: {} MB detected", size_mb);
            }
        }
        None => defmt::warn!("SD: Card not ready during init; continuing without mounted card"),
    }
    Ok(sdcard)
}