-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds configuration for motion and tap detection features, and some re…
…factoring (#5) * Just backing up some work. Added a soft reset in the init method so the chip returns to a known state and the config file can be loaded again for sure. Waits for the internal status to be ok after completing loading the config file to ensure that it was successful, with a timeout. Sets up the accelerometer into a known configuration at the end of init so it is usable right away, considering adding some type states instead. Currently full of some test methods written to get the any motion and tap detection features working. * Updates the `embedded-hal` dependency from ^0.2 to 1.0.0-alpha.10. * Adds the public `features` module and `EditFeatures` struct for efficient editing of feature configurations instead of reading and writing the entire register contents from the chip every time. Implements setting the feature configurations for the motion and tap detection features, other features are still pending. Adds additional methods to the driver for configuring the interrupt lines, and tweaks the methods for mapping them to features. * Refactors the driver to add type states to ensure that bad things aren't done such as: * Doing things before initializing * Editing features when in a low power mode, as this requires long delays between burst write bytes Renames and reorganizes some of the methods. Adds additional info the README in terms of what is done and what still needs done. * Adds documentation for the remaining items that can be documented (i.e. everything but bit masks). Adds the `set_fifo_self_wakeup` method. * Removes the `derive-new` dependency per the pull request discussion: #5 --------- Co-authored-by: Dan Whitman <dwhitman44@mgail.com>
- Loading branch information
Showing
4 changed files
with
701 additions
and
326 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,21 @@ | ||
[package] | ||
name = "bma423" | ||
version = "0.0.1" | ||
edition = "2021" | ||
authors = ["Pierre-Yves Aillet <pyaillet@gmail.com>"] | ||
categories = ["embedded", "hardware-support"] | ||
description = "Rust driver for Bma423 accelerometer" | ||
repository = "https://github.com/pyaillet/bma423-rs" | ||
edition = "2021" | ||
license = "MIT OR Apache-2.0" | ||
name = "bma423" | ||
readme = "README.md" | ||
|
||
repository = "https://github.com/pyaillet/bma423-rs" | ||
version = "0.0.1" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
[dependencies] | ||
embedded-hal = "^0.2" | ||
num_enum = { version = "^0.5", default-features = false } | ||
accelerometer = { version = "^0.12", optional = true } | ||
bitmask-enum = { version = "^1.1" } | ||
accelerometer = {version = "^0.12", optional = true} | ||
bitmask-enum = {version = "^1.1"} | ||
embedded-hal = "1.0.0-alpha.10" | ||
num_enum = {version = "^0.5", default-features = false} | ||
|
||
[features] | ||
default = [ "accel" ] | ||
accel = [ "accelerometer" ] | ||
accel = ["accelerometer"] | ||
default = ["accel"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
//! Items for configuring the features of the chip. | ||
//! | ||
//! The main item is [`EditFeatures`]. | ||
|
||
use core::ops::RangeInclusive; | ||
|
||
use bitmask_enum::bitmask; | ||
|
||
use crate::{Error, FullPower, Reg}; | ||
|
||
pub(crate) const FEATURE_SIZE: usize = 70; | ||
|
||
#[repr(u8)] | ||
#[derive(Copy, Clone, Debug)] | ||
enum FeatureOffset { | ||
AnyMotion = 0x00, | ||
NoMotion = 0x04, | ||
//StepCounterParam = 0x08, | ||
//StepCounter = 0x3A, | ||
SingleTap = 0x3C, | ||
DoubleTap = 0x3E, | ||
//WristWear = 0x40, | ||
//ConfigId = 0x42, | ||
//AxesRemap = 0x44, | ||
} | ||
|
||
/// Which motion feature | ||
#[derive(Copy, Clone, Debug)] | ||
pub enum MotionFeature { | ||
/// Any motion detection feature | ||
AnyMotion, | ||
/// No motion detection feature | ||
NoMotion, | ||
} | ||
|
||
// Motion feature valid value ranges | ||
const MOTION_THRESHOLD_RANGE: RangeInclusive<u16> = 0..=0x7FF; | ||
const MOTION_DURATION_RANGE: RangeInclusive<u16> = 0..=0x1FFF; | ||
|
||
/// Motion feature axes. | ||
/// | ||
/// Can be combined like a bitmask. | ||
#[bitmask(u8)] | ||
#[derive(Copy, Clone, Debug)] | ||
pub enum MotionAxes { | ||
AxisX = Self(0b0010_0000), | ||
AxisY = Self(0b0100_0000), | ||
AxisZ = Self(0b1000_0000), | ||
} | ||
|
||
// Tap sensitivity valid value ranges | ||
const TAP_SENSITIVITY_RANGE: RangeInclusive<u8> = 0..=7; | ||
|
||
/// Which tap feature | ||
#[derive(Copy, Clone, Debug)] | ||
pub enum TapFeature { | ||
/// Single tap detection feature | ||
SingleTap, | ||
/// Double tap detection feature | ||
DoubleTap, | ||
} | ||
|
||
/// Allows editing feature configurations in an efficient way. | ||
/// | ||
/// This can be obtained from the driver by calling | ||
/// [`edit_features`](crate::Bma423::edit_features). | ||
/// Once the desired features are configured, one must | ||
/// call [`write`](EditFeatures::write) to write the | ||
/// configurations back to the chip so that they take | ||
/// effect. | ||
pub struct EditFeatures<'a, I2C> { | ||
pub(crate) register: [u8; FEATURE_SIZE + 1], | ||
pub(crate) driver: &'a mut crate::Bma423<I2C, FullPower>, | ||
} | ||
impl<I2C: embedded_hal::i2c::I2c> EditFeatures<'_, I2C> { | ||
/// Allows editing the features register without the offset. | ||
fn edit_register(&mut self, f: impl FnOnce(&mut [u8])) { | ||
f(&mut self.register[1..FEATURE_SIZE + 1]); | ||
} | ||
|
||
/// Sets the motion detection feature configuration. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// - `which` Specifies which motion feature to configure. | ||
/// - `threshold` Slope threshold for motion detection. | ||
/// The least significant bit is 0.48828125 mg, and the valid | ||
/// range is 0 to 0x7FF (1 g). | ||
/// The default value is 0xAA (83 mg). | ||
/// - `duration` The number of consecutive data points for which | ||
/// the threshold condition must be respected. | ||
/// In terms of time, the least significant bit is 20 ms, and the | ||
/// valid range is 0 to 0x1FFF (163 s). | ||
/// The default value is 5 (100 ms). | ||
/// - `enabled_axes` Axes for which to enable the motion detection. | ||
pub fn set_motion_config( | ||
&mut self, | ||
which: MotionFeature, | ||
threshold: u16, | ||
duration: u16, | ||
enabled_axes: MotionAxes, | ||
) -> Result<(), Error<I2C::Error>> { | ||
// Validate arguments | ||
if !MOTION_THRESHOLD_RANGE.contains(&threshold) | ||
|| !MOTION_DURATION_RANGE.contains(&duration) | ||
{ | ||
return Err(Error::BadArgument); | ||
} | ||
|
||
self.edit_register(|reg| { | ||
let offset = match which { | ||
MotionFeature::AnyMotion => FeatureOffset::AnyMotion, | ||
MotionFeature::NoMotion => FeatureOffset::NoMotion, | ||
} as usize; | ||
|
||
// Set the threshold | ||
let threshold = threshold.to_le_bytes(); | ||
reg[offset + 0] = threshold[0]; | ||
Check warning on line 118 in src/features.rs
|
||
reg[offset + 1] = threshold[1]; | ||
|
||
// Set the duration | ||
let duration = duration.to_le_bytes(); | ||
reg[offset + 2] = duration[0]; | ||
reg[offset + 3] = duration[1]; | ||
|
||
// Set enabled axes | ||
reg[offset + 3] = u8::from(enabled_axes) & 0xE0; | ||
}); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Sets the tap detection feature configuration. | ||
/// | ||
/// The features can be enabled using [`edit_feature`](crate::Bma423::edit_features). | ||
/// | ||
/// # Arguments | ||
/// | ||
/// - `which` Specifies which tap feature to configure. | ||
/// - `sensitivity` A sensitivity level from 0 (most sensitive) to | ||
/// 7 (least sensitive). | ||
/// The default value is 3. | ||
/// - `enable` Whether to enable or disable tap detection. | ||
pub fn set_tap_config( | ||
&mut self, | ||
which: TapFeature, | ||
sensitivity: u8, | ||
enable: bool, | ||
) -> Result<(), Error<I2C::Error>> { | ||
if !TAP_SENSITIVITY_RANGE.contains(&sensitivity) { | ||
return Err(Error::BadArgument); | ||
} | ||
|
||
self.edit_register(|reg| { | ||
let offset = match which { | ||
TapFeature::SingleTap => FeatureOffset::SingleTap, | ||
TapFeature::DoubleTap => FeatureOffset::DoubleTap, | ||
} as usize; | ||
|
||
reg[offset] = sensitivity << 1; | ||
if enable { | ||
reg[offset] |= 1; | ||
} | ||
}); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Writes the edited features back to the chip so that they take effect. | ||
pub fn write(mut self) -> Result<(), Error<I2C::Error>> { | ||
self.register[0] = Reg::FeatureConfig.into(); | ||
self.driver.write(&self.register) | ||
} | ||
} |
Oops, something went wrong.