use embassy_time::Delay;
use embedded_hal_bus::spi::ExclusiveDevice;
pub use embedded_sdmmc as fs;
use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx, SdCard, TimeSource, Timestamp};
use esp_hal::Blocking;
use esp_hal::gpio::{Level, Output, OutputConfig};
use esp_hal::peripherals::DMA_CH2;
use esp_hal::spi::Mode;
use esp_hal::spi::master::{Config, Spi};
use esp_hal::time::Rate;
use crate::SpiBusResources;
pub const INIT_FREQUENCY: Rate = Rate::from_khz(400);
pub const FREQUENCY: Rate = Rate::from_mhz(20);
pub type SdSpi = ExclusiveDevice<Spi<'static, Blocking>, Output<'static>, Delay>;
pub type Card = SdCard<SdSpi, Delay>;
pub type Error = embedded_sdmmc::SdCardError;
fn spi_config(frequency: Rate) -> Config {
Config::default()
.with_frequency(frequency)
.with_mode(Mode::_0)
}
impl SpiBusResources {
pub fn into_sd(self) -> Result<Sd, Error> {
let out = OutputConfig::default();
let ext_cs = Output::new(self.ext_cs, Level::High, out);
let sd_cs = Output::new(self.sd_cs, Level::High, out);
let mut spi = Spi::new(self.spi, spi_config(INIT_FREQUENCY))
.expect("400 kHz mode 0 is a valid SPI configuration")
.with_sck(self.sck)
.with_mosi(self.mosi)
.with_miso(self.miso);
spi.write(&[0xFF; 10]).map_err(|_| Error::Transport)?;
let Ok(dev) = ExclusiveDevice::new(spi, sd_cs, Delay);
let card = SdCard::new(dev, Delay);
card.num_bytes()?; card.spi(|dev| dev.bus_mut().apply_config(&spi_config(FREQUENCY)))
.expect("20 MHz mode 0 is a valid SPI configuration");
Ok(Sd {
card,
_ext_cs: ext_cs,
_dma: self.dma,
})
}
}
pub struct Sd {
card: Card,
_ext_cs: Output<'static>,
_dma: DMA_CH2<'static>,
}
impl Sd {
pub fn size_bytes(&self) -> Result<u64, Error> {
self.card.num_bytes()
}
pub fn card_type(&self) -> Option<embedded_sdmmc::embedded_sdmmc_types::sdcard::CardType> {
self.card.get_card_type()
}
pub fn card(&self) -> &Card {
&self.card
}
}
impl BlockDevice for Sd {
type Error = Error;
fn read(&self, blocks: &mut [Block], start: BlockIdx) -> Result<(), Error> {
self.card.read(blocks, start)
}
fn write(&self, blocks: &[Block], start: BlockIdx) -> Result<(), Error> {
self.card.write(blocks, start)
}
fn num_blocks(&self) -> Result<BlockCount, Error> {
self.card.num_blocks()
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct FixedTime;
impl TimeSource for FixedTime {
fn get_timestamp(&self) -> Timestamp {
Timestamp::from_calendar(2026, 1, 1, 0, 0, 0).expect("valid date")
}
}