sdmmc_core/response/sd/r5/
flags.rs

1use crate::lib_bitfield;
2use crate::result::{Error, Result};
3
4mod io_current_state;
5
6pub use io_current_state::*;
7
8lib_bitfield! {
9    /// Represents the response flags for the [R5](super::R5) response in SD mode.
10    pub Flags(u8): u8 {
11        /// CRC check failed from previous command.
12        pub crc_error: 7;
13        /// Command not legal for the card state.
14        pub illegal_command: 6;
15        raw_io_current_state: 5, 4;
16        /// A general or unknown error occurred.
17        pub error: 3;
18        /// An invalid function number requested.
19        pub function_number: 1;
20        /// Command argument out of range for this card.
21        pub out_of_range: 0;
22    }
23}
24
25impl Flags {
26    /// Creates a new [Flags].
27    pub const fn new() -> Self {
28        Self(0)
29    }
30
31    /// Gets the `IO_CURRENT_STATE` field of [Flags].
32    pub const fn io_current_state(&self) -> Result<IoCurrentState> {
33        IoCurrentState::from_raw(self.raw_io_current_state())
34    }
35
36    /// Sets the `IO_CURRENT_STATE` field of [Flags].
37    pub fn set_io_current_state(&mut self, val: IoCurrentState) {
38        self.set_raw_io_current_state(val.into_raw())
39    }
40
41    /// Attempts to convert a [`u8`] into a [Flags].
42    pub const fn try_from_bits(val: u8) -> Result<Self> {
43        let flags = Self(val);
44
45        match flags.io_current_state() {
46            Ok(_) => Ok(flags),
47            Err(_) => Err(Error::invalid_field_variant(
48                "r5::flags::io_current_state",
49                flags.raw_io_current_state() as usize,
50            )),
51        }
52    }
53}
54
55impl Default for Flags {
56    fn default() -> Self {
57        Self::new()
58    }
59}
60
61impl From<Flags> for u8 {
62    fn from(val: Flags) -> Self {
63        val.bits()
64    }
65}
66
67impl TryFrom<u8> for Flags {
68    type Error = Error;
69
70    fn try_from(val: u8) -> Result<Self> {
71        Self::try_from_bits(val)
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn test_valid() {
81        let mut flags = Flags::new();
82
83        test_field!(flags, out_of_range: 0);
84        test_field!(flags, function_number: 1);
85        test_field!(flags, error: 3);
86        test_field!(flags, illegal_command: 6);
87        test_field!(flags, crc_error: 7);
88
89        [
90            IoCurrentState::Disabled,
91            IoCurrentState::Command,
92            IoCurrentState::Transfer,
93        ]
94        .into_iter()
95        .for_each(|io_cs| {
96            let raw_io_cs = io_cs.into_raw();
97            let mut exp_flags = Flags(raw_io_cs << 4);
98            assert_eq!(Flags::try_from_bits(raw_io_cs << 4), Ok(exp_flags));
99            assert_eq!(exp_flags.io_current_state(), Ok(io_cs));
100
101            exp_flags.set_io_current_state(IoCurrentState::new());
102            assert_eq!(exp_flags.io_current_state(), Ok(IoCurrentState::new()));
103        });
104    }
105
106    #[test]
107    fn test_invalid() {
108        let raw_io_cs = [
109            IoCurrentState::Disabled,
110            IoCurrentState::Command,
111            IoCurrentState::Transfer,
112        ]
113        .map(|r| r.into_raw());
114
115        (0..=u8::MAX)
116            .filter(|b| !raw_io_cs.iter().any(|&c| ((b >> 4) & 0x3) == c))
117            .for_each(|invalid_bits| {
118                let invalid_io_cs = (invalid_bits >> 4) & 0x3;
119
120                assert_eq!(
121                    Flags::try_from_bits(invalid_bits),
122                    Err(Error::invalid_field_variant(
123                        "r5::flags::io_current_state",
124                        invalid_io_cs as usize
125                    )),
126                );
127            });
128    }
129}