sdmmc_core/command/class/class10/cmd6/
arg.rs

1use crate::lib_bitfield;
2use crate::result::{Error, Result};
3
4mod access_mode;
5mod command_system;
6mod driver_strength;
7mod mode;
8mod power_limit;
9
10pub use access_mode::*;
11pub use command_system::*;
12pub use driver_strength::*;
13pub use mode::*;
14pub use power_limit::*;
15
16lib_bitfield! {
17    /// Argumentument for CMD6.
18    pub Argument(u32): u8 {
19        raw_mode: 31;
20        raw_power_limit: 15, 12;
21        raw_driver_strength: 11, 8;
22        raw_command_system: 7, 4;
23        raw_access_mode: 3, 0;
24    }
25}
26
27impl Argument {
28    /// Represents the byte length of the [Argument].
29    pub const LEN: usize = 4;
30    /// Represents the raw default value of the [Argument].
31    pub const DEFAULT: u32 = 0;
32
33    /// Creates a new [Argument].
34    pub const fn new() -> Self {
35        Self(0)
36    }
37
38    /// Gets the [AccessMode] for the `CMD6` [Argument].
39    pub const fn access_mode(&self) -> Result<AccessMode> {
40        AccessMode::from_raw(self.raw_access_mode())
41    }
42
43    /// Sets the [AccessMode] for the `CMD6` [Argument].
44    pub fn set_access_mode(&mut self, val: AccessMode) {
45        self.set_raw_access_mode(val.into_raw() as u32);
46    }
47
48    /// Gets the [CommandSystem] for the `CMD6` [Argument].
49    pub const fn command_system(&self) -> Result<CommandSystem> {
50        CommandSystem::from_raw(self.raw_command_system())
51    }
52
53    /// Sets the [CommandSystem] for the `CMD6` [Argument].
54    pub fn set_command_system(&mut self, val: CommandSystem) {
55        self.set_raw_command_system(val.into_raw() as u32);
56    }
57
58    /// Gets the [DriverStrength] for the `CMD6` [Argument].
59    pub const fn driver_strength(&self) -> Result<DriverStrength> {
60        DriverStrength::from_raw(self.raw_driver_strength())
61    }
62
63    /// Sets the [DriverStrength] for the `CMD6` [Argument].
64    pub fn set_driver_strength(&mut self, val: DriverStrength) {
65        self.set_raw_driver_strength(val.into_raw() as u32);
66    }
67
68    /// Gets the [PowerLimit] for the `CMD6` [Argument].
69    pub const fn power_limit(&self) -> Result<PowerLimit> {
70        PowerLimit::from_raw(self.raw_power_limit())
71    }
72
73    /// Sets the [PowerLimit] for the `CMD6` [Argument].
74    pub fn set_power_limit(&mut self, val: PowerLimit) {
75        self.set_raw_power_limit(val.into_raw() as u32)
76    }
77
78    /// Gets the [Mode] for the `CMD6` [Argument].
79    pub const fn mode(&self) -> Result<Mode> {
80        Mode::from_raw(self.raw_mode() as u8)
81    }
82
83    /// Sets the [Mode] for the `CMD6` [Argument].
84    pub fn set_mode(&mut self, val: Mode) {
85        self.set_raw_mode(val.into_raw() != 0);
86    }
87
88    /// Attempts to convert a [`u32`] into an [Argument].
89    pub const fn try_from_bits(val: u32) -> Result<Self> {
90        match Self(val) {
91            arg if arg.access_mode().is_err() => Err(Error::invalid_field_variant(
92                "cmd::argument::access_mode",
93                arg.raw_access_mode() as usize,
94            )),
95            arg if arg.command_system().is_err() => Err(Error::invalid_field_variant(
96                "cmd::argument::command_system",
97                arg.raw_command_system() as usize,
98            )),
99            arg if arg.driver_strength().is_err() => Err(Error::invalid_field_variant(
100                "cmd::argument::driver_strength",
101                arg.raw_driver_strength() as usize,
102            )),
103            arg if arg.power_limit().is_err() => Err(Error::invalid_field_variant(
104                "cmd::argument::power_limit",
105                arg.raw_power_limit() as usize,
106            )),
107            arg if arg.mode().is_err() => Err(Error::invalid_field_variant(
108                "cmd::argument::mode",
109                arg.raw_mode() as usize,
110            )),
111            arg => Ok(arg),
112        }
113    }
114
115    /// Converts the [Argument] into a byte array.
116    pub const fn bytes(&self) -> [u8; Self::LEN] {
117        self.0.to_be_bytes()
118    }
119
120    /// Attempts to convert a [`u32`] into an [Argument].
121    pub const fn try_from_bytes(val: &[u8]) -> Result<Self> {
122        match val.len() {
123            len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
124            _ => Self::try_from_bits(u32::from_be_bytes([val[0], val[1], val[2], val[3]])),
125        }
126    }
127}
128
129impl Default for Argument {
130    fn default() -> Self {
131        Self::new()
132    }
133}
134
135impl TryFrom<u32> for Argument {
136    type Error = Error;
137
138    fn try_from(val: u32) -> Result<Self> {
139        Self::try_from_bits(val)
140    }
141}
142
143impl From<Argument> for u32 {
144    fn from(val: Argument) -> Self {
145        val.bits()
146    }
147}
148
149impl From<Argument> for [u8; Argument::LEN] {
150    fn from(val: Argument) -> Self {
151        val.bytes()
152    }
153}
154
155impl TryFrom<&[u8]> for Argument {
156    type Error = Error;
157
158    fn try_from(val: &[u8]) -> Result<Self> {
159        Self::try_from_bytes(val)
160    }
161}
162
163impl<const N: usize> TryFrom<&[u8; N]> for Argument {
164    type Error = Error;
165
166    fn try_from(val: &[u8; N]) -> Result<Self> {
167        Self::try_from_bytes(val.as_ref())
168    }
169}
170
171impl<const N: usize> TryFrom<[u8; N]> for Argument {
172    type Error = Error;
173
174    fn try_from(val: [u8; N]) -> Result<Self> {
175        Self::try_from_bytes(val.as_ref())
176    }
177}
178
179#[cfg(test)]
180mod tests {
181    use super::*;
182
183    #[test]
184    fn test_fields() {
185        let mut arg = Argument::new();
186
187        assert_eq!(arg.access_mode(), Ok(AccessMode::new()));
188        assert_eq!(arg.command_system(), Ok(CommandSystem::new()));
189        assert_eq!(arg.driver_strength(), Ok(DriverStrength::new()));
190        assert_eq!(arg.power_limit(), Ok(PowerLimit::new()));
191
192        [
193            AccessMode::Sdr12,
194            AccessMode::Sdr25,
195            AccessMode::Sdr50,
196            AccessMode::Sdr104,
197            AccessMode::Ddr50,
198        ]
199        .into_iter()
200        .for_each(|exp_access_mode| {
201            arg.set_access_mode(exp_access_mode);
202            assert_eq!(arg.access_mode(), Ok(exp_access_mode));
203        });
204
205        [
206            CommandSystem::SystemDefault,
207            CommandSystem::ForEC,
208            CommandSystem::Otp,
209            CommandSystem::Assd,
210            CommandSystem::Vendor,
211        ]
212        .into_iter()
213        .for_each(|exp_command_system| {
214            arg.set_command_system(exp_command_system);
215            assert_eq!(arg.command_system(), Ok(exp_command_system));
216        });
217
218        [
219            DriverStrength::TypeB,
220            DriverStrength::TypeA,
221            DriverStrength::TypeC,
222            DriverStrength::TypeD,
223        ]
224        .into_iter()
225        .for_each(|exp_driver_strength| {
226            arg.set_driver_strength(exp_driver_strength);
227            assert_eq!(arg.driver_strength(), Ok(exp_driver_strength));
228        });
229
230        [
231            PowerLimit::W072,
232            PowerLimit::W144,
233            PowerLimit::W216,
234            PowerLimit::W288,
235            PowerLimit::W180,
236        ]
237        .into_iter()
238        .for_each(|exp_power_limit| {
239            arg.set_power_limit(exp_power_limit);
240            assert_eq!(arg.power_limit(), Ok(exp_power_limit));
241        });
242
243        [Mode::Check, Mode::Switch]
244            .into_iter()
245            .for_each(|exp_mode| {
246                arg.set_mode(exp_mode);
247                assert_eq!(arg.mode(), Ok(exp_mode));
248            });
249    }
250}