sdmmc_core/response/sd/
r6.rs

1use crate::crc::Crc7;
2use crate::result::{Error, Result};
3use crate::{lib_bitfield, response};
4
5mod card_status;
6
7pub use card_status::*;
8
9/// Represents the command index field value of the [R6] response in SD mode.
10pub const COMMAND_INDEX: u8 = 0b11;
11
12lib_bitfield! {
13    /// Represents the Published RCA response in SD mode.
14    pub R6(MSB0 [u8; 6]): u16 {
15        start_bit: 47;
16        direction: 46;
17        raw_command_index: 45, 40;
18        /// The new published RCA number of the card.
19        pub rca: 39, 24;
20        raw_card_status: 23, 8;
21        raw_crc: 7, 1;
22        end_bit: 0;
23    }
24}
25
26response! {
27    R6 {
28        response_mode: Sd,
29    }
30}
31
32impl R6 {
33    /// Represents the byte length of the [R6] response in SD mode.
34    pub const LEN: usize = 6;
35    pub const DEFAULT: [u8; Self::LEN] = [COMMAND_INDEX, 0x00, 0x00, 0x00, 0x00, 0x45];
36
37    /// Creates a new [R6].
38    pub const fn new() -> Self {
39        Self(Self::DEFAULT)
40    }
41
42    /// Gets the command index field  of the [R6].
43    ///
44    /// Should always be [COMMAND_INDEX].
45    pub const fn command_index(&self) -> u8 {
46        self.raw_command_index() as u8
47    }
48
49    /// Gets the [CardStatus] for the [R6].
50    pub const fn card_status(&self) -> Result<CardStatus> {
51        CardStatus::try_from_bits(self.raw_card_status())
52    }
53
54    /// Sets the [CardStatus] for the [R6].
55    pub fn set_card_status(&mut self, val: CardStatus) {
56        self.set_raw_card_status(val.bits());
57    }
58
59    /// Gets the [Crc7] field of the [R6].
60    pub const fn crc(&self) -> Crc7 {
61        Crc7::from_bits(self.raw_crc() as u8)
62    }
63
64    /// Calculates and sets the [Crc7] field of the [R6].
65    ///
66    /// Returns the calculated [Crc7].
67    pub fn calculate_crc(&mut self) -> Crc7 {
68        let crc = Crc7::calculate(self.0[..Self::LEN - 1].as_ref());
69        self.set_raw_crc(crc.bits() as u16);
70        crc
71    }
72
73    /// Attempts to convert a byte slice into a [R6].
74    pub const fn try_from_bytes(val: &[u8]) -> Result<Self> {
75        match val.len() {
76            len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
77            _ => {
78                let crc = Crc7::calculate(&[val[0], val[1], val[2], val[3], val[4]]);
79
80                match R6([val[0], val[1], val[2], val[3], val[4], val[5]]) {
81                    r6 if r6.start_bit() => Err(Error::invalid_field_variant("r6::start_bit", 1)),
82                    r6 if r6.direction() => Err(Error::invalid_field_variant("r6::direction", 1)),
83                    r6 if r6.command_index() != COMMAND_INDEX => Err(Error::invalid_field_variant(
84                        "r6::command_index",
85                        r6.command_index() as usize,
86                    )),
87                    r6 if r6.card_status().is_err() => Err(Error::invalid_field_variant(
88                        "r6::card_status",
89                        r6.raw_card_status() as usize,
90                    )),
91                    r6 if r6.raw_crc() as u8 != crc.bits() => {
92                        Err(Error::invalid_crc7(r6.raw_crc() as u8, crc.bits()))
93                    }
94                    r6 if !r6.end_bit() => Err(Error::invalid_field_variant("r6::end_bit", 0)),
95                    r6 => Ok(r6),
96                }
97            }
98        }
99    }
100}
101
102impl Default for R6 {
103    fn default() -> Self {
104        Self::new()
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111    use crate::test_field;
112    use crate::util::raw_with_crc;
113
114    #[test]
115    fn test_fields() {
116        let mut r6 = R6::new();
117
118        assert_eq!(r6.card_status(), Ok(CardStatus::new()));
119
120        let raw_cs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
121
122        raw_cs
123            .into_iter()
124            .zip([
125                CurrentState::Idle,
126                CurrentState::Ready,
127                CurrentState::Identification,
128                CurrentState::Standby,
129                CurrentState::Transfer,
130                CurrentState::Data,
131                CurrentState::Receive,
132                CurrentState::Program,
133                CurrentState::Disabled,
134            ])
135            .for_each(|(cstate_raw, cstate)| {
136                assert_eq!(CurrentState::from_raw(cstate_raw), Ok(cstate));
137                let cs = CardStatus::try_from_bits((cstate_raw as u16) << 9).unwrap();
138
139                r6.set_card_status(cs);
140                assert_eq!(r6.card_status(), Ok(cs));
141
142                let (raw, _crc) = raw_with_crc([COMMAND_INDEX, 0, 0, cstate_raw << 1, 0, 0]);
143
144                let exp_r6 = R6(raw);
145                assert_eq!(R6::try_from_bytes(raw.as_ref()), Ok(exp_r6));
146
147                assert_eq!(exp_r6.card_status(), Ok(cs));
148            });
149
150        (0..=0xf)
151            .filter(|r| !raw_cs.iter().any(|cs| cs == r))
152            .for_each(|invalid_cs| {
153                let err_cs = u16::from_be_bytes([invalid_cs << 1, 0]);
154                assert_eq!(
155                    R6::try_from_bytes(&[COMMAND_INDEX, 0, 0, invalid_cs << 1, 0, 0]),
156                    Err(Error::invalid_field_variant(
157                        "r6::card_status",
158                        err_cs as usize
159                    ))
160                );
161            });
162
163        (1..=u16::BITS)
164            .map(|r| ((1u32 << r) - 1) as u16)
165            .for_each(|rca| {
166                let [rca0, rca1] = rca.to_be_bytes();
167                let (raw, _crc) = raw_with_crc([0x03, rca0, rca1, 0, 0, 0]);
168                let mut exp_r6 = R6(raw);
169
170                assert_eq!(R6::try_from_bytes(raw.as_ref()), Ok(exp_r6));
171                assert_eq!(exp_r6.rca(), rca);
172
173                exp_r6.set_rca(0);
174                assert_eq!(exp_r6.rca(), 0);
175
176                exp_r6.set_rca(rca);
177                assert_eq!(exp_r6.rca(), rca);
178            });
179    }
180}