1#![no_std]
115#![allow(clippy::too_many_arguments)]
116
117pub mod reg;
118mod reg_helper;
119
120use core::fmt::{Debug, Display};
121use core::result::Result;
122
123pub use reg_helper::{ErrorReg, RegisterBus};
124
125use embedded_hal::digital::StatefulOutputPin;
126use embedded_hal::{i2c, spi};
127
128pub const G: f32 = 9.80665; pub const MAX_BUF_LEN: usize = 16;
137
138#[derive(Debug, Clone, Copy, PartialEq)]
140#[repr(u8)]
141pub enum Res {
142 Bit10 = 0,
143 Full = 1,
144}
145
146#[derive(Debug, Clone, Copy, PartialEq)]
148#[repr(u8)]
149pub enum Justify {
150 Right = 0,
151 Left = 1,
152}
153
154#[derive(Debug, Clone, Copy, PartialEq)]
156#[repr(u8)]
157pub enum Range {
158 R2G = 0b_00,
159 R4G = 0b_01,
160 R8G = 0b_10,
161 R16G = 0b_11,
162}
163
164#[derive(Debug, Clone, Copy, PartialEq)]
166#[repr(u16)]
167pub enum Unit {
168 U2G = 256,
169 U4G = 128,
170 U8G = 64,
171 U16G = 32,
172}
173
174#[derive(Debug, Clone, Copy, PartialEq)]
176#[repr(u8)]
177pub enum Wakeup {
178 Hz8 = 0b_00,
179 Hz4 = 0b_01,
180 Hz2 = 0b_10,
181 Hz1 = 0b_11,
182}
183
184#[derive(Debug, Clone, Copy, PartialEq)]
186#[repr(u8)]
187pub enum FifoMode {
188 Bypass = 0b_00,
189 Fifo = 0b_01,
190 Stream = 0b_10,
191 Trigger = 0b_11,
192}
193
194#[derive(Debug, Clone, Copy, PartialEq)]
196#[repr(u8)]
197pub enum Rate {
198 R3200 = 0b_1111,
199 R1600 = 0b_1110,
200 R800 = 0b_1101,
201 R400 = 0b_1100,
202 R200 = 0b_1011,
203 R100 = 0b_1010,
204 R50 = 0b_1001,
205 R25 = 0b_1000,
206 R12_5 = 0b_0111,
207 R6_25 = 0b_0110,
208 R3_13 = 0b_0101,
209 R1_56 = 0b_0100,
210 R0_78 = 0b_0011,
211 R0_39 = 0b_0010,
212 R0_20 = 0b_0001,
213 R0_10 = 0b_0000,
214}
215
216#[derive(Debug, Clone, Copy, PartialEq)]
218pub struct IntSource {
219 pub data_ready: bool,
220 pub single_tap: bool,
221 pub double_tap: bool,
222 pub activity: bool,
223 pub inactivity: bool,
224 pub free_fall: bool,
225 pub watermark: bool,
226 pub overrun: bool,
227}
228
229pub type AdxlResult<T, B> = Result<T, Error<ErrorReg<<B as RegisterBus>::Error>>>;
230
231pub struct AdxlBusI2c<I2C> {
236 pub i2c: I2C,
237 pub addr: u8,
238}
239
240pub struct AdxlBusSpi<SPI, CS> {
241 pub spi: SPI,
242 pub spi_cs: CS,
243}
244
245pub struct Adxl345<B> {
246 bus: B,
247 res: Res,
248 justify: Justify,
249 range: Range,
250 unit: Unit,
251}
252
253impl<B: RegisterBus> Adxl345<B> {
254 pub fn new(bus: B) -> Self {
255 Self {
256 bus,
257 res: Res::Full,
258 justify: Justify::Right,
259 range: Range::R16G,
260 unit: Unit::U2G,
261 }
262 }
263
264 pub fn reset(&mut self) -> AdxlResult<(), B> {
268 self.write_reg_addr_raw(0x2D, &[0x00])?;
270 self.write_reg_addr_raw(0x1D, &[0x00])?;
272
273 for reg in 0x21..=0x2B {
275 self.write_reg_addr_raw(reg, &[0x00])?;
276 }
277
278 self.write_reg_addr_raw(0x2C, &[0x0A])?;
280
281 for reg in 0x2E..=0x31 {
283 self.write_reg_addr_raw(reg, &[0x00])?;
284 }
285
286 self.write_reg_addr_raw(0x38, &[0x00])?;
288 Ok(())
289 }
290
291 pub fn init_defaults(&mut self) -> AdxlResult<(), B> {
293 let id = reg::DEVID.read(&mut self.bus)?;
295 if reg::ADXL_DEVICE_ID != id as u8 {
296 return Err(Error::Init);
297 }
298
299 self.reset()?;
300
301 self.set_fifo_ctl(FifoMode::Stream, false, 24)?;
303
304 self.set_rate(Rate::R800)?;
306
307 self.set_data_format(Res::Full, Justify::Right, Range::R16G)?;
309
310 self.set_measure(true)?;
312
313 Ok(())
314 }
315
316 pub fn read_reg_addr_raw(&mut self, reg_addr: u8, buf: &mut [u8]) -> AdxlResult<(), B> {
320 self.bus
321 .read_register(reg_addr, buf)
322 .map_err(ErrorReg::Bus)?;
323 Ok(())
324 }
325
326 pub fn write_reg_addr_raw(&mut self, reg_addr: u8, buf: &[u8]) -> AdxlResult<(), B> {
328 self.bus
329 .write_register(reg_addr, buf)
330 .map_err(ErrorReg::Bus)?;
331 Ok(())
332 }
333
334 pub fn read_device_id(&mut self) -> AdxlResult<u8, B> {
338 Ok(reg::DEVID.read(&mut self.bus)? as u8)
339 }
340
341 pub fn read_fifo_status_trig(&mut self) -> AdxlResult<u8, B> {
343 Ok(reg::FIFO_STATUS.read_field(&mut self.bus, reg::FL_FS::FIFO_TRIG)? as u8)
344 }
345
346 pub fn read_fifo_status_entries(&mut self) -> AdxlResult<u8, B> {
348 Ok(reg::FIFO_STATUS.read_field(&mut self.bus, reg::FL_FS::ENTRIES)? as u8)
349 }
350
351 #[inline]
353 pub fn read_axis_raw_buf(&mut self) -> AdxlResult<[u8; 6], B> {
354 let mut buf = [0_u8; 6];
355 reg::DATAX0.read_raw_buffer(&mut self.bus, &mut buf)?;
356
357 Ok(buf)
358 }
359
360 pub fn read_axis_lsb_units(&mut self) -> AdxlResult<(i16, i16, i16), B> {
362 let buf = self.read_axis_raw_buf()?;
364
365 let mut x = i16::from_le_bytes([buf[0], buf[1]]);
367 let mut y = i16::from_le_bytes([buf[2], buf[3]]);
368 let mut z = i16::from_le_bytes([buf[4], buf[5]]);
369
370 if self.justify == Justify::Left {
372 let shift: u8 = {
373 match (self.res, self.range) {
374 (_, Range::R2G) => 6,
375 (Res::Bit10, _) => 6,
376 (Res::Full, Range::R4G) => 5,
377 (Res::Full, Range::R8G) => 4,
378 (Res::Full, Range::R16G) => 3,
379 }
380 };
381
382 x >>= shift;
383 y >>= shift;
384 z >>= shift;
385 }
386
387 Ok((x, y, z))
388 }
389
390 pub fn read_axis(&mut self) -> AdxlResult<(f32, f32, f32), B> {
392 let data = self.read_axis_lsb_units()?;
393
394 Ok(self.convert_lsb_to_accel(data))
396 }
397
398 #[inline]
400 pub fn convert_lsb_to_accel(&self, data: (i16, i16, i16)) -> (f32, f32, f32) {
401 (
403 data.0 as f32 / (self.unit as u16 as f32) * G,
404 data.1 as f32 / (self.unit as u16 as f32) * G,
405 data.2 as f32 / (self.unit as u16 as f32) * G,
406 )
407 }
408
409 pub fn is_asleep(&mut self) -> AdxlResult<bool, B> {
411 Ok(reg::ACT_TAP_STATUS.read_field(&mut self.bus, reg::FL_ATS::ASLEEP)? as u8 != 0)
412 }
413
414 pub fn read_act_source_status(&mut self) -> AdxlResult<(bool, bool, bool), B> {
416 let mut buf = [0_u32; 3];
417
418 reg::ACT_TAP_STATUS.read_multiple_fields(
419 &mut self.bus,
420 &[
421 reg::FL_ATS::ACT_X_SRC,
422 reg::FL_ATS::ACT_Y_SRC,
423 reg::FL_ATS::ACT_Z_SRC,
424 ],
425 &mut buf,
426 )?;
427
428 let (x, y, z) = (buf[0] != 0, buf[1] != 0, buf[2] != 0);
429
430 Ok((x, y, z))
431 }
432
433 pub fn read_tap_source_status(&mut self) -> AdxlResult<(bool, bool, bool), B> {
435 let mut buf = [0_u32; 3];
436
437 reg::ACT_TAP_STATUS.read_multiple_fields(
438 &mut self.bus,
439 &[
440 reg::FL_ATS::TAP_X_SRC,
441 reg::FL_ATS::TAP_Y_SRC,
442 reg::FL_ATS::TAP_Z_SRC,
443 ],
444 &mut buf,
445 )?;
446
447 let (x, y, z) = (buf[0] != 0, buf[1] != 0, buf[2] != 0);
448
449 Ok((x, y, z))
450 }
451
452 #[rustfmt::skip]
453 pub fn read_int_source(&mut self) -> AdxlResult<IntSource, B> {
458 let value = reg::INT_SOURCE.read(&mut self.bus)? as u8;
459
460 let data_ready = (value & 0b_1000_0000) != 0;
461 let single_tap = (value & 0b_0100_0000) != 0;
462 let double_tap = (value & 0b_0010_0000) != 0;
463 let activity = (value & 0b_0001_0000) != 0;
464 let inactivity = (value & 0b_0000_1000) != 0;
465 let free_fall = (value & 0b_0000_0100) != 0;
466 let watermark = (value & 0b_0000_0010) != 0;
467 let overrun = (value & 0b_0000_0001) != 0;
468
469 Ok(IntSource {
470 data_ready,
471 single_tap,
472 double_tap,
473 activity,
474 inactivity,
475 free_fall,
476 watermark,
477 overrun,
478 })
479 }
480
481 pub fn set_measure(&mut self, on: bool) -> AdxlResult<(), B> {
485 reg::POWER_CTL.write_field(&mut self.bus, reg::FL_PC::MEASURE, on as u32)?;
486 Ok(())
487 }
488
489 pub fn set_power_ctl(
492 &mut self,
493 link: bool,
494 auto_sleep: bool,
495 measure: bool,
496 sleep: bool,
497 wakeup: Wakeup,
498 ) -> AdxlResult<(), B> {
499 let value = (link as u8) << 5
500 | (auto_sleep as u8) << 4
501 | (measure as u8) << 3
502 | (sleep as u8) << 2
503 | (wakeup as u8);
504
505 reg::POWER_CTL.write(&mut self.bus, value as u32)?;
506 Ok(())
507 }
508
509 pub fn set_low_power(&mut self, on: bool) -> AdxlResult<(), B> {
511 reg::BW_RATE.write_field(&mut self.bus, reg::FL_BR::LOW_POWER, on as u32)?;
512 Ok(())
513 }
514
515 pub fn set_rate(&mut self, rate: Rate) -> AdxlResult<(), B> {
517 reg::BW_RATE.write_field(&mut self.bus, reg::FL_BR::RATE, rate as u32)?;
518 Ok(())
519 }
520
521 pub fn set_self_test(&mut self, on: bool) -> AdxlResult<(), B> {
523 reg::DATA_FORMAT.write_field(&mut self.bus, reg::FL_DF::SELF_TEST, on as u32)?;
524 Ok(())
525 }
526
527 pub fn set_data_format(
529 &mut self,
530 res: Res,
531 justify: Justify,
532 range: Range,
533 ) -> AdxlResult<(), B> {
534 reg::DATA_FORMAT.write_multiple_fields(&mut self.bus, &[
536 (reg::FL_DF::FULL_RES, res as u32),
537 (reg::FL_DF::JUSTIFY, justify as u32),
538 (reg::FL_DF::RANGE, range as u32),
539 ])?;
540
541 self.res = res;
542 self.justify = justify;
543 self.range = range;
544
545 self.unit = {
546 match (res, range) {
547 (Res::Full, _) => Unit::U2G,
548 (Res::Bit10, Range::R2G) => Unit::U2G,
549 (Res::Bit10, Range::R4G) => Unit::U4G,
550 (Res::Bit10, Range::R8G) => Unit::U8G,
551 (Res::Bit10, Range::R16G) => Unit::U16G,
552 }
553 };
554
555 Ok(())
556 }
557
558 pub fn set_spi_wire_mode(&mut self, three_wire_mode: bool) -> AdxlResult<(), B> {
560 reg::DATA_FORMAT.write_field(&mut self.bus, reg::FL_DF::SPI, three_wire_mode as u32)?;
561 Ok(())
562 }
563
564 pub fn set_fifo_ctl(
566 &mut self,
567 fifo_mode: FifoMode,
568 trigger: bool,
569 watermark_samples_num: u8,
570 ) -> AdxlResult<(), B> {
571 let watermark_samples_num = watermark_samples_num.min(31);
572
573 reg::FIFO_CTL.write_multiple_fields(&mut self.bus, &[
574 (reg::FL_FC::FIFO_MODE, fifo_mode as u32),
575 (reg::FL_FC::TRIGGER, trigger as u32),
576 (reg::FL_FC::SAMPLES, watermark_samples_num as u32),
577 ])?;
578
579 Ok(())
580 }
581
582 pub fn calibrate_axis_offsets(&mut self) -> AdxlResult<(i8, i8, i8), B> {
588 self.set_measure(false)?;
590 self.clear_axis_offsets()?;
591 self.set_fifo_ctl(FifoMode::Stream, false, 24)?;
592 self.set_rate(Rate::R400)?;
593 self.set_data_format(Res::Full, Justify::Right, Range::R16G)?;
594
595 self.set_measure(true)?;
597
598 let mut buf = [(0_i16, 0_i16, 0_i16); 32];
600
601 for i in 0..32 {
603 buf[i] = self.read_axis_lsb_units()?;
604 }
605
606 loop {
608 match self.read_fifo_status_entries() {
609 Ok(s) if s >= 31 => {
610 for el in buf.iter_mut() {
612 *el = self.read_axis_lsb_units()?;
613 }
614 break;
615 }
616 Err(e) => {
617 return Err(e);
618 }
619 _ => {
620 continue;
621 }
622 }
623 }
624
625 let sum_x: i32 = buf.iter().map(|&(x, ..)| x as i32).sum();
627 let sum_y: i32 = buf.iter().map(|&(_, y, _)| y as i32).sum();
628 let sum_z: i32 = buf.iter().map(|&(_, _, z)| z as i32).sum();
629
630 let n = buf.len() as i32;
631 let m_x = (sum_x + n / 2) / n; let m_y = (sum_y + n / 2) / n;
633 let m_z = (sum_z + n / 2) / n - self.unit as i32; let x_off = -(m_x / 4) as i8;
636 let y_off = -(m_y / 4) as i8;
637 let z_off = -(m_z / 4) as i8;
638
639 self.set_axis_offsets(x_off, y_off, z_off)?;
641
642 self.init_defaults()?;
644
645 Ok((x_off, y_off, z_off))
646 }
647
648 #[inline]
655 pub fn set_axis_offsets(&mut self, x: i8, y: i8, z: i8) -> AdxlResult<(), B> {
656 reg::OFSX.write(&mut self.bus, x as u32)?;
657 reg::OFSY.write(&mut self.bus, y as u32)?;
658 reg::OFSZ.write(&mut self.bus, z as u32)?;
659 Ok(())
660 }
661
662 #[inline]
664 pub fn clear_axis_offsets(&mut self) -> AdxlResult<(), B> {
665 self.set_axis_offsets(0, 0, 0)?;
666 Ok(())
667 }
668
669 pub fn set_thresh_tap(&mut self, val: u8) -> AdxlResult<(), B> {
673 reg::THRESH_TAP.write(&mut self.bus, val as u32)?;
674 Ok(())
675 }
676
677 pub fn set_duration(&mut self, val: u8) -> AdxlResult<(), B> {
683 reg::DUR.write(&mut self.bus, val as u32)?;
684 Ok(())
685 }
686
687 pub fn set_latent(&mut self, val: u8) -> AdxlResult<(), B> {
693 reg::LATENT.write(&mut self.bus, val as u32)?;
694 Ok(())
695 }
696
697 pub fn set_window(&mut self, val: u8) -> AdxlResult<(), B> {
704 reg::WINDOW.write(&mut self.bus, val as u32)?;
705 Ok(())
706 }
707
708 pub fn set_thresh_act(&mut self, val: u8) -> AdxlResult<(), B> {
714 reg::THRESH_ACT.write(&mut self.bus, val as u32)?;
715 Ok(())
716 }
717
718 pub fn set_thresh_inact(&mut self, val: u8) -> AdxlResult<(), B> {
724 reg::THRESH_INACT.write(&mut self.bus, val as u32)?;
725 Ok(())
726 }
727
728 pub fn set_time_inact(&mut self, val: u8) -> AdxlResult<(), B> {
737 reg::TIME_INACT.write(&mut self.bus, val as u32)?;
738 Ok(())
739 }
740
741 pub fn set_act_inact_ctl(
749 &mut self,
750 act_acdc: bool,
751 act_x_en: bool,
752 act_y_en: bool,
753 act_z_en: bool,
754 inact_acdc: bool,
755 inact_x_en: bool,
756 inact_y_en: bool,
757 inact_z_en: bool,
758 ) -> AdxlResult<(), B> {
759 let value = (act_acdc as u8) << 7
760 | (act_x_en as u8) << 6
761 | (act_y_en as u8) << 5
762 | (act_z_en as u8) << 4
763 | (inact_acdc as u8) << 3
764 | (inact_x_en as u8) << 2
765 | (inact_y_en as u8) << 1
766 | (inact_z_en as u8);
767
768 reg::ACT_INACT_CTL.write(&mut self.bus, value as u32)?;
769
770 Ok(())
771 }
772
773 pub fn set_thresh_ff(&mut self, val: u8) -> AdxlResult<(), B> {
779 reg::THRESH_FF.write(&mut self.bus, val as u32)?;
780 Ok(())
781 }
782
783 pub fn set_time_ff(&mut self, val: u8) -> AdxlResult<(), B> {
788 reg::TIME_FF.write(&mut self.bus, val as u32)?;
789 Ok(())
790 }
791
792 pub fn set_tap_supress(&mut self, on: bool) -> AdxlResult<(), B> {
796 reg::TAP_AXES.write_field(&mut self.bus, reg::FL_TA::SUPPRESS, on as u32)?;
797 Ok(())
798 }
799
800 pub fn set_tap_axes(&mut self, tap_x: bool, tap_y: bool, tap_z: bool) -> AdxlResult<(), B> {
805 reg::TAP_AXES.write_multiple_fields(&mut self.bus, &[
806 (reg::FL_TA::TAP_X_EN, tap_x as u32),
807 (reg::FL_TA::TAP_Y_EN, tap_y as u32),
808 (reg::FL_TA::TAP_Z_EN, tap_z as u32),
809 ])?;
810
811 Ok(())
812 }
813
814 #[inline]
815 pub fn set_int_enable_direct(&mut self, value: u8) -> AdxlResult<(), B> {
819 reg::INT_ENABLE.write(&mut self.bus, value as u32)?;
820
821 Ok(())
822 }
823
824 pub fn set_int_enable(
828 &mut self,
829 data_ready: bool,
830 single_tap: bool,
831 double_tap: bool,
832 activity: bool,
833 inactivity: bool,
834 free_fall: bool,
835 watermark: bool,
836 overrun: bool,
837 ) -> AdxlResult<(), B> {
838 let value = (data_ready as u8) << 7
839 | (single_tap as u8) << 6
840 | (double_tap as u8) << 5
841 | (activity as u8) << 4
842 | (inactivity as u8) << 3
843 | (free_fall as u8) << 2
844 | (watermark as u8) << 1
845 | (overrun as u8);
846
847 reg::INT_ENABLE.write(&mut self.bus, value as u32)?;
848
849 Ok(())
850 }
851
852 #[inline]
853 pub fn set_int_map_direct(&mut self, value: u8) -> AdxlResult<(), B> {
858 reg::INT_MAP.write(&mut self.bus, value as u32)?;
859
860 Ok(())
861 }
862
863 pub fn set_int_map(
868 &mut self,
869 data_ready: bool,
870 single_tap: bool,
871 double_tap: bool,
872 activity: bool,
873 inactivity: bool,
874 free_fall: bool,
875 watermark: bool,
876 overrun: bool,
877 ) -> AdxlResult<(), B> {
878 let value = (data_ready as u8) << 7
879 | (single_tap as u8) << 6
880 | (double_tap as u8) << 5
881 | (activity as u8) << 4
882 | (inactivity as u8) << 3
883 | (free_fall as u8) << 2
884 | (watermark as u8) << 1
885 | (overrun as u8);
886
887 reg::INT_MAP.write(&mut self.bus, value as u32)?;
888
889 Ok(())
890 }
891}
892
893#[derive(Debug, Clone, Copy, PartialEq, Eq)]
898pub enum Error<E: Debug> {
899 Init,
900 Config,
901 BufferLen,
902 Inner(E),
903}
904
905impl<E: Debug + Display> Display for Error<E> {
906 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
907 match &self {
908 Error::Init => write!(f, "device id mismatch"),
909 Error::Config => write!(f, "configuration error"),
910 Error::BufferLen => write!(f, "buffer len error"),
911 Error::Inner(e) => Display::fmt(e, f),
912 }
913 }
914}
915
916impl<E: Debug> From<E> for Error<E> {
917 fn from(error: E) -> Self {
918 Error::Inner(error)
919 }
920}
921
922impl<I2C: i2c::I2c> RegisterBus for AdxlBusI2c<I2C> {
930 type Error = I2C::Error;
931
932 fn read_register(&mut self, reg_addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
933 self.i2c.write_read(self.addr, &[reg_addr], buffer)
934 }
935
936 fn write_register(&mut self, reg_addr: u8, data: &[u8]) -> Result<(), Self::Error> {
937 assert!(data.len() <= MAX_BUF_LEN, "buffer too large");
938
939 let mut buf = [0u8; MAX_BUF_LEN + 1];
940 buf[0] = reg_addr;
941 buf[1..data.len() + 1].copy_from_slice(data);
942
943 self.i2c.write(self.addr, &buf[..data.len() + 1])
944 }
945}
946
947impl<SPI: spi::SpiBus, CS: StatefulOutputPin> RegisterBus for AdxlBusSpi<SPI, CS> {
951 type Error = SPI::Error;
952
953 fn read_register(&mut self, reg_addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
954 assert!(buffer.len() <= MAX_BUF_LEN, "buffer too large");
955
956 let addr_byte = if buffer.len() > 1 {
957 reg_addr | 0xC0 }
959 else {
960 reg_addr | 0x80 };
962
963 let mut temp_buf = [0u8; MAX_BUF_LEN + 1];
965
966 self.spi_cs.set_low().expect("SPI CS pin");
967 let result = self
968 .spi
969 .transfer(&mut temp_buf[..buffer.len() + 1], &[addr_byte]);
970 self.spi_cs.set_high().expect("SPI CS pin");
971
972 buffer.copy_from_slice(&temp_buf[1..buffer.len() + 1]);
974
975 result
976 }
977
978 fn write_register(&mut self, reg_addr: u8, data: &[u8]) -> Result<(), Self::Error> {
979 assert!(data.len() <= MAX_BUF_LEN, "buffer too large");
980
981 let addr_byte = if data.len() > 1 {
982 reg_addr | 0x40 }
984 else {
985 reg_addr };
987
988 let mut buf = [0u8; MAX_BUF_LEN + 1];
990 buf[0] = addr_byte;
991 buf[1..data.len() + 1].copy_from_slice(data);
992
993 self.spi_cs.set_low().expect("SPI CS pin");
994 let result = self.spi.write(&buf[..data.len() + 1]);
995 self.spi_cs.set_high().expect("SPI CS pin");
996
997 result
998 }
999}