1#![cfg_attr(not(any(test, feature = "std")), no_std)]
30
31extern crate alloc;
32#[macro_use]
33extern crate log;
34#[cfg(feature = "spidev")]
35extern crate spidev;
36
37pub mod bus;
38pub mod delay;
39mod sd;
40
41use bus::Error;
42pub use sd::registers::NumBlocks;
43use sd::{registers::CSD, BLOCK_SIZE};
44
45pub struct SD<BUS> {
46 bus: BUS,
47 card: sd::Card,
48 csd: CSD,
49}
50
51type LBA = u32;
52
53#[cfg_attr(not(feature = "async"), deasync::deasync)]
54impl<E, BUS> SD<BUS>
55where
56 BUS: bus::Read<Error = E> + bus::Write<Error = E> + bus::Bus<Error = E>,
57{
58 pub async fn init(mut bus: BUS, card: sd::Card) -> Result<Self, Error<E>> {
59 bus.before()?;
60 let result = bus.read_csd().await;
61 bus.after()?;
62 result.map(|csd| Self { bus, card, csd })
63 }
64
65 pub fn csd(&self) -> CSD {
66 self.csd
67 }
68
69 pub fn bus<R>(&mut self, f: impl Fn(&mut BUS) -> R) -> R {
70 f(&mut self.bus)
71 }
72
73 pub async fn read<'a, B>(&mut self, address: LBA, blocks: B) -> Result<(), Error<E>>
74 where
75 B: core::iter::ExactSizeIterator<Item = &'a mut [u8; BLOCK_SIZE]> + Send,
76 {
77 if blocks.len() == 0 {
78 return Ok(());
79 }
80 self.bus.before()?;
81 let address = if self.card.high_capacity() { address } else { address * BLOCK_SIZE as u32 };
82 let result = self.bus.read(address, blocks).await;
83 self.bus.after().and(result)
84 }
85
86 pub async fn write<'a, B>(&mut self, address: LBA, blocks: B) -> Result<(), Error<E>>
87 where
88 B: core::iter::ExactSizeIterator<Item = &'a [u8; BLOCK_SIZE]> + Send,
89 {
90 if blocks.len() == 0 {
91 return Ok(());
92 }
93 let address = if self.card.high_capacity() { address } else { address * BLOCK_SIZE as u32 };
94 self.bus.before()?;
95 let result = self.bus.write(address, blocks).await;
96 self.bus.after().and(result)
97 }
98
99 pub fn num_blocks(&self) -> NumBlocks {
100 self.csd.num_blocks()
101 }
102
103 pub fn block_size_shift(&self) -> u8 {
104 self.csd.block_size_shift()
105 }
106}