sdmmc_core/response/sd/
r7.rs1use crate::crc::Crc7;
2use crate::result::{Error, Result};
3use crate::{lib_bitfield, response};
4
5mod voltage_accepted;
6
7pub use voltage_accepted::*;
8
9const COMMAND_INDEX: u8 = 0b00_1000;
10
11lib_bitfield! {
12 pub R7(MSB0 [u8; 6]): u8 {
14 start_bit: 47;
15 direction: 46;
16 raw_command_index: 45, 40;
17 pub pcie_12v_support: 21;
19 pub pcie: 20;
21 raw_voltage_accepted: 19, 16;
22 pub echo_check: 15, 8;
24 raw_crc: 7, 1;
25 end_bit: 0;
26 }
27}
28
29response! {
30 R7 {
31 response_mode: Sd,
32 }
33}
34
35impl R7 {
36 pub const LEN: usize = 6;
38 pub const DEFAULT: [u8; Self::LEN] = [COMMAND_INDEX, 0, 0, 0x1, 0, 0x41];
40
41 pub const fn new() -> Self {
43 Self(Self::DEFAULT)
44 }
45
46 pub const fn command_index(&self) -> u8 {
48 self.raw_command_index()
49 }
50
51 pub const fn voltage_accepted(&self) -> Result<VoltageAccepted> {
53 VoltageAccepted::from_raw(self.raw_voltage_accepted())
54 }
55
56 pub fn set_voltage_accepted(&mut self, voltage_accepted: VoltageAccepted) {
58 self.set_raw_voltage_accepted(voltage_accepted.into_raw());
59 }
60
61 pub const fn crc(&self) -> Crc7 {
63 Crc7::from_bits(self.raw_crc())
64 }
65
66 pub fn calculate_crc(&mut self) -> Crc7 {
70 let crc = Crc7::calculate(self.0[..Self::LEN - 1].as_ref());
71 self.set_raw_crc(crc.bits());
72 crc
73 }
74
75 pub const fn try_from_bytes(val: &[u8]) -> Result<Self> {
77 match val.len() {
78 len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
79 _ => {
80 let crc = Crc7::calculate(&[val[0], val[1], val[2], val[3], val[4]]);
81
82 match R7([val[0], val[1], val[2], val[3], val[4], val[5]]) {
83 r7 if r7.start_bit() => Err(Error::invalid_field_variant("r7::start_bit", 1)),
84 r7 if r7.direction() => Err(Error::invalid_field_variant("r7::direction", 1)),
85 r7 if r7.command_index() != COMMAND_INDEX => Err(Error::invalid_field_variant(
86 "r7::command_index",
87 r7.command_index() as usize,
88 )),
89 r7 if r7.voltage_accepted().is_err() => Err(Error::invalid_field_variant(
90 "r7::voltage_accepted",
91 r7.raw_voltage_accepted() as usize,
92 )),
93 r7 if r7.raw_crc() != crc.bits() => {
94 Err(Error::invalid_crc7(r7.raw_crc(), crc.bits()))
95 }
96 r7 if !r7.end_bit() => Err(Error::invalid_field_variant("r7::end_bit", 0)),
97 r7 => Ok(r7),
98 }
99 }
100 }
101 }
102}
103
104impl Default for R7 {
105 fn default() -> Self {
106 Self::new()
107 }
108}
109
110impl From<R7> for [u8; R7::LEN] {
111 fn from(val: R7) -> Self {
112 val.bytes()
113 }
114}
115
116impl TryFrom<&[u8]> for R7 {
117 type Error = Error;
118
119 fn try_from(val: &[u8]) -> Result<Self> {
120 Self::try_from_bytes(val)
121 }
122}
123
124impl<const N: usize> TryFrom<[u8; N]> for R7 {
125 type Error = Error;
126
127 fn try_from(val: [u8; N]) -> Result<Self> {
128 Self::try_from_bytes(val.as_ref())
129 }
130}
131
132impl<const N: usize> TryFrom<&[u8; N]> for R7 {
133 type Error = Error;
134
135 fn try_from(val: &[u8; N]) -> Result<Self> {
136 Self::try_from_bytes(val.as_ref())
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 use crate::test_field;
144 use crate::util::raw_with_crc;
145
146 #[test]
147 fn test_fields() {
148 let mut r7 = R7::new();
149
150 assert!(!r7.pcie());
151 assert!(!r7.pcie_12v_support());
152
153 test_field!(r7, pcie { bit: 20, [u8; R7::LEN] });
154 test_field!(r7, pcie_12v_support { bit: 21, [u8; R7::LEN] });
155
156 assert_eq!(r7.voltage_accepted(), Ok(VoltageAccepted::new()));
157 assert_eq!(r7.echo_check(), 0);
158
159 (0..=u8::MAX).zip(0..=u8::MAX).for_each(|(flags, echo)| {
160 let (raw, _crc) = raw_with_crc([COMMAND_INDEX, 0, 0, flags, echo, 0]);
161 let raw_va = flags & 0xf;
162
163 match VoltageAccepted::from_raw(raw_va) {
164 Ok(va) => {
165 r7 = R7(raw);
166
167 assert_eq!(R7::try_from_bytes(raw.as_ref()), Ok(r7));
168 assert_eq!(R7::try_from(raw), Ok(r7));
169 assert_eq!(r7.bytes(), raw);
170
171 test_field!(r7, pcie { bit: 20, [u8; R7::LEN] });
172 test_field!(r7, pcie_12v_support { bit: 21, [u8; R7::LEN] });
173
174 assert_eq!(r7.voltage_accepted(), Ok(va));
175
176 r7.set_voltage_accepted(VoltageAccepted::new());
177 assert_eq!(r7.voltage_accepted(), Ok(VoltageAccepted::new()));
178
179 r7.set_voltage_accepted(va);
180 assert_eq!(r7.voltage_accepted(), Ok(va));
181
182 assert_eq!(r7.echo_check(), echo);
183
184 r7.set_echo_check(0);
185 assert_eq!(r7.echo_check(), 0);
186
187 r7.set_echo_check(echo);
188 assert_eq!(r7.echo_check(), echo);
189 }
190 Err(_) => {
191 assert_eq!(
192 R7::try_from_bytes(raw.as_ref()),
193 Err(Error::invalid_field_variant(
194 "r7::voltage_accepted",
195 raw_va as usize
196 ))
197 );
198 assert_eq!(
199 R7::try_from(raw),
200 Err(Error::invalid_field_variant(
201 "r7::voltage_accepted",
202 raw_va as usize
203 ))
204 );
205 }
206 }
207 });
208 }
209}