embedded_sdmmc/sdcard/
proto.rs

1//! Constants from the SD Specifications
2//!
3//! Based on SdFat, under the following terms:
4//!
5//! > Copyright (c) 2011-2018 Bill Greiman
6//! > This file is part of the SdFat library for SD memory cards.
7//! >
8//! > MIT License
9//! >
10//! > Permission is hereby granted, free of charge, to any person obtaining a
11//! > copy of this software and associated documentation files (the "Software"),
12//! > to deal in the Software without restriction, including without limitation
13//! > the rights to use, copy, modify, merge, publish, distribute, sublicense,
14//! > and/or sell copies of the Software, and to permit persons to whom the
15//! > Software is furnished to do so, subject to the following conditions:
16//! >
17//! > The above copyright notice and this permission notice shall be included
18//! > in all copies or substantial portions of the Software.
19//! >
20//! > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21//! > OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22//! > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23//! > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24//! > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25//! > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26//! > DEALINGS IN THE SOFTWARE.
27
28//==============================================================================
29
30// Possible errors the SD card can return
31
32/// Card indicates last operation was a success
33pub const ERROR_OK: u8 = 0x00;
34
35//==============================================================================
36
37// SD Card Commands
38
39/// GO_IDLE_STATE - init card in spi mode if CS low
40pub const CMD0: u8 = 0x00;
41/// SEND_IF_COND - verify SD Memory Card interface operating condition.*/
42pub const CMD8: u8 = 0x08;
43/// SEND_CSD - read the Card Specific Data (CSD register)
44pub const CMD9: u8 = 0x09;
45/// STOP_TRANSMISSION - end multiple block read sequence
46pub const CMD12: u8 = 0x0C;
47/// SEND_STATUS - read the card status register
48pub const CMD13: u8 = 0x0D;
49/// READ_SINGLE_BLOCK - read a single data block from the card
50pub const CMD17: u8 = 0x11;
51/// READ_MULTIPLE_BLOCK - read a multiple data blocks from the card
52pub const CMD18: u8 = 0x12;
53/// WRITE_BLOCK - write a single data block to the card
54pub const CMD24: u8 = 0x18;
55/// WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION
56pub const CMD25: u8 = 0x19;
57/// APP_CMD - escape for application specific command
58pub const CMD55: u8 = 0x37;
59/// READ_OCR - read the OCR register of a card
60pub const CMD58: u8 = 0x3A;
61/// CRC_ON_OFF - enable or disable CRC checking
62pub const CMD59: u8 = 0x3B;
63/// Pre-erased before writing
64///
65/// > It is recommended using this command preceding CMD25, some of the cards will be faster for Multiple
66/// > Write Blocks operation. Note that the host should send ACMD23 just before WRITE command if the host
67/// > wants to use the pre-erased feature
68pub const ACMD23: u8 = 0x17;
69/// SD_SEND_OP_COMD - Sends host capacity support information and activates
70/// the card's initialization process
71pub const ACMD41: u8 = 0x29;
72
73//==============================================================================
74
75/// status for card in the ready state
76pub const R1_READY_STATE: u8 = 0x00;
77
78/// status for card in the idle state
79pub const R1_IDLE_STATE: u8 = 0x01;
80
81/// status bit for illegal command
82pub const R1_ILLEGAL_COMMAND: u8 = 0x04;
83
84/// start data token for read or write single block*/
85pub const DATA_START_BLOCK: u8 = 0xFE;
86
87/// stop token for write multiple blocks*/
88pub const STOP_TRAN_TOKEN: u8 = 0xFD;
89
90/// start data token for write multiple blocks*/
91pub const WRITE_MULTIPLE_TOKEN: u8 = 0xFC;
92
93/// mask for data response tokens after a write block operation
94pub const DATA_RES_MASK: u8 = 0x1F;
95
96/// write data accepted token
97pub const DATA_RES_ACCEPTED: u8 = 0x05;
98
99/// Card Specific Data, version 1
100#[derive(Default, Debug)]
101#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
102pub struct CsdV1 {
103    /// The 16-bytes of data in this Card Specific Data block
104    pub data: [u8; 16],
105}
106
107/// Card Specific Data, version 2
108#[derive(Default, Debug)]
109#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
110pub struct CsdV2 {
111    /// The 16-bytes of data in this Card Specific Data block
112    pub data: [u8; 16],
113}
114
115/// Card Specific Data
116#[derive(Debug)]
117#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
118pub enum Csd {
119    /// A version 1 CSD
120    V1(CsdV1),
121    /// A version 2 CSD
122    V2(CsdV2),
123}
124
125impl CsdV1 {
126    /// Create a new, empty, CSD
127    pub fn new() -> CsdV1 {
128        CsdV1::default()
129    }
130
131    define_field!(csd_ver, u8, 0, 6, 2);
132    define_field!(data_read_access_time1, u8, 1, 0, 8);
133    define_field!(data_read_access_time2, u8, 2, 0, 8);
134    define_field!(max_data_transfer_rate, u8, 3, 0, 8);
135    define_field!(card_command_classes, u16, [(4, 0, 8), (5, 4, 4)]);
136    define_field!(read_block_length, u8, 5, 0, 4);
137    define_field!(read_partial_blocks, bool, 6, 7);
138    define_field!(write_block_misalignment, bool, 6, 6);
139    define_field!(read_block_misalignment, bool, 6, 5);
140    define_field!(dsr_implemented, bool, 6, 4);
141    define_field!(device_size, u32, [(6, 0, 2), (7, 0, 8), (8, 6, 2)]);
142    define_field!(max_read_current_vdd_max, u8, 8, 0, 3);
143    define_field!(max_read_current_vdd_min, u8, 8, 3, 3);
144    define_field!(max_write_current_vdd_max, u8, 9, 2, 3);
145    define_field!(max_write_current_vdd_min, u8, 9, 5, 3);
146    define_field!(device_size_multiplier, u8, [(9, 0, 2), (10, 7, 1)]);
147    define_field!(erase_single_block_enabled, bool, 10, 6);
148    define_field!(erase_sector_size, u8, [(10, 0, 6), (11, 7, 1)]);
149    define_field!(write_protect_group_size, u8, 11, 0, 7);
150    define_field!(write_protect_group_enable, bool, 12, 7);
151    define_field!(write_speed_factor, u8, 12, 2, 3);
152    define_field!(max_write_data_length, u8, [(12, 0, 2), (13, 6, 2)]);
153    define_field!(write_partial_blocks, bool, 13, 5);
154    define_field!(file_format, u8, 14, 2, 2);
155    define_field!(temporary_write_protection, bool, 14, 4);
156    define_field!(permanent_write_protection, bool, 14, 5);
157    define_field!(copy_flag_set, bool, 14, 6);
158    define_field!(file_format_group_set, bool, 14, 7);
159    define_field!(crc, u8, 15, 0, 8);
160
161    /// Returns the card capacity in bytes
162    pub fn card_capacity_bytes(&self) -> u64 {
163        let multiplier = self.device_size_multiplier() + self.read_block_length() + 2;
164        (u64::from(self.device_size()) + 1) << multiplier
165    }
166
167    /// Returns the card capacity in 512-byte blocks
168    pub fn card_capacity_blocks(&self) -> u32 {
169        let multiplier = self.device_size_multiplier() + self.read_block_length() - 7;
170        (self.device_size() + 1) << multiplier
171    }
172}
173
174impl CsdV2 {
175    /// Create a new, empty, CSD
176    pub fn new() -> CsdV2 {
177        CsdV2::default()
178    }
179
180    define_field!(csd_ver, u8, 0, 6, 2);
181    define_field!(data_read_access_time1, u8, 1, 0, 8);
182    define_field!(data_read_access_time2, u8, 2, 0, 8);
183    define_field!(max_data_transfer_rate, u8, 3, 0, 8);
184    define_field!(card_command_classes, u16, [(4, 0, 8), (5, 4, 4)]);
185    define_field!(read_block_length, u8, 5, 0, 4);
186    define_field!(read_partial_blocks, bool, 6, 7);
187    define_field!(write_block_misalignment, bool, 6, 6);
188    define_field!(read_block_misalignment, bool, 6, 5);
189    define_field!(dsr_implemented, bool, 6, 4);
190    define_field!(device_size, u32, [(7, 0, 6), (8, 0, 8), (9, 0, 8)]);
191    define_field!(erase_single_block_enabled, bool, 10, 6);
192    define_field!(erase_sector_size, u8, [(10, 0, 6), (11, 7, 1)]);
193    define_field!(write_protect_group_size, u8, 11, 0, 7);
194    define_field!(write_protect_group_enable, bool, 12, 7);
195    define_field!(write_speed_factor, u8, 12, 2, 3);
196    define_field!(max_write_data_length, u8, [(12, 0, 2), (13, 6, 2)]);
197    define_field!(write_partial_blocks, bool, 13, 5);
198    define_field!(file_format, u8, 14, 2, 2);
199    define_field!(temporary_write_protection, bool, 14, 4);
200    define_field!(permanent_write_protection, bool, 14, 5);
201    define_field!(copy_flag_set, bool, 14, 6);
202    define_field!(file_format_group_set, bool, 14, 7);
203    define_field!(crc, u8, 15, 0, 8);
204
205    /// Returns the card capacity in bytes
206    pub fn card_capacity_bytes(&self) -> u64 {
207        (u64::from(self.device_size()) + 1) * 512 * 1024
208    }
209
210    /// Returns the card capacity in 512-byte blocks
211    pub fn card_capacity_blocks(&self) -> u32 {
212        (self.device_size() + 1) * 1024
213    }
214}
215
216/// Perform the 7-bit CRC used on the SD card
217pub fn crc7(data: &[u8]) -> u8 {
218    let mut crc = 0u8;
219    for mut d in data.iter().cloned() {
220        for _bit in 0..8 {
221            crc <<= 1;
222            if ((d & 0x80) ^ (crc & 0x80)) != 0 {
223                crc ^= 0x09;
224            }
225            d <<= 1;
226        }
227    }
228    (crc << 1) | 1
229}
230
231/// Perform the X25 CRC calculation, as used for data blocks.
232pub fn crc16(data: &[u8]) -> u16 {
233    let mut crc = 0u16;
234    for &byte in data {
235        crc = ((crc >> 8) & 0xFF) | (crc << 8);
236        crc ^= u16::from(byte);
237        crc ^= (crc & 0xFF) >> 4;
238        crc ^= crc << 12;
239        crc ^= (crc & 0xFF) << 5;
240    }
241    crc
242}
243
244// ****************************************************************************
245//
246// Unit Tests
247//
248// ****************************************************************************
249
250#[cfg(test)]
251mod test {
252    use super::*;
253
254    #[test]
255    fn test_crc7() {
256        const DATA: [u8; 15] = hex!("00 26 00 32 5F 59 83 C8 AD DB CF FF D2 40 40");
257        assert_eq!(crc7(&DATA), 0xA5);
258    }
259
260    #[test]
261    fn test_crc16() {
262        // An actual CSD read from an SD card
263        const DATA: [u8; 16] = hex!("00 26 00 32 5F 5A 83 AE FE FB CF FF 92 80 40 DF");
264        assert_eq!(crc16(&DATA), 0x9fc5);
265    }
266
267    #[test]
268    fn test_csdv1b() {
269        const EXAMPLE: CsdV1 = CsdV1 {
270            data: hex!("00 26 00 32 5F 59 83 C8 AD DB CF FF D2 40 40 A5"),
271        };
272
273        // CSD Structure: describes version of CSD structure
274        // 0b00 [Interpreted: Version 1.0]
275        assert_eq!(EXAMPLE.csd_ver(), 0x00);
276
277        // Data Read Access Time 1: defines Asynchronous part of the read
278        // access time 0x26 [Interpreted: 1.5 x 1ms]
279        assert_eq!(EXAMPLE.data_read_access_time1(), 0x26);
280
281        // Data Read Access Time 2: worst case clock dependent factor for data
282        // access time 0x00 [Decimal: 0 x 100 Clocks]
283        assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
284
285        // Max Data Transfer Rate: sometimes stated as Mhz
286        // 0x32 [Interpreted: 2.5 x 10Mbit/s]
287        assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
288
289        // Card Command Classes: 0x5f5 [Interpreted: Class 0: Yes. Class 1:
290        // No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6:
291        // Yes. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class
292        // 11: No. ]
293        assert_eq!(EXAMPLE.card_command_classes(), 0x5f5);
294
295        // Max Read Data Block Length:
296        // 0x9 [Interpreted: 512 Bytes]
297        assert_eq!(EXAMPLE.read_block_length(), 0x09);
298
299        // Partial Blocks for Read Allowed:
300        // 0b1 [Interpreted: Yes]
301        assert!(EXAMPLE.read_partial_blocks());
302
303        // Write Block Misalignment:
304        // 0b0 [Interpreted: No]
305        assert!(!EXAMPLE.write_block_misalignment());
306
307        // Read Block Misalignment:
308        // 0b0 [Interpreted: No]
309        assert!(!EXAMPLE.read_block_misalignment());
310
311        // DSR Implemented: indicates configurable driver stage integrated on
312        // card 0b0 [Interpreted: No]
313        assert!(!EXAMPLE.dsr_implemented());
314
315        // Device Size: to calculate the card capacity excl. security area
316        // ((device size + 1)*device size multiplier*max read data block
317        // length) bytes 0xf22 [Decimal: 3874]
318        assert_eq!(EXAMPLE.device_size(), 3874);
319
320        // Max Read Current @ VDD Min:
321        // 0x5 [Interpreted: 35mA]
322        assert_eq!(EXAMPLE.max_read_current_vdd_min(), 5);
323
324        // Max Read Current @ VDD Max:
325        // 0x5 [Interpreted: 80mA]
326        assert_eq!(EXAMPLE.max_read_current_vdd_max(), 5);
327
328        // Max Write Current @ VDD Min:
329        // 0x6 [Interpreted: 60mA]
330        assert_eq!(EXAMPLE.max_write_current_vdd_min(), 6);
331
332        // Max Write Current @ VDD Max::
333        // 0x6 [Interpreted: 200mA]
334        assert_eq!(EXAMPLE.max_write_current_vdd_max(), 6);
335
336        // Device Size Multiplier:
337        // 0x7 [Interpreted: x512]
338        assert_eq!(EXAMPLE.device_size_multiplier(), 7);
339
340        // Erase Single Block Enabled:
341        // 0x1 [Interpreted: Yes]
342        assert!(EXAMPLE.erase_single_block_enabled());
343
344        // Erase Sector Size: size of erasable sector in write blocks
345        // 0x1f [Interpreted: 32 blocks]
346        assert_eq!(EXAMPLE.erase_sector_size(), 0x1F);
347
348        // Write Protect Group Size:
349        // 0x7f [Interpreted: 128 sectors]
350        assert_eq!(EXAMPLE.write_protect_group_size(), 0x7f);
351
352        // Write Protect Group Enable:
353        // 0x1 [Interpreted: Yes]
354        assert!(EXAMPLE.write_protect_group_enable());
355
356        // Write Speed Factor: block program time as multiple of read access time
357        // 0x4 [Interpreted: x16]
358        assert_eq!(EXAMPLE.write_speed_factor(), 0x4);
359
360        // Max Write Data Block Length:
361        // 0x9 [Interpreted: 512 Bytes]
362        assert_eq!(EXAMPLE.max_write_data_length(), 0x9);
363
364        // Partial Blocks for Write Allowed:
365        // 0x0 [Interpreted: No]
366        assert!(!EXAMPLE.write_partial_blocks());
367
368        // File Format Group:
369        // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
370        assert!(!EXAMPLE.file_format_group_set());
371
372        // Copy Flag:
373        // 0b1 [Interpreted: Non-Original]
374        assert!(EXAMPLE.copy_flag_set());
375
376        // Permanent Write Protection:
377        // 0b0 [Interpreted: No]
378        assert!(!EXAMPLE.permanent_write_protection());
379
380        // Temporary Write Protection:
381        // 0b0 [Interpreted: No]
382        assert!(!EXAMPLE.temporary_write_protection());
383
384        // File Format:
385        // 0x0 [Interpreted: Hard Disk with Partition Table]
386        assert_eq!(EXAMPLE.file_format(), 0x00);
387
388        // CRC7 Checksum + always 1 in LSB:
389        // 0xa5
390        assert_eq!(EXAMPLE.crc(), 0xa5);
391
392        assert_eq!(EXAMPLE.card_capacity_bytes(), 1_015_808_000);
393        assert_eq!(EXAMPLE.card_capacity_blocks(), 1_984_000);
394    }
395
396    #[test]
397    fn test_csdv1() {
398        const EXAMPLE: CsdV1 = CsdV1 {
399            data: hex!("00 7F 00 32 5B 5A 83 AF 7F FF CF 80 16 80 00 6F"),
400        };
401        // CSD Structure: describes version of CSD structure
402        // 0b00 [Interpreted: Version 1.0]
403        assert_eq!(EXAMPLE.csd_ver(), 0x00);
404
405        // Data Read Access Time 1: defines Asynchronous part of the read access time
406        // 0x7f [Interpreted: 8.0 x 10ms]
407        assert_eq!(EXAMPLE.data_read_access_time1(), 0x7F);
408
409        // Data Read Access Time 2: worst case clock dependent factor for data access time
410        // 0x00 [Decimal: 0 x 100 Clocks]
411        assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
412
413        // Max Data Transfer Rate: sometimes stated as Mhz
414        // 0x32 [Interpreted: 2.5 x 10Mbit/s]
415        assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
416
417        // Card Command Classes:
418        // 0x5b5 [Interpreted: Class 0: Yes. Class 1: No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6: No. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class 11: No. ]
419        assert_eq!(EXAMPLE.card_command_classes(), 0x5b5);
420
421        // Max Read Data Block Length:
422        // 0xa [Interpreted: 1024 Bytes]
423        assert_eq!(EXAMPLE.read_block_length(), 0x0a);
424
425        // Partial Blocks for Read Allowed:
426        // 0b1 [Interpreted: Yes]
427        assert!(EXAMPLE.read_partial_blocks());
428
429        // Write Block Misalignment:
430        // 0b0 [Interpreted: No]
431        assert!(!EXAMPLE.write_block_misalignment());
432
433        // Read Block Misalignment:
434        // 0b0 [Interpreted: No]
435        assert!(!EXAMPLE.read_block_misalignment());
436
437        // DSR Implemented: indicates configurable driver stage integrated on card
438        // 0b0 [Interpreted: No]
439        assert!(!EXAMPLE.dsr_implemented());
440
441        // Device Size: to calculate the card capacity excl. security area
442        // ((device size + 1)*device size multiplier*max read data block
443        // length) bytes 0xebd [Decimal: 3773]
444        assert_eq!(EXAMPLE.device_size(), 3773);
445
446        // Max Read Current @ VDD Min:
447        // 0x7 [Interpreted: 100mA]
448        assert_eq!(EXAMPLE.max_read_current_vdd_min(), 7);
449
450        // Max Read Current @ VDD Max:
451        // 0x7 [Interpreted: 200mA]
452        assert_eq!(EXAMPLE.max_read_current_vdd_max(), 7);
453
454        // Max Write Current @ VDD Min:
455        // 0x7 [Interpreted: 100mA]
456        assert_eq!(EXAMPLE.max_write_current_vdd_min(), 7);
457
458        // Max Write Current @ VDD Max::
459        // 0x7 [Interpreted: 200mA]
460        assert_eq!(EXAMPLE.max_write_current_vdd_max(), 7);
461
462        // Device Size Multiplier:
463        // 0x7 [Interpreted: x512]
464        assert_eq!(EXAMPLE.device_size_multiplier(), 7);
465
466        // Erase Single Block Enabled:
467        // 0x1 [Interpreted: Yes]
468        assert!(EXAMPLE.erase_single_block_enabled());
469
470        // Erase Sector Size: size of erasable sector in write blocks
471        // 0x1f [Interpreted: 32 blocks]
472        assert_eq!(EXAMPLE.erase_sector_size(), 0x1F);
473
474        // Write Protect Group Size:
475        // 0x00 [Interpreted: 1 sectors]
476        assert_eq!(EXAMPLE.write_protect_group_size(), 0x00);
477
478        // Write Protect Group Enable:
479        // 0x0 [Interpreted: No]
480        assert!(!EXAMPLE.write_protect_group_enable());
481
482        // Write Speed Factor: block program time as multiple of read access time
483        // 0x5 [Interpreted: x32]
484        assert_eq!(EXAMPLE.write_speed_factor(), 0x5);
485
486        // Max Write Data Block Length:
487        // 0xa [Interpreted: 1024 Bytes]
488        assert_eq!(EXAMPLE.max_write_data_length(), 0xa);
489
490        // Partial Blocks for Write Allowed:
491        // 0x0 [Interpreted: No]
492        assert!(!EXAMPLE.write_partial_blocks());
493
494        // File Format Group:
495        // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
496        assert!(!EXAMPLE.file_format_group_set());
497
498        // Copy Flag:
499        // 0b0 [Interpreted: Original]
500        assert!(!EXAMPLE.copy_flag_set());
501
502        // Permanent Write Protection:
503        // 0b0 [Interpreted: No]
504        assert!(!EXAMPLE.permanent_write_protection());
505
506        // Temporary Write Protection:
507        // 0b0 [Interpreted: No]
508        assert!(!EXAMPLE.temporary_write_protection());
509
510        // File Format:
511        // 0x0 [Interpreted: Hard Disk with Partition Table]
512        assert_eq!(EXAMPLE.file_format(), 0x00);
513
514        // CRC7 Checksum + always 1 in LSB:
515        // 0x6f
516        assert_eq!(EXAMPLE.crc(), 0x6F);
517
518        assert_eq!(EXAMPLE.card_capacity_bytes(), 1_978_662_912);
519        assert_eq!(EXAMPLE.card_capacity_blocks(), 3_864_576);
520    }
521
522    #[test]
523    fn test_csdv2() {
524        const EXAMPLE: CsdV2 = CsdV2 {
525            data: hex!("40 0E 00 32 5B 59 00 00 1D 69 7F 80 0A 40 00 8B"),
526        };
527        // CSD Structure: describes version of CSD structure
528        // 0b01 [Interpreted: Version 2.0 SDHC]
529        assert_eq!(EXAMPLE.csd_ver(), 0x01);
530
531        // Data Read Access Time 1: defines Asynchronous part of the read access time
532        // 0x0e [Interpreted: 1.0 x 1ms]
533        assert_eq!(EXAMPLE.data_read_access_time1(), 0x0E);
534
535        // Data Read Access Time 2: worst case clock dependent factor for data access time
536        // 0x00 [Decimal: 0 x 100 Clocks]
537        assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
538
539        // Max Data Transfer Rate: sometimes stated as Mhz
540        // 0x32 [Interpreted: 2.5 x 10Mbit/s]
541        assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
542
543        // Card Command Classes:
544        // 0x5b5 [Interpreted: Class 0: Yes. Class 1: No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6: No. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class 11: No. ]
545        assert_eq!(EXAMPLE.card_command_classes(), 0x5b5);
546
547        // Max Read Data Block Length:
548        // 0x9 [Interpreted: 512 Bytes]
549        assert_eq!(EXAMPLE.read_block_length(), 0x09);
550
551        // Partial Blocks for Read Allowed:
552        // 0b0 [Interpreted: Yes]
553        assert!(!EXAMPLE.read_partial_blocks());
554
555        // Write Block Misalignment:
556        // 0b0 [Interpreted: No]
557        assert!(!EXAMPLE.write_block_misalignment());
558
559        // Read Block Misalignment:
560        // 0b0 [Interpreted: No]
561        assert!(!EXAMPLE.read_block_misalignment());
562
563        // DSR Implemented: indicates configurable driver stage integrated on card
564        // 0b0 [Interpreted: No]
565        assert!(!EXAMPLE.dsr_implemented());
566
567        // Device Size: to calculate the card capacity excl. security area
568        // ((device size + 1)* 512kbytes
569        // 0x001d69 [Decimal: 7529]
570        assert_eq!(EXAMPLE.device_size(), 7529);
571
572        // Erase Single Block Enabled:
573        // 0x1 [Interpreted: Yes]
574        assert!(EXAMPLE.erase_single_block_enabled());
575
576        // Erase Sector Size: size of erasable sector in write blocks
577        // 0x7f [Interpreted: 128 blocks]
578        assert_eq!(EXAMPLE.erase_sector_size(), 0x7F);
579
580        // Write Protect Group Size:
581        // 0x00 [Interpreted: 1 sectors]
582        assert_eq!(EXAMPLE.write_protect_group_size(), 0x00);
583
584        // Write Protect Group Enable:
585        // 0x0 [Interpreted: No]
586        assert!(!EXAMPLE.write_protect_group_enable());
587
588        // Write Speed Factor: block program time as multiple of read access time
589        // 0x2 [Interpreted: x4]
590        assert_eq!(EXAMPLE.write_speed_factor(), 0x2);
591
592        // Max Write Data Block Length:
593        // 0x9 [Interpreted: 512 Bytes]
594        assert_eq!(EXAMPLE.max_write_data_length(), 0x9);
595
596        // Partial Blocks for Write Allowed:
597        // 0x0 [Interpreted: No]
598        assert!(!EXAMPLE.write_partial_blocks());
599
600        // File Format Group:
601        // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
602        assert!(!EXAMPLE.file_format_group_set());
603
604        // Copy Flag:
605        // 0b0 [Interpreted: Original]
606        assert!(!EXAMPLE.copy_flag_set());
607
608        // Permanent Write Protection:
609        // 0b0 [Interpreted: No]
610        assert!(!EXAMPLE.permanent_write_protection());
611
612        // Temporary Write Protection:
613        // 0b0 [Interpreted: No]
614        assert!(!EXAMPLE.temporary_write_protection());
615
616        // File Format:
617        // 0x0 [Interpreted: Hard Disk with Partition Table]
618        assert_eq!(EXAMPLE.file_format(), 0x00);
619
620        // CRC7 Checksum + always 1 in LSB:
621        // 0x8b
622        assert_eq!(EXAMPLE.crc(), 0x8b);
623
624        assert_eq!(EXAMPLE.card_capacity_bytes(), 3_947_888_640);
625        assert_eq!(EXAMPLE.card_capacity_blocks(), 7_710_720);
626    }
627
628    #[test]
629    fn test_csdv2b() {
630        const EXAMPLE: CsdV2 = CsdV2 {
631            data: hex!("40 0E 00 32 5B 59 00 00 3A 91 7F 80 0A 40 00 05"),
632        };
633        // CSD Structure: describes version of CSD structure
634        // 0b01 [Interpreted: Version 2.0 SDHC]
635        assert_eq!(EXAMPLE.csd_ver(), 0x01);
636
637        // Data Read Access Time 1: defines Asynchronous part of the read access time
638        // 0x0e [Interpreted: 1.0 x 1ms]
639        assert_eq!(EXAMPLE.data_read_access_time1(), 0x0E);
640
641        // Data Read Access Time 2: worst case clock dependent factor for data access time
642        // 0x00 [Decimal: 0 x 100 Clocks]
643        assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
644
645        // Max Data Transfer Rate: sometimes stated as Mhz
646        // 0x32 [Interpreted: 2.5 x 10Mbit/s]
647        assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
648
649        // Card Command Classes:
650        // 0x5b5 [Interpreted: Class 0: Yes. Class 1: No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6: No. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class 11: No. ]
651        assert_eq!(EXAMPLE.card_command_classes(), 0x5b5);
652
653        // Max Read Data Block Length:
654        // 0x9 [Interpreted: 512 Bytes]
655        assert_eq!(EXAMPLE.read_block_length(), 0x09);
656
657        // Partial Blocks for Read Allowed:
658        // 0b0 [Interpreted: Yes]
659        assert!(!EXAMPLE.read_partial_blocks());
660
661        // Write Block Misalignment:
662        // 0b0 [Interpreted: No]
663        assert!(!EXAMPLE.write_block_misalignment());
664
665        // Read Block Misalignment:
666        // 0b0 [Interpreted: No]
667        assert!(!EXAMPLE.read_block_misalignment());
668
669        // DSR Implemented: indicates configurable driver stage integrated on card
670        // 0b0 [Interpreted: No]
671        assert!(!EXAMPLE.dsr_implemented());
672
673        // Device Size: to calculate the card capacity excl. security area
674        // ((device size + 1)* 512kbytes
675        // 0x003a91 [Decimal: 7529]
676        assert_eq!(EXAMPLE.device_size(), 14993);
677
678        // Erase Single Block Enabled:
679        // 0x1 [Interpreted: Yes]
680        assert!(EXAMPLE.erase_single_block_enabled());
681
682        // Erase Sector Size: size of erasable sector in write blocks
683        // 0x7f [Interpreted: 128 blocks]
684        assert_eq!(EXAMPLE.erase_sector_size(), 0x7F);
685
686        // Write Protect Group Size:
687        // 0x00 [Interpreted: 1 sectors]
688        assert_eq!(EXAMPLE.write_protect_group_size(), 0x00);
689
690        // Write Protect Group Enable:
691        // 0x0 [Interpreted: No]
692        assert!(!EXAMPLE.write_protect_group_enable());
693
694        // Write Speed Factor: block program time as multiple of read access time
695        // 0x2 [Interpreted: x4]
696        assert_eq!(EXAMPLE.write_speed_factor(), 0x2);
697
698        // Max Write Data Block Length:
699        // 0x9 [Interpreted: 512 Bytes]
700        assert_eq!(EXAMPLE.max_write_data_length(), 0x9);
701
702        // Partial Blocks for Write Allowed:
703        // 0x0 [Interpreted: No]
704        assert!(!EXAMPLE.write_partial_blocks());
705
706        // File Format Group:
707        // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
708        assert!(!EXAMPLE.file_format_group_set());
709
710        // Copy Flag:
711        // 0b0 [Interpreted: Original]
712        assert!(!EXAMPLE.copy_flag_set());
713
714        // Permanent Write Protection:
715        // 0b0 [Interpreted: No]
716        assert!(!EXAMPLE.permanent_write_protection());
717
718        // Temporary Write Protection:
719        // 0b0 [Interpreted: No]
720        assert!(!EXAMPLE.temporary_write_protection());
721
722        // File Format:
723        // 0x0 [Interpreted: Hard Disk with Partition Table]
724        assert_eq!(EXAMPLE.file_format(), 0x00);
725
726        // CRC7 Checksum + always 1 in LSB:
727        // 0x05
728        assert_eq!(EXAMPLE.crc(), 0x05);
729
730        assert_eq!(EXAMPLE.card_capacity_bytes(), 7_861_174_272);
731        assert_eq!(EXAMPLE.card_capacity_blocks(), 15_353_856);
732    }
733}
734
735// ****************************************************************************
736//
737// End Of File
738//
739// ****************************************************************************