#![no_std]
#![doc = include_str!("../README.md")]
pub mod prelude;
pub mod register;
use core::fmt::Debug;
use embedded_hal::i2c::{I2c, SevenBitAddress};
use embedded_hal::spi::SpiDevice;
use prelude::*;
use st_mems_bus::*;
pub struct Lis2mdl<B> {
pub bus: B,
}
#[derive(Debug)]
pub enum Error<B> {
Bus(B), UnexpectedValue, }
impl<B> Lis2mdl<B>
where
B: BusOperation,
{
pub fn new_bus(bus: B) -> Self {
Self { bus }
}
}
impl<P> Lis2mdl<i2c::I2cBus<P>>
where
P: I2c,
{
pub fn new_i2c(i2c: P, address: I2CAddress) -> Self {
let bus = i2c::I2cBus::new(i2c, address as SevenBitAddress);
Self { bus }
}
}
impl<P> Lis2mdl<spi::SpiBus<P>>
where
P: SpiDevice,
{
pub fn new_spi(spi: P) -> Self {
let bus = spi::SpiBus::new(spi);
Self { bus }
}
}
impl<B: BusOperation> Lis2mdl<B> {
pub fn write_to_register(&mut self, reg: u8, buf: &[u8]) -> Result<(), Error<B::Error>> {
self.bus.write_to_register(reg, buf).map_err(Error::Bus)
}
pub fn read_from_register(&mut self, reg: u8, buf: &mut [u8]) -> Result<(), Error<B::Error>> {
self.bus.read_from_register(reg, buf).map_err(Error::Bus)
}
pub 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)?;
Ok(())
}
pub fn mag_user_offset_get(&mut self) -> Result<[i16; 3], Error<B::Error>> {
let val = OffsetXYZ::read(self)?;
Ok([val.x, val.y, val.z])
}
pub fn operating_mode_set(&mut self, val: Md) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self)?;
reg.set_md(val as u8);
reg.write(self)
}
pub fn operating_mode_get(&mut self) -> Result<Md, Error<B::Error>> {
let reg = CfgRegA::read(self)?;
let val = Md::try_from(reg.md()).unwrap_or_default();
Ok(val)
}
pub fn data_rate_set(&mut self, val: Odr) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self)?;
reg.set_odr(val as u8);
reg.write(self)
}
pub fn data_rate_get(&mut self) -> Result<Odr, Error<B::Error>> {
let reg = CfgRegA::read(self)?;
let val = Odr::try_from(reg.odr()).unwrap_or_default();
Ok(val)
}
pub fn power_mode_set(&mut self, val: PowerMode) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self)?;
reg.set_lp(val as u8);
reg.write(self)?;
Ok(())
}
pub fn power_mode_get(&mut self) -> Result<PowerMode, Error<B::Error>> {
let reg = CfgRegA::read(self)?;
let val = PowerMode::try_from(reg.lp()).unwrap_or_default();
Ok(val)
}
pub fn offset_temp_comp_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self)?;
reg.set_comp_temp_en(val);
reg.write(self)?;
Ok(())
}
pub fn offset_temp_comp_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegA::read(self)?.comp_temp_en();
Ok(val)
}
pub fn low_pass_bandwidth_set(&mut self, val: LowPassFilter) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self)?;
reg.set_lpf(val as u8);
reg.write(self)?;
Ok(())
}
pub fn low_pass_bandwidth_get(&mut self) -> Result<LowPassFilter, Error<B::Error>> {
let reg = CfgRegB::read(self)?;
let val = LowPassFilter::try_from(reg.lpf()).unwrap_or_default();
Ok(val)
}
pub fn set_rst_mode_set(&mut self, val: SetRst) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self)?;
reg.set_set_rst(val as u8);
reg.write(self)?;
Ok(())
}
pub fn set_rst_mode_get(&mut self) -> Result<SetRst, Error<B::Error>> {
let reg = CfgRegB::read(self)?;
let val = SetRst::try_from(reg.set_rst()).unwrap_or_default();
Ok(val)
}
pub fn set_rst_sensor_single_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self)?;
reg.set_off_canc_one_shot(val);
reg.write(self)?;
Ok(())
}
pub fn set_rst_sensor_single_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegB::read(self)?.off_canc_one_shot();
Ok(val)
}
pub fn block_data_update_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self)?;
reg.set_bdu(val);
reg.write(self)?;
Ok(())
}
pub fn block_data_update_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self)?.bdu();
Ok(val)
}
pub fn mag_data_ready_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = StatusReg::read(self)?.zyxda();
Ok(val)
}
pub fn mag_data_ovr_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = StatusReg::read(self)?.zyxor();
Ok(val)
}
pub fn magnetic_raw_get(&mut self) -> Result<[i16; 3], Error<B::Error>> {
let val = OutXYZ::read(self)?;
Ok([val.x, val.y, val.z])
}
pub fn temperature_raw_get(&mut self) -> Result<i16, Error<B::Error>> {
TempOut::read(self).map(|temp| temp.0)
}
pub fn device_id_get(&mut self) -> Result<u8, Error<B::Error>> {
WhoAmI::read(self).map(|who_am_i| who_am_i.0)
}
pub fn reset_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self)?;
reg.set_soft_rst(val);
reg.write(self)?;
Ok(())
}
pub fn reset_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegA::read(self)?.soft_rst();
Ok(val)
}
pub fn boot_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegA::read(self)?;
reg.set_reboot(val);
reg.write(self)?;
Ok(())
}
pub fn boot_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegA::read(self)?.reboot();
Ok(val)
}
pub fn self_test_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self)?;
reg.set_self_test(val);
reg.write(self)?;
Ok(())
}
pub fn self_test_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self)?.self_test();
Ok(val)
}
pub fn data_format_set(&mut self, val: Ble) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self)?;
reg.set_ble(val as u8);
reg.write(self)?;
Ok(())
}
pub fn data_format_get(&mut self) -> Result<Ble, Error<B::Error>> {
let reg = CfgRegC::read(self)?;
let val = Ble::try_from(reg.ble()).unwrap_or_default();
Ok(val)
}
pub fn status_get(&mut self) -> Result<StatusReg, Error<B::Error>> {
let val = StatusReg::read(self)?;
Ok(val)
}
pub fn offset_int_conf_set(&mut self, val: IntOnDataoff) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegB::read(self)?;
reg.set_int_on_dataoff(val as u8);
reg.write(self)?;
Ok(())
}
pub fn offset_int_conf_get(&mut self) -> Result<IntOnDataoff, Error<B::Error>> {
let reg = CfgRegB::read(self)?;
let val = IntOnDataoff::try_from(reg.int_on_dataoff()).unwrap_or_default();
Ok(val)
}
pub fn drdy_on_pin_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self)?;
reg.set_drdy_on_pin(val);
reg.write(self)?;
Ok(())
}
pub fn drdy_on_pin_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self)?.drdy_on_pin();
Ok(val)
}
pub fn int_on_pin_set(&mut self, val: u8) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self)?;
reg.set_int_on_pin(val);
reg.write(self)?;
Ok(())
}
pub fn int_on_pin_get(&mut self) -> Result<u8, Error<B::Error>> {
let val: u8 = CfgRegC::read(self)?.int_on_pin();
Ok(val)
}
pub fn int_gen_conf_set(&mut self, val: &IntCrtlReg) -> Result<(), Error<B::Error>> {
val.write(self)
}
pub fn int_gen_conf_get(&mut self) -> Result<IntCrtlReg, Error<B::Error>> {
IntCrtlReg::read(self)
}
pub fn int_gen_source_get(&mut self) -> Result<IntSourceReg, Error<B::Error>> {
IntSourceReg::read(self)
}
pub fn int_gen_threshold_set(&mut self, val: u16) -> Result<(), Error<B::Error>> {
IntThs::new().with_threshold(val).write(self)
}
pub fn int_gen_threshold_get(&mut self) -> Result<u16, Error<B::Error>> {
Ok(IntThs::read(self)?.threshold())
}
pub fn spi_mode_set(&mut self, val: Sim) -> Result<(), Error<B::Error>> {
let mut reg_val = CfgRegC::read(self)?;
reg_val.set_four_wire_spi(val as u8);
reg_val.write(self)?;
Ok(())
}
pub fn spi_mode_get(&mut self) -> Result<Sim, Error<B::Error>> {
let reg_val = CfgRegC::read(self)?;
let val = Sim::try_from(reg_val.four_wire_spi()).unwrap_or_default();
Ok(val)
}
pub fn i2c_interface_set(&mut self, val: I2cSwitch) -> Result<(), Error<B::Error>> {
let mut reg = CfgRegC::read(self)?;
reg.set_i2c_dis(val as u8);
reg.write(self)?;
Ok(())
}
pub fn i2c_interface_get(&mut self) -> Result<I2cSwitch, Error<B::Error>> {
let reg = CfgRegC::read(self)?;
let val = I2cSwitch::try_from(reg.i2c_dis()).unwrap_or_default();
Ok(val)
}
}
pub fn from_lsb_to_mgauss(lsb: i16) -> f32 {
lsb as f32 * 1.5
}
pub fn from_lsb_to_celsius(lsb: i16) -> f32 {
lsb as f32 / 8.0 + 25.0
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq)]
pub enum I2CAddress {
I2cAdd = 0x1E,
}
pub const ID: u8 = 0x40;