1use crate::Error;
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36pub enum PowerMode {
37 Normal,
39 LowPower,
41 Sleep,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48pub enum ClockSource {
49 Internal20MHz = 0,
51 AutoSelect = 1,
53 Stop = 7,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61#[cfg_attr(feature = "defmt", derive(defmt::Format))]
62pub enum LowPowerRate {
63 Hz0_24 = 0,
65 Hz0_49 = 1,
67 Hz0_98 = 2,
69 Hz1_95 = 3,
71 Hz3_91 = 4,
73 Hz7_81 = 5,
75 Hz15_63 = 6,
77 Hz31_25 = 7,
79 Hz62_50 = 8,
81 Hz125 = 9,
83 Hz250 = 10,
85 Hz500 = 11,
87}
88
89impl LowPowerRate {
90 pub const fn rate_hz(&self) -> f32 {
92 match self {
93 Self::Hz0_24 => 0.24,
94 Self::Hz0_49 => 0.49,
95 Self::Hz0_98 => 0.98,
96 Self::Hz1_95 => 1.95,
97 Self::Hz3_91 => 3.91,
98 Self::Hz7_81 => 7.81,
99 Self::Hz15_63 => 15.63,
100 Self::Hz31_25 => 31.25,
101 Self::Hz62_50 => 62.50,
102 Self::Hz125 => 125.0,
103 Self::Hz250 => 250.0,
104 Self::Hz500 => 500.0,
105 }
106 }
107
108 pub const fn period_ms(&self) -> f32 {
110 1000.0 / self.rate_hz()
111 }
112
113 pub const fn odr_value(&self) -> u8 {
115 *self as u8
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121#[cfg_attr(feature = "defmt", derive(defmt::Format))]
122pub enum WomMode {
123 CompareInitialSample = 0,
125 CompareCurrentSample = 1,
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
131#[cfg_attr(feature = "defmt", derive(defmt::Format))]
132pub struct LowPowerConfig {
133 pub accel_rate: LowPowerRate,
135 pub enable_wake_on_motion: bool,
137 pub wom_threshold: u16,
140 pub wom_mode: WomMode,
142}
143
144impl Default for LowPowerConfig {
145 fn default() -> Self {
146 Self {
147 accel_rate: LowPowerRate::Hz31_25,
148 enable_wake_on_motion: false,
149 wom_threshold: 20, wom_mode: WomMode::CompareCurrentSample,
151 }
152 }
153}
154
155impl LowPowerConfig {
156 pub const fn new(rate: LowPowerRate, wom_threshold_mg: u16) -> Result<Self, Error<()>> {
165 if wom_threshold_mg > 1020 {
166 return Err(Error::InvalidConfig);
167 }
168 Ok(Self {
169 accel_rate: rate,
170 enable_wake_on_motion: true,
171 wom_threshold: wom_threshold_mg,
172 wom_mode: WomMode::CompareCurrentSample,
173 })
174 }
175
176 pub fn wom_threshold_register_value(&self) -> u8 {
181 u8::try_from(self.wom_threshold / 4).unwrap_or(255)
182 }
183
184 pub const fn without_wom(rate: LowPowerRate) -> Self {
186 Self {
187 accel_rate: rate,
188 enable_wake_on_motion: false,
189 wom_threshold: 0,
190 wom_mode: WomMode::CompareCurrentSample,
191 }
192 }
193}
194
195#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
197#[cfg_attr(feature = "defmt", derive(defmt::Format))]
198pub struct CycleConfig {
199 pub enable_accel_cycle: bool,
201 pub enable_gyro_cycle: bool,
203 pub enable_i2c_master_cycle: bool,
205}
206
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
209#[cfg_attr(feature = "defmt", derive(defmt::Format))]
210#[allow(clippy::struct_excessive_bools)]
211pub struct PowerStatus {
212 pub mode: PowerMode,
214 pub sleep: bool,
216 pub low_power: bool,
218 pub temp_disabled: bool,
220 pub accel_cycle: bool,
222 pub gyro_cycle: bool,
224 pub i2c_master_cycle: bool,
226}
227
228impl Default for PowerStatus {
229 fn default() -> Self {
230 Self {
231 mode: PowerMode::Normal,
232 sleep: false,
233 low_power: false,
234 temp_disabled: false,
235 accel_cycle: false,
236 gyro_cycle: false,
237 i2c_master_cycle: false,
238 }
239 }
240}
241
242#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
244#[cfg_attr(feature = "defmt", derive(defmt::Format))]
245#[allow(clippy::struct_excessive_bools)]
246pub struct SensorPowerConfig {
247 pub disable_accel_x: bool,
249 pub disable_accel_y: bool,
251 pub disable_accel_z: bool,
253 pub disable_gyro_x: bool,
255 pub disable_gyro_y: bool,
257 pub disable_gyro_z: bool,
259}
260
261impl SensorPowerConfig {
262 pub const fn all_enabled() -> Self {
264 Self {
265 disable_accel_x: false,
266 disable_accel_y: false,
267 disable_accel_z: false,
268 disable_gyro_x: false,
269 disable_gyro_y: false,
270 disable_gyro_z: false,
271 }
272 }
273
274 pub const fn accel_disabled() -> Self {
276 Self {
277 disable_accel_x: true,
278 disable_accel_y: true,
279 disable_accel_z: true,
280 disable_gyro_x: false,
281 disable_gyro_y: false,
282 disable_gyro_z: false,
283 }
284 }
285
286 pub const fn gyro_disabled() -> Self {
288 Self {
289 disable_accel_x: false,
290 disable_accel_y: false,
291 disable_accel_z: false,
292 disable_gyro_x: true,
293 disable_gyro_y: true,
294 disable_gyro_z: true,
295 }
296 }
297
298 pub const fn is_accel_enabled(&self) -> bool {
300 !self.disable_accel_x && !self.disable_accel_y && !self.disable_accel_z
301 }
302
303 pub const fn is_gyro_enabled(&self) -> bool {
305 !self.disable_gyro_x && !self.disable_gyro_y && !self.disable_gyro_z
306 }
307}
308
309#[cfg(test)]
310#[allow(clippy::unwrap_used)]
311mod tests {
312 use super::*;
313
314 #[test]
315 #[allow(clippy::float_cmp)]
316 fn test_low_power_rate_values() {
317 assert_eq!(LowPowerRate::Hz31_25.rate_hz(), 31.25);
318 assert_eq!(LowPowerRate::Hz125.rate_hz(), 125.0);
319 assert!(LowPowerRate::Hz31_25.period_ms() > 30.0);
320 assert!(LowPowerRate::Hz31_25.period_ms() < 33.0);
321 }
322
323 #[test]
324 fn test_low_power_config_default() {
325 let config = LowPowerConfig::default();
326 assert_eq!(config.accel_rate, LowPowerRate::Hz31_25);
327 assert!(!config.enable_wake_on_motion);
328 }
329
330 #[test]
331 fn test_low_power_config_new() {
332 let config = LowPowerConfig::new(LowPowerRate::Hz62_50, 100);
333 assert!(config.is_ok());
334 let config = config.unwrap();
335 assert_eq!(config.accel_rate, LowPowerRate::Hz62_50);
336 assert_eq!(config.wom_threshold, 100);
337 assert!(config.enable_wake_on_motion);
338 }
339
340 #[test]
341 fn test_low_power_config_invalid_threshold() {
342 let config = LowPowerConfig::new(LowPowerRate::Hz31_25, 1100);
343 assert!(config.is_err());
344 }
345
346 #[test]
347 fn test_wom_threshold_register_value() {
348 let config = LowPowerConfig {
349 wom_threshold: 100,
350 ..Default::default()
351 };
352 assert_eq!(config.wom_threshold_register_value(), 25);
353
354 let config = LowPowerConfig {
355 wom_threshold: 20,
356 ..Default::default()
357 };
358 assert_eq!(config.wom_threshold_register_value(), 5);
359 }
360
361 #[test]
362 fn test_sensor_power_config() {
363 let config = SensorPowerConfig::all_enabled();
364 assert!(config.is_accel_enabled());
365 assert!(config.is_gyro_enabled());
366
367 let config = SensorPowerConfig::accel_disabled();
368 assert!(!config.is_accel_enabled());
369 assert!(config.is_gyro_enabled());
370
371 let config = SensorPowerConfig::gyro_disabled();
372 assert!(config.is_accel_enabled());
373 assert!(!config.is_gyro_enabled());
374 }
375
376 #[test]
377 fn test_cycle_config_default() {
378 let config = CycleConfig::default();
379 assert!(!config.enable_accel_cycle);
380 assert!(!config.enable_gyro_cycle);
381 assert!(!config.enable_i2c_master_cycle);
382 }
383
384 #[test]
385 fn test_power_status_default() {
386 let status = PowerStatus::default();
387 assert_eq!(status.mode, PowerMode::Normal);
388 assert!(!status.sleep);
389 assert!(!status.low_power);
390 }
391}