use embassy_nrf::{
interrupt::typelevel::{self, Binding},
peripherals::{P0_08, P0_16, TWISPI0},
twim::{self, InterruptHandler},
Peri,
};
use embassy_sync::channel::DynamicSender;
use embassy_time::{Duration, Ticker};
use lsm303agr::{
interface::I2cInterface, mode::MagOneShot, AccelMode, AccelOutputDataRate, Acceleration, Error as LsmError,
Lsm303agr, MagMode, MagOutputDataRate, MagneticField, Status,
};
use static_cell::ConstStaticCell;
type I2C<'d> = twim::Twim<'d, TWISPI0>;
pub type Error = LsmError<twim::Error>;
pub struct Sensor<'d> {
sensor: Lsm303agr<I2cInterface<I2C<'d>>, MagOneShot>,
}
pub fn new_lsm303agr<'d>(
twispi0: Peri<'static, TWISPI0>,
irq: impl Binding<typelevel::TWISPI0, InterruptHandler<TWISPI0>> + 'd,
sda: Peri<'static, P0_16>,
scl: Peri<'static, P0_08>,
) -> Lsm303agr<I2cInterface<I2C<'d>>, MagOneShot> {
let config = twim::Config::default();
static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]);
let twi = twim::Twim::new(twispi0, irq, sda, scl, config, RAM_BUFFER.take());
Lsm303agr::new_with_i2c(twi)
}
impl<'d> Sensor<'d> {
pub async fn new(
twispi0: Peri<'static, TWISPI0>,
irq: impl Binding<typelevel::TWISPI0, InterruptHandler<TWISPI0>> + 'd,
sda: Peri<'static, P0_16>,
scl: Peri<'static, P0_08>,
) -> Result<Self, Error> {
let mut sensor = new_lsm303agr(twispi0, irq, sda, scl);
sensor.init().await?;
sensor
.set_accel_mode_and_odr(&mut embassy_time::Delay, AccelMode::Normal, AccelOutputDataRate::Hz10)
.await?;
sensor
.set_mag_mode_and_odr(
&mut embassy_time::Delay,
MagMode::HighResolution,
MagOutputDataRate::Hz10,
)
.await?;
sensor.mag_enable_low_pass_filter().await?;
sensor.enable_mag_offset_cancellation().await?;
Ok(Self { sensor })
}
pub async fn accel_status(&mut self) -> Result<Status, Error> {
self.sensor.accel_status().await
}
pub async fn accel_data(&mut self) -> Result<Acceleration, Error> {
self.sensor.acceleration().await
}
pub async fn accel_run(
&mut self,
rate: AccelOutputDataRate,
sender: DynamicSender<'_, Acceleration>,
) -> Result<(), Error> {
let delay = match rate {
AccelOutputDataRate::Hz1 => Duration::from_millis(1000),
AccelOutputDataRate::Hz10 => Duration::from_millis(100),
AccelOutputDataRate::Hz25 => Duration::from_millis(40),
AccelOutputDataRate::Hz50 => Duration::from_millis(20),
AccelOutputDataRate::Hz100 => Duration::from_millis(10),
AccelOutputDataRate::Hz200 => Duration::from_millis(5),
AccelOutputDataRate::Hz400 => Duration::from_micros(2500),
AccelOutputDataRate::Khz1_344 => Duration::from_micros(744),
AccelOutputDataRate::Khz1_620LowPower => Duration::from_micros(617),
AccelOutputDataRate::Khz5_376LowPower => Duration::from_micros(186),
};
let mut ticker = Ticker::every(delay);
loop {
ticker.next().await;
let data = self.accel_data().await?;
let _ = sender.try_send(data);
}
}
pub async fn mag_data(&mut self) -> Result<MagneticField, Error> {
self.sensor.magnetic_field().await
}
pub async fn mag_status(&mut self) -> Result<Status, Error> {
self.sensor.mag_status().await
}
}