lis3dh_spi/
ctrl_reg_4_value.rs

1use crate::enabled_enum::OnOff;
2use num_derive::FromPrimitive;
3use num_traits::FromPrimitive;
4
5#[repr(u8)]
6#[derive(Copy, Clone, Debug, PartialEq)]
7pub enum SpiModeSelection {
8    FourWireInterface,
9    ThreeWireInterface,
10}
11impl Default for SpiModeSelection {
12    fn default() -> Self {
13        SpiModeSelection::FourWireInterface
14    }
15}
16
17const SELF_TEST_BIT_OFFSET: u8 = 1;
18#[repr(u8)]
19#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq)]
20pub enum SelfTest {
21    NormalMode,
22    SelfTest0,
23    SelfTest1,
24}
25impl Default for SelfTest {
26    fn default() -> Self {
27        SelfTest::NormalMode
28    }
29}
30
31const HIGH_RESOLUTION_OUTPUT_MODE_BIT_OFFSET: u8 = 3;
32
33const FULL_SCALE_SELECTION_OUTPUT_MODE_BIT_OFFSET: u8 = 4;
34#[repr(u8)]
35#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq)]
36pub enum FullScaleSelection {
37    Gravity2G,
38    Gravity4G,
39    Gravity8G,
40    Gravity16G,
41}
42impl Default for FullScaleSelection {
43    fn default() -> Self {
44        FullScaleSelection::Gravity2G
45    }
46}
47
48const BLE_SETTING_BIT_OFFSET: u8 = 6;
49#[repr(u8)]
50#[derive(Copy, Clone, Debug, PartialEq)]
51pub enum Endianness {
52    LSBLowerAddress,
53    MSBLowerAddress,
54}
55impl Default for Endianness {
56    fn default() -> Self {
57        Endianness::LSBLowerAddress
58    }
59}
60
61const BDU_SETTING_BIT_OFFSET: u8 = 7;
62#[repr(u8)]
63#[derive(Copy, Clone, Debug, PartialEq)]
64pub enum BlockDataUpdate {
65    ContinuousUpdate,
66    NotUpdated,
67}
68impl Default for BlockDataUpdate {
69    fn default() -> Self {
70        BlockDataUpdate::ContinuousUpdate
71    }
72}
73
74#[derive(Clone, Copy, Default, PartialEq)]
75pub struct CtrlReg4Value {
76    sim: SpiModeSelection,
77    st: SelfTest,
78    hr: OnOff,
79    fs: FullScaleSelection,
80    ble: Endianness,
81    bdu: BlockDataUpdate,
82}
83
84impl CtrlReg4Value {
85    pub(super) fn set_sim(&mut self, sim: SpiModeSelection) {
86        self.sim = sim;
87    }
88
89    pub(super) fn set_st(&mut self, st: SelfTest) {
90        self.st = st;
91    }
92
93    pub(super) fn set_hr(&mut self, hr: OnOff) {
94        self.hr = hr;
95    }
96
97    pub(super) fn set_fs(&mut self, fs: FullScaleSelection) {
98        self.fs = fs;
99    }
100
101    pub(super) fn set_ble(&mut self, ble: Endianness) {
102        self.ble = ble;
103    }
104
105    pub(super) fn set_bdu(&mut self, bdu: BlockDataUpdate) {
106        self.bdu = bdu;
107    }
108
109    pub(super) fn sim(&self) -> SpiModeSelection {
110        self.sim
111    }
112    pub(super) fn st(&self) -> SelfTest {
113        self.st
114    }
115    pub(super) fn hr(&self) -> OnOff {
116        self.hr
117    }
118    pub(super) fn fs(&self) -> FullScaleSelection {
119        self.fs
120    }
121    pub(super) fn ble(&self) -> Endianness {
122        self.ble
123    }
124    pub(super) fn bdu(&self) -> BlockDataUpdate {
125        self.bdu
126    }
127
128    pub(super) fn get_raw_value(&self) -> u8 {
129        (self.bdu as u8) << BDU_SETTING_BIT_OFFSET
130            | (self.ble as u8) << BLE_SETTING_BIT_OFFSET
131            | (self.fs as u8) << FULL_SCALE_SELECTION_OUTPUT_MODE_BIT_OFFSET
132            | (self.hr as u8) << HIGH_RESOLUTION_OUTPUT_MODE_BIT_OFFSET
133            | (self.st as u8) << SELF_TEST_BIT_OFFSET
134            | self.sim as u8
135    }
136    pub(super) fn from_raw_value(value: u8) -> Self {
137        let sim = if value & 1 == 1 {
138            SpiModeSelection::ThreeWireInterface
139        } else {
140            SpiModeSelection::FourWireInterface
141        };
142        let st =
143            SelfTest::from_u8((value & 0b110) >> SELF_TEST_BIT_OFFSET).unwrap();
144        let hr = if (value >> HIGH_RESOLUTION_OUTPUT_MODE_BIT_OFFSET) & 1 == 1 {
145            OnOff::Enabled
146        } else {
147            OnOff::Disabled
148        };
149        let fs = FullScaleSelection::from_u8(
150            (value & 0b0011_0000)
151                >> FULL_SCALE_SELECTION_OUTPUT_MODE_BIT_OFFSET,
152        )
153        .unwrap();
154        let ble = if value >> BLE_SETTING_BIT_OFFSET & 1 == 1 {
155            Endianness::MSBLowerAddress
156        } else {
157            Endianness::LSBLowerAddress
158        };
159        let bdu = if value >> BDU_SETTING_BIT_OFFSET & 1 == 1 {
160            BlockDataUpdate::NotUpdated
161        } else {
162            BlockDataUpdate::ContinuousUpdate
163        };
164        CtrlReg4Value {
165            sim,
166            st,
167            hr,
168            fs,
169            ble,
170            bdu,
171        }
172    }
173}
174
175#[cfg(test)]
176mod test {
177    #[test]
178    fn conversion_from_raw_value_works() {
179        let raw_value = 0b0101_0100_u8;
180        let ctrl_reg_4 = super::CtrlReg4Value::from_raw_value(raw_value);
181        assert_eq!(ctrl_reg_4.st, super::SelfTest::SelfTest1)
182    }
183
184    #[test]
185    fn conversion_to_raw_value_works() {
186        let mut ctrl_reg_value = super::CtrlReg4Value::default();
187
188        ctrl_reg_value.sim = super::SpiModeSelection::ThreeWireInterface;
189        ctrl_reg_value.st = super::SelfTest::SelfTest1;
190        ctrl_reg_value.hr = super::OnOff::Enabled;
191        ctrl_reg_value.fs = super::FullScaleSelection::Gravity8G;
192        ctrl_reg_value.ble = super::Endianness::MSBLowerAddress;
193        assert_eq!(ctrl_reg_value.get_raw_value(), 0b0110_1101);
194    }
195}