stk8ba58/accelerometer.rs
1use core::fmt::Debug;
2
3use accelerometer_hal::{
4 vector::{F32x3, I16x3},
5 Accelerometer, Error, RawAccelerometer,
6};
7use embedded_hal::i2c::I2c;
8
9use crate::{
10 registers::{Axis, BwSel, Read},
11 Stk8ba58,
12};
13
14impl<I2C, E> Accelerometer for Stk8ba58<I2C>
15where
16 I2C: I2c<Error = E>,
17 E: Debug,
18{
19 type Error = E;
20
21 /// Get normalized ±g reading from the accelerometer.
22 ///
23 /// **Note**: it is expected that you call this when you know
24 /// data is ready and valid, like in response to an
25 /// interrupt or polling far slower than your data rate.
26 ///
27 /// Usage
28 /// ```no_run
29 /// let accel = accelerometer.accel_norm().unwrap();
30 /// let (x, y, z) = (accel.x, accel.y, accel.z)
31 /// println!("X = {x}\nY = {y},\nZ = [z]");
32 /// ```
33 ///
34 /// # Errors
35 /// - Any I²C errors will cause the function to fail.
36 fn accel_norm(&mut self) -> Result<F32x3, Error<E>> {
37 const I12_MAX: f32 = 2048.0;
38 let raw_data: I16x3 = self.accel_raw()?;
39 let range: f32 = self.range.into();
40
41 let x = (raw_data.x as f32 / I12_MAX) * range;
42 let y = (raw_data.y as f32 / I12_MAX) * range;
43 let z = (raw_data.z as f32 / I12_MAX) * range;
44
45 Ok(F32x3::new(x, y, z))
46 }
47
48 /// Read the rample rate from the `BWSEL` register and convert it to Hz.
49 ///
50 /// **Note**: You likely want to use `.read_mode(BwSel::default())` from `registers::Read`
51 ///
52 /// # Errors
53 /// - Any I²C errors will cause the function to fail.
54 fn sample_rate(&mut self) -> Result<f32, Error<Self::Error>> {
55 Ok(self.read_mode(BwSel::default())?.into())
56 }
57}
58
59impl<I2C, E> RawAccelerometer<I16x3> for Stk8ba58<I2C>
60where
61 I2C: I2c<Error = E>,
62 E: Debug,
63{
64 type Error = E;
65
66 /// Get raw acceleration reading from the accelerometer.
67 /// Keep in mind readings are 12 bits.
68 ///
69 /// **Note**: it is expected that you call this when you know
70 /// data is ready and valid, like in response to an
71 /// interrupt or polling far slower than your data rate.
72 ///
73 /// # Errors
74 /// - Any I²C errors will cause the function to fail.
75 fn accel_raw(&mut self) -> Result<I16x3, Error<E>> {
76 const NEGATIVE: i16 = 0b1000_0000_0000; // Two's complement negative sign for 12 bits
77
78 let mut xyz = [0, 0, 0];
79 let axis = [Axis::X, Axis::Y, Axis::Z];
80
81 for (i, axis) in axis.iter().enumerate() {
82 // LSB should be read first due to data protection
83 let lsb = self.axis_lsb(axis)?;
84 let lsb = (lsb as i16) >> 4; // Move the bits to occupy positions 3-0 instead of 7-4
85
86 let msb = self.axis_msb(axis)?;
87 let msb = (msb as i16) << 4; // Move the bits to occupy positions 11-4 instead of 7-0
88
89 let sign = if (msb & NEGATIVE) == NEGATIVE {
90 0b1111_1111_0000_0000u16 as i16 // Correct for two's complement negative sign
91 } else {
92 0
93 };
94
95 let accel_raw = msb | lsb | sign;
96
97 xyz[i] = accel_raw;
98 }
99
100 Ok(I16x3::new(xyz[0], xyz[1], xyz[2]))
101 }
102}