Skip to content

Commit

Permalink
feat: add freefall and motion detection support
Browse files Browse the repository at this point in the history
  • Loading branch information
elrafoon committed May 15, 2024
1 parent 40342c3 commit 9bbf67b
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 0 deletions.
82 changes: 82 additions & 0 deletions src/common/config_ff_mt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use embedded_hal::i2c::{I2c, SevenBitAddress};

use crate::{
mode,
register_access::{BitFlags, Register},
types::{FreefallMotionAxisActivity, FreefallMotionSource},
Error, FreefallMotionConfiguration, FreefallMotionDebounceMode, FreefallMotionDetectionMode,
Mma8x5x,
};

/// Freefall/motion detection configuration
impl<E, I2C, IC> Mma8x5x<I2C, IC, mode::Standby>
where
I2C: I2c<SevenBitAddress, Error = E>,
{
/// enable freefall or motion detection
pub fn enable_freefall_motion_detection(
&mut self,
conf: FreefallMotionConfiguration,
) -> Result<(), Error<E>> {
let mut value = match conf.detection_mode {
FreefallMotionDetectionMode::Freefall => 0,
FreefallMotionDetectionMode::Motion => BitFlags::OAE,
};

if conf.event_latch {
value |= BitFlags::ELE;
}

if conf.x_axis {
value |= BitFlags::XEFE;
}

if conf.y_axis {
value |= BitFlags::YEFE;
}

if conf.z_axis {
value |= BitFlags::ZEFE;
}

self.write_reg(Register::FF_MT_CFG, value)?;

let mut value = match conf.debounce_mode {
FreefallMotionDebounceMode::IncrementOrDecrement => 0,
FreefallMotionDebounceMode::IncrementOrClear => BitFlags::DBCNTM,
};
let thres: u8 = (conf.threshold / 63).clamp(0, 127).try_into().unwrap();
value |= thres;
self.write_reg(Register::FF_MT_THS, value)?;

self.write_reg(Register::FF_MT_COUNT, value)?;

Ok(())
}
}

impl<E, I2C, IC> Mma8x5x<I2C, IC, mode::Active>
where
I2C: I2c<SevenBitAddress, Error = E>,
{
/// get source of the freefall/motion event
pub fn freefall_motion_source(&mut self) -> Result<Option<FreefallMotionSource>, Error<E>> {
let act = |he, hp| match (he, hp) {
(false, _) => FreefallMotionAxisActivity::None,
(true, false) => FreefallMotionAxisActivity::Positive,
(true, true) => FreefallMotionAxisActivity::Negative,
};

self.read_reg(Register::FF_MT_SRC).map(|src| {
if (src & BitFlags::EA) != 0 {
Some(FreefallMotionSource {
x_axis: act((src & BitFlags::XHE) != 0, (src & BitFlags::XHP) != 0),
y_axis: act((src & BitFlags::YHE) != 0, (src & BitFlags::YHP) != 0),
z_axis: act((src & BitFlags::ZHE) != 0, (src & BitFlags::ZHP) != 0),
})
} else {
None
}
})
}
}
1 change: 1 addition & 0 deletions src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod common_impl;
mod config;
mod config_auto_sleep;
mod config_ff_mt;
mod config_int;
mod config_pl;
mod mode_change;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ mod types;
use crate::types::MMA845X_BASE_ADDR;
pub use crate::types::{
ic, mode, AutoSleepDataRate, DataStatus, DebounceCounterMode, EnabledInterrupts, Error,
FreefallMotionConfiguration, FreefallMotionDebounceMode, FreefallMotionDetectionMode,
FrontBackOrientation, GScale, InterruptPinConfiguration, InterruptPinPolarity,
InterruptPinRoutes, InterruptSourcePinRoute, InterruptStatus, Measurement, ModeChangeError,
OutputDataRate, PortraitLandscapeOrientation, PortraitLandscapeStatus, PowerMode, ReadMode,
Expand Down
18 changes: 18 additions & 0 deletions src/register_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ impl Register {
pub const XYZ_DATA_CFG: u8 = 0x0E;
pub const PL_CFG: u8 = 0x11;
pub const PL_COUNT: u8 = 0x12;
pub const FF_MT_CFG: u8 = 0x15;
pub const FF_MT_SRC: u8 = 0x16;
pub const FF_MT_THS: u8 = 0x17;
pub const FF_MT_COUNT: u8 = 0x17;
pub const PL_STATUS: u8 = 0x10;
pub const ASLP_COUNT: u8 = 0x29;
pub const CTRL_REG1: u8 = 0x2A;
Expand Down Expand Up @@ -61,6 +65,20 @@ impl BitFlags {
pub const LO: u8 = 1 << 6;
pub const NEWLP: u8 = 1 << 7;

pub const XEFE: u8 = 1 << 3;
pub const YEFE: u8 = 1 << 4;
pub const ZEFE: u8 = 1 << 5;
pub const OAE: u8 = 1 << 6;
pub const ELE: u8 = 1 << 7;

pub const XHP: u8 = 1 << 0;
pub const XHE: u8 = 1 << 1;
pub const YHP: u8 = 1 << 2;
pub const YHE: u8 = 1 << 3;
pub const ZHP: u8 = 1 << 4;
pub const ZHE: u8 = 1 << 5;
pub const EA: u8 = 1 << 7;

pub const SRC_DRDY: u8 = 1;
pub const SRC_FF_MT: u8 = 1 << 2;
pub const SRC_PULSE: u8 = 1 << 3;
Expand Down
80 changes: 80 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ pub mod ic {
/// Mode markers
pub mod mode {
/// Standby mode
#[derive(Debug)]
pub struct Standby;
/// Active mode
#[derive(Debug)]
pub struct Active;
}

Expand Down Expand Up @@ -205,6 +207,84 @@ pub enum FrontBackOrientation {
Back,
}

/// Freefall/Motion detection mode
#[derive(Default, Debug)]
pub enum FreefallMotionDetectionMode {
/// detect freefall
#[default]
Freefall,
/// detect motion
Motion,
}

/// Freefall/Motion debounce mode
#[derive(Default, Debug)]
pub enum FreefallMotionDebounceMode {
/// Increments or decrements debounce
#[default]
IncrementOrDecrement,
/// Increments or clears counter
IncrementOrClear,
}

/// Freefall/Motion detection configuration
#[derive(Debug)]
pub struct FreefallMotionConfiguration {
/// if true, event is latched into FF_MT_SRC and must be read to clear
pub event_latch: bool,
/// detection mode
pub detection_mode: FreefallMotionDetectionMode,
/// enable detection in x-axis
pub x_axis: bool,
/// enable detection in y-axis
pub y_axis: bool,
/// enable detection in z-axis
pub z_axis: bool,
/// detection threshold, in 1/1000 G
pub threshold: u16,
/// debounce counter mode
pub debounce_mode: FreefallMotionDebounceMode,
/// debounce sample count
pub debounce_count: u8,
}

impl Default for FreefallMotionConfiguration {
fn default() -> Self {
Self {
event_latch: false,
detection_mode: Default::default(),
x_axis: true,
y_axis: true,
z_axis: true,
threshold: 500,
debounce_mode: Default::default(),
debounce_count: 0,
}
}
}

/// Freefall/Motion axis activity
#[derive(Debug)]
pub enum FreefallMotionAxisActivity {
/// motion in the axis not detected
None,
/// positive axis movement detected
Positive,
/// negative axis movement detected
Negative,
}

/// Freefall/Motion event source
#[derive(Debug)]
pub struct FreefallMotionSource {
/// movement activity in x-axis
pub x_axis: FreefallMotionAxisActivity,
/// movement activity in y-axis
pub y_axis: FreefallMotionAxisActivity,
/// movement activity in z-axis
pub z_axis: FreefallMotionAxisActivity,
}

/// Current interrupt status
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct InterruptStatus {
Expand Down

0 comments on commit 9bbf67b

Please sign in to comment.