1#![no_std]
12
13pub use accelerometer;
14use accelerometer::error::Error as AccelerometerError;
15use accelerometer::vector::{F32x3, I16x3};
16use accelerometer::{Accelerometer, RawAccelerometer};
17use embedded_hal::i2c::I2c;
18
19pub mod config;
20pub mod register;
21use config::*;
22use register::*;
23use register::{DataRate, Mode, Range, Register, SlaveAddr};
24
25#[derive(Debug)]
28pub enum Error<BusError, PinError> {
29 Bus(BusError),
31 Pin(PinError),
32
33 InvalidAxis,
35
36 InvalidDataRate,
38
39 InvalidRange,
41
42 InvalidMode,
44
45 WriteToReadOnly,
47
48 WrongAddress,
50}
51
52pub struct Kxtj3<I2C> {
54 i2c: I2C,
56
57 address: u8,
59}
60
61impl<I2C, E> Kxtj3<I2C>
62where
63 I2C: I2c<Error = E>,
64{
65 pub fn new(i2c: I2C, address: SlaveAddr) -> Result<Self, Error<E, core::convert::Infallible>> {
81 Self::new_with_config(i2c, address, Configuration::default())
82 }
83
84 pub fn new_with_config(
85 i2c: I2C,
86 address: SlaveAddr,
87 config: Configuration,
88 ) -> Result<Self, Error<E, core::convert::Infallible>> {
89 let mut kxtj3 = Kxtj3 {
90 i2c,
91 address: address.addr(),
92 };
93 kxtj3.configure(config)?;
94
95 Ok(kxtj3)
96 }
97
98 pub fn configure(
100 &mut self,
101 conf: Configuration,
102 ) -> Result<(), Error<E, core::convert::Infallible>> {
103 if self.get_device_id()? != DEVICE_ID {
104 return Err(Error::WrongAddress);
105 }
106 self.enable_standby_mode()?;
107 self.set_mode(conf.mode)?;
108 self.set_range(conf.range)?;
109 self.set_datarate(conf.datarate)?;
110
111 if conf.enable_new_acceleration_interrupt {
112 self.enable_new_accelration_interrupt()?;
113 }
114 if let Some(md_conf) = conf.motion_detection {
115 self.enable_motion_detection()?;
116 self.set_motion_detection_datarate(md_conf.datarate)?;
117 self.set_motion_detection_latch_mode(md_conf.latch_mode)?;
118 self.set_motion_detection_na_counter(md_conf.non_activity_counter)?;
119 self.set_motion_detection_wakeup_counter(md_conf.wakeup_counter)?;
120 self.set_motion_detection_threshold(md_conf.wakeup_threshold)?;
121 self.enable_motion_detection_axes(
122 md_conf.enable_x_negative,
123 md_conf.enable_x_positive,
124 md_conf.enable_y_negative,
125 md_conf.enable_y_positive,
126 md_conf.enable_z_negative,
127 md_conf.enable_z_positive,
128 )?;
129 if let Some(ip_conf) = md_conf.interrupt_pin {
130 self.set_motion_detection_interrupt_pin_polarity(ip_conf.polarity)?;
131 self.set_motion_detection_interrupt_pin_response(ip_conf.response)?;
132 }
133 }
134 self.disable_standby_mode()
135 }
136
137 fn write_register(
139 &mut self,
140 register: Register,
141 value: u8,
142 ) -> Result<(), Error<E, core::convert::Infallible>> {
143 if register.read_only() {
144 return Err(Error::WriteToReadOnly);
145 }
146
147 self.i2c
148 .write(self.address, &[register.addr(), value])
149 .map_err(Error::Bus)
150 }
151
152 fn read_register(
154 &mut self,
155 register: Register,
156 ) -> Result<u8, Error<E, core::convert::Infallible>> {
157 let mut data = [0];
158 self.i2c
159 .write_read(self.address, &[register.addr()], &mut data)
160 .map_err(Error::Bus)
161 .and(Ok(data[0]))
162 }
163
164 pub fn get_device_id(&mut self) -> Result<u8, Error<E, core::convert::Infallible>> {
166 self.read_register(Register::WHOAMI)
167 }
168
169 pub fn enable_standby_mode(&mut self) -> Result<(), Error<E, core::convert::Infallible>> {
172 self.register_clear_bits(Register::CTRL1, PC1_EN)
173 }
174
175 pub fn disable_standby_mode(&mut self) -> Result<(), Error<E, core::convert::Infallible>> {
178 self.register_set_bits(Register::CTRL1, PC1_EN)
179 }
180
181 pub fn set_mode(&mut self, mode: Mode) -> Result<(), Error<E, core::convert::Infallible>> {
185 match mode {
186 Mode::LowPower => {
187 self.register_clear_bits(Register::CTRL1, RES_EN)?;
188 }
189 Mode::HighResolution => {
190 self.register_set_bits(Register::CTRL1, RES_EN)?;
191 }
192 _ => {
193 return Err(Error::InvalidMode);
194 }
195 }
196
197 Ok(())
198 }
199
200 pub fn get_mode(&mut self) -> Result<Mode, Error<E, core::convert::Infallible>> {
202 let ctrl1 = self.read_register(Register::CTRL1)?;
203
204 let is_pc1_set = (ctrl1 >> 7) & 0x01 != 0;
205 let is_res_set = (ctrl1 >> 6) & 0x01 != 0;
206
207 let mode = match (is_pc1_set, is_res_set) {
208 (false, _) => Mode::Standby,
209 (true, false) => Mode::LowPower,
210 (true, true) => Mode::HighResolution,
211 };
212
213 Ok(mode)
214 }
215
216 pub fn set_datarate(
220 &mut self,
221 datarate: DataRate,
222 ) -> Result<(), Error<E, core::convert::Infallible>> {
223 self.modify_register(Register::DATA_CTRL, |mut data_ctrl| {
224 data_ctrl &= !ODR_MASK;
226 data_ctrl |= datarate.bits();
228
229 data_ctrl
230 })
231 }
232
233 pub fn get_datarate(&mut self) -> Result<DataRate, Error<E, core::convert::Infallible>> {
235 let data_ctrl = self.read_register(Register::DATA_CTRL)?;
236 let odr = data_ctrl & 0x0F;
237
238 DataRate::try_from(odr).map_err(|_| Error::InvalidDataRate)
239 }
240
241 pub fn set_range(&mut self, range: Range) -> Result<(), Error<E, core::convert::Infallible>> {
245 self.modify_register(Register::CTRL1, |mut ctrl1| {
246 ctrl1 &= !GSEL_MASK;
247 ctrl1 |= range.bits() << 2;
248 ctrl1
249 })
250 }
251
252 pub fn get_range(&mut self) -> Result<Range, Error<E, core::convert::Infallible>> {
254 let ctrl1 = self.read_register(Register::CTRL1)?;
255 let gsel = (ctrl1 >> 2) & 0x07;
256
257 Range::try_from(gsel).map_err(|_| Error::InvalidRange)
258 }
259
260 fn read_accel_bytes(&mut self) -> Result<[u8; 6], Error<E, core::convert::Infallible>> {
262 let mut data = [0u8; 6];
263
264 self.i2c
265 .write_read(self.address, &[Register::XOUT_L.addr() | 0x80], &mut data)
266 .map_err(Error::Bus)
267 .and(Ok(data))
268 }
269
270 pub fn enable_new_accelration_interrupt(
274 &mut self,
275 ) -> Result<(), Error<E, core::convert::Infallible>> {
276 self.register_set_bits(Register::CTRL1, DRDYE_EN)
277 }
278
279 pub fn enable_motion_detection(&mut self) -> Result<(), Error<E, core::convert::Infallible>> {
283 self.register_set_bits(Register::CTRL1, WUFE_EN)
284 }
285
286 pub fn enable_motion_detection_physical_interrupt_pin(
290 &mut self,
291 ) -> Result<(), Error<E, core::convert::Infallible>> {
292 self.register_set_bits(Register::INT_CTRL1, IEN_EN)
293 }
294
295 pub fn set_motion_detection_interrupt_pin_polarity(
299 &mut self,
300 polarity: InterruptPinPolarity,
301 ) -> Result<(), Error<E, core::convert::Infallible>> {
302 match polarity {
303 InterruptPinPolarity::ActiveHigh => self.register_set_bits(Register::INT_CTRL1, IEA_EN),
304 InterruptPinPolarity::ActiveLow => {
305 self.register_clear_bits(Register::INT_CTRL1, IEA_EN)
306 }
307 }
308 }
309
310 pub fn set_motion_detection_interrupt_pin_response(
314 &mut self,
315 response: InterruptPinResponse,
316 ) -> Result<(), Error<E, core::convert::Infallible>> {
317 match response {
318 InterruptPinResponse::Latched => self.register_clear_bits(Register::INT_CTRL1, IEL_EN),
319 InterruptPinResponse::Pulsed => self.register_set_bits(Register::INT_CTRL1, IEL_EN),
320 }
321 }
322
323 pub fn set_motion_detection_datarate(
327 &mut self,
328 datarate: MotionDetectionDataRate,
329 ) -> Result<(), Error<E, core::convert::Infallible>> {
330 self.modify_register(Register::CTRL2, |mut ctrl2| {
331 ctrl2 &= !ODRW_MASK;
332 ctrl2 |= datarate.bits();
333 ctrl2
334 })
335 }
336
337 pub fn get_motion_detection_datarate(
339 &mut self,
340 ) -> Result<MotionDetectionDataRate, Error<E, core::convert::Infallible>> {
341 let data_ctrl = self.read_register(Register::CTRL2)?;
342 let odr = data_ctrl & 0x07;
343 MotionDetectionDataRate::try_from(odr).map_err(|_| Error::InvalidDataRate)
344 }
345
346 pub fn set_motion_detection_latch_mode(
350 &mut self,
351 latch_mode: MotionDetectionLatchMode,
352 ) -> Result<(), Error<E, core::convert::Infallible>> {
353 self.modify_register(Register::INT_CTRL2, |mut int_ctrl2| {
354 int_ctrl2 &= !ULMODE_EN;
355 int_ctrl2 |= latch_mode.bits() << 7;
356 int_ctrl2
357 })
358 }
359
360 pub fn set_motion_detection_wakeup_counter(
366 &mut self,
367 wakeup_counter: u8,
368 ) -> Result<(), Error<E, core::convert::Infallible>> {
369 self.write_register(Register::WAKEUP_COUNTER, wakeup_counter)
370 }
371
372 pub fn set_motion_detection_na_counter(
378 &mut self,
379 na_counter: u8,
380 ) -> Result<(), Error<E, core::convert::Infallible>> {
381 self.write_register(Register::NA_COUNTER, na_counter)
382 }
383
384 pub fn set_motion_detection_threshold(
390 &mut self,
391 desired_threshold: u8,
392 ) -> Result<(), Error<E, core::convert::Infallible>> {
393 let upper_8_bits = (desired_threshold >> 4) as u8;
394 let lower_8_bits = (desired_threshold << 4) as u8;
395 self.write_register(Register::WAKEUP_THRESHOLD_H, upper_8_bits)?;
396 self.write_register(Register::WAKEUP_THRESHOLD_L, lower_8_bits)
397 }
398
399 pub fn get_motion_detection_axis(
401 &mut self,
402 ) -> Result<MotionDetectionAxis, Error<E, core::convert::Infallible>> {
403 let int_src2 = self.read_register(Register::INT_SOURCE2)?;
404 MotionDetectionAxis::try_from(int_src2).map_err(|_| Error::InvalidAxis)
405 }
406 pub fn is_motion_detected(&mut self) -> Result<bool, Error<E, core::convert::Infallible>> {
408 let int_src1 = self.read_register(Register::INT_SOURCE1)?;
409 let wufs = (int_src1 >> 1) & 0x01 != 0;
410 Ok(wufs)
411 }
412
413 pub fn is_acceleration_data_ready(
415 &mut self,
416 ) -> Result<bool, Error<E, core::convert::Infallible>> {
417 let int_src1 = self.read_register(Register::INT_SOURCE1)?;
418 let drdy = (int_src1 >> 4) & 0x01 != 0;
419 Ok(drdy)
420 }
421
422 pub fn enable_motion_detection_axes(
426 &mut self,
427 x_negative: bool,
428 x_positive: bool,
429 y_negative: bool,
430 y_positive: bool,
431 z_negative: bool,
432 z_positive: bool,
433 ) -> Result<(), Error<E, core::convert::Infallible>> {
434 self.modify_register(Register::INT_CTRL2, |mut int_ctrl2| {
435 int_ctrl2 &= !WUE_MASK;
436 int_ctrl2 |= if x_negative {
437 MotionDetectionAxis::X_Negative.bits()
438 } else {
439 0
440 };
441 int_ctrl2 |= if x_positive {
442 MotionDetectionAxis::X_Positive.bits()
443 } else {
444 0
445 };
446 int_ctrl2 |= if y_negative {
447 MotionDetectionAxis::Y_Negative.bits()
448 } else {
449 0
450 };
451 int_ctrl2 |= if y_positive {
452 MotionDetectionAxis::Y_Positive.bits()
453 } else {
454 0
455 };
456 int_ctrl2 |= if z_negative {
457 MotionDetectionAxis::Z_Negative.bits()
458 } else {
459 0
460 };
461 int_ctrl2 |= if z_positive {
462 MotionDetectionAxis::Z_Positive.bits()
463 } else {
464 0
465 };
466 int_ctrl2
467 })
468 }
469
470 pub fn clear_motion_detection_lathced_info(
473 &mut self,
474 ) -> Result<(), Error<E, core::convert::Infallible>> {
475 self.read_register(Register::INT_REL)?;
476 Ok(())
477 }
478
479 fn modify_register<F>(
483 &mut self,
484 register: Register,
485 f: F,
486 ) -> Result<(), Error<E, core::convert::Infallible>>
487 where
488 F: FnOnce(u8) -> u8,
489 {
490 let value = self.read_register(register)?;
491
492 self.write_register(register, f(value))
493 }
494
495 pub fn register_clear_bits(
501 &mut self,
502 reg: Register,
503 bits: u8,
504 ) -> Result<(), Error<E, core::convert::Infallible>> {
505 self.modify_register(reg, |v| v & !bits)
506 }
507
508 pub fn register_set_bits(
514 &mut self,
515 reg: Register,
516 bits: u8,
517 ) -> Result<(), Error<E, core::convert::Infallible>> {
518 self.modify_register(reg, |v| v | bits)
519 }
520}
521
522impl<I2C, E> RawAccelerometer<I16x3> for Kxtj3<I2C>
523where
524 I2C: I2c<Error = E>,
525 E: core::fmt::Debug,
526{
527 type Error = Error<E, core::convert::Infallible>;
528
529 fn accel_raw(&mut self) -> Result<I16x3, AccelerometerError<Self::Error>> {
530 let accel_bytes = self.read_accel_bytes()?;
531
532 let x = i16::from_le_bytes(accel_bytes[0..2].try_into().unwrap());
533 let y = i16::from_le_bytes(accel_bytes[2..4].try_into().unwrap());
534 let z = i16::from_le_bytes(accel_bytes[4..6].try_into().unwrap());
535
536 Ok(I16x3::new(x, y, z))
537 }
538}
539
540impl<I2C, E> Accelerometer for Kxtj3<I2C>
541where
542 I2C: I2c<Error = E>,
543 E: core::fmt::Debug,
544{
545 type Error = Error<E, core::convert::Infallible>;
546
547 fn accel_norm(&mut self) -> Result<F32x3, AccelerometerError<Self::Error>> {
549 let mode = self.get_mode()?;
550 let range = self.get_range()?;
551
552 let (scale, shift) = match (mode, range) {
561 (Mode::HighResolution, Range::G8_14Bit) => (0.001, 2),
563 (Mode::HighResolution, Range::G16_14Bit) => (0.002, 2),
564 (Mode::HighResolution, Range::G2) => (0.001, 4),
566 (Mode::HighResolution, Range::G4) => (0.002, 4),
567 (Mode::HighResolution, Range::G8) => (0.004, 4),
568 (Mode::HighResolution, Range::G16_1)
569 | (Mode::HighResolution, Range::G16_2)
570 | (Mode::HighResolution, Range::G16_3) => (0.008, 4),
571
572 (Mode::LowPower, Range::G2) => (0.015, 8),
574 (Mode::LowPower, Range::G4) => (0.031, 8),
575 (Mode::LowPower, Range::G8) => (0.062, 8),
576 (Mode::LowPower, Range::G16_1)
577 | (Mode::LowPower, Range::G16_2)
578 | (Mode::LowPower, Range::G16_3) => (0.125, 8),
579
580 _ => (0.0, 0),
581 };
582
583 let acc_raw = self.accel_raw()?;
584 let x = (acc_raw.x >> shift) as f32 * scale;
585 let y = (acc_raw.y >> shift) as f32 * scale;
586 let z = (acc_raw.z >> shift) as f32 * scale;
587
588 Ok(F32x3::new(x, y, z))
589 }
590
591 fn sample_rate(&mut self) -> Result<f32, AccelerometerError<Self::Error>> {
593 Ok(self.get_datarate()?.sample_rate())
594 }
595}