microbit_bsp/motion/
mod.rs1use embassy_nrf::{
6 interrupt::typelevel::{self, Binding},
7 peripherals::{P0_08, P0_16, TWISPI0},
8 twim::{self, InterruptHandler},
9 Peri,
10};
11use embassy_sync::channel::DynamicSender;
12use embassy_time::{Duration, Ticker};
13use lsm303agr::{
14 interface::I2cInterface, mode::MagOneShot, AccelMode, AccelOutputDataRate, Acceleration, Error as LsmError,
15 Lsm303agr, MagMode, MagOutputDataRate, MagneticField, Status,
16};
17use static_cell::ConstStaticCell;
18
19type I2C<'d> = twim::Twim<'d, TWISPI0>;
20
21pub type Error = LsmError<twim::Error>;
23
24pub struct Sensor<'d> {
26 sensor: Lsm303agr<I2cInterface<I2C<'d>>, MagOneShot>,
27}
28
29pub fn new_lsm303agr<'d>(
68 twispi0: Peri<'static, TWISPI0>,
69 irq: impl Binding<typelevel::TWISPI0, InterruptHandler<TWISPI0>> + 'd,
70 sda: Peri<'static, P0_16>,
71 scl: Peri<'static, P0_08>,
72) -> Lsm303agr<I2cInterface<I2C<'d>>, MagOneShot> {
73 let config = twim::Config::default();
74 static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]);
75 let twi = twim::Twim::new(twispi0, irq, sda, scl, config, RAM_BUFFER.take());
76 Lsm303agr::new_with_i2c(twi)
77}
78
79impl<'d> Sensor<'d> {
80 pub async fn new(
86 twispi0: Peri<'static, TWISPI0>,
87 irq: impl Binding<typelevel::TWISPI0, InterruptHandler<TWISPI0>> + 'd,
88 sda: Peri<'static, P0_16>,
89 scl: Peri<'static, P0_08>,
90 ) -> Result<Self, Error> {
91 let mut sensor = new_lsm303agr(twispi0, irq, sda, scl);
92 sensor.init().await?;
93 sensor
94 .set_accel_mode_and_odr(&mut embassy_time::Delay, AccelMode::Normal, AccelOutputDataRate::Hz10)
95 .await?;
96
97 sensor
98 .set_mag_mode_and_odr(
99 &mut embassy_time::Delay,
100 MagMode::HighResolution,
101 MagOutputDataRate::Hz10,
102 )
103 .await?;
104 sensor.mag_enable_low_pass_filter().await?;
105 sensor.enable_mag_offset_cancellation().await?;
106
107 Ok(Self { sensor })
108 }
109
110 pub async fn accel_status(&mut self) -> Result<Status, Error> {
116 self.sensor.accel_status().await
117 }
118
119 pub async fn accel_data(&mut self) -> Result<Acceleration, Error> {
127 self.sensor.acceleration().await
128 }
129
130 pub async fn accel_run(
136 &mut self,
137 rate: AccelOutputDataRate,
138 sender: DynamicSender<'_, Acceleration>,
139 ) -> Result<(), Error> {
140 let delay = match rate {
141 AccelOutputDataRate::Hz1 => Duration::from_millis(1000),
142 AccelOutputDataRate::Hz10 => Duration::from_millis(100),
143 AccelOutputDataRate::Hz25 => Duration::from_millis(40),
144 AccelOutputDataRate::Hz50 => Duration::from_millis(20),
145 AccelOutputDataRate::Hz100 => Duration::from_millis(10),
146 AccelOutputDataRate::Hz200 => Duration::from_millis(5),
147 AccelOutputDataRate::Hz400 => Duration::from_micros(2500),
148 AccelOutputDataRate::Khz1_344 => Duration::from_micros(744),
149 AccelOutputDataRate::Khz1_620LowPower => Duration::from_micros(617),
150 AccelOutputDataRate::Khz5_376LowPower => Duration::from_micros(186),
151 };
152 let mut ticker = Ticker::every(delay);
153 loop {
154 ticker.next().await;
155 let data = self.accel_data().await?;
156 let _ = sender.try_send(data);
157 }
158 }
159
160 pub async fn mag_data(&mut self) -> Result<MagneticField, Error> {
167 self.sensor.magnetic_field().await
168 }
169
170 pub async fn mag_status(&mut self) -> Result<Status, Error> {
176 self.sensor.mag_status().await
177 }
178}