1use core::fmt;
2use core::marker::PhantomData;
3
4#[derive(Debug, Copy, Clone)]
6#[non_exhaustive]
7pub enum CardCapacity {
8 StandardCapacity,
10 HighCapacity,
12}
13
14impl Default for CardCapacity {
15 fn default() -> Self {
16 CardCapacity::StandardCapacity
17 }
18}
19
20#[derive(Copy, Clone, Debug, Eq, PartialEq)]
22#[allow(missing_docs)]
23pub enum BusWidth {
24 #[non_exhaustive]
25 Unknown,
26 One = 1,
27 Four = 4,
28 Eight = 8,
29}
30
31#[derive(Debug, Copy, Clone, Eq, PartialEq)]
32pub enum BlockSize {
33 #[non_exhaustive]
34 B1 = 0,
35 B2 = 1,
36 B4 = 2,
37 B8 = 3,
38 B16 = 4,
39 B32 = 5,
40 B64 = 6,
41 B128 = 7,
42 B256 = 8,
43 B512 = 9,
44 B1024 = 10,
45 B2048 = 11,
46 B4096 = 12,
47 B8192 = 13,
48 B16kB = 14,
49 Unknown = 15,
50}
51
52#[derive(Eq, PartialEq, Copy, Clone, Debug)]
58#[allow(dead_code)]
59pub enum CurrentState {
60 Ready = 1,
62 Identification = 2,
64 Standby = 3,
66 Transfer = 4,
68 Sending = 5,
70 Receiving = 6,
72 Programming = 7,
74 Disconnected = 8,
76 BusTest = 9,
78 Sleep = 10,
80 Error = 128,
83}
84
85impl From<u8> for CurrentState {
86 fn from(n: u8) -> Self {
87 match n {
88 1 => Self::Ready,
89 2 => Self::Identification,
90 3 => Self::Standby,
91 4 => Self::Transfer,
92 5 => Self::Sending,
93 6 => Self::Receiving,
94 7 => Self::Programming,
95 8 => Self::Disconnected,
96 9 => Self::BusTest,
97 10 => Self::Sleep,
98 _ => Self::Error,
99 }
100 }
101}
102
103#[derive(Copy, Clone, Eq, PartialEq)]
104#[allow(non_camel_case_types)]
105pub enum CurrentConsumption {
106 I_0mA,
107 I_1mA,
108 I_5mA,
109 I_10mA,
110 I_25mA,
111 I_35mA,
112 I_45mA,
113 I_60mA,
114 I_80mA,
115 I_100mA,
116 I_200mA,
117}
118impl From<&CurrentConsumption> for u32 {
119 fn from(i: &CurrentConsumption) -> u32 {
120 match i {
121 CurrentConsumption::I_0mA => 0,
122 CurrentConsumption::I_1mA => 1,
123 CurrentConsumption::I_5mA => 5,
124 CurrentConsumption::I_10mA => 10,
125 CurrentConsumption::I_25mA => 25,
126 CurrentConsumption::I_35mA => 35,
127 CurrentConsumption::I_45mA => 45,
128 CurrentConsumption::I_60mA => 60,
129 CurrentConsumption::I_80mA => 80,
130 CurrentConsumption::I_100mA => 100,
131 CurrentConsumption::I_200mA => 200,
132 }
133 }
134}
135impl CurrentConsumption {
136 fn from_minimum_reg(reg: u128) -> CurrentConsumption {
137 match reg & 0x7 {
138 0 => CurrentConsumption::I_0mA,
139 1 => CurrentConsumption::I_1mA,
140 2 => CurrentConsumption::I_5mA,
141 3 => CurrentConsumption::I_10mA,
142 4 => CurrentConsumption::I_25mA,
143 5 => CurrentConsumption::I_35mA,
144 6 => CurrentConsumption::I_60mA,
145 _ => CurrentConsumption::I_100mA,
146 }
147 }
148 fn from_maximum_reg(reg: u128) -> CurrentConsumption {
149 match reg & 0x7 {
150 0 => CurrentConsumption::I_1mA,
151 1 => CurrentConsumption::I_5mA,
152 2 => CurrentConsumption::I_10mA,
153 3 => CurrentConsumption::I_25mA,
154 4 => CurrentConsumption::I_35mA,
155 5 => CurrentConsumption::I_45mA,
156 6 => CurrentConsumption::I_80mA,
157 _ => CurrentConsumption::I_200mA,
158 }
159 }
160}
161impl fmt::Debug for CurrentConsumption {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 let ma: u32 = self.into();
164 write!(f, "{} mA", ma)
165 }
166}
167
168#[derive(Clone, Copy, Default)]
172pub struct OCR<Ext>(pub(crate) u32, PhantomData<Ext>);
173impl<Ext> From<u32> for OCR<Ext> {
174 fn from(word: u32) -> Self {
175 Self(word, PhantomData)
176 }
177}
178impl<Ext> OCR<Ext> {
179 pub fn is_busy(&self) -> bool {
181 self.0 & 0x8000_0000 == 0 }
183}
184
185#[derive(Clone, Copy, Default)]
189pub struct CID<Ext> {
190 pub(crate) inner: u128,
191 pub(crate) bytes: [u8; 16],
192 ext: PhantomData<Ext>,
193}
194impl<Ext> From<u128> for CID<Ext> {
195 fn from(inner: u128) -> Self {
196 Self {
197 inner,
198 bytes: inner.to_be_bytes(),
199 ext: PhantomData,
200 }
201 }
202}
203impl<Ext> From<[u32; 4]> for CID<Ext> {
205 fn from(words: [u32; 4]) -> Self {
206 let inner = ((words[3] as u128) << 96)
207 | ((words[2] as u128) << 64)
208 | ((words[1] as u128) << 32)
209 | words[0] as u128;
210 inner.into()
211 }
212}
213impl<Ext> CID<Ext> {
214 pub fn manufacturer_id(&self) -> u8 {
216 self.bytes[0]
217 }
218 #[allow(unused)]
219 fn crc7(&self) -> u8 {
220 (self.bytes[15] >> 1) & 0x7F
221 }
222}
223
224#[derive(Clone, Copy, Default)]
226pub struct CSD<Ext>(pub(crate) u128, PhantomData<Ext>);
227impl<Ext> From<u128> for CSD<Ext> {
228 fn from(inner: u128) -> Self {
229 Self(inner, PhantomData)
230 }
231}
232impl<Ext> From<[u32; 4]> for CSD<Ext> {
234 fn from(words: [u32; 4]) -> Self {
235 let inner = ((words[3] as u128) << 96)
236 | ((words[2] as u128) << 64)
237 | ((words[1] as u128) << 32)
238 | words[0] as u128;
239 inner.into()
240 }
241}
242
243impl<Ext> CSD<Ext> {
244 pub fn version(&self) -> u8 {
246 (self.0 >> 126) as u8 & 3
247 }
248 pub fn transfer_rate(&self) -> u8 {
250 (self.0 >> 96) as u8
251 }
252 pub fn block_length(&self) -> BlockSize {
255 match (self.0 >> 80) & 0xF {
257 0 => BlockSize::B1,
258 1 => BlockSize::B2,
259 2 => BlockSize::B4,
260 3 => BlockSize::B8,
261 4 => BlockSize::B16,
262 5 => BlockSize::B32,
263 6 => BlockSize::B64,
264 7 => BlockSize::B128,
265 8 => BlockSize::B256,
266 9 => BlockSize::B512,
267 10 => BlockSize::B1024,
268 11 => BlockSize::B2048,
269 12 => BlockSize::B4096,
270 13 => BlockSize::B8192,
271 14 => BlockSize::B16kB,
272 _ => BlockSize::Unknown,
273 }
274 }
275 pub fn read_current_minimum_vdd(&self) -> CurrentConsumption {
277 CurrentConsumption::from_minimum_reg((self.0 >> 59) & 0x7)
278 }
279 pub fn write_current_minimum_vdd(&self) -> CurrentConsumption {
281 CurrentConsumption::from_minimum_reg((self.0 >> 56) & 0x7)
282 }
283 pub fn read_current_maximum_vdd(&self) -> CurrentConsumption {
285 CurrentConsumption::from_maximum_reg((self.0 >> 53) & 0x7)
286 }
287 pub fn write_current_maximum_vdd(&self) -> CurrentConsumption {
289 CurrentConsumption::from_maximum_reg((self.0 >> 50) & 0x7)
290 }
291}
292
293#[derive(Clone, Copy)]
299pub struct CardStatus<Ext>(pub(crate) u32, PhantomData<Ext>);
300
301impl<Ext> From<u32> for CardStatus<Ext> {
302 fn from(word: u32) -> Self {
303 Self(word, PhantomData)
304 }
305}
306
307impl<Ext> CardStatus<Ext> {
308 pub fn out_of_range(&self) -> bool {
310 self.0 & 0x8000_0000 != 0
311 }
312 pub fn address_error(&self) -> bool {
314 self.0 & 0x4000_0000 != 0
315 }
316 pub fn block_len_error(&self) -> bool {
318 self.0 & 0x2000_0000 != 0
319 }
320 pub fn erase_seq_error(&self) -> bool {
322 self.0 & 0x1000_0000 != 0
323 }
324 pub fn erase_param(&self) -> bool {
326 self.0 & 0x800_0000 != 0
327 }
328 pub fn wp_violation(&self) -> bool {
330 self.0 & 0x400_0000 != 0
331 }
332 pub fn card_is_locked(&self) -> bool {
334 self.0 & 0x200_0000 != 0
335 }
336 pub fn lock_unlock_failed(&self) -> bool {
338 self.0 & 0x100_0000 != 0
339 }
340 pub fn com_crc_error(&self) -> bool {
342 self.0 & 0x80_0000 != 0
343 }
344 pub fn illegal_command(&self) -> bool {
346 self.0 & 0x40_0000 != 0
347 }
348 pub fn card_ecc_failed(&self) -> bool {
350 self.0 & 0x20_0000 != 0
351 }
352 pub fn cc_error(&self) -> bool {
354 self.0 & 0x10_0000 != 0
355 }
356 pub fn error(&self) -> bool {
358 self.0 & 0x8_0000 != 0
359 }
360 pub fn csd_overwrite(&self) -> bool {
362 self.0 & 0x1_0000 != 0
363 }
364 pub fn wp_erase_skip(&self) -> bool {
366 self.0 & 0x8000 != 0
367 }
368 pub fn erase_reset(&self) -> bool {
370 self.0 & 0x2000 != 0
371 }
372 pub fn state(&self) -> CurrentState {
374 CurrentState::from(((self.0 >> 9) & 0xF) as u8)
375 }
376 pub fn ready_for_data(&self) -> bool {
378 self.0 & 0x100 != 0
379 }
380 pub fn app_cmd(&self) -> bool {
382 self.0 & 0x20 != 0
383 }
384}
385
386#[derive(Debug, Copy, Clone, Default)]
390pub struct RCA<Ext>(pub(crate) u32, PhantomData<Ext>);
391impl<Ext> From<u32> for RCA<Ext> {
392 fn from(word: u32) -> Self {
393 Self(word, PhantomData)
394 }
395}
396impl<Ext> RCA<Ext> {
397 pub fn address(&self) -> u16 {
399 (self.0 >> 16) as u16
400 }
401}