use bitflags::bitflags;
use crate::register_address::{RegRead, WhoAmIA, WhoAmIG, WhoAmIM};
#[derive(Debug)]
pub enum Error<CommE, PinE> {
Comm(CommE),
Pin(PinE),
InvalidInputData,
}
#[derive(Debug)]
pub struct ModeChangeError<CommE, PinE, DEV> {
pub error: Error<CommE, PinE>,
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) range: AccelRange,
}
impl RegRead<(u16, u16, u16)> for Acceleration {
type Output = (u16, u16, u16);
const ADDR: u8 = 0x02;
#[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) / 0b1_0000
}
#[inline]
pub const fn y_unscaled(&self) -> i16 {
(self.y as i16) / 0b1_0000
}
#[inline]
pub const fn z_unscaled(&self) -> i16 {
(self.z as i16) / 0b1_0000
}
#[inline]
pub const fn xyz_unscaled(&self) -> (i16, i16, i16) {
let factor = 0b1_0000;
(
(self.x as i16) / factor,
(self.y as i16) / factor,
(self.z as i16) / factor,
)
}
#[inline]
pub const fn x_mg(&self) -> i32 {
self.x_unscaled() as i32
}
#[inline]
pub const fn y_mg(&self) -> i32 {
self.y_unscaled() as i32
}
#[inline]
pub const fn z_mg(&self) -> i32 {
self.z_unscaled() as i32
}
#[inline]
pub const fn xyz_mg(&self) -> (i32, i32, i32) {
let (x_unscaled, y_unscaled, z_unscaled) = self.xyz_unscaled();
let scaling_factor = 1;
(
(x_unscaled as i32) * scaling_factor,
(y_unscaled as i32) * scaling_factor,
(z_unscaled as i32) * scaling_factor,
)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AccelBandwidth {
Hz7_81,
Hz15_63,
Hz31_25,
Hz62_5,
Hz125,
Hz250,
Hz500,
Hz1000,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AccelMode {
Normal,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AccelRange {
G2 = 2,
G4 = 4,
G8 = 8,
G16 = 16,
}
bitflags! {
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct StatusFlags: u8 {
const DATA_INT = 0b10000000;
const FIFO_WM_INT = 0b01000000;
const FIFO_FULL_INT = 0b00100000;
}
}
#[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 xyz_new_data(&self) -> bool {
self.flags.contains(StatusFlags::DATA_INT)
}
}
bitflags! {
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct GyroStatusFlags: u8 {
const DATA_INT = 0b10000000;
const AUTO_OFFSET_INT = 0b01000000;
const FAST_OFFSET_INT = 0b00100000;
const FIFO_INT = 0b00010000;
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct GyroStatus {
flags: GyroStatusFlags,
}
impl GyroStatus {
pub(crate) const fn new(flags: GyroStatusFlags) -> Self {
Self { flags }
}
#[inline]
pub const fn xyz_new_data(&self) -> bool {
self.flags.contains(GyroStatusFlags::DATA_INT)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Temperature {
pub(crate) raw: u8,
}
impl RegRead<u8> for Temperature {
type Output = Self;
const ADDR: u8 = 0x08;
#[inline]
fn from_data(data: u8) -> Self::Output {
Temperature { raw: data }
}
}
impl Temperature {
const CENTER: f32 = 23.0;
#[inline]
pub const fn raw(&self) -> u8 {
self.raw
}
#[inline]
pub const fn unscaled(&self) -> i8 {
self.raw as i8
}
#[inline]
pub fn degrees_celsius(&self) -> f32 {
f32::from(self.unscaled()) / 2.0 + Self::CENTER
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GyroFilterBandwidth {
Hz32,
Hz64,
Hz12,
Hz23,
Hz47,
Hz116,
Hz230,
Hz523,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GyroMode {
Normal,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GyroRange {
R2000 = 2000,
R1000 = 1000,
R500 = 500,
R250 = 250,
R125 = 125,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AngularRate {
pub(crate) x: u16,
pub(crate) y: u16,
pub(crate) z: u16,
pub(crate) mode: GyroMode,
pub(crate) range: GyroRange,
}
impl RegRead<(u16, u16, u16)> for AngularRate {
type Output = (u16, u16, u16);
const ADDR: u8 = 0x02;
#[inline(always)]
fn from_data(data: (u16, u16, u16)) -> Self::Output {
data
}
}
impl AngularRate {
#[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 fn x_dps(&self) -> f64 {
let factor: f64 = (self.range as i32 as f64) / 32767_f64;
(self.x_unscaled() as f64) * factor
}
#[inline]
pub fn y_dps(&self) -> f64 {
let factor: f64 = (self.range as i32 as f64) / 32767_f64;
(self.y_unscaled() as f64) * factor
}
#[inline]
pub fn z_dps(&self) -> f64 {
let factor: f64 = (self.range as i32 as f64) / 32767_f64;
(self.z_unscaled() as f64) * factor
}
#[inline]
pub fn xyz_dps(&self) -> (f64, f64, f64) {
let (x_unscaled, y_unscaled, z_unscaled) = self.xyz_unscaled();
let scaling_factor: f64 = (self.range as i32 as f64) / 32767_f64;
(
(x_unscaled as f64) * scaling_factor,
(y_unscaled as f64) * scaling_factor,
(z_unscaled as f64) * scaling_factor,
)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GyroscopeId {
raw: u8,
}
impl GyroscopeId {
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 == WhoAmIG::ID
}
}
#[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, Clone, Copy, PartialEq)]
pub enum MagOpMode {
Normal,
Forced,
Sleep,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MagneticFieldData {
pub(crate) x: u16,
pub(crate) y: u16,
pub(crate) z: u16,
pub(crate) rhall: u16,
pub trim_data: TrimData,
}
impl RegRead<(u16, u16, u16, u16)> for MagneticFieldData {
type Output = (u16, u16, u16, u16);
const ADDR: u8 = 0x42;
#[inline(always)]
fn from_data(data: (u16, u16, u16, u16)) -> Self::Output {
data
}
}
impl MagneticFieldData {
#[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 rhall_raw(&self) -> u16 {
self.rhall
}
#[inline]
pub const fn xyzr_raw(&self) -> (u16, u16, u16, u16) {
(self.x, self.y, self.z, self.rhall)
}
#[inline]
pub const fn x_unscaled(&self) -> i16 {
(self.x as i16) >> 3
}
#[inline]
pub const fn y_unscaled(&self) -> i16 {
(self.y as i16) >> 3
}
#[inline]
pub const fn z_unscaled(&self) -> i16 {
(self.z as i16) >> 1
}
#[inline]
pub const fn rhall_unscaled(&self) -> u16 {
self.rhall >> 2
}
#[inline]
pub const fn data_ready(&self) -> bool {
self.rhall & 0b0000_0000_0000_0001 == 1
}
#[inline]
pub const fn xyzr_unscaled(&self) -> (i16, i16, i16, u16) {
(
self.x_unscaled(),
self.y_unscaled(),
self.z_unscaled(),
self.rhall_unscaled(),
)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TrimX1Y1 {
dig_x1: i8,
dig_y1: i8,
}
impl RegRead<[u8; 2]> for TrimX1Y1 {
type Output = TrimX1Y1;
const ADDR: u8 = 0x5d;
#[inline(always)]
fn from_data(data: [u8; 2]) -> Self::Output {
TrimX1Y1 {
dig_x1: i8::from_le_bytes([data[0]]),
dig_y1: i8::from_le_bytes([data[1]]),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TrimXYZ {
dig_z4: i16,
dig_x2: i8,
dig_y2: i8,
}
impl RegRead<[u8; 4]> for TrimXYZ {
type Output = TrimXYZ;
const ADDR: u8 = 0x62;
#[inline(always)]
fn from_data(data: [u8; 4]) -> Self::Output {
TrimXYZ {
dig_z4: i16::from_le_bytes([data[0], data[1]]),
dig_x2: i8::from_le_bytes([data[2]]),
dig_y2: i8::from_le_bytes([data[3]]),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TrimXY1XY2 {
dig_z2: i16,
dig_z1: i16,
dig_xyz1: u16,
dig_z3: i16,
dig_xy1: u8,
dig_xy2: i8,
}
impl RegRead<[u8; 10]> for TrimXY1XY2 {
type Output = TrimXY1XY2;
const ADDR: u8 = 0x68;
#[inline(always)]
fn from_data(data: [u8; 10]) -> Self::Output {
TrimXY1XY2 {
dig_z2: i16::from_le_bytes([data[0], data[1]]),
dig_z1: i16::from_le_bytes([data[2], data[3]]),
dig_xyz1: u16::from_le_bytes([data[4], data[5]]) & 0x7fff,
dig_z3: i16::from_le_bytes([data[6], data[7]]),
dig_xy1: data[8],
dig_xy2: i8::from_le_bytes([data[9]]),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TrimData {
pub(crate) dig_x1: i8,
pub(crate) dig_y1: i8,
pub(crate) dig_z4: i16,
pub(crate) dig_x2: i8,
pub(crate) dig_y2: i8,
pub(crate) dig_z2: i16,
pub(crate) dig_z1: i16,
pub(crate) dig_xyz1: u16,
pub(crate) dig_z3: i16,
pub(crate) dig_xy1: u8,
pub(crate) dig_xy2: i8,
}
impl From<(TrimX1Y1, TrimXYZ, TrimXY1XY2)> for TrimData {
#[inline(always)]
fn from(
(
TrimX1Y1 { dig_x1, dig_y1 },
TrimXYZ {
dig_z4,
dig_x2,
dig_y2,
},
TrimXY1XY2 {
dig_z2,
dig_z1,
dig_xyz1,
dig_z3,
dig_xy1,
dig_xy2,
},
): (TrimX1Y1, TrimXYZ, TrimXY1XY2),
) -> Self {
TrimData {
dig_x1,
dig_y1,
dig_z4,
dig_x2,
dig_y2,
dig_z2,
dig_z1,
dig_xyz1,
dig_z3,
dig_xy1,
dig_xy2,
}
}
}