pub mod bus;
pub mod read;
pub mod write;
use embedded_hal::digital::OutputPin;
use embedded_timers::{clock::Clock, instant::Instant};
use crate::{
delay::Delay,
sd::{
command::{AppCommand, Command, SendInterfaceCondition},
response::{self, R1Status},
Card,
},
};
pub use bus::{BUSError, Bus, Transfer};
impl<E, F, SPI, CS, C, I> Bus<SPI, CS, C>
where
SPI: Transfer<Error = E>,
CS: OutputPin<Error = F>,
C: Clock<Instant = I>,
I: Instant,
{
#[cfg_attr(not(feature = "async"), deasync::deasync)]
async fn go_idle(&mut self, delay: &mut impl Delay) -> Result<(), BUSError<E, F>> {
for _ in 0..32 {
match self.send_command(Command::GoIdleState).await {
Ok(r) => match r.r1.has(R1Status::InIdleState) {
true => return Ok(()),
false => return Err(BUSError::NotIdle),
},
Err(BUSError::NoResponse) => (),
Err(e) => return Err(e),
}
delay.delay_ms(10).await;
}
Err(BUSError::NoResponse)
}
#[cfg_attr(not(feature = "async"), deasync::deasync)]
pub async fn init(&mut self, mut delay: impl Delay) -> Result<Card, BUSError<E, F>> {
self.deselect()?;
trace!("Supply 74 clock cycles");
self.tx(&[0xFF; 10]).await?;
self.select()?;
trace!("Go idle");
self.go_idle(&mut delay).await?;
trace!("Query version");
let mut version = 1;
let r = self.send_command(Command::SendIfCond(SendInterfaceCondition::spi())).await?;
if !r.r1.has(R1Status::IllegalCommand) {
version = 2;
let r7 = response::R7(r.ex);
if !r7.voltage_accepted() || r7.echo_back_check_pattern() != 0xAA {
return Err(BUSError::Generic);
}
}
trace!("Version is {}", version);
trace!("Initialize");
let mut r1 = response::R1::default();
for _ in 0..100 {
r1 = self.send_app_command(AppCommand::SDSendOpCond(version > 1)).await?.r1;
if !r1.has(R1Status::InIdleState) {
break;
}
delay.delay_ms(10).await;
}
if r1.has(R1Status::InIdleState) {
return Err(BUSError::Generic);
}
trace!("Read OCR");
let mut card = Card::SDSC(version);
if version > 1 {
let r = self.send_app_command(AppCommand::ReadOCR).await?;
let r3 = response::R3(r.ex);
if r3.card_capacity_status() {
card = Card::SDHC;
}
}
self.deselect()?;
self.rx(&mut [0; 1]).await?; Ok(card)
}
}