#![no_std]
#![deny(
missing_docs,
missing_debug_implementations,
missing_copy_implementations,
trivial_casts,
unstable_features,
unused_import_braces,
unused_qualifications,
//warnings
)]
#![allow(
dead_code,
clippy::uninit_assumed_init,
clippy::too_many_arguments,
clippy::upper_case_acronyms
)]
extern crate cast;
extern crate embedded_hal as ehal;
extern crate generic_array;
extern crate nb;
extern crate safe_transmute;
use core::mem::MaybeUninit;
use ehal::blocking::i2c::WriteRead;
use generic_array::typenum::consts::*;
use generic_array::{ArrayLength, GenericArray};
const EM7180_ADDRESS: u8 = 0x28;
#[derive(Debug, Copy, Clone)]
pub struct USFS<I2C> {
com: I2C,
address: u8,
int_pin: u8,
pass_thru: bool,
}
#[derive(Debug, Copy, Clone)]
pub enum Error<E> {
InvalidDevice(u8),
BusError(E),
Timeout,
}
impl<E> From<E> for Error<E> {
fn from(error: E) -> Self {
Error::BusError(error)
}
}
impl<I2C, E> USFS<I2C>
where
I2C: WriteRead<Error = E>,
{
pub fn default(i2c: I2C) -> Result<USFS<I2C>, Error<E>>
where
I2C: WriteRead<Error = E>,
{
USFS::new(i2c, EM7180_ADDRESS, 8, false)
}
pub fn new(i2c: I2C, address: u8, int_pin: u8, pass_thru: bool) -> Result<USFS<I2C>, Error<E>>
where
I2C: WriteRead<Error = E>,
{
let mut chip = USFS {
com: i2c,
address,
int_pin,
pass_thru,
};
let wai = chip.get_product_id()?;
if wai == 0x80 {
let acc_bw: u8 = 0x03;
let gyro_bw: u8 = 0x03;
let qrt_div: u8 = 0x01;
let mag_rt: u8 = 0x64;
let acc_rt: u8 = 0x14;
let gyro_rt: u8 = 0x14;
let baro_rt: u8 = 0x32;
let acc_fs: u16 = 0x08;
let gyro_fs: u16 = 0x7D0;
let mag_fs: u16 = 0x3E8;
chip.load_fw_from_eeprom()?;
chip.init_hardware(
acc_bw, gyro_bw, acc_fs, gyro_fs, mag_fs, qrt_div, mag_rt, acc_rt, gyro_rt, baro_rt,
)?;
Ok(chip)
} else {
Err(Error::InvalidDevice(wai))
}
}
fn read_byte(&mut self, reg: u8) -> Result<u8, E> {
let mut data: [u8; 1] = [0];
self.com.write_read(self.address, &[reg], &mut data)?;
Ok(data[0])
}
fn read_registers<N>(&mut self, reg: Register) -> Result<GenericArray<u8, N>, E>
where
N: ArrayLength<u8>,
{
let mut buffer: GenericArray<u8, N> =
unsafe { MaybeUninit::<GenericArray<u8, N>>::uninit().assume_init() };
{
let buffer: &mut [u8] = &mut buffer;
const I2C_AUTO_INCREMENT: u8 = 0;
self.com
.write_read(self.address, &[(reg as u8) | I2C_AUTO_INCREMENT], buffer)?;
}
Ok(buffer)
}
fn read_4bytes(&mut self, reg: Register) -> Result<[u8; 4], E> {
let buffer: GenericArray<u8, U4> = self.read_registers(reg)?;
let mut ret: [u8; 4] = Default::default();
ret.copy_from_slice(buffer.as_slice());
Ok(ret)
}
fn read_6bytes(&mut self, reg: Register) -> Result<[u8; 6], E> {
let buffer: GenericArray<u8, U6> = self.read_registers(reg)?;
let mut ret: [u8; 6] = Default::default();
ret.copy_from_slice(buffer.as_slice());
Ok(ret)
}
fn read_16bytes(&mut self, reg: Register) -> Result<[u8; 16], E> {
let buffer: GenericArray<u8, U16> = self.read_registers(reg)?;
let mut ret: [u8; 16] = Default::default();
ret.copy_from_slice(buffer.as_slice());
Ok(ret)
}
fn read_register(&mut self, reg: Register) -> Result<u8, E> {
let mut data: [u8; 1] = [0];
self.com.write_read(self.address, &[reg as u8], &mut data)?;
Ok(data[0])
}
fn write_register(&mut self, reg: Register, byte: u8) -> Result<(), E> {
let mut buffer = [0];
self.com
.write_read(self.address, &[reg as u8, byte], &mut buffer)
}
fn em7180_set_integer_param(&mut self, param: u8, param_val: u32) -> Result<(), E> {
let bytes_0 = (param_val & (0xFF)) as u8;
let bytes_1 = ((param_val >> 8) & (0xFF)) as u8;
let bytes_2 = ((param_val >> 16) & (0xFF)) as u8;
let bytes_3 = ((param_val >> 24) & (0xFF)) as u8;
let param = param | 0x80;
self.write_register(Register::EM7180_LoadParamByte0, bytes_0)?; self.write_register(Register::EM7180_LoadParamByte1, bytes_1)?;
self.write_register(Register::EM7180_LoadParamByte2, bytes_2)?;
self.write_register(Register::EM7180_LoadParamByte3, bytes_3)?; self.write_register(Register::EM7180_ParamRequest, param)?;
self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
while stat != param {
stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
}
self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?;
Ok(())
}
fn em7180_set_mag_acc_fs(&mut self, mag_fs: u16, acc_fs: u16) -> Result<(), E> {
let bytes_0 = (mag_fs & (0xFF)) as u8;
let bytes_1 = ((mag_fs >> 8) & (0xFF)) as u8;
let bytes_2 = (acc_fs & (0xFF)) as u8;
let bytes_3 = ((acc_fs >> 8) & (0xFF)) as u8;
self.write_register(Register::EM7180_LoadParamByte0, bytes_0)?; self.write_register(Register::EM7180_LoadParamByte1, bytes_1)?; self.write_register(Register::EM7180_LoadParamByte2, bytes_2)?; self.write_register(Register::EM7180_LoadParamByte3, bytes_3)?; self.write_register(Register::EM7180_ParamRequest, 0xCA)?; self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
while stat != 0xCA {
stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
}
self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?;
Ok(())
}
fn em7180_set_gyro_fs(&mut self, gyro_fs: u16) -> Result<(), E> {
let bytes_0 = (gyro_fs & (0xFF)) as u8;
let bytes_1 = ((gyro_fs >> 8) & (0xFF)) as u8;
let bytes_2 = 0x00;
let bytes_3 = 0x00;
self.write_register(Register::EM7180_LoadParamByte0, bytes_0)?; self.write_register(Register::EM7180_LoadParamByte1, bytes_1)?; self.write_register(Register::EM7180_LoadParamByte2, bytes_2)?; self.write_register(Register::EM7180_LoadParamByte3, bytes_3)?; self.write_register(Register::EM7180_ParamRequest, 0xCB)?; self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
while stat != 0xCB {
stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
}
self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?;
Ok(())
}
fn load_fw_from_eeprom(&mut self) -> Result<(), E> {
let mut stat = self.read_register(Register::EM7180_SentralStatus)? & 0x01;
let mut count = 0;
while stat != 0 {
self.write_register(Register::EM7180_ResetRequest, 0x01)?;
count += 1;
stat = self.read_register(Register::EM7180_SentralStatus)? & 0x01;
if count > 10 {
break;
};
}
Ok(())
}
fn init_hardware(
&mut self,
acc_bw: u8,
gyro_bw: u8,
acc_fs: u16,
gyro_fs: u16,
mag_fs: u16,
qrt_div: u8,
mag_rt: u8,
acc_rt: u8,
gyro_rt: u8,
baro_rt: u8,
) -> Result<(), Error<E>> {
self.write_register(Register::EM7180_HostControl, 0x00)?; self.write_register(Register::EM7180_PassThruControl, 0x00)?; self.write_register(Register::EM7180_HostControl, 0x01)?; self.write_register(Register::EM7180_HostControl, 0x00)?;
self.write_register(Register::EM7180_ACC_LPF_BW, acc_bw)?; self.write_register(Register::EM7180_GYRO_LPF_BW, gyro_bw)?; self.write_register(Register::EM7180_QRateDivisor, qrt_div)?; self.write_register(Register::EM7180_MagRate, mag_rt)?; self.write_register(Register::EM7180_AccelRate, acc_rt)?; self.write_register(Register::EM7180_GyroRate, gyro_rt)?; self.write_register(Register::EM7180_BaroRate, 0x80 | baro_rt)?;
self.write_register(Register::EM7180_AlgorithmControl, 0x00)?; self.write_register(Register::EM7180_EnableEvents, 0x07)?;
self.write_register(Register::EM7180_HostControl, 0x01)?;
self.write_register(Register::EM7180_ParamRequest, 0x4A)?;
self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
while param_xfer != 0x4A {
param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
}
self.write_register(Register::EM7180_ParamRequest, 0x4B)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
while param_xfer != 0x4B {
param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
}
self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?;
self.em7180_set_integer_param(0x49, 0x00)?;
self.em7180_set_mag_acc_fs(mag_fs, acc_fs)?; self.em7180_set_gyro_fs(gyro_fs)?;
self.write_register(Register::EM7180_ParamRequest, 0x4A)?; self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
while param_xfer != 0x4A {
param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
}
self.write_register(Register::EM7180_ParamRequest, 0x4B)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
while param_xfer != 0x4B {
param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
}
self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?;
Ok(())
}
pub fn get_product_id(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_ProductID)
}
pub fn get_rom_version(&mut self) -> Result<[u8; 2], E> {
let rom_version1 = self.read_register(Register::EM7180_ROMVersion1)?;
let rom_version2 = self.read_register(Register::EM7180_ROMVersion2)?;
Ok([rom_version1, rom_version2])
}
pub fn get_sentral_status(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_SentralStatus)
}
pub fn check_run_status(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_RunStatus)
}
pub fn check_status(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_EventStatus)
}
pub fn check_errors(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_Error)
}
pub fn check_sensor_status(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_SensorStatus)
}
pub fn check_feature_flags(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_FeatureFlags)
}
pub fn get_actual_magnetometer_rate(&mut self) -> Result<u8, E> {
self.read_register(Register::EM7180_ActualMagRate)
}
pub fn get_actual_accel_rate(&mut self) -> Result<u8, E> {
Ok(self.read_register(Register::EM7180_ActualAccelRate)? * 10)
}
pub fn get_actual_gyroscope_rate(&mut self) -> Result<u8, E> {
Ok(self.read_register(Register::EM7180_ActualGyroRate)? * 10)
}
pub fn read_sentral_accel_data(&mut self) -> Result<[i16; 3], E> {
let raw_data = self.read_6bytes(Register::EM7180_AX)?;
let ax = (raw_data[1] as i16) << 8 | raw_data[0] as i16;
let ay = (raw_data[3] as i16) << 8 | raw_data[2] as i16;
let az = (raw_data[5] as i16) << 8 | raw_data[4] as i16;
Ok([ax, ay, az])
}
pub fn read_sentral_gyro_data(&mut self) -> Result<[i16; 3], E> {
let raw_data = self.read_6bytes(Register::EM7180_GX)?;
let ax = (raw_data[1] as i16) << 8 | raw_data[0] as i16;
let ay = (raw_data[3] as i16) << 8 | raw_data[2] as i16;
let az = (raw_data[5] as i16) << 8 | raw_data[4] as i16;
Ok([ax, ay, az])
}
pub fn read_sentral_mag_data(&mut self) -> Result<[i16; 3], E> {
let raw_data = self.read_6bytes(Register::EM7180_MX)?;
let ax = (raw_data[1] as i16) << 8 | raw_data[0] as i16;
let ay = (raw_data[3] as i16) << 8 | raw_data[2] as i16;
let az = (raw_data[5] as i16) << 8 | raw_data[4] as i16;
Ok([ax, ay, az])
}
pub fn read_sentral_quat_qata(&mut self) -> Result<[f32; 4], E> {
let raw_data_qx = self.read_4bytes(Register::EM7180_QX)?;
let qx = reg_to_float(&raw_data_qx);
let raw_data_qy = self.read_4bytes(Register::EM7180_QY)?;
let qy = reg_to_float(&raw_data_qy);
let raw_data_qz = self.read_4bytes(Register::EM7180_QZ)?;
let qz = reg_to_float(&raw_data_qz);
let raw_data_qw = self.read_4bytes(Register::EM7180_QW)?;
let qw = reg_to_float(&raw_data_qw);
Ok([qx, qy, qz, qw])
}
pub fn read_sentral_baro_data(&mut self) -> Result<i16, E> {
let raw_data = self.read_6bytes(Register::EM7180_Baro)?; Ok((raw_data[1] as i16) << 8 | raw_data[0] as i16) }
pub fn read_sentral_temp_data(&mut self) -> Result<i16, E> {
let raw_data = self.read_6bytes(Register::EM7180_Temp)?; Ok((raw_data[1] as i16) << 8 | raw_data[0] as i16) }
}
#[derive(Debug, Copy, Clone)]
#[allow(non_camel_case_types)]
enum Register {
EM7180_EventStatus = 0x35,
EM7180_Error = 0x50,
EM7180_ProductID = 0x90,
EM7180_HostControl = 0x34,
EM7180_PassThruControl = 0xA0,
EM7180_ACC_LPF_BW = 0x5B,
EM7180_GYRO_LPF_BW = 0x5C,
EM7180_QRateDivisor = 0x32,
EM7180_MagRate = 0x55,
EM7180_AccelRate = 0x56,
EM7180_GyroRate = 0x57,
EM7180_BaroRate = 0x58,
EM7180_AlgorithmControl = 0x54,
EM7180_EnableEvents = 0x33,
EM7180_SensorStatus = 0x36,
EM7180_ActualMagRate = 0x45,
EM7180_ActualAccelRate = 0x46,
EM7180_ActualGyroRate = 0x47,
EM7180_ParamRequest = 0x64,
EM7180_ParamAcknowledge = 0x3A,
EM7180_ROMVersion1 = 0x70,
EM7180_ROMVersion2 = 0x71,
EM7180_LoadParamByte0 = 0x60,
EM7180_LoadParamByte1 = 0x61,
EM7180_LoadParamByte2 = 0x62,
EM7180_LoadParamByte3 = 0x63,
EM7180_SavedParamByte0 = 0x3B,
EM7180_SavedParamByte1 = 0x3C,
EM7180_SavedParamByte2 = 0x3D,
EM7180_SavedParamByte3 = 0x3E,
EM7180_FeatureFlags = 0x39,
EM7180_SentralStatus = 0x37,
EM7180_ResetRequest = 0x9B,
EM7180_RunStatus = 0x92,
EM7180_QX = 0x00, EM7180_QY = 0x04, EM7180_QZ = 0x08, EM7180_QW = 0x0C, EM7180_AX = 0x1A, EM7180_GX = 0x22, EM7180_MX = 0x12, EM7180_Baro = 0x2A, EM7180_Temp = 0x2E, }
fn reg_to_float(buf: &[u8]) -> f32 {
unsafe { safe_transmute::guarded_transmute::<f32>(buf).unwrap() }
}
pub fn raw_temperature_to_celsius(raw_temperature: i16) -> f64 {
raw_temperature as f64 * 0.01f64
}
pub fn raw_temperature_to_fahrenheit(raw_temperature: i16) -> f64 {
9.0f64 * raw_temperature_to_celsius(raw_temperature) / 5.0f64 + 32.0f64
}
pub fn raw_pressure_to_mbar(raw_pressure: i16) -> f64 {
raw_pressure as f64 * 0.01f64 + 1013.25f64
}
pub fn raw_pressure_to_feet(_raw_pressure: i16) -> f64 {
0.0
}