use crate::{AdxlError, AdxlResult, Result};
use std::convert::{TryFrom, TryInto};
pub trait Adxl345: Adxl345Reader + Adxl345Writer {}
pub trait Adxl345Reader {
fn access(&self, register: u8) -> AdxlResult<u8>;
fn acceleration(&self) -> AdxlResult<(i16, i16, i16)>;
fn free_fall(&self) -> AdxlResult<(u8, u8)> {
Ok((self.free_fall_threshold()?, self.free_fall_time()?))
}
fn offset_adjustment(&self) -> AdxlResult<(i8, i8, i8)> {
Ok((self.x_offset()?, self.y_offset()?, self.z_offset()?))
}
fn tap(&self) -> AdxlResult<Tap> {
let values = [
self.tap_threshold()?,
self.tap_duration()?,
self.tap_latency()?,
self.tap_window()?,
];
Ok(values.into())
}
fn activity_control(&self) -> AdxlResult<ActivityMode> {
let register = 0x27;
let data = self.access(register)?;
let result =
ActivityMode::from_bits(data).ok_or_else(|| AdxlError::UnknownModeBit(data))?;
Ok(result)
}
fn activity_threshold(&self) -> AdxlResult<u8> {
let register = 0x24;
Ok(self.access(register)?)
}
fn activity_tap_status(&self) -> AdxlResult<ATStatus> {
let register = 0x2b;
let data = self.access(register)?;
let result = ATStatus::from_bits(data).ok_or_else(|| AdxlError::UnknownModeBit(data))?;
Ok(result)
}
fn bandwidth_rate(&self) -> AdxlResult<BandwidthRateControl> {
let register = 0x2c;
Ok(self.access(register)?.try_into()?)
}
fn data_format(&self) -> AdxlResult<DataFormat> {
let register = 0x31;
Ok(self.access(register)?.try_into()?)
}
fn device_id(&self) -> AdxlResult<u8> {
let register = 0x00;
Ok(self.access(register)?)
}
fn free_fall_threshold(&self) -> AdxlResult<u8> {
let register = 0x28;
Ok(self.access(register)?)
}
fn free_fall_time(&self) -> AdxlResult<u8> {
let register = 0x29;
Ok(self.access(register)?)
}
fn fifo_control(&self) -> AdxlResult<FifoControl> {
let register = 0x38;
Ok(self.access(register)?.into())
}
fn fifo_status(&self) -> AdxlResult<FifoStatus> {
let register = 0x39;
Ok(self.access(register)?.try_into()?)
}
fn inactivity_threshold(&self) -> AdxlResult<u8> {
let register = 0x25;
Ok(self.access(register)?)
}
fn inactivity_time(&self) -> AdxlResult<u8> {
let register = 0x26;
Ok(self.access(register)?)
}
fn interrupt_control(&self) -> AdxlResult<IntControlMode> {
let register = 0x2e;
let data = self.access(register)?;
let result =
IntControlMode::from_bits(data).ok_or_else(|| AdxlError::UnknownModeBit(data))?;
Ok(result)
}
fn interrupt_map(&self) -> AdxlResult<IntMapMode> {
let register = 0x2f;
let data = self.access(register)?;
let result = IntMapMode::from_bits(data).ok_or_else(|| AdxlError::UnknownModeBit(data))?;
Ok(result)
}
fn interrupt_source(&self) -> AdxlResult<IntSource> {
let register = 0x30;
let data = self.access(register)?;
let result = IntSource::from_bits(data).ok_or_else(|| AdxlError::UnknownModeBit(data))?;
Ok(result)
}
fn power_control(&self) -> AdxlResult<PowerControl> {
let register = 0x2d;
Ok(self.access(register)?.try_into()?)
}
fn tap_control(&self) -> AdxlResult<TapMode> {
let register = 0x2a;
let data = self.access(register)?;
let result = TapMode::from_bits(data).ok_or_else(|| AdxlError::UnknownModeBit(data))?;
Ok(result)
}
fn tap_duration(&self) -> AdxlResult<u8> {
let register = 0x21;
Ok(self.access(register)?)
}
fn tap_latency(&self) -> AdxlResult<u8> {
let register = 0x22;
Ok(self.access(register)?)
}
fn tap_threshold(&self) -> AdxlResult<u8> {
let register = 0x1d;
Ok(self.access(register)?)
}
fn tap_window(&self) -> AdxlResult<u8> {
let register = 0x23;
Ok(self.access(register)?)
}
fn x_offset(&self) -> AdxlResult<i8> {
let register = 0x1e;
Ok(self.access(register)? as i8)
}
fn y_offset(&self) -> AdxlResult<i8> {
let register = 0x1f;
Ok(self.access(register)? as i8)
}
fn z_offset(&self) -> AdxlResult<i8> {
let register = 0x20;
Ok(self.access(register)? as i8)
}
}
pub trait Adxl345Writer {
fn command(&mut self, register: u8, byte: u8) -> Result;
fn init(&mut self) -> Result;
fn set_inactivity(&mut self, thresh: u8, time: u8) -> Result {
self.set_inactivity_threshold(thresh)?;
self.set_inactivity_time(time)
}
fn set_free_fall(&mut self, thresh: u8, time: u8) -> Result {
self.set_free_fall_threshold(thresh)?;
self.set_free_fall_time(time)
}
fn set_activity_control<AM>(&mut self, mode: AM) -> Result
where
AM: Into<ActivityMode>,
{
let register = 0x27;
self.command(register, mode.into().bits())
}
fn set_activity_threshold(&mut self, thresh: u8) -> Result {
let register = 0x24;
self.command(register, thresh)
}
fn set_bandwidth_rate<BRC>(&mut self, mode: BRC) -> Result
where
BRC: TryInto<BandwidthRateControl, Error = AdxlError>,
{
let register = 0x2c;
self.command(register, mode.try_into()?.byte[0])
}
fn set_data_format<DF>(&mut self, mode: DF) -> Result
where
DF: TryInto<DataFormat, Error = AdxlError>,
{
let register = 0x31;
self.command(register, mode.try_into()?.byte[0])
}
fn set_free_fall_threshold(&mut self, thresh: u8) -> Result {
let register = 0x28;
self.command(register, thresh)
}
fn set_free_fall_time(&mut self, time: u8) -> Result {
let register = 0x29;
self.command(register, time)
}
fn set_fifo_control<FC>(&mut self, mode: FC) -> Result
where
FC: Into<FifoControl>,
{
let register = 0x38;
self.command(register, mode.into().byte[0])
}
fn set_inactivity_threshold(&mut self, thresh: u8) -> Result {
let register = 0x25;
self.command(register, thresh)
}
fn set_inactivity_time(&mut self, time: u8) -> Result {
let register = 0x26;
self.command(register, time)
}
fn set_interrupt_control<IC>(&mut self, mode: IC) -> Result
where
IC: Into<IntControlMode>,
{
let register = 0x2e;
self.command(register, mode.into().bits())
}
fn set_interrupt_map<IM>(&mut self, mode: IM) -> Result
where
IM: Into<IntMapMode>,
{
let register = 0x2f;
self.command(register, mode.into().bits())
}
fn set_offset_adjustment<X, Y, Z>(&mut self, x: X, y: Y, z: Z) -> Result
where
X: Into<Option<i8>>,
Y: Into<Option<i8>>,
Z: Into<Option<i8>>,
{
let x = x.into();
let y = y.into();
let z = z.into();
if let Some(x) = x {
self.set_x_offset(x)?
};
if let Some(y) = y {
self.set_x_offset(y)?
};
if let Some(z) = z {
self.set_x_offset(z)?
};
Ok(())
}
fn set_power_control<PC>(&mut self, mode: PC) -> Result
where
PC: TryInto<PowerControl, Error = AdxlError>,
{
let register = 0x2d;
self.command(register, mode.try_into()?.byte[0])
}
fn set_tap<T>(&mut self, tap: T) -> Result
where
T: Into<Tap>,
{
let tap = tap.into();
self.set_tap_threshold(tap.threshold)?;
self.set_tap_duration(tap.duration)?;
self.set_tap_latency(tap.latency)?;
self.set_tap_window(tap.window)
}
fn set_tap_control<TM>(&mut self, mode: TM) -> Result
where
TM: Into<TapMode>,
{
let register = 0x2a;
self.command(register, mode.into().bits())
}
fn set_tap_duration(&mut self, duration: u8) -> Result {
let register = 0x21;
self.command(register, duration)
}
fn set_tap_latency(&mut self, latency: u8) -> Result {
let register = 0x22;
self.command(register, latency)
}
fn set_tap_threshold(&mut self, threshold: u8) -> Result {
let register = 0x1d;
self.command(register, threshold)
}
fn set_tap_window(&mut self, window: u8) -> Result {
let register = 0x23;
self.command(register, window)
}
fn set_x_offset(&mut self, x: i8) -> Result {
let register = 0x1e;
self.command(register, x as u8)
}
fn set_y_offset(&mut self, y: i8) -> Result {
let register = 0x1f;
self.command(register, y as u8)
}
fn set_z_offset(&mut self, z: i8) -> Result {
let register = 0x20;
self.command(register, z as u8)
}
}
bitflags! {
#[derive(Default)]
pub struct ActivityMode: u8 {
const ACT_AC = 0x80;
const ACT_DC = 0x00;
const ACT_X_ENABLE = 0x40;
const ACT_X_DISABLE = 0x00;
const ACT_Y_ENABLE = 0x20;
const ACT_Y_DISABLE = 0x00;
const ACT_Z_ENABLE = 0x10;
const ACT_Z_DISABLE = 0x00;
const INACT_AC = 0x08;
const INACT_DC = 0x00;
const INACT_X_ENABLE = 0x04;
const INACT_X_DISABLE = 0x00;
const INACT_Y_ENABLE = 0x02;
const INACT_Y_DISABLE = 0x00;
const INACT_Z_ENABLE = 0x01;
const INACT_Z_DISABLE = 0x00;
}
}
bitflags! {
pub struct ATStatus: u8 {
const ACT_X = 0x40;
const ACT_Y = 0x20;
const ACT_Z = 0x10;
const ASLEEP = 0x08;
const TAP_X = 0x04;
const TAP_Y = 0x02;
const TAP_Z = 0x01;
}
}
#[repr(C, align(1))]
#[derive(BitfieldStruct, Clone, Copy)]
pub struct BandwidthRateControl {
#[bitfield(name = "low_power", ty = "bool", bits = "4..=4")]
#[bitfield(name = "rate", ty = "u8", bits = "0..=3")]
byte: [u8; 1],
}
impl TryFrom<u8> for BandwidthRateControl {
type Error = AdxlError;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
if value & !0x1f == 0 {
Ok(Self { byte: [value; 1] })
} else {
Err(AdxlError::UnknownModeBit(value))
}
}
}
#[repr(C, align(1))]
#[derive(BitfieldStruct, Clone, Copy)]
pub struct DataFormat {
#[bitfield(name = "self_test", ty = "bool", bits = "7..=7")]
#[bitfield(name = "spi", ty = "bool", bits = "6..=6")]
#[bitfield(name = "int_invert", ty = "bool", bits = "5..=5")]
#[bitfield(name = "full_res", ty = "bool", bits = "3..=3")]
#[bitfield(name = "justify", ty = "bool", bits = "2..=2")]
#[bitfield(name = "range", ty = "u8", bits = "0..=1")]
byte: [u8; 1],
}
impl TryFrom<u8> for DataFormat {
type Error = AdxlError;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
if value & !0xef == 0 {
Ok(Self { byte: [value; 1] })
} else {
Err(AdxlError::UnknownModeBit(value))
}
}
}
#[repr(C, align(1))]
#[derive(BitfieldStruct, Clone, Copy)]
pub struct FifoControl {
#[bitfield(name = "fifo_mode", ty = "u8", bits = "6..=7")]
#[bitfield(name = "trigger", ty = "bool", bits = "5..=5")]
#[bitfield(name = "samples", ty = "u8", bits = "0..=4")]
byte: [u8; 1],
}
impl From<u8> for FifoControl {
fn from(value: u8) -> Self {
Self { byte: [value; 1] }
}
}
#[repr(C, align(1))]
#[derive(BitfieldStruct, Clone, Copy)]
pub struct FifoStatus {
#[bitfield(name = "fifo_trigger", ty = "bool", bits = "7..=7")]
#[bitfield(name = "entries", ty = "u8", bits = "0..=5")]
byte: [u8; 1],
}
impl TryFrom<u8> for FifoStatus {
type Error = AdxlError;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
if value & !0xbf == 0 {
Ok(Self { byte: [value; 1] })
} else {
Err(AdxlError::UnknownModeBit(value))
}
}
}
bitflags! {
#[derive(Default)]
pub struct IntControlMode: u8 {
const DATA_READY_DISABLE = 0x00;
const DATA_READY_ENABLE = 0x80;
const SINGLE_TAP_DISABLE = 0x00;
const SINGLE_TAP_ENABLE = 0x40;
const DOUBLE_TAP_DISABLE = 0x00;
const DOUBLE_TAP_ENABLE = 0x20;
const ACTIVITY_DISABLE = 0x00;
const ACTIVITY_ENABLE = 0x10;
const INACTIVITY_DISABLE = 0x00;
const INACTIVITY_ENABLE = 0x08;
const FREE_FALL_DISABLE = 0x00;
const FREE_FALL_ENABLE = 0x04;
const WATERMARK_DISABLE = 0x00;
const WATERMARK_ENABLE = 0x02;
const OVERRUN_DISABLE = 0x00;
const OVERRUN_ENABLE = 0x01;
}
}
bitflags! {
#[derive(Default)]
pub struct IntMapMode: u8 {
const DATA_READY_INT1 = 0x00;
const DATA_READY_INT2 = 0x80;
const SINGLE_TAP_INT1 = 0x00;
const SINGLE_TAP_INT2 = 0x40;
const DOUBLE_TAP_INT1 = 0x00;
const DOUBLE_TAP_INT2 = 0x20;
const ACTIVITY_INT1 = 0x00;
const ACTIVITY_INT2 = 0x10;
const INACTIVITY_INT1 = 0x00;
const INACTIVITY_INT2 = 0x08;
const FREE_FALL_INT1 = 0x00;
const FREE_FALL_INT2 = 0x04;
const WATERMARK_INT1 = 0x00;
const WATERMARK_INT2 = 0x02;
const OVERRUN_INT1 = 0x00;
const OVERRUN_INT2 = 0x01;
}
}
bitflags! {
#[derive(Default)]
pub struct IntSource: u8 {
const DATA_READY = 0x80;
const SINGLE_TAP = 0x40;
const DOUBLE_TAP = 0x20;
const ACTIVITY = 0x10;
const INACTIVITY = 0x08;
const FREE_FALL = 0x04;
const WATERMARK = 0x02;
const OVERRUN = 0x01;
}
}
#[repr(C, align(1))]
#[derive(BitfieldStruct, Clone, Copy)]
pub struct PowerControl {
#[bitfield(name = "link", ty = "bool", bits = "5..=5")]
#[bitfield(name = "auto_sleep", ty = "bool", bits = "4..=4")]
#[bitfield(name = "measure", ty = "bool", bits = "3..=3")]
#[bitfield(name = "sleep", ty = "bool", bits = "2..=2")]
#[bitfield(name = "wakeup", ty = "u8", bits = "0..=1")]
byte: [u8; 1],
}
impl TryFrom<u8> for PowerControl {
type Error = AdxlError;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
if value & !0x3f == 0 {
Ok(Self { byte: [value; 1] })
} else {
Err(AdxlError::UnknownModeBit(value))
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Tap {
threshold: u8,
duration: u8,
latency: u8,
window: u8,
}
impl Tap {
pub fn new(threshold: u8, duration: u8, latency: u8, window: u8) -> Self {
Tap {
threshold,
duration,
latency,
window,
}
}
}
impl From<(u8, u8, u8, u8)> for Tap {
fn from(tap: (u8, u8, u8, u8)) -> Self {
Tap {
threshold: tap.0,
duration: tap.1,
latency: tap.2,
window: tap.3,
}
}
}
impl From<[u8; 4]> for Tap {
fn from(tap: [u8; 4]) -> Self {
Tap {
threshold: tap[0],
duration: tap[1],
latency: tap[2],
window: tap[3],
}
}
}
bitflags! {
#[derive(Default)]
pub struct TapMode: u8 {
const DT_DISABLE = 0x08;
const DT_ENABLE = 0x00;
const X_DISABLE = 0x00;
const X_ENABLE = 0x04;
const Y_DISABLE = 0x00;
const Y_ENABLE = 0x02;
const Z_DISABLE = 0x00;
const Z_ENABLE = 0x01;
}
}