use bitflags::bitflags;
use crate::register_address::{RegRead, StatusRegAuxA, WhoAmIA, WhoAmIM};
#[derive(Debug)]
pub enum Error<CommE> {
Comm(CommE),
InvalidInputData,
}
impl<CommE> From<CommE> for Error<CommE> {
fn from(e: CommE) -> Self {
Self::Comm(e)
}
}
#[derive(Debug)]
pub struct ModeChangeError<CommE, DEV> {
pub error: Error<CommE>,
pub dev: DEV,
}
pub mod mode {
#[derive(Debug)]
pub enum MagOneShot {}
#[derive(Debug)]
pub enum MagContinuous {}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AccelerometerId {
raw: u8,
}
impl AccelerometerId {
pub(crate) fn from_bits_truncate(raw: u8) -> Self {
Self { raw }
}
pub const fn raw(&self) -> u8 {
self.raw
}
pub const fn is_correct(&self) -> bool {
self.raw == WhoAmIA::ID
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Acceleration {
pub(crate) x: u16,
pub(crate) y: u16,
pub(crate) z: u16,
pub(crate) mode: AccelMode,
pub(crate) scale: AccelScale,
}
impl RegRead<(u16, u16, u16)> for Acceleration {
type Output = (u16, u16, u16);
const ADDR: u8 = 0x28;
#[inline(always)]
fn from_data(data: (u16, u16, u16)) -> Self::Output {
data
}
}
impl Acceleration {
#[inline]
pub const fn x_raw(&self) -> u16 {
self.x
}
#[inline]
pub const fn y_raw(&self) -> u16 {
self.y
}
#[inline]
pub const fn z_raw(&self) -> u16 {
self.z
}
#[inline]
pub const fn xyz_raw(&self) -> (u16, u16, u16) {
(self.x, self.y, self.z)
}
#[inline]
pub const fn x_unscaled(&self) -> i16 {
(self.x as i16) / self.mode.resolution_factor()
}
#[inline]
pub const fn y_unscaled(&self) -> i16 {
(self.y as i16) / self.mode.resolution_factor()
}
#[inline]
pub const fn z_unscaled(&self) -> i16 {
(self.z as i16) / self.mode.resolution_factor()
}
#[inline]
pub const fn xyz_unscaled(&self) -> (i16, i16, i16) {
let resolution_factor = self.mode.resolution_factor();
(
(self.x as i16) / resolution_factor,
(self.y as i16) / resolution_factor,
(self.z as i16) / resolution_factor,
)
}
#[inline]
pub const fn x_mg(&self) -> i32 {
(self.x_unscaled() as i32) * self.mode.scaling_factor(self.scale)
}
#[inline]
pub const fn y_mg(&self) -> i32 {
(self.y_unscaled() as i32) * self.mode.scaling_factor(self.scale)
}
#[inline]
pub const fn z_mg(&self) -> i32 {
(self.z_unscaled() as i32) * self.mode.scaling_factor(self.scale)
}
#[inline]
pub const fn xyz_mg(&self) -> (i32, i32, i32) {
let (x_unscaled, y_unscaled, z_unscaled) = self.xyz_unscaled();
let scaling_factor = self.mode.scaling_factor(self.scale);
(
(x_unscaled as i32) * scaling_factor,
(y_unscaled as i32) * scaling_factor,
(z_unscaled as i32) * scaling_factor,
)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MagnetometerId {
raw: u8,
}
impl MagnetometerId {
pub(crate) fn from_bits_truncate(raw: u8) -> Self {
Self { raw }
}
pub const fn raw(&self) -> u8 {
self.raw
}
pub const fn is_correct(&self) -> bool {
self.raw == WhoAmIM::ID
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct MagneticField {
pub(crate) x: u16,
pub(crate) y: u16,
pub(crate) z: u16,
}
impl RegRead<(u16, u16, u16)> for MagneticField {
type Output = Self;
const ADDR: u8 = 0x68;
#[inline(always)]
fn from_data((x, y, z): (u16, u16, u16)) -> Self::Output {
Self { x, y, z }
}
}
impl MagneticField {
const SCALING_FACTOR: i32 = 150;
#[inline]
pub const fn x_raw(&self) -> u16 {
self.x
}
#[inline]
pub const fn y_raw(&self) -> u16 {
self.y
}
#[inline]
pub const fn z_raw(&self) -> u16 {
self.z
}
#[inline]
pub const fn xyz_raw(&self) -> (u16, u16, u16) {
(self.x, self.y, self.z)
}
#[inline]
pub const fn x_unscaled(&self) -> i16 {
self.x as i16
}
#[inline]
pub const fn y_unscaled(&self) -> i16 {
self.y as i16
}
#[inline]
pub const fn z_unscaled(&self) -> i16 {
self.z as i16
}
#[inline]
pub const fn xyz_unscaled(&self) -> (i16, i16, i16) {
(self.x as i16, self.y as i16, self.z as i16)
}
#[inline]
pub const fn x_nt(&self) -> i32 {
(self.x_unscaled() as i32) * Self::SCALING_FACTOR
}
#[inline]
pub const fn y_nt(&self) -> i32 {
(self.y_unscaled() as i32) * Self::SCALING_FACTOR
}
#[inline]
pub const fn z_nt(&self) -> i32 {
(self.z_unscaled() as i32) * Self::SCALING_FACTOR
}
#[inline]
pub const fn xyz_nt(&self) -> (i32, i32, i32) {
(self.x_nt(), self.y_nt(), self.z_nt())
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AccelOutputDataRate {
Hz1,
Hz10,
Hz25,
Hz50,
Hz100,
Hz200,
Hz400,
Khz1_344,
Khz1_620LowPower,
Khz5_376LowPower,
}
impl AccelOutputDataRate {
pub const fn from_hertz(hz: u16) -> Option<Self> {
Some(match hz {
1 => Self::Hz1,
10 => Self::Hz10,
25 => Self::Hz25,
50 => Self::Hz50,
100 => Self::Hz100,
200 => Self::Hz200,
400 => Self::Hz400,
1344 => Self::Khz1_344,
1620 => Self::Khz1_620LowPower,
5376 => Self::Khz5_376LowPower,
_ => return None,
})
}
pub(crate) const fn turn_on_time_us_frac_1(&self) -> u32 {
match self {
Self::Hz1 => 1000,
Self::Hz10 => 100,
Self::Hz25 => 40,
Self::Hz50 => 20,
Self::Hz100 => 10,
Self::Hz200 => 5,
Self::Hz400 => 3, Self::Khz1_344 => 1, Self::Khz1_620LowPower => 1, Self::Khz5_376LowPower => 1, }
}
pub(crate) const fn turn_on_time_us_frac_7(&self) -> u32 {
match self {
Self::Hz1 => 7000,
Self::Hz10 => 700,
Self::Hz25 => 280,
Self::Hz50 => 140,
Self::Hz100 => 70,
Self::Hz200 => 35,
Self::Hz400 => 18, Self::Khz1_344 => 6, Self::Khz1_620LowPower => 5, Self::Khz5_376LowPower => 2, }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AccelMode {
PowerDown,
LowPower,
Normal,
HighResolution,
}
impl AccelMode {
pub(crate) const fn turn_on_time_us(&self, odr: AccelOutputDataRate) -> u32 {
match self {
Self::PowerDown => 0,
Self::LowPower => 1000,
Self::Normal => 1600,
Self::HighResolution => odr.turn_on_time_us_frac_7(),
}
}
pub(crate) const fn change_time_us(&self, other: AccelMode, odr: AccelOutputDataRate) -> u32 {
match (self, other) {
(Self::HighResolution, Self::LowPower) => odr.turn_on_time_us_frac_1(),
(Self::HighResolution, Self::Normal) => odr.turn_on_time_us_frac_1(),
(Self::Normal, Self::LowPower) => odr.turn_on_time_us_frac_1(),
(Self::Normal, Self::HighResolution) => odr.turn_on_time_us_frac_7(),
(Self::LowPower, Self::Normal) => odr.turn_on_time_us_frac_1(),
(Self::LowPower, Self::HighResolution) => odr.turn_on_time_us_frac_7(),
(Self::PowerDown, new_mode) => new_mode.turn_on_time_us(odr),
_ => 0,
}
}
pub(crate) const fn resolution_factor(&self) -> i16 {
match self {
Self::PowerDown => 1,
Self::HighResolution => 1 << 4,
Self::Normal => 1 << 6,
Self::LowPower => 1 << 8,
}
}
pub(crate) const fn scaling_factor(&self, scale: AccelScale) -> i32 {
match self {
Self::PowerDown => 0,
Self::HighResolution => scale as i32 / 2,
Self::Normal => scale as i32 * 2,
Self::LowPower => scale as i32 * 8,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AccelScale {
G2 = 2,
G4 = 4,
G8 = 8,
G16 = 16,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MagOutputDataRate {
Hz10,
Hz20,
Hz50,
Hz100,
}
impl MagOutputDataRate {
pub const fn from_hertz(hz: u16) -> Option<Self> {
Some(match hz {
10 => Self::Hz10,
20 => Self::Hz20,
50 => Self::Hz50,
100 => Self::Hz100,
_ => return None,
})
}
pub(crate) const fn turn_on_time_us_frac_1(&self) -> u32 {
match self {
Self::Hz10 => 100,
Self::Hz20 => 50,
Self::Hz50 => 20,
Self::Hz100 => 10,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MagMode {
LowPower,
HighResolution,
}
impl Default for MagMode {
fn default() -> Self {
Self::HighResolution
}
}
impl MagMode {
pub(crate) const fn turn_on_time_us(&self) -> u32 {
match self {
Self::LowPower => 9400,
Self::HighResolution => 6400,
}
}
}
bitflags! {
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct StatusFlags: u8 {
const ZYXOR = 0b10000000;
const ZOR = 0b01000000;
const YOR = 0b00100000;
const XOR = 0b00010000;
const ZYXDA = 0b00001000;
const ZDA = 0b00000100;
const YDA = 0b00000010;
const XDA = 0b00000001;
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct Status {
flags: StatusFlags,
}
impl Status {
pub(crate) const fn new(flags: StatusFlags) -> Self {
Self { flags }
}
#[inline]
pub const fn x_new_data(&self) -> bool {
self.flags.contains(StatusFlags::XDA)
}
#[inline]
pub const fn y_new_data(&self) -> bool {
self.flags.contains(StatusFlags::YDA)
}
#[inline]
pub const fn z_new_data(&self) -> bool {
self.flags.contains(StatusFlags::ZDA)
}
#[inline]
pub const fn xyz_new_data(&self) -> bool {
self.flags.contains(StatusFlags::ZYXDA)
}
#[inline]
pub const fn x_overrun(&self) -> bool {
self.flags.contains(StatusFlags::XOR)
}
#[inline]
pub const fn y_overrun(&self) -> bool {
self.flags.contains(StatusFlags::YOR)
}
#[inline]
pub const fn z_overrun(&self) -> bool {
self.flags.contains(StatusFlags::ZOR)
}
#[inline]
pub const fn xyz_overrun(&self) -> bool {
self.flags.contains(StatusFlags::ZYXOR)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct TemperatureStatus {
flags: StatusRegAuxA,
}
impl TemperatureStatus {
pub(crate) const fn new(flags: StatusRegAuxA) -> Self {
Self { flags }
}
#[inline]
pub const fn overrun(&self) -> bool {
self.flags.contains(StatusRegAuxA::TOR)
}
#[inline]
pub const fn new_data(&self) -> bool {
self.flags.contains(StatusRegAuxA::TDA)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Temperature {
pub(crate) raw: u16,
}
impl RegRead<u16> for Temperature {
type Output = Self;
const ADDR: u8 = 0x0C;
#[inline]
fn from_data(data: u16) -> Self::Output {
Temperature { raw: data }
}
}
impl Temperature {
const DEFAULT: f32 = 25.0;
#[inline]
pub const fn raw(&self) -> u16 {
self.raw
}
#[inline]
pub const fn unscaled(&self) -> i16 {
self.raw as i16
}
#[inline]
pub fn degrees_celsius(&self) -> f32 {
(self.unscaled() as f32) / 256.0 + Self::DEFAULT
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FifoMode {
Bypass,
Fifo,
Stream,
StreamToFifo,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Interrupt {
Aoi1,
Aoi2,
Click,
DataReady1,
DataReady2,
FifoOverrun,
FifoWatermark,
}