1#![doc = include_str!("../README.md")]
2#![doc(hidden)]
3#![cfg_attr(not(any(test, feature = "std")), no_std)]
4
5#[cfg(all(feature = "async", feature = "async-trait"))]
6extern crate alloc;
7#[cfg(feature = "logging")]
8#[macro_use]
9extern crate log;
10#[cfg(feature = "spidev")]
11extern crate spidev;
12
13#[cfg(not(feature = "logging"))]
14#[macro_use]
15mod logging {
16 #[macro_export]
17 macro_rules! trace {
18 ($($arg:tt)*) => { _ = ($($arg)*) };
19 }
20}
21
22pub mod bus;
23pub mod delay;
24mod sd;
25
26use bus::Error;
27pub use sd::registers::NumBlocks;
28use sd::{registers::CSD, BLOCK_SIZE};
29
30pub struct SD<BUS> {
31 bus: BUS,
32 card: sd::Card,
33 csd: CSD,
34}
35
36type LBA = u32;
37
38#[cfg_attr(not(feature = "async"), deasync::deasync)]
39impl<E, BUS> SD<BUS>
40where
41 BUS: bus::Read<Error = E> + bus::Write<Error = E> + bus::Bus<Error = E>,
42{
43 pub async fn init(mut bus: BUS, card: sd::Card) -> Result<Self, Error<E>> {
44 bus.before()?;
45 let result = bus.read_csd().await;
46 bus.after()?;
47 result.map(|csd| Self { bus, card, csd })
48 }
49
50 pub fn csd(&self) -> CSD {
51 self.csd
52 }
53
54 pub fn bus<R>(&mut self, f: impl Fn(&mut BUS) -> R) -> R {
55 f(&mut self.bus)
56 }
57
58 pub async fn read<'a, B>(&mut self, address: LBA, blocks: B) -> Result<(), Error<E>>
59 where
60 B: core::iter::ExactSizeIterator<Item = &'a mut [u8; BLOCK_SIZE]> + Send,
61 {
62 if blocks.len() == 0 {
63 return Ok(());
64 }
65 self.bus.before()?;
66 let address = if self.card.high_capacity() { address } else { address * BLOCK_SIZE as u32 };
67 let result = self.bus.read(address, blocks).await;
68 self.bus.after().and(result)
69 }
70
71 pub async fn write<'a, B>(&mut self, address: LBA, blocks: B) -> Result<(), Error<E>>
72 where
73 B: core::iter::ExactSizeIterator<Item = &'a [u8; BLOCK_SIZE]> + Send,
74 {
75 if blocks.len() == 0 {
76 return Ok(());
77 }
78 let address = if self.card.high_capacity() { address } else { address * BLOCK_SIZE as u32 };
79 self.bus.before()?;
80 let result = self.bus.write(address, blocks).await;
81 self.bus.after().and(result)
82 }
83
84 pub fn num_blocks(&self) -> NumBlocks {
85 self.csd.num_blocks()
86 }
87
88 pub fn block_size_shift(&self) -> u8 {
89 self.csd.block_size_shift()
90 }
91}