sdmmc_core/response/
start.rs

1use crate::lib_bitfield;
2use crate::result::{Error, Result};
3
4lib_bitfield! {
5    /// Represents the starting byte of card responses in SD mode.
6    pub Start(u8): u8 {
7        /// The MSB of the response, should always be `0`.
8        pub start_bit: 7;
9        /// The transmission bit, should always be `0`.
10        pub transmission_bit: 6;
11        /// Represents a 6-bit index ranging from `0-63`, indicating the `CMD` number for the response.
12        pub command_index: 5, 0;
13    }
14}
15
16impl Start {
17    /// Represents the byte length of the [Start].
18    pub const LEN: usize = 1;
19    /// Represents the default value of the [Start].
20    pub const DEFAULT: u8 = 0;
21    /// Represents the valid bitmask of the [Start].
22    pub const MASK: u8 = 0b0011_1111;
23
24    /// Creates a new [Start].
25    pub const fn new() -> Self {
26        Self(Self::DEFAULT)
27    }
28
29    /// Converts a [`u8`] into a [Start].
30    ///
31    /// # Note
32    ///
33    /// Masks the value to a valid [Start] value.
34    pub const fn from_bits(val: u8) -> Self {
35        Self(val & Self::MASK)
36    }
37
38    /// Attempts to convert a [`u8`] into a [Start].
39    pub const fn try_from_bits(val: u8) -> Result<Self> {
40        match val {
41            v if (v & !Self::MASK) != 0 => Err(Error::invalid_field_variant("start", v as usize)),
42            v => Ok(Self(v)),
43        }
44    }
45}
46
47impl Default for Start {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl TryFrom<u8> for Start {
54    type Error = Error;
55
56    fn try_from(val: u8) -> Result<Self> {
57        Self::try_from_bits(val)
58    }
59}
60
61impl From<Start> for u8 {
62    fn from(val: Start) -> Self {
63        val.bits()
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_fields() {
73        let mut s = Start::new();
74
75        assert_eq!(s.command_index(), 0);
76        assert!(!s.transmission_bit());
77        assert!(!s.start_bit());
78
79        (0..=0x3f).for_each(|cmd| {
80            s.set_command_index(cmd);
81            assert_eq!(s.command_index(), cmd);
82
83            // make sure we didn't corrupt other fields
84            assert!(!s.transmission_bit());
85            assert!(!s.start_bit());
86        });
87
88        // the interface will accept invalid command index, but masks the value.
89        (0x40..=u8::MAX).for_each(|invalid_cmd| {
90            s.set_command_index(invalid_cmd);
91            assert_eq!(s.command_index(), invalid_cmd & Start::MASK);
92        });
93    }
94}