#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::Mode;
use crc_all::Crc;
pub mod device_config;
pub mod sensor_config;
pub mod system_config;
pub mod alert_config;
pub const MODE: Mode = embedded_hal::spi::MODE_0;
pub struct Tmag5170<SPI, CS> {
spi: SPI,
cs: CS,
crc: Crc<u8>, }
pub enum ExtError<E> {
E(E),
CrcError,
}
impl<SPI, CS, E> Tmag5170<SPI, CS>
where
SPI: Transfer<u8, Error = E>,
CS: OutputPin,
{
pub fn new(spi: SPI, cs: CS) -> Self {
let crc = Crc::<u8>::new(0x03, 4, 0x0f, 0x00, false);
Tmag5170 { spi, cs, crc }
}
fn write_register(&mut self, reg: Register, value: u16, cmd: u8) -> Result<(), ExtError<E>> {
self.crc.init();
let mut buffer: [u8; 4] = [0; 4];
let value_bytes = value.to_be_bytes();
buffer[0] = reg.addr();
buffer[1] = value_bytes[0];
buffer[2] = value_bytes[1];
buffer[3] = cmd << 4;
self.crc.update(&buffer);
let crc4 = self.crc.finish();
buffer[3] |= crc4;
let _ = self.cs.set_low();
let res = self.spi.transfer(&mut buffer);
let _ = self.cs.set_high();
match res {
Ok(_buf) => (),
Err(e) => return Err(ExtError::E(e)),
};
let packet_crc4 = buffer[3] & 0x0f; buffer[3] &= 0xf0; self.crc.init();
self.crc.update(&buffer);
let calc_crc4 = self.crc.finish();
if packet_crc4 == calc_crc4 {
Ok(())
} else {
Err(ExtError::CrcError)
}
}
fn read_register(&mut self, reg: Register, cmd: u8) -> Result<u16, ExtError<E>> {
self.crc.init();
let mut buffer: [u8; 4] = [0; 4];
buffer[0] = reg.addr() | 0x80; buffer[1] = 0;
buffer[2] = 0;
buffer[3] = cmd << 4;
self.crc.update(&buffer);
let crc4 = self.crc.finish();
buffer[3] |= crc4;
let _ = self.cs.set_low();
let res = self.spi.transfer(&mut buffer);
let _ = self.cs.set_high();
match res {
Ok(_buf) => (),
Err(e) => return Err(ExtError::E(e)),
};
let packet_crc4 = buffer[3] & 0x0f; buffer[3] &= 0xf0; self.crc.init();
self.crc.update(&buffer);
let calc_crc4 = self.crc.finish();
if packet_crc4 == calc_crc4 {
let value = ((buffer[1] as u16) << 8) + buffer[2] as u16;
Ok(value)
} else {
Err(ExtError::CrcError)
}
}
fn read_special(&mut self, cmd: u8) -> Result<(u16, u16), ExtError<E>> {
self.crc.init();
let mut buffer: [u8; 4] = [0; 4];
buffer[0] = 0x80; buffer[1] = 0;
buffer[2] = 0;
buffer[3] = cmd << 4;
self.crc.update(&buffer);
let crc4 = self.crc.finish();
buffer[3] |= crc4;
let _ = self.cs.set_low();
let res = self.spi.transfer(&mut buffer);
let _ = self.cs.set_high();
match res {
Ok(_buf) => (),
Err(e) => return Err(ExtError::E(e)),
};
let packet_crc4 = buffer[3] & 0x0f; buffer[3] &= 0xf0; self.crc.init();
self.crc.update(&buffer);
let calc_crc4 = self.crc.finish();
if packet_crc4 == calc_crc4 {
let ch1 = ((buffer[1] as u16) << 4) + (buffer[2] & 0x0f) as u16;
let ch2 = ((buffer[0] as u16) << 4) + (buffer[2] >> 4) as u16;
Ok((ch1, ch2))
} else {
Err(ExtError::CrcError)
}
}
pub fn read_mag_registers(&mut self) -> Result<(i16, i16, i16), ExtError<E>> {
let x = self.read_register(Register::X_CH_RESULT, 0x00)?;
let y = self.read_register(Register::Y_CH_RESULT, 0x00)?;
let z = self.read_register(Register::Z_CH_RESULT, 0x00)?;
Ok((x as i16, y as i16, z as i16))
}
pub fn read_angle_registers(&mut self) -> Result<(i16, i16), ExtError<E>> {
let a = self.read_register(Register::ANGLE_RESULT, 0x00)?;
let m = self.read_register(Register::MAGNITUDE_RESULT, 0x00)?;
Ok((a as i16, m as i16))
}
pub fn read_temp_register(&mut self) -> Result<i16, ExtError<E>> {
let t = self.read_register(Register::TEMP_RESULT, 0x00)?;
Ok(t as i16)
}
pub fn read_am(&mut self) -> Result<(u16, u16), ExtError<E>> {
let (a, m) = self.read_special(0x00)?;
Ok((a, m))
}
pub fn read_conv_status_register(&mut self) -> Result<i16, ExtError<E>> {
let s = self.read_register(Register::CONV_STATUS, 0x00)?;
Ok(s as i16)
}
pub fn read_afe_status_register(&mut self) -> Result<i16, ExtError<E>> {
let s = self.read_register(Register::AFE_STATUS, 0x00)?;
Ok(s as i16)
}
pub fn read_sys_status_register(&mut self) -> Result<i16, ExtError<E>> {
let s = self.read_register(Register::SYS_STATUS, 0x00)?;
Ok(s as i16)
}
pub fn read_test_config_register(&mut self) -> Result<i16, ExtError<E>> {
let tc = self.read_register(Register::TEST_CONFIG, 0x00)?;
Ok(tc as i16)
}
pub fn conv_start(&mut self) -> Result<(), ExtError<E>> {
self.read_register(Register::DEVICE_CONFIG, 0x01)?;
Ok(())
}
pub fn apply_device_config(
&mut self,
config: device_config::DeviceConfig,
) -> Result<(), ExtError<E>> {
self.write_register(Register::DEVICE_CONFIG, config.to_u16(), 0x00)?;
Ok(())
}
pub fn apply_sensor_config(
&mut self,
config: sensor_config::SensorConfig,
) -> Result<(), ExtError<E>> {
self.write_register(Register::SENSOR_CONFIG, config.to_u16(), 0x00)?;
Ok(())
}
pub fn apply_system_config(
&mut self,
config: system_config::SystemConfig,
) -> Result<(), ExtError<E>> {
self.write_register(Register::SYSTEM_CONFIG, config.to_u16(), 0x00)?;
Ok(())
}
pub fn apply_alert_config(
&mut self,
config: alert_config::AlertConfig,
) -> Result<(), ExtError<E>> {
self.write_register(Register::ALERT_CONFIG, config.to_u16(), 0x00)?;
Ok(())
}
}
#[allow(dead_code)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
enum Register {
DEVICE_CONFIG = 0x00,
SENSOR_CONFIG = 0x01,
SYSTEM_CONFIG = 0x02,
ALERT_CONFIG = 0x03,
X_THRX_CONFIG = 0x04,
Y_THRX_CONFIG = 0x05,
Z_THRX_CONFIG = 0x06,
T_THRX_CONFIG = 0x07,
CONV_STATUS = 0x08,
X_CH_RESULT = 0x09,
Y_CH_RESULT = 0x0A,
Z_CH_RESULT = 0x0B,
TEMP_RESULT = 0x0C,
AFE_STATUS = 0x0D,
SYS_STATUS = 0x0E,
TEST_CONFIG = 0x0F,
OSC_MONITOR = 0x10,
MAG_GAIN_CONFIG = 0x11,
ANGLE_RESULT = 0x13,
MAGNITUDE_RESULT = 0x14,
}
impl Register {
fn addr(self) -> u8 {
self as u8
}
}