use super::{
BusOperation, DelayNs, I2c, RegisterOperation, SensorOperation, SevenBitAddress, SpiDevice,
bisync, i2c, prelude::*, spi,
};
use core::fmt::Debug;
use core::marker::PhantomData;
#[bisync]
pub struct Lis2mdl<B, T, S>
where
B: BusOperation,
T: DelayNs,
S: SensorState,
{
pub bus: B,
pub tim: T,
_state: PhantomData<S>,
}
#[derive(Debug)]
#[bisync]
pub enum Error<B> {
Bus(B), UnexpectedValue, InvalidConfiguration,
HwNoResponse,
}
#[bisync]
impl<B, T, S> Lis2mdl<B, T, S>
where
B: BusOperation,
T: DelayNs,
S: SensorState,
{
pub fn new_bus(bus: B, tim: T) -> Self {
Self {
bus,
tim,
_state: PhantomData,
}
}
}
#[bisync]
impl<P, T> Lis2mdl<i2c::I2cBus<P>, T, OnState>
where
P: I2c,
T: DelayNs,
{
pub fn new_i2c(i2c: P, address: I2CAddress, tim: T) -> Self {
let bus = i2c::I2cBus::new(i2c, address as SevenBitAddress);
Self {
bus,
tim,
_state: PhantomData,
}
}
}
#[bisync]
impl<P, T, S> Lis2mdl<spi::SpiBus<P>, T, S>
where
P: SpiDevice,
T: DelayNs,
S: SensorState,
{
pub fn new_spi(spi: P, tim: T) -> Self {
let bus = spi::SpiBus::new(spi);
Self {
bus,
tim,
_state: PhantomData,
}
}
}
#[bisync]
impl<B, T, S> SensorOperation for Lis2mdl<B, T, S>
where
B: BusOperation,
T: DelayNs,
S: SensorState,
{
type Error = Error<B::Error>;
async fn write_to_register(&mut self, reg: u8, buf: &[u8]) -> Result<(), Error<B::Error>> {
self.bus
.write_to_register(reg, buf)
.await
.map_err(Error::Bus)
}
async fn read_from_register(&mut self, reg: u8, buf: &mut [u8]) -> Result<(), Error<B::Error>> {
self.bus
.read_from_register(reg, buf)
.await
.map_err(Error::Bus)
}
}
#[bisync]
impl<B, T> Lis2mdl<B, T, OnState>
where
B: BusOperation,
T: DelayNs,
{
pub async fn mag_user_offset_set(&mut self, val: &[i16; 3]) -> Result<(), Error<B::Error>> {
let offset = OffsetXYZ {
x: val[0],
y: val[1],
z: val[2],
};
offset.write(self).await?;
Ok(())
}
pub async fn mag_user_offset_get(&mut self) -> Result<[i16; 3], Error<B::Error>> {
let val = OffsetXYZ::read(self).await?;
Ok([val.x, val.y, val.z])
}
pub async fn operating_mode_set(&mut self, val: Md) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self).await?;
reg.set_md(val as u8);
reg.write(self).await
}
pub async fn operating_mode_get(&mut self) -> Result<Md, Error<B::Error>> {
let reg = CfgRegA::read(self).await?;
let val = Md::try_from(reg.md()).unwrap_or_default();
Ok(val)
}
pub async fn data_rate_set(&mut self, val: Odr) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self).await?;
reg.set_odr(val as u8);
reg.write(self).await
}
pub async fn data_rate_get(&mut self) -> Result<Odr, Error<B::Error>> {
let reg = CfgRegA::read(self).await?;
let val = Odr::try_from(reg.odr()).unwrap_or_default();
Ok(val)
}
pub async fn power_mode_set(&mut self, val: PowerMode) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self).await?;
reg.set_lp(val as u8);
reg.write(self).await?;
Ok(())
}
pub async fn power_mode_get(&mut self) -> Result<PowerMode, Error<B::Error>> {
let reg = CfgRegA::read(self).await?;
let val = PowerMode::try_from(reg.lp()).unwrap_or_default();
Ok(val)
}
pub async fn offset_temp_comp_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self).await?;
reg.set_comp_temp_en(val);
reg.write(self).await?;
Ok(())
}
pub async fn offset_temp_comp_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegA::read(self).await?.comp_temp_en();
Ok(val)
}
pub async fn low_pass_bandwidth_set(
&mut self,
val: LowPassFilter,
) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self).await?;
reg.set_lpf(val as u8);
reg.write(self).await?;
Ok(())
}
pub async fn low_pass_bandwidth_get(&mut self) -> Result<LowPassFilter, Error<B::Error>> {
let reg = CfgRegB::read(self).await?;
let val = LowPassFilter::try_from(reg.lpf()).unwrap_or_default();
Ok(val)
}
pub async fn set_rst_mode_set(&mut self, val: SetRst) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self).await?;
reg.set_set_rst(val as u8);
reg.write(self).await?;
Ok(())
}
pub async fn set_rst_mode_get(&mut self) -> Result<SetRst, Error<B::Error>> {
let reg = CfgRegB::read(self).await?;
let val = SetRst::try_from(reg.set_rst()).unwrap_or_default();
Ok(val)
}
pub async fn set_rst_sensor_single_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self).await?;
let rst = SetRst::try_from(reg.set_rst()).map_err(|_| Error::UnexpectedValue)?;
if val == 1 && rst != SetRst::SensOffCancEveryOdr {
return Err(Error::InvalidConfiguration);
}
reg.set_off_canc_one_shot(val);
reg.write(self).await?;
Ok(())
}
pub async fn set_rst_sensor_single_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegB::read(self).await?.off_canc_one_shot();
Ok(val)
}
pub async fn block_data_update_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self).await?;
reg.set_bdu(val);
reg.write(self).await?;
Ok(())
}
pub async fn block_data_update_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self).await?.bdu();
Ok(val)
}
pub async fn mag_data_ready_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = StatusReg::read(self).await?.zyxda();
Ok(val)
}
pub async fn mag_data_ovr_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = StatusReg::read(self).await?.zyxor();
Ok(val)
}
pub async fn magnetic_raw_get(&mut self) -> Result<[i16; 3], Error<B::Error>> {
let val = OutXYZ::read(self).await?;
Ok([val.x, val.y, val.z])
}
pub async fn temperature_raw_get(&mut self) -> Result<i16, Error<B::Error>> {
TempOut::read(self).await.map(|temp| temp.0)
}
pub async fn device_id_get(&mut self) -> Result<u8, Error<B::Error>> {
WhoAmI::read(self).await.map(|reg| reg.who_am_i())
}
pub async fn sw_reset(&mut self) -> Result<(), Error<B::Error>> {
let mut cfg_reg_a = CfgRegA::default();
let mut retry: u8 = 0;
cfg_reg_a.set_soft_rst(1);
cfg_reg_a.write(self).await?;
loop {
cfg_reg_a = CfgRegA::read(self).await?;
if cfg_reg_a.soft_rst() == 0 {
return Ok(());
}
retry += 1;
if retry > 3 {
break;
}
self.tim.delay_us(5).await;
}
Err(Error::HwNoResponse)
}
#[deprecated(since = "2.0.0", note = "please use sw_reset")]
pub async fn reset_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self).await?;
reg.set_soft_rst(val);
reg.write(self).await?;
Ok(())
}
#[deprecated(since = "2.0.0", note = "please use sw_reset")]
pub async fn reset_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegA::read(self).await?.soft_rst();
Ok(val)
}
pub async fn reboot(&mut self) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self).await?;
reg.set_reboot(1);
reg.write(self).await?;
self.tim.delay_ms(20).await;
Ok(())
}
#[deprecated(since = "2.0.0", note = "please use reboot")]
pub async fn boot_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self).await?;
reg.set_reboot(val);
reg.write(self).await?;
Ok(())
}
#[deprecated(since = "2.0.0", note = "please use reboot")]
pub async fn boot_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegA::read(self).await?.reboot();
Ok(val)
}
pub async fn self_test_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self).await?;
reg.set_self_test(val);
reg.write(self).await?;
Ok(())
}
pub async fn self_test_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self).await?.self_test();
Ok(val)
}
pub async fn data_format_set(&mut self, val: Ble) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self).await?;
reg.set_ble(val as u8);
reg.write(self).await?;
Ok(())
}
pub async fn data_format_get(&mut self) -> Result<Ble, Error<B::Error>> {
let reg = CfgRegC::read(self).await?;
let val = Ble::try_from(reg.ble()).unwrap_or_default();
Ok(val)
}
pub async fn status_get(&mut self) -> Result<StatusReg, Error<B::Error>> {
let val = StatusReg::read(self).await?;
Ok(val)
}
pub async fn offset_int_conf_set(&mut self, val: IntOnDataoff) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self).await?;
reg.set_int_on_dataoff(val as u8);
reg.write(self).await?;
Ok(())
}
pub async fn offset_int_conf_get(&mut self) -> Result<IntOnDataoff, Error<B::Error>> {
let reg = CfgRegB::read(self).await?;
let val = IntOnDataoff::try_from(reg.int_on_dataoff()).unwrap_or_default();
Ok(val)
}
pub async fn drdy_on_pin_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self).await?;
reg.set_drdy_on_pin(val);
reg.write(self).await?;
Ok(())
}
pub async fn drdy_on_pin_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self).await?.drdy_on_pin();
Ok(val)
}
pub async fn int_on_pin_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self).await?;
reg.set_int_on_pin(val);
reg.write(self).await?;
Ok(())
}
pub async fn int_on_pin_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self).await?.int_on_pin();
Ok(val)
}
pub async fn int_gen_conf_set(&mut self, val: &IntCrtlReg) -> Result<(), Error<B::Error>> {
val.write(self).await
}
pub async fn int_gen_conf_get(&mut self) -> Result<IntCrtlReg, Error<B::Error>> {
IntCrtlReg::read(self).await
}
pub async fn int_gen_source_get(&mut self) -> Result<IntSourceReg, Error<B::Error>> {
IntSourceReg::read(self).await
}
pub async fn int_gen_threshold_set(&mut self, val: u16) -> Result<(), Error<B::Error>> {
IntThs::new().with_threshold(val).write(self).await
}
pub async fn int_gen_threshold_get(&mut self) -> Result<u16, Error<B::Error>> {
Ok(IntThs::read(self).await?.threshold())
}
pub async fn spi_mode_set(&mut self, val: Sim) -> Result<(), Error<B::Error>> {
let mut reg_val = CfgRegC::read(self).await?;
reg_val.set_four_wire_spi(val as u8);
reg_val.write(self).await?;
Ok(())
}
pub async fn spi_mode_get(&mut self) -> Result<Sim, Error<B::Error>> {
let reg_val = CfgRegC::read(self).await?;
let val = Sim::try_from(reg_val.four_wire_spi()).unwrap_or_default();
Ok(val)
}
pub async fn i2c_interface_set(&mut self, val: I2cSwitch) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self).await?;
reg.set_i2c_dis(val as u8);
reg.write(self).await?;
Ok(())
}
pub async fn i2c_interface_get(&mut self) -> Result<I2cSwitch, Error<B::Error>> {
let reg = CfgRegC::read(self).await?;
let val = I2cSwitch::try_from(reg.i2c_dis()).unwrap_or_default();
Ok(val)
}
}
#[bisync]
pub fn from_lsb_to_mgauss(lsb: i16) -> f32 {
lsb as f32 * 1.5
}
#[bisync]
pub fn from_lsb_to_celsius(lsb: i16) -> f32 {
lsb as f32 / 8.0 + 25.0
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq)]
#[bisync]
pub enum I2CAddress {
I2cAdd = 0x1E,
}
#[bisync]
pub const ID: u8 = 0x40;