#![allow(non_camel_case_types)]
use bitflags::bitflags;
#[cfg(feature = "defmt")]
use defmt::trace;
use embedded_hal::i2c::blocking::I2c;
#[allow(clippy::upper_case_acronyms)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FlagRegister {
INT_EN = 0x0B,
INT_CFG = 0x0C,
INT_SRC = 0x0D,
INT_DIR = 0x0E,
PARA = 0x0F,
}
pub(crate) const INT_SRC_VARIANTS: [INT_SRC; 6] = [
INT_SRC::PA_RDY,
INT_SRC::T_RDY,
INT_SRC::PA_TRAV,
INT_SRC::T_TRAV,
INT_SRC::PA_WIN,
INT_SRC::T_WIN,
];
bitflags! {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct INT_SRC: u8 {
const TH_ERR = 0b1000_0000;
const DEV_RDY = 0b0100_0000;
const PA_RDY = 0b0010_0000;
const T_RDY = 0b0001_0000;
const READ_RDY = Self::PA_RDY.bits | Self::T_RDY.bits;
const PA_TRAV = 0b0000_1000;
const T_TRAV = 0b0000_0100;
const PA_WIN = 0b0000_0010;
const T_WIN = 0b0000_0001;
}
pub struct INT_EN: u8 {
const PA_RDY_EN = 0b0010_0000;
const T_RDY_EN = 0b0001_0000;
const RDY_EN = Self::PA_RDY_EN.bits | Self::T_RDY_EN.bits;
const PA_TRAV_EN = 0b0000_1000;
const T_TRAV_EN = 0b0000_0100;
const PA_WIN_EN = 0b0000_0010;
const T_WIN_EN = 0b0000_0001;
}
pub struct INT_CFG: u8 {
const PA_MODE = 0b0100_0000;
const PA_RDY_CFG = 0b0010_0000;
const T_RDY_CFG = 0b0001_0000;
const PA_TRAV_CFG = 0b0000_1000;
const T_TRAV_CFG = 0b0000_0100;
const PA_WIN_CFG = 0b0000_0010;
const T_WIN_CFG = 0b0000_0001;
}
pub struct INT_DIR: u8 {
const CMPS_EN = 0b1000_0000;
const P_TRAV_DIR = 0b0000_1000;
const T_TRAV_DIR = 0b0000_0100;
const P_WIN_DIR = 0b0000_0010;
const T_WIN_DIR = 0b0000_0001;
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PARA: u8 {
const CMPS_EN = 0b1000_0000;
}
}
macro_rules! getter {
($funcname:ident -> $reg:ident) => {
fn $funcname(&mut self) -> Result<$reg, I::Error> {
#[cfg(feature = "defmt")]
trace!("Reading flags from {}", FlagRegister::$reg);
Ok(<$reg>::from_bits_truncate(
self.read_flags(FlagRegister::$reg)?,
))
}
};
}
macro_rules! setter {
($funcname:ident -> $reg:ident) => {
fn $funcname(&mut self, val: $reg) -> Result<(), I::Error> {
#[cfg(feature = "defmt")]
trace!("Writing flags to {}", FlagRegister::$reg);
self.write_flags(FlagRegister::$reg, val.bits())
}
};
}
pub trait Flags<I: I2c> {
fn read_flags(&mut self, reg: FlagRegister) -> Result<u8, I::Error>;
fn write_flags(&mut self, reg: FlagRegister, val: u8) -> Result<(), I::Error>;
getter! { get_interrupts -> INT_SRC }
getter! { get_interrupt_extras -> INT_DIR }
getter! { get_interrupts_enabled -> INT_EN }
getter! { get_interrupts_pinout -> INT_CFG }
getter! { para -> PARA }
setter! { set_interrupts_enabled -> INT_EN }
setter! { set_interrupts_pinout -> INT_CFG }
setter! { set_para -> PARA }
}
impl<I: I2c, T> Flags<I> for T
where
T: super::Registers<I>,
{
fn read_flags(&mut self, reg: FlagRegister) -> Result<u8, I::Error> {
self.read_raw(reg as u8)
}
fn write_flags(&mut self, reg: FlagRegister, val: u8) -> Result<(), I::Error> {
self.write_raw(reg as u8, val)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn contains_sanity_check() {
assert!(INT_SRC::from_bits_truncate(0x50).contains(INT_SRC::DEV_RDY));
}
#[test]
#[should_panic]
fn no_contains_sanity_check() {
assert!(INT_SRC::from_bits_truncate(0x50).contains(INT_SRC::PA_RDY));
}
}