1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub enum OperatingMode {
6 SoftwareReset,
8 NoPower,
10 PowerOnDefault,
12 PowerDown,
14 MagOnly,
16 AccelMag,
18 AccelGyroMag,
20 Ois,
22 AccelGyroOnly,
24 GyroOnly,
26 AccelOnly,
28 LowPowerAccel,
30 LowPowerAllOff,
32 WakeOnMotion,
34}
35
36#[derive(Clone, Copy, Debug, PartialEq, Eq)]
37pub(crate) enum TransitionDelay {
38 Immediate,
39 T0,
40 T1PlusT5,
41 T2PlusT5,
42 T3PlusT5,
43 T4PlusT5,
44 T6,
45 T7,
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub(crate) struct ModeTransition {
50 pub from: OperatingMode,
51 pub to: OperatingMode,
52 pub delay: TransitionDelay,
53}
54
55const MODE_TRANSITIONS: &[ModeTransition] = &[
56 ModeTransition {
57 from: OperatingMode::SoftwareReset,
58 to: OperatingMode::PowerOnDefault,
59 delay: TransitionDelay::T0,
60 },
61 ModeTransition {
62 from: OperatingMode::NoPower,
63 to: OperatingMode::PowerOnDefault,
64 delay: TransitionDelay::T0,
65 },
66 ModeTransition {
67 from: OperatingMode::PowerOnDefault,
68 to: OperatingMode::PowerDown,
69 delay: TransitionDelay::T6,
70 },
71 ModeTransition {
72 from: OperatingMode::PowerDown,
73 to: OperatingMode::PowerOnDefault,
74 delay: TransitionDelay::T7,
75 },
76 ModeTransition {
77 from: OperatingMode::PowerOnDefault,
78 to: OperatingMode::MagOnly,
79 delay: TransitionDelay::T6,
80 },
81 ModeTransition {
82 from: OperatingMode::MagOnly,
83 to: OperatingMode::PowerOnDefault,
84 delay: TransitionDelay::T3PlusT5,
85 },
86 ModeTransition {
87 from: OperatingMode::PowerOnDefault,
88 to: OperatingMode::AccelMag,
89 delay: TransitionDelay::T6,
90 },
91 ModeTransition {
92 from: OperatingMode::AccelMag,
93 to: OperatingMode::PowerOnDefault,
94 delay: TransitionDelay::T1PlusT5,
95 },
96 ModeTransition {
97 from: OperatingMode::PowerOnDefault,
98 to: OperatingMode::AccelGyroMag,
99 delay: TransitionDelay::T6,
100 },
101 ModeTransition {
102 from: OperatingMode::AccelGyroMag,
103 to: OperatingMode::PowerOnDefault,
104 delay: TransitionDelay::T1PlusT5,
105 },
106 ModeTransition {
107 from: OperatingMode::PowerOnDefault,
108 to: OperatingMode::Ois,
109 delay: TransitionDelay::T6,
110 },
111 ModeTransition {
112 from: OperatingMode::Ois,
113 to: OperatingMode::PowerOnDefault,
114 delay: TransitionDelay::T1PlusT5,
115 },
116 ModeTransition {
117 from: OperatingMode::PowerOnDefault,
118 to: OperatingMode::AccelGyroOnly,
119 delay: TransitionDelay::T6,
120 },
121 ModeTransition {
122 from: OperatingMode::AccelGyroOnly,
123 to: OperatingMode::PowerOnDefault,
124 delay: TransitionDelay::T1PlusT5,
125 },
126 ModeTransition {
127 from: OperatingMode::PowerOnDefault,
128 to: OperatingMode::GyroOnly,
129 delay: TransitionDelay::T6,
130 },
131 ModeTransition {
132 from: OperatingMode::GyroOnly,
133 to: OperatingMode::PowerOnDefault,
134 delay: TransitionDelay::T4PlusT5,
135 },
136 ModeTransition {
137 from: OperatingMode::PowerOnDefault,
138 to: OperatingMode::AccelOnly,
139 delay: TransitionDelay::T6,
140 },
141 ModeTransition {
142 from: OperatingMode::AccelOnly,
143 to: OperatingMode::PowerOnDefault,
144 delay: TransitionDelay::T1PlusT5,
145 },
146 ModeTransition {
147 from: OperatingMode::PowerOnDefault,
148 to: OperatingMode::LowPowerAccel,
149 delay: TransitionDelay::T6,
150 },
151 ModeTransition {
152 from: OperatingMode::LowPowerAccel,
153 to: OperatingMode::PowerOnDefault,
154 delay: TransitionDelay::T2PlusT5,
155 },
156 ModeTransition {
157 from: OperatingMode::PowerOnDefault,
158 to: OperatingMode::LowPowerAllOff,
159 delay: TransitionDelay::T7,
160 },
161 ModeTransition {
162 from: OperatingMode::LowPowerAllOff,
163 to: OperatingMode::PowerOnDefault,
164 delay: TransitionDelay::T6,
165 },
166 ModeTransition {
167 from: OperatingMode::LowPowerAllOff,
168 to: OperatingMode::WakeOnMotion,
169 delay: TransitionDelay::T2PlusT5,
170 },
171 ModeTransition {
172 from: OperatingMode::WakeOnMotion,
173 to: OperatingMode::LowPowerAllOff,
174 delay: TransitionDelay::T2PlusT5,
175 },
176 ModeTransition {
177 from: OperatingMode::LowPowerAccel,
178 to: OperatingMode::LowPowerAllOff,
179 delay: TransitionDelay::T2PlusT5,
180 },
181];
182
183#[derive(Clone, Copy, Debug, PartialEq, Eq)]
184pub(crate) struct OperatingModeStateMachine {
185 mode: OperatingMode,
186}
187
188impl OperatingModeStateMachine {
189 pub const fn new(mode: OperatingMode) -> Self {
190 Self { mode }
191 }
192
193 pub const fn mode(self) -> OperatingMode {
194 self.mode
195 }
196
197 pub fn set_mode(&mut self, mode: OperatingMode) {
198 self.mode = mode;
199 }
200
201 #[allow(dead_code)]
202 pub fn transition_to(&mut self, target: OperatingMode) -> Result<TransitionDelay, ()> {
203 if self.mode == target {
204 return Ok(TransitionDelay::Immediate);
205 }
206
207 let delay = transition_delay(self.mode, target).ok_or(())?;
208 self.mode = target;
209 Ok(delay)
210 }
211}
212
213pub(crate) fn transition_delay(from: OperatingMode, to: OperatingMode) -> Option<TransitionDelay> {
214 if from == to {
215 return Some(TransitionDelay::Immediate);
216 }
217
218 if matches!(to, OperatingMode::SoftwareReset | OperatingMode::NoPower) {
219 return Some(TransitionDelay::Immediate);
220 }
221
222 MODE_TRANSITIONS
223 .iter()
224 .find(|entry| entry.from == from && entry.to == to)
225 .map(|entry| entry.delay)
226}