1use core::time::Duration;
2use core::{convert::TryFrom, slice};
3
4use embedded_hal::digital::OutputPin;
5use embedded_timers::{clock::Clock, instant::Instant};
6
7use crate::{
8 bus::Read,
9 sd::{
10 command::Command,
11 registers::CSD,
12 transfer::{Token, TokenError},
13 BLOCK_SIZE,
14 },
15};
16
17use super::bus::{BUSError, Bus, Error, Transfer};
18
19impl<E, F, SPI, CS, C, I> Bus<SPI, CS, C>
20where
21 SPI: Transfer<Error = E>,
22 CS: OutputPin<Error = F>,
23 C: Clock<Instant = I>,
24 I: Instant,
25{
26 #[cfg_attr(not(feature = "async"), deasync::deasync)]
27 pub(crate) async fn read_block(&mut self, block: &mut [u8]) -> Result<(), BUSError<E, F>> {
28 let deadline = self.clock.now() + Duration::from_millis(100);
29 let token = loop {
30 if self.clock.now() > deadline {
31 return Err(BUSError::Timeout);
32 }
33 let mut byte = 0u8;
34 self.rx(slice::from_mut(&mut byte)).await?;
35 if byte == 0xFF {
36 continue;
37 }
38 match Token::try_from(byte) {
39 Ok(token) => break token,
40 Err(TokenError::NotToken) => continue,
41 Err(e) => return Err(BUSError::Transfer(e)),
42 }
43 };
44 if token != Token::Start {
45 return Err(BUSError::Generic);
46 }
47 self.rx(block).await?;
48 let mut crc = [0u8; 2];
49 self.rx(&mut crc).await
50 }
51}
52
53#[cfg_attr(not(feature = "async"), deasync::deasync)]
54impl<E, F, SPI, CS, C, I> Read for Bus<SPI, CS, C>
55where
56 SPI: Transfer<Error = E>,
57 CS: OutputPin<Error = F>,
58 C: Clock<Instant = I>,
59 I: Instant,
60{
61 type Error = Error<E, F>;
62
63 async fn read_csd(&mut self) -> Result<CSD, BUSError<E, F>> {
64 self.tx(&[0xFF; 5]).await?;
65 self.select()?;
66 self.send_command(Command::SendCSD(0)).await?;
67 let mut buffer = [0u8; 16];
68 self.read_block(&mut buffer).await?;
69 self.deselect()?;
70 self.tx(&[0xFF]).await?; CSD::try_from(u128::from_be_bytes(buffer)).ok_or(BUSError::Generic)
72 }
73
74 async fn read<'a, B>(&mut self, address: u32, blocks: B) -> Result<(), BUSError<E, F>>
75 where
76 B: core::iter::ExactSizeIterator<Item = &'a mut [u8; BLOCK_SIZE]>,
77 {
78 self.tx(&[0xFF; 5]).await?;
79 self.select()?;
80 let num_blocks = blocks.len();
81 let cmd = match num_blocks {
82 1 => Command::ReadSingleBlock(address),
83 _ => Command::ReadMultipleBlock(address),
84 };
85 self.send_command(cmd).await?;
86 for block in blocks {
87 self.read_block(block).await?;
88 }
89 if num_blocks > 1 {
90 self.send_command(Command::StopTransmission).await?;
91 self.wait(Duration::from_millis(100)).await?;
92 }
93 self.deselect()?;
94 self.tx(&[0xFF]).await }
96}