1use crate::register::{ctrl8, status_int, status0, status1};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8pub enum InterruptPin {
9 Int1,
11 Int2,
13}
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17#[cfg_attr(feature = "defmt", derive(defmt::Format))]
18pub struct InterruptConfig {
19 pub ctrl9_handshake_statusint: bool,
21 pub motion_pin: InterruptPin,
23 pub pedometer: bool,
25 pub significant_motion: bool,
27 pub no_motion: bool,
29 pub any_motion: bool,
31 pub tap: bool,
33}
34
35impl InterruptConfig {
36 pub const DEFAULT: Self = Self {
38 ctrl9_handshake_statusint: false,
39 motion_pin: InterruptPin::Int1,
40 pedometer: false,
41 significant_motion: false,
42 no_motion: false,
43 any_motion: false,
44 tap: false,
45 };
46
47 pub const fn new() -> Self {
49 Self::DEFAULT
50 }
51
52 #[must_use]
54 pub const fn with_motion_pin(mut self, pin: InterruptPin) -> Self {
55 self.motion_pin = pin;
56 self
57 }
58
59 #[must_use]
61 pub const fn with_ctrl9_handshake_statusint(mut self, enable: bool) -> Self {
62 self.ctrl9_handshake_statusint = enable;
63 self
64 }
65
66 #[must_use]
68 pub const fn with_tap(mut self, enable: bool) -> Self {
69 self.tap = enable;
70 self
71 }
72
73 #[must_use]
75 pub const fn with_any_motion(mut self, enable: bool) -> Self {
76 self.any_motion = enable;
77 self
78 }
79
80 #[must_use]
82 pub const fn with_no_motion(mut self, enable: bool) -> Self {
83 self.no_motion = enable;
84 self
85 }
86
87 #[must_use]
89 pub const fn with_significant_motion(mut self, enable: bool) -> Self {
90 self.significant_motion = enable;
91 self
92 }
93
94 #[must_use]
96 pub const fn with_pedometer(mut self, enable: bool) -> Self {
97 self.pedometer = enable;
98 self
99 }
100
101 pub(crate) const fn ctrl8_value(self) -> u8 {
102 let mut value = 0;
103 if self.ctrl9_handshake_statusint {
104 value |= ctrl8::CTRL9_HANDSHAKE_STATUSINT;
105 }
106 if matches!(self.motion_pin, InterruptPin::Int1) {
107 value |= ctrl8::MOTION_INT_INT1;
108 }
109 if self.pedometer {
110 value |= ctrl8::PEDOMETER_EN;
111 }
112 if self.significant_motion {
113 value |= ctrl8::SIGNIFICANT_MOTION_EN;
114 }
115 if self.no_motion {
116 value |= ctrl8::NO_MOTION_EN;
117 }
118 if self.any_motion {
119 value |= ctrl8::ANY_MOTION_EN;
120 }
121 if self.tap {
122 value |= ctrl8::TAP_EN;
123 }
124 value
125 }
126}
127
128impl Default for InterruptConfig {
129 fn default() -> Self {
130 Self::DEFAULT
131 }
132}
133
134#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
136#[cfg_attr(feature = "defmt", derive(defmt::Format))]
137pub struct InterruptStatus {
138 pub cmd_done: bool,
140 pub data_locked: bool,
142 pub data_available: bool,
144 pub accel_ready: bool,
146 pub gyro_ready: bool,
148 pub ae_ready: bool,
150 pub tap: bool,
152 pub any_motion: bool,
154 pub no_motion: bool,
156 pub significant_motion: bool,
158 pub wake_on_motion: bool,
160 pub pedometer: bool,
162}
163
164impl InterruptStatus {
165 pub(crate) const fn from_regs(status_int_reg: u8, status0_reg: u8, status1_reg: u8) -> Self {
166 Self {
167 cmd_done: (status_int_reg & status_int::CMD_DONE) != 0
168 || (status1_reg & status1::CMD_DONE) != 0,
169 data_locked: (status_int_reg & status_int::LOCKED) != 0,
170 data_available: (status_int_reg & status_int::AVAIL) != 0,
171 accel_ready: (status0_reg & status0::ACCEL_AVAIL) != 0,
172 gyro_ready: (status0_reg & status0::GYRO_AVAIL) != 0,
173 ae_ready: (status0_reg & status0::AE_AVAIL) != 0,
174 tap: (status1_reg & status1::TAP) != 0,
175 any_motion: (status1_reg & status1::ANY_MOTION) != 0,
176 no_motion: (status1_reg & status1::NO_MOTION) != 0,
177 significant_motion: (status1_reg & status1::SIGNIFICANT_MOTION) != 0,
178 wake_on_motion: (status1_reg & status1::WOM) != 0,
179 pedometer: (status1_reg & status1::PEDOMETER) != 0,
180 }
181 }
182
183 pub const fn any(self) -> bool {
185 self.cmd_done
186 || self.data_locked
187 || self.data_available
188 || self.accel_ready
189 || self.gyro_ready
190 || self.ae_ready
191 || self.tap
192 || self.any_motion
193 || self.no_motion
194 || self.significant_motion
195 || self.wake_on_motion
196 || self.pedometer
197 }
198}
199
200#[derive(Debug)]
202#[cfg_attr(feature = "defmt", derive(defmt::Format))]
203pub enum InterruptWaitError<E> {
204 Missing,
206 Pin(E),
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213 use crate::register::{status_int, status0, status1};
214
215 #[test]
216 fn decode_interrupt_status() {
217 let status = InterruptStatus::from_regs(
218 status_int::AVAIL,
219 status0::ACCEL_AVAIL | status0::GYRO_AVAIL,
220 status1::TAP | status1::ANY_MOTION | status1::CMD_DONE | status1::WOM,
221 );
222
223 assert!(status.cmd_done);
224 assert!(status.data_available);
225 assert!(status.accel_ready);
226 assert!(status.gyro_ready);
227 assert!(status.tap);
228 assert!(status.any_motion);
229 assert!(status.wake_on_motion);
230 assert!(!status.no_motion);
231 assert!(status.any());
232 }
233}