#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error<E> {
Bus(E),
InvalidChipId(u8),
FatalError,
FeatureEngineNotReady(u8),
SelfTestTimeout,
}
pub const I2C_ADDRESS_PRIMARY: u8 = 0x68;
pub const I2C_ADDRESS_ALTERNATE: u8 = 0x69;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct StatusWord(pub u16);
impl StatusWord {
pub const fn por_detected(self) -> bool {
self.0 & 0x0001 != 0
}
pub const fn drdy_temp(self) -> bool {
self.0 & (1 << 5) != 0
}
pub const fn drdy_gyro(self) -> bool {
self.0 & (1 << 6) != 0
}
pub const fn drdy_accel(self) -> bool {
self.0 & (1 << 7) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ErrorWord(pub u16);
impl ErrorWord {
pub const fn fatal(self) -> bool {
self.0 & 0x0001 != 0
}
pub const fn accel_conf_error(self) -> bool {
self.0 & (1 << 5) != 0
}
pub const fn gyro_conf_error(self) -> bool {
self.0 & (1 << 6) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct InterruptStatus(pub u16);
impl InterruptStatus {
pub const fn no_motion(self) -> bool {
self.0 & (1 << 0) != 0
}
pub const fn any_motion(self) -> bool {
self.0 & (1 << 1) != 0
}
pub const fn flat(self) -> bool {
self.0 & (1 << 2) != 0
}
pub const fn orientation(self) -> bool {
self.0 & (1 << 3) != 0
}
pub const fn step_detector(self) -> bool {
self.0 & (1 << 4) != 0
}
pub const fn step_counter(self) -> bool {
self.0 & (1 << 5) != 0
}
pub const fn significant_motion(self) -> bool {
self.0 & (1 << 6) != 0
}
pub const fn tilt(self) -> bool {
self.0 & (1 << 7) != 0
}
pub const fn tap(self) -> bool {
self.0 & (1 << 8) != 0
}
pub const fn feature_status(self) -> bool {
self.0 & (1 << 10) != 0
}
pub const fn temp_data_ready(self) -> bool {
self.0 & (1 << 11) != 0
}
pub const fn gyro_data_ready(self) -> bool {
self.0 & (1 << 12) != 0
}
pub const fn accel_data_ready(self) -> bool {
self.0 & (1 << 13) != 0
}
pub const fn fifo_watermark(self) -> bool {
self.0 & (1 << 14) != 0
}
pub const fn fifo_full(self) -> bool {
self.0 & (1 << 15) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SelfTestSelection {
Accelerometer,
Gyroscope,
Both,
}
impl SelfTestSelection {
pub const fn to_word(self) -> u16 {
match self {
Self::Accelerometer => 0x0001,
Self::Gyroscope => 0x0002,
Self::Both => 0x0003,
}
}
pub const fn tests_accelerometer(self) -> bool {
matches!(self, Self::Accelerometer | Self::Both)
}
pub const fn tests_gyroscope(self) -> bool {
matches!(self, Self::Gyroscope | Self::Both)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SelfTestDetail(pub u16);
impl SelfTestDetail {
pub const fn acc_sens_x_ok(self) -> bool {
self.0 & (1 << 0) != 0
}
pub const fn acc_sens_y_ok(self) -> bool {
self.0 & (1 << 1) != 0
}
pub const fn acc_sens_z_ok(self) -> bool {
self.0 & (1 << 2) != 0
}
pub const fn gyr_sens_x_ok(self) -> bool {
self.0 & (1 << 3) != 0
}
pub const fn gyr_sens_y_ok(self) -> bool {
self.0 & (1 << 4) != 0
}
pub const fn gyr_sens_z_ok(self) -> bool {
self.0 & (1 << 5) != 0
}
pub const fn gyr_drive_ok(self) -> bool {
self.0 & (1 << 6) != 0
}
pub const fn accelerometer_ok(self) -> bool {
self.acc_sens_x_ok() && self.acc_sens_y_ok() && self.acc_sens_z_ok()
}
pub const fn gyroscope_ok(self) -> bool {
self.gyr_sens_x_ok() && self.gyr_sens_y_ok() && self.gyr_sens_z_ok() && self.gyr_drive_ok()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SelfTestResult {
pub selection: SelfTestSelection,
pub passed: bool,
pub sample_rate_error: bool,
pub error_status: u8,
pub detail: SelfTestDetail,
}
impl SelfTestResult {
pub const fn accelerometer_ok(self) -> bool {
if self.selection.tests_accelerometer() {
self.detail.accelerometer_ok()
} else {
true
}
}
pub const fn gyroscope_ok(self) -> bool {
if self.selection.tests_gyroscope() {
self.detail.gyroscope_ok()
} else {
true
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AxisData {
pub x: i16,
pub y: i16,
pub z: i16,
}
impl AxisData {
pub fn as_g(self, range: AccelRange) -> [f32; 3] {
let scale = range.scale_g_per_lsb();
[
self.x as f32 * scale,
self.y as f32 * scale,
self.z as f32 * scale,
]
}
pub fn as_dps(self, range: GyroRange) -> [f32; 3] {
let scale = range.scale_dps_per_lsb();
[
self.x as f32 * scale,
self.y as f32 * scale,
self.z as f32 * scale,
]
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ImuData {
pub accel: AxisData,
pub gyro: AxisData,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DeviceState {
pub chip_id: u8,
pub status: StatusWord,
pub error: ErrorWord,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OutputDataRate {
Hz0_78125 = 0x1,
Hz1_5625 = 0x2,
Hz3_125 = 0x3,
Hz6_25 = 0x4,
Hz12_5 = 0x5,
Hz25 = 0x6,
Hz50 = 0x7,
Hz100 = 0x8,
Hz200 = 0x9,
Hz400 = 0xA,
Hz800 = 0xB,
Hz1600 = 0xC,
Hz3200 = 0xD,
Hz6400 = 0xE,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Bandwidth {
OdrOver2 = 0,
OdrOver4 = 1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AverageSamples {
Avg1 = 0,
Avg2 = 1,
Avg4 = 2,
Avg8 = 3,
Avg16 = 4,
Avg32 = 5,
Avg64 = 6,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AccelMode {
Disabled = 0,
LowPower = 3,
Normal = 4,
HighPerformance = 7,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum GyroMode {
Disabled = 0,
DriveEnabledOnly = 1,
LowPower = 3,
Normal = 4,
HighPerformance = 7,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AccelRange {
G2 = 0,
G4 = 1,
G8 = 2,
G16 = 3,
}
impl AccelRange {
pub const fn scale_g_per_lsb(self) -> f32 {
match self {
Self::G2 => 2.0 / 32768.0,
Self::G4 => 4.0 / 32768.0,
Self::G8 => 8.0 / 32768.0,
Self::G16 => 16.0 / 32768.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum GyroRange {
Dps125 = 0,
Dps250 = 1,
Dps500 = 2,
Dps1000 = 3,
Dps2000 = 4,
}
impl GyroRange {
pub const fn scale_dps_per_lsb(self) -> f32 {
match self {
Self::Dps125 => 125.0 / 32768.0,
Self::Dps250 => 250.0 / 32768.0,
Self::Dps500 => 500.0 / 32768.0,
Self::Dps1000 => 1000.0 / 32768.0,
Self::Dps2000 => 2000.0 / 32768.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AccelConfig {
pub mode: AccelMode,
pub average: AverageSamples,
pub bandwidth: Bandwidth,
pub range: AccelRange,
pub odr: OutputDataRate,
}
impl Default for AccelConfig {
fn default() -> Self {
Self {
mode: AccelMode::Normal,
average: AverageSamples::Avg1,
bandwidth: Bandwidth::OdrOver2,
range: AccelRange::G8,
odr: OutputDataRate::Hz50,
}
}
}
impl AccelConfig {
pub const fn to_word(self) -> u16 {
((self.mode as u16) << 12)
| ((self.average as u16) << 8)
| ((self.bandwidth as u16) << 7)
| ((self.range as u16) << 4)
| self.odr as u16
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct GyroConfig {
pub mode: GyroMode,
pub average: AverageSamples,
pub bandwidth: Bandwidth,
pub range: GyroRange,
pub odr: OutputDataRate,
}
impl Default for GyroConfig {
fn default() -> Self {
Self {
mode: GyroMode::Normal,
average: AverageSamples::Avg1,
bandwidth: Bandwidth::OdrOver2,
range: GyroRange::Dps2000,
odr: OutputDataRate::Hz50,
}
}
}
impl GyroConfig {
pub const fn to_word(self) -> u16 {
((self.mode as u16) << 12)
| ((self.average as u16) << 8)
| ((self.bandwidth as u16) << 7)
| ((self.range as u16) << 4)
| self.odr as u16
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FifoConfig {
pub stop_on_full: bool,
pub include_time: bool,
pub include_accel: bool,
pub include_gyro: bool,
pub include_temperature: bool,
}
impl FifoConfig {
pub const fn to_word(self) -> u16 {
(self.stop_on_full as u16)
| ((self.include_time as u16) << 8)
| ((self.include_accel as u16) << 9)
| ((self.include_gyro as u16) << 10)
| ((self.include_temperature as u16) << 11)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum InterruptChannel {
Int1,
Int2,
Ibi,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum InterruptRoute {
Disabled = 0,
Int1 = 1,
Int2 = 2,
Ibi = 3,
}
impl From<InterruptRoute> for u16 {
fn from(value: InterruptRoute) -> Self {
value as u16
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ActiveLevel {
Low,
High,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OutputMode {
PushPull,
OpenDrain,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct InterruptPinConfig {
pub active_level: ActiveLevel,
pub output_mode: OutputMode,
pub enabled: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum InterruptSource {
NoMotion,
AnyMotion,
Flat,
Orientation,
StepDetector,
StepCounter,
SignificantMotion,
Tilt,
Tap,
I3cSync,
FeatureStatus,
TempDataReady,
GyroDataReady,
AccelDataReady,
FifoWatermark,
FifoFull,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum EventReportMode {
AllEvents,
FirstEventOnly,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct StepCounterConfig {
pub watermark_level: u16,
pub reset_counter: bool,
}
impl StepCounterConfig {
pub const fn disabled() -> Self {
Self {
watermark_level: 0,
reset_counter: false,
}
}
pub const fn with_watermark(steps: u16) -> Self {
Self {
watermark_level: if steps > 1023 { 1023 } else { steps },
reset_counter: false,
}
}
pub const fn to_word(self) -> u16 {
(self.watermark_level & 0x03FF) | ((self.reset_counter as u16) << 10)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FeatureBlockingMode {
Disabled = 0,
AccelOver1p5g = 1,
AccelOver1p5gOrHalfSlope = 2,
AccelOver1p5gOrFullSlope = 3,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OrientationMode {
Symmetrical = 0,
LandscapeWide = 1,
PortraitWide = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TapAxis {
X = 0,
Y = 1,
Z = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TapReportingMode {
Immediate = 0,
Confirmed = 1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TapDetectionMode {
Sensitive = 0,
Normal = 1,
Robust = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FlatConfig {
pub theta: u8,
pub blocking: FeatureBlockingMode,
pub hold_time: u8,
pub slope_threshold: u8,
pub hysteresis: u8,
pub report_mode: EventReportMode,
pub interrupt_hold: u8,
}
impl FlatConfig {
pub fn hold_time_from_seconds(seconds: f32) -> u8 {
(seconds * 50.0).clamp(0.0, 255.0) as u8
}
pub fn hold_time_to_seconds(raw: u8) -> f32 {
raw as f32 / 50.0
}
pub fn slope_threshold_from_g(g: f32) -> u8 {
(g * 512.0).clamp(0.0, 255.0) as u8
}
pub fn slope_threshold_to_g(raw: u8) -> f32 {
raw as f32 / 512.0
}
pub fn interrupt_hold_from_millis(millis: f32) -> u8 {
AnyMotionConfig::interrupt_hold_from_millis(millis)
}
pub fn interrupt_hold_to_millis(raw: u8) -> f32 {
AnyMotionConfig::interrupt_hold_to_millis(raw)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct OrientationConfig {
pub upside_down_enabled: bool,
pub mode: OrientationMode,
pub blocking: FeatureBlockingMode,
pub theta: u8,
pub hold_time: u8,
pub slope_threshold: u8,
pub hysteresis: u8,
pub report_mode: EventReportMode,
pub interrupt_hold: u8,
}
impl OrientationConfig {
pub fn hold_time_from_seconds(seconds: f32) -> u8 {
(seconds * 50.0).clamp(0.0, 31.0) as u8
}
pub fn hold_time_to_seconds(raw: u8) -> f32 {
f32::from(raw & 0x1F) / 50.0
}
pub fn slope_threshold_from_g(g: f32) -> u8 {
FlatConfig::slope_threshold_from_g(g)
}
pub fn slope_threshold_to_g(raw: u8) -> f32 {
FlatConfig::slope_threshold_to_g(raw)
}
pub fn hysteresis_from_g(g: f32) -> u8 {
(g * 512.0).clamp(0.0, 255.0) as u8
}
pub fn hysteresis_to_g(raw: u8) -> f32 {
raw as f32 / 512.0
}
pub fn interrupt_hold_from_millis(millis: f32) -> u8 {
AnyMotionConfig::interrupt_hold_from_millis(millis)
}
pub fn interrupt_hold_to_millis(raw: u8) -> f32 {
AnyMotionConfig::interrupt_hold_to_millis(raw)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct TapConfig {
pub axis: TapAxis,
pub reporting_mode: TapReportingMode,
pub max_peaks_for_tap: u8,
pub mode: TapDetectionMode,
pub single_tap_enabled: bool,
pub double_tap_enabled: bool,
pub triple_tap_enabled: bool,
pub tap_peak_threshold: u16,
pub max_gesture_duration: u8,
pub max_duration_between_peaks: u8,
pub tap_shock_settling_duration: u8,
pub min_quiet_duration_between_taps: u8,
pub quiet_time_after_gesture: u8,
pub report_mode: EventReportMode,
pub interrupt_hold: u8,
}
impl TapConfig {
pub fn tap_peak_threshold_from_g(g: f32) -> u16 {
(g * 512.0).clamp(0.0, 1023.0) as u16
}
pub fn tap_peak_threshold_to_g(raw: u16) -> f32 {
(raw & 0x03FF) as f32 / 512.0
}
pub fn max_gesture_duration_from_seconds(seconds: f32) -> u8 {
(seconds * 25.0).clamp(0.0, 63.0) as u8
}
pub fn max_gesture_duration_to_seconds(raw: u8) -> f32 {
f32::from(raw & 0x3F) / 25.0
}
pub fn short_duration_from_seconds(seconds: f32) -> u8 {
(seconds * 200.0).clamp(0.0, 15.0) as u8
}
pub fn short_duration_to_seconds(raw: u8) -> f32 {
f32::from(raw & 0x0F) / 200.0
}
pub fn quiet_time_after_gesture_from_seconds(seconds: f32) -> u8 {
(seconds * 25.0).clamp(0.0, 15.0) as u8
}
pub fn quiet_time_after_gesture_to_seconds(raw: u8) -> f32 {
f32::from(raw & 0x0F) / 25.0
}
pub fn interrupt_hold_from_millis(millis: f32) -> u8 {
AnyMotionConfig::interrupt_hold_from_millis(millis)
}
pub fn interrupt_hold_to_millis(raw: u8) -> f32 {
AnyMotionConfig::interrupt_hold_to_millis(raw)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SignificantMotionConfig {
pub block_size: u16,
pub peak_to_peak_min: u16,
pub mean_crossing_rate_min: u8,
pub peak_to_peak_max: u16,
pub mean_crossing_rate_max: u8,
pub report_mode: EventReportMode,
pub interrupt_hold: u8,
}
impl SignificantMotionConfig {
pub fn block_size_from_seconds(seconds: f32) -> u16 {
(seconds * 50.0).clamp(0.0, 65535.0) as u16
}
pub fn block_size_to_seconds(raw: u16) -> f32 {
raw as f32 / 50.0
}
pub fn peak_to_peak_from_g(g: f32) -> u16 {
(g * 512.0).clamp(0.0, 1023.0) as u16
}
pub fn peak_to_peak_to_g(raw: u16) -> f32 {
(raw & 0x03FF) as f32 / 512.0
}
pub fn interrupt_hold_from_millis(millis: f32) -> u8 {
AnyMotionConfig::interrupt_hold_from_millis(millis)
}
pub fn interrupt_hold_to_millis(raw: u8) -> f32 {
AnyMotionConfig::interrupt_hold_to_millis(raw)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct TiltConfig {
pub segment_size: u8,
pub min_tilt_angle: u8,
pub beta_acc_mean: u16,
pub report_mode: EventReportMode,
pub interrupt_hold: u8,
}
impl TiltConfig {
pub fn segment_size_from_seconds(seconds: f32) -> u8 {
(seconds * 50.0).clamp(0.0, 255.0) as u8
}
pub fn segment_size_to_seconds(raw: u8) -> f32 {
raw as f32 / 50.0
}
pub fn interrupt_hold_from_millis(millis: f32) -> u8 {
AnyMotionConfig::interrupt_hold_from_millis(millis)
}
pub fn interrupt_hold_to_millis(raw: u8) -> f32 {
AnyMotionConfig::interrupt_hold_to_millis(raw)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AltAccelConfig {
pub mode: AccelMode,
pub average: AverageSamples,
pub odr: OutputDataRate,
}
impl AltAccelConfig {
pub const fn to_word(self) -> u16 {
((self.mode as u16) << 12) | ((self.average as u16) << 8) | self.odr as u16
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AltGyroConfig {
pub mode: GyroMode,
pub average: AverageSamples,
pub odr: OutputDataRate,
}
impl AltGyroConfig {
pub const fn to_word(self) -> u16 {
((self.mode as u16) << 12) | ((self.average as u16) << 8) | self.odr as u16
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AltConfigSwitchSource {
None = 0,
NoMotion = 1,
AnyMotion = 2,
Flat = 3,
Orientation = 4,
StepDetector = 5,
StepCounter = 6,
SignificantMotion = 7,
Tilt = 8,
Tap = 9,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AltConfigControl {
pub accel_enabled: bool,
pub gyro_enabled: bool,
pub reset_on_user_config_write: bool,
pub switch_to_alternate: AltConfigSwitchSource,
pub switch_to_user: AltConfigSwitchSource,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AltStatus(pub u16);
impl AltStatus {
pub const fn accel_uses_alternate(self) -> bool {
self.0 & 0x0001 != 0
}
pub const fn gyro_uses_alternate(self) -> bool {
self.0 & (1 << 4) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AltAccelSwitchProfile {
pub user_accel: AccelConfig,
pub alternate_accel: AltAccelConfig,
pub control: AltConfigControl,
}
impl AltAccelSwitchProfile {
pub const fn low_power_to_high_performance(
user_odr: OutputDataRate,
alternate_odr: OutputDataRate,
switch_to_alternate: AltConfigSwitchSource,
switch_to_user: AltConfigSwitchSource,
) -> Self {
Self {
user_accel: AccelConfig {
mode: AccelMode::LowPower,
average: AverageSamples::Avg2,
bandwidth: Bandwidth::OdrOver2,
range: AccelRange::G8,
odr: user_odr,
},
alternate_accel: AltAccelConfig {
mode: AccelMode::HighPerformance,
average: AverageSamples::Avg1,
odr: alternate_odr,
},
control: AltConfigControl {
accel_enabled: true,
gyro_enabled: false,
reset_on_user_config_write: true,
switch_to_alternate,
switch_to_user,
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ReferenceUpdate {
OnDetection,
EverySample,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct MotionAxes {
pub x: bool,
pub y: bool,
pub z: bool,
}
impl MotionAxes {
pub const XYZ: Self = Self {
x: true,
y: true,
z: true,
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AnyMotionConfig {
pub axes: MotionAxes,
pub threshold: u16,
pub hysteresis: u16,
pub duration: u16,
pub wait_time: u8,
pub reference_update: ReferenceUpdate,
pub report_mode: EventReportMode,
pub interrupt_hold: u8,
}
impl AnyMotionConfig {
pub fn threshold_from_g(g: f32) -> u16 {
(g * 512.0).clamp(0.0, 4095.0) as u16
}
pub fn threshold_to_g(raw: u16) -> f32 {
(raw & 0x0FFF) as f32 / 512.0
}
pub fn hysteresis_from_g(g: f32) -> u16 {
(g * 512.0).clamp(0.0, 1023.0) as u16
}
pub fn hysteresis_to_g(raw: u16) -> f32 {
(raw & 0x03FF) as f32 / 512.0
}
pub fn duration_from_seconds(seconds: f32) -> u16 {
(seconds * 50.0).clamp(0.0, 8191.0) as u16
}
pub fn duration_to_seconds(raw: u16) -> f32 {
(raw & 0x1FFF) as f32 / 50.0
}
pub fn wait_time_from_seconds(seconds: f32) -> u8 {
(seconds * 50.0).clamp(0.0, 7.0) as u8
}
pub fn wait_time_to_seconds(raw: u8) -> f32 {
(raw & 0x07) as f32 / 50.0
}
pub fn interrupt_hold_from_millis(millis: f32) -> u8 {
let mut encoded = 0u8;
let mut hold_ms = 0.625f32;
while hold_ms < millis && encoded < 13 {
encoded += 1;
hold_ms *= 2.0;
}
encoded
}
pub fn interrupt_hold_to_millis(raw: u8) -> f32 {
let mut hold_ms = 0.625f32;
let mut encoded = 0u8;
while encoded < raw.min(13) {
hold_ms *= 2.0;
encoded += 1;
}
hold_ms
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct NoMotionConfig {
pub axes: MotionAxes,
pub threshold: u16,
pub hysteresis: u16,
pub duration: u16,
pub wait_time: u8,
pub reference_update: ReferenceUpdate,
pub report_mode: EventReportMode,
pub interrupt_hold: u8,
}
impl NoMotionConfig {
pub fn threshold_from_g(g: f32) -> u16 {
(g * 512.0).clamp(0.0, 4095.0) as u16
}
pub fn threshold_to_g(raw: u16) -> f32 {
(raw & 0x0FFF) as f32 / 512.0
}
pub fn hysteresis_from_g(g: f32) -> u16 {
(g * 512.0).clamp(0.0, 1023.0) as u16
}
pub fn hysteresis_to_g(raw: u16) -> f32 {
(raw & 0x03FF) as f32 / 512.0
}
pub fn duration_from_seconds(seconds: f32) -> u16 {
(seconds * 50.0).clamp(0.0, 8191.0) as u16
}
pub fn duration_to_seconds(raw: u16) -> f32 {
(raw & 0x1FFF) as f32 / 50.0
}
pub fn wait_time_from_seconds(seconds: f32) -> u8 {
(seconds * 50.0).clamp(0.0, 7.0) as u8
}
pub fn wait_time_to_seconds(raw: u8) -> f32 {
(raw & 0x07) as f32 / 50.0
}
pub fn interrupt_hold_from_millis(millis: f32) -> u8 {
AnyMotionConfig::interrupt_hold_from_millis(millis)
}
pub fn interrupt_hold_to_millis(raw: u8) -> f32 {
AnyMotionConfig::interrupt_hold_to_millis(raw)
}
}