1#![no_std]
12#![allow(async_fn_in_trait)]
13
14use core::convert::{TryFrom, TryInto};
15use core::fmt::Debug;
16
17use accelerometer::vector::{F32x3, I16x3};
18use embedded_hal_async::i2c::I2c;
19use embedded_hal_async::spi::{self, SpiDevice};
20
21mod interrupts;
22mod register;
23
24use interrupts::*;
25pub use interrupts::{
26 Detect4D, Interrupt1, Interrupt2, InterruptConfig, InterruptMode, InterruptSource, IrqPin,
27 IrqPin1Config, IrqPin2Config, LatchInterruptRequest,
28};
29
30use register::*;
31pub use register::{
32 DataRate, DataStatus, Duration, FifoMode, FifoStatus, Mode, Range, Register, SlaveAddr,
33 Threshold,
34};
35
36#[derive(Debug)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40pub enum Error<BusError> {
41 Bus(BusError),
43
44 InvalidDataRate,
46
47 InvalidMode,
49
50 InvalidRange,
52
53 WriteToReadOnly,
55
56 WrongAddress,
58}
59
60pub struct Lis3dh<CORE> {
62 core: CORE,
63}
64
65impl<I2C, E> Lis3dh<Lis3dhI2C<I2C>>
66where
67 I2C: I2c<Error = E>,
68{
69 pub async fn new_i2c(i2c: I2C, address: SlaveAddr) -> Result<Self, Error<E>> {
72 Self::new_i2c_with_config(i2c, address, Configuration::default()).await
73 }
74
75 pub async fn new_i2c_without_config(i2c: I2C, address: SlaveAddr) -> Self {
79 let core = Lis3dhI2C {
80 i2c,
81 address: address.addr(),
82 };
83
84 Lis3dh { core }
85 }
86
87 pub async fn new_i2c_with_config(
88 i2c: I2C,
89 address: SlaveAddr,
90 config: Configuration,
91 ) -> Result<Self, Error<E>> {
92 let core = Lis3dhI2C {
93 i2c,
94 address: address.addr(),
95 };
96
97 let mut lis3dh = Lis3dh { core };
98
99 lis3dh.configure(config).await?;
100
101 Ok(lis3dh)
102 }
103}
104
105impl<SPI, ESPI> Lis3dh<Lis3dhSPI<SPI>>
106where
107 SPI: SpiDevice<Error = ESPI>,
108{
109 pub async fn new_spi(spi: SPI) -> Result<Self, Error<ESPI>> {
111 Self::new_spi_with_config(spi, Configuration::default()).await
112 }
113
114 pub async fn new_spi_without_config(spi: SPI) -> Self {
118 let core = Lis3dhSPI { spi };
119
120 Lis3dh { core }
121 }
122
123 pub async fn new_spi_with_config(spi: SPI, config: Configuration) -> Result<Self, Error<ESPI>> {
124 let core = Lis3dhSPI { spi };
125
126 let mut lis3dh = Lis3dh { core };
127
128 lis3dh.configure(config).await?;
129
130 Ok(lis3dh)
131 }
132}
133
134impl<CORE> Lis3dh<CORE>
135where
136 CORE: Lis3dhCore,
137{
138 pub async fn configure(&mut self, conf: Configuration) -> Result<(), Error<CORE::BusError>> {
140 if self.get_device_id().await? != DEVICE_ID {
141 return Err(Error::WrongAddress);
142 }
143
144 if conf.block_data_update || conf.enable_temperature {
145 self.write_register(Register::CTRL4, BDU).await?;
147 }
148
149 self.set_mode(conf.mode).await?;
150
151 self.set_datarate(conf.datarate).await?;
152
153 self.enable_axis((conf.enable_x_axis, conf.enable_y_axis, conf.enable_z_axis))
154 .await?;
155
156 if conf.enable_temperature {
157 self.enable_temp(true).await?;
158 }
159
160 self.write_register(Register::TEMP_CFG, ADC_EN).await
162 }
163
164 pub async fn get_device_id(&mut self) -> Result<u8, Error<CORE::BusError>> {
166 self.read_register(Register::WHOAMI).await
167 }
168
169 async fn enable_axis(
172 &mut self,
173 (x, y, z): (bool, bool, bool),
174 ) -> Result<(), Error<CORE::BusError>> {
175 self.modify_register(Register::CTRL1, |mut ctrl1| {
176 ctrl1 &= !(X_EN | Y_EN | Z_EN); ctrl1 |= if x { X_EN } else { 0 };
179 ctrl1 |= if y { Y_EN } else { 0 };
180 ctrl1 |= if z { Z_EN } else { 0 };
181
182 ctrl1
183 })
184 .await
185 }
186
187 pub async fn set_mode(&mut self, mode: Mode) -> Result<(), Error<CORE::BusError>> {
202 match mode {
203 Mode::LowPower => {
204 self.register_set_bits(Register::CTRL1, LP_EN).await?;
205 self.register_clear_bits(Register::CTRL4, HR).await?;
206 }
207 Mode::Normal => {
208 self.register_clear_bits(Register::CTRL1, LP_EN).await?;
209 self.register_clear_bits(Register::CTRL4, HR).await?;
210 }
211 Mode::HighResolution => {
212 self.register_clear_bits(Register::CTRL1, LP_EN).await?;
213 self.register_set_bits(Register::CTRL4, HR).await?;
214 }
215 }
216
217 Ok(())
218 }
219
220 pub async fn get_mode(&mut self) -> Result<Mode, Error<CORE::BusError>> {
222 let ctrl1 = self.read_register(Register::CTRL1).await?;
223 let ctrl4 = self.read_register(Register::CTRL4).await?;
224
225 let is_lp_set = (ctrl1 >> 3) & 0x01 != 0;
226 let is_hr_set = (ctrl4 >> 3) & 0x01 != 0;
227
228 let mode = match (is_lp_set, is_hr_set) {
229 (true, false) => Mode::LowPower,
230 (false, false) => Mode::Normal,
231 (false, true) => Mode::HighResolution,
232 _ => return Err(Error::InvalidMode),
233 };
234
235 Ok(mode)
236 }
237
238 pub async fn set_datarate(&mut self, datarate: DataRate) -> Result<(), Error<CORE::BusError>> {
240 self.modify_register(Register::CTRL1, |mut ctrl1| {
241 ctrl1 &= !ODR_MASK;
243 ctrl1 |= datarate.bits() << 4;
245
246 ctrl1
247 })
248 .await
249 }
250
251 pub async fn get_datarate(&mut self) -> Result<DataRate, Error<CORE::BusError>> {
253 let ctrl1 = self.read_register(Register::CTRL1).await?;
254 let odr = (ctrl1 >> 4) & 0x0F;
255
256 DataRate::try_from(odr).map_err(|_| Error::InvalidDataRate)
257 }
258
259 pub async fn set_range(&mut self, range: Range) -> Result<(), Error<CORE::BusError>> {
261 self.modify_register(Register::CTRL4, |mut ctrl4| {
262 ctrl4 &= !FS_MASK;
264 ctrl4 |= range.bits() << 4;
266
267 ctrl4
268 })
269 .await
270 }
271
272 pub async fn get_range(&mut self) -> Result<Range, Error<CORE::BusError>> {
274 let ctrl4 = self.read_register(Register::CTRL4).await?;
275 let fs = (ctrl4 >> 4) & 0b0011;
276
277 Range::try_from(fs).map_err(|_| Error::InvalidRange)
278 }
279
280 pub async fn set_ref(&mut self, reference: u8) -> Result<(), Error<CORE::BusError>> {
282 self.write_register(Register::REFERENCE, reference).await
283 }
284
285 pub async fn get_ref(&mut self) -> Result<u8, Error<CORE::BusError>> {
287 self.read_register(Register::REFERENCE).await
288 }
289
290 pub async fn get_status(&mut self) -> Result<DataStatus, Error<CORE::BusError>> {
292 let stat = self.read_register(Register::STATUS).await?;
293
294 Ok(DataStatus {
295 zyxor: (stat & ZYXOR) != 0,
296 xyzor: ((stat & XOR) != 0, (stat & YOR) != 0, (stat & ZOR) != 0),
297 zyxda: (stat & ZYXDA) != 0,
298 xyzda: ((stat & XDA) != 0, (stat & YDA) != 0, (stat & ZDA) != 0),
299 })
300 }
301
302 pub async fn is_data_ready(&mut self) -> Result<bool, Error<CORE::BusError>> {
306 let value = self.get_status().await?;
307
308 Ok(value.zyxda)
309 }
310
311 pub async fn enable_temp(&mut self, enable: bool) -> Result<(), Error<CORE::BusError>> {
314 self.register_xset_bits(Register::TEMP_CFG, ADC_EN & TEMP_EN, enable)
315 .await?;
316
317 if enable {
319 self.register_xset_bits(Register::CTRL4, BDU, true).await?;
320 }
321
322 Ok(())
323 }
324
325 pub async fn get_temp_out(&mut self) -> Result<i16, Error<CORE::BusError>> {
328 let out_l = self.read_register(Register::OUT_ADC3_L).await?;
329 let out_h = self.read_register(Register::OUT_ADC3_H).await?;
330
331 Ok(i16::from_le_bytes([out_l, out_h]))
332 }
333
334 pub async fn get_temp_outf(&mut self) -> Result<f32, Error<CORE::BusError>> {
338 let temp_out = self.get_temp_out().await?;
339
340 Ok(temp_out as f32 / 256.0 + 25.0)
341 }
342
343 async fn modify_register<F>(
347 &mut self,
348 register: Register,
349 f: F,
350 ) -> Result<(), Error<CORE::BusError>>
351 where
352 F: FnOnce(u8) -> u8,
353 {
354 let value = self.read_register(register).await?;
355
356 self.write_register(register, f(value)).await
357 }
358
359 pub async fn register_clear_bits(
366 &mut self,
367 reg: Register,
368 bits: u8,
369 ) -> Result<(), Error<CORE::BusError>> {
370 self.modify_register(reg, |v| v & !bits).await
371 }
372
373 pub async fn register_set_bits(
381 &mut self,
382 reg: Register,
383 bits: u8,
384 ) -> Result<(), Error<CORE::BusError>> {
385 self.modify_register(reg, |v| v | bits).await
386 }
387
388 async fn register_xset_bits(
391 &mut self,
392 reg: Register,
393 bits: u8,
394 set: bool,
395 ) -> Result<(), Error<CORE::BusError>> {
396 if set {
397 self.register_set_bits(reg, bits).await
398 } else {
399 self.register_clear_bits(reg, bits).await
400 }
401 }
402
403 pub async fn configure_interrupt_pin<P: IrqPin>(
414 &mut self,
415 pin: P,
416 ) -> Result<(), Error<CORE::BusError>> {
417 self.write_register(P::ctrl_reg(), pin.bits()).await
418 }
419
420 pub async fn configure_irq_src<I: Interrupt>(
432 &mut self,
433 int: I,
434 interrupt_mode: InterruptMode,
435 interrupt_config: InterruptConfig,
436 ) -> Result<(), Error<CORE::BusError>> {
437 self.configure_irq_src_and_control(
438 int,
439 interrupt_mode,
440 interrupt_config,
441 LatchInterruptRequest::default(),
442 Detect4D::default(),
443 )
444 .await
445 }
446
447 pub async fn configure_irq_src_and_control<I: Interrupt>(
466 &mut self,
467 _int: I,
468 interrupt_mode: InterruptMode,
469 interrupt_config: InterruptConfig,
470 latch_interrupt_request: LatchInterruptRequest,
471 detect_4d: Detect4D,
472 ) -> Result<(), Error<CORE::BusError>> {
473 let latch_interrupt_request =
474 matches!(latch_interrupt_request, LatchInterruptRequest::Enable);
475
476 let detect_4d = matches!(detect_4d, Detect4D::Enable);
477
478 if latch_interrupt_request || detect_4d {
479 let latch = (latch_interrupt_request as u8) << I::lir_int_bit();
480 let d4d = (detect_4d as u8) << I::d4d_int_bit();
481 self.register_set_bits(Register::CTRL5, latch | d4d).await?;
482 }
483 self.write_register(I::cfg_reg(), interrupt_config.to_bits(interrupt_mode))
484 .await
485 }
486
487 #[doc(alias = "INT1_DURATION")]
497 #[doc(alias = "INT2_DURATION")]
498 pub async fn configure_irq_duration<I: Interrupt>(
499 &mut self,
500 _int: I,
501 duration: Duration,
502 ) -> Result<(), Error<CORE::BusError>> {
503 self.write_register(I::duration_reg(), duration.0).await
504 }
505
506 #[doc(alias = "INT1_THS")]
516 #[doc(alias = "INT2_THS")]
517 pub async fn configure_irq_threshold<I: Interrupt>(
518 &mut self,
519 _int: I,
520 threshold: Threshold,
521 ) -> Result<(), Error<CORE::BusError>> {
522 self.write_register(I::ths_reg(), threshold.0).await
523 }
524
525 pub async fn get_irq_src<I: Interrupt>(
528 &mut self,
529 _int: I,
530 ) -> Result<InterruptSource, Error<CORE::BusError>> {
531 let irq_src = self.read_register(I::src_reg()).await?;
532 Ok(InterruptSource::from_bits(irq_src))
533 }
534
535 #[doc(alias = "ACT_THS")]
557 #[doc(alias = "ACT_DUR")]
558 #[doc(alias = "act")]
559 pub async fn configure_switch_to_low_power(
560 &mut self,
561 threshold: Threshold,
562 duration: Duration,
563 ) -> Result<(), Error<CORE::BusError>> {
564 self.write_register(Register::ACT_THS, threshold.0 & 0b0111_1111)
565 .await?;
566 self.write_register(Register::ACT_DUR, duration.0).await
567 }
568
569 pub async fn reboot_memory_content(&mut self) -> Result<(), Error<CORE::BusError>> {
571 self.register_set_bits(Register::CTRL5, 0b1000_0000).await
572 }
573
574 const FIFO_ENABLE_BIT: u8 = 0b0100_0000;
575
576 pub async fn enable_fifo(
578 &mut self,
579 mode: FifoMode,
580 threshold: u8,
581 ) -> Result<(), Error<CORE::BusError>> {
582 debug_assert!(threshold <= 0b0001_1111);
583
584 let bits = (threshold & 0b0001_1111) | mode.to_bits();
585 self.write_register(Register::FIFO_CTRL, bits).await?;
586 self.register_set_bits(Register::CTRL5, Self::FIFO_ENABLE_BIT)
587 .await
588 }
589
590 pub async fn disable_fifo(&mut self) -> Result<(), Error<CORE::BusError>> {
592 self.write_register(Register::FIFO_CTRL, 0x00).await?;
593 self.register_clear_bits(Register::CTRL5, Self::FIFO_ENABLE_BIT)
594 .await
595 }
596
597 pub async fn get_fifo_status(&mut self) -> Result<FifoStatus, Error<CORE::BusError>> {
599 let status = self.read_register(Register::FIFO_SRC).await?;
600
601 Ok(FifoStatus::from_bits(status))
602 }
603
604 pub async fn accel_norm(&mut self) -> Result<F32x3, Error<CORE::BusError>> {
608 let mode = self.get_mode().await?;
611 let range = self.get_range().await?;
612
613 let scale = match (mode, range) {
618 (Mode::HighResolution, Range::G2) => 0.001,
620 (Mode::HighResolution, Range::G4) => 0.002,
621 (Mode::HighResolution, Range::G8) => 0.004,
622 (Mode::HighResolution, Range::G16) => 0.012,
623 (Mode::Normal, Range::G2) => 0.004,
625 (Mode::Normal, Range::G4) => 0.008,
626 (Mode::Normal, Range::G8) => 0.016,
627 (Mode::Normal, Range::G16) => 0.048,
628 (Mode::LowPower, Range::G2) => 0.016,
630 (Mode::LowPower, Range::G4) => 0.032,
631 (Mode::LowPower, Range::G8) => 0.064,
632 (Mode::LowPower, Range::G16) => 0.192,
633 };
634
635 let shift: u8 = match mode {
641 Mode::HighResolution => 4, Mode::Normal => 6, Mode::LowPower => 8, };
645
646 let acc_raw = self.accel_raw().await?;
647 let x = (acc_raw.x >> shift) as f32 * scale;
648 let y = (acc_raw.y >> shift) as f32 * scale;
649 let z = (acc_raw.z >> shift) as f32 * scale;
650
651 Ok(F32x3::new(x, y, z))
652 }
653
654 pub async fn sample_rate(&mut self) -> Result<f32, Error<CORE::BusError>> {
656 Ok(self.get_datarate().await?.sample_rate())
657 }
658
659 pub async fn accel_raw(&mut self) -> Result<I16x3, Error<CORE::BusError>> {
663 let accel_bytes = self.read_accel_bytes().await?;
664
665 let x = i16::from_le_bytes(accel_bytes[0..2].try_into().unwrap());
666 let y = i16::from_le_bytes(accel_bytes[2..4].try_into().unwrap());
667 let z = i16::from_le_bytes(accel_bytes[4..6].try_into().unwrap());
668
669 Ok(I16x3::new(x, y, z))
670 }
671}
672
673pub trait Lis3dhCore {
674 type BusError;
675
676 async fn write_register(
677 &mut self,
678 register: Register,
679 value: u8,
680 ) -> Result<(), Error<Self::BusError>>;
681
682 async fn read_register(&mut self, register: Register) -> Result<u8, Error<Self::BusError>>;
683
684 async fn read_accel_bytes(&mut self) -> Result<[u8; 6], Error<Self::BusError>>;
685}
686
687impl<CORE> Lis3dhCore for Lis3dh<CORE>
688where
689 CORE: Lis3dhCore,
690{
691 type BusError = CORE::BusError;
692
693 async fn write_register(
694 &mut self,
695 register: Register,
696 value: u8,
697 ) -> Result<(), Error<Self::BusError>> {
698 self.core.write_register(register, value).await
699 }
700
701 async fn read_register(&mut self, register: Register) -> Result<u8, Error<Self::BusError>> {
702 self.core.read_register(register).await
703 }
704
705 async fn read_accel_bytes(&mut self) -> Result<[u8; 6], Error<Self::BusError>> {
706 self.core.read_accel_bytes().await
707 }
708}
709
710pub struct Lis3dhI2C<I2C> {
712 i2c: I2C,
714
715 address: u8,
717}
718
719impl<I2C, E> Lis3dhCore for Lis3dhI2C<I2C>
720where
721 I2C: I2c<Error = E>,
722{
723 type BusError = E;
724
725 async fn write_register(
727 &mut self,
728 register: Register,
729 value: u8,
730 ) -> Result<(), Error<Self::BusError>> {
731 if register.read_only() {
732 return Err(Error::WriteToReadOnly);
733 }
734
735 self.i2c
736 .write(self.address, &[register.addr(), value])
737 .await
738 .map_err(Error::Bus)
739 }
740
741 async fn read_register(&mut self, register: Register) -> Result<u8, Error<Self::BusError>> {
743 let mut data = [0];
744
745 self.i2c
746 .write_read(self.address, &[register.addr()], &mut data)
747 .await
748 .map_err(Error::Bus)
749 .and(Ok(data[0]))
750 }
751
752 async fn read_accel_bytes(&mut self) -> Result<[u8; 6], Error<Self::BusError>> {
754 let mut data = [0u8; 6];
755
756 self.i2c
757 .write_read(self.address, &[Register::OUT_X_L.addr() | 0x80], &mut data)
758 .await
759 .map_err(Error::Bus)
760 .and(Ok(data))
761 }
762}
763
764pub struct Lis3dhSPI<SPI> {
766 spi: SPI,
768}
769
770impl<SPI, ESPI> Lis3dhSPI<SPI>
771where
772 SPI: SpiDevice<Error = ESPI>,
773{
774 async unsafe fn write_multiple_regs(
777 &mut self,
778 start_register: Register,
779 data: &[u8],
780 ) -> Result<(), Error<ESPI>> {
781 self.spi
782 .transaction(&mut [
783 spi::Operation::Write(&[start_register.addr() | 0x40]),
784 spi::Operation::Write(data),
785 ])
786 .await
787 .map_err(Error::Bus)?;
788
789 Ok(())
790 }
791
792 async fn read_multiple_regs(
794 &mut self,
795 start_register: Register,
796 buf: &mut [u8],
797 ) -> Result<(), Error<ESPI>> {
798 self.spi
799 .transaction(&mut [
800 spi::Operation::Write(&[start_register.addr() | 0xC0]),
801 spi::Operation::TransferInPlace(buf),
802 ])
803 .await
804 .map_err(Error::Bus)?;
805
806 Ok(())
807 }
808}
809
810impl<SPI, ESPI> Lis3dhCore for Lis3dhSPI<SPI>
811where
812 SPI: SpiDevice<Error = ESPI>,
813{
814 type BusError = ESPI;
815
816 async fn write_register(
818 &mut self,
819 register: Register,
820 value: u8,
821 ) -> Result<(), Error<Self::BusError>> {
822 if register.read_only() {
823 return Err(Error::WriteToReadOnly);
824 }
825 unsafe { self.write_multiple_regs(register, &[value]).await }
826 }
827
828 async fn read_register(&mut self, register: Register) -> Result<u8, Error<Self::BusError>> {
830 let mut data = [0];
831
832 self.spi
833 .transaction(&mut [
834 spi::Operation::Write(&[register.addr() | 0x80]),
835 spi::Operation::TransferInPlace(&mut data),
836 ])
837 .await
838 .map_err(Error::Bus)?;
839
840 Ok(data[0])
841 }
842
843 async fn read_accel_bytes(&mut self) -> Result<[u8; 6], Error<Self::BusError>> {
845 let mut data = [0u8; 6];
846 self.read_multiple_regs(Register::OUT_X_L, &mut data)
847 .await?;
848 Ok(data)
849 }
850}
851
852#[derive(Debug, Clone, Copy)]
854#[cfg_attr(feature = "defmt", derive(defmt::Format))]
855pub struct Configuration {
856 pub mode: Mode,
858 pub datarate: DataRate,
860 pub enable_x_axis: bool,
862 pub enable_y_axis: bool,
864 pub enable_z_axis: bool,
866 pub block_data_update: bool,
873 pub enable_temperature: bool,
877}
878
879impl Default for Configuration {
880 fn default() -> Self {
881 Self {
882 enable_temperature: false,
883 block_data_update: true,
884 mode: Mode::HighResolution, datarate: DataRate::Hz_400,
886 enable_x_axis: true,
887 enable_y_axis: true,
888 enable_z_axis: true,
889 }
890 }
891}