lsm6ds3tr/
lib.rs

1#![cfg_attr(not(test), no_std)]
2#![allow(dead_code)]
3
4mod consts;
5mod data;
6pub mod interface;
7mod registers;
8mod settings;
9
10use consts::*;
11pub use data::XYZ;
12use interface::Interface;
13pub use registers::{AccelSampleRate, AccelScale};
14use registers::{
15    Ctrl3C, GyroSampleRate, GyroScale, RegisterAddress, RegisterBits, RegisterConfig,
16    RegisterValue, TapSrc, WakeUpSrc,
17};
18pub use settings::{
19    irq::{InterruptRoute, TapIrqSettings, TapRecognitionMode},
20    AccelSettings, GyroSettings, IrqSettings, LsmSettings,
21};
22
23extern crate alloc;
24use alloc::vec::Vec;
25
26/// Device driver
27pub struct LSM6DS3TR<I>
28where
29    I: Interface,
30{
31    interface: I,
32    pub settings: LsmSettings,
33}
34
35impl<I> LSM6DS3TR<I>
36where
37    I: Interface,
38{
39    /// Returns uninitialized device object with default settings
40    pub fn new(interface: I) -> Self {
41        Self {
42            interface,
43            settings: Default::default(),
44        }
45    }
46
47    /// Returns uninitialized device object with provided settings
48    pub fn with_settings(mut self, settings: LsmSettings) -> Self {
49        self.settings = settings;
50        self
51    }
52
53    /// Initializes device with stored settings
54    pub fn init(&mut self) -> Result<(), I::Error> {
55        self.init_accel()?;
56        self.init_gyro()?;
57        self.init_irqs()?;
58        self.init_other()?;
59        Ok(())
60    }
61
62    /// Returns if device is reachable
63    pub fn is_reachable(&mut self) -> Result<bool, I::Error> {
64        Ok(self.read_register(RegisterAddress::WHO_AM_I.address())? == LSM6DS3TR_ID)
65    }
66
67    /// Performs a software reset
68    pub fn software_reset(&mut self) -> Result<(), I::Error> {
69        let ctrl3_c = Ctrl3C {
70            software_reset: RegisterBits::new(1),
71            ..Default::default()
72        };
73        self.write_register_config(ctrl3_c.config())?;
74        Ok(())
75    }
76
77    /// Initializes accelerometer with stored settings
78    pub fn init_accel(&mut self) -> Result<(), I::Error> {
79        self.write_register_config(self.settings.accel.config())?;
80        Ok(())
81    }
82
83    /// Initializes gyroscope with stored settings
84    pub fn init_gyro(&mut self) -> Result<(), I::Error> {
85        self.write_register_config(self.settings.gyro.config())?;
86        Ok(())
87    }
88
89    /// Initializes interrupts with stored settings
90    pub fn init_irqs(&mut self) -> Result<(), I::Error> {
91        for config in self.settings.irq.configs() {
92            self.write_register_config(config)?;
93        }
94        Ok(())
95    }
96
97    /// Initializes other options with stored settings
98    pub fn init_other(&mut self) -> Result<(), I::Error> {
99        if self.settings.low_performance_mode {
100            self.write_register(RegisterAddress::CTRL6_C.address(), 1 << 4)?; // TODO make it right like the others
101            self.write_register(RegisterAddress::CTRL7_G.address(), 1 << 7)?; // TODO make it right like the others
102        }
103        Ok(())
104    }
105
106    /// Returns accelerometer raw readings
107    pub fn read_accel_raw(&mut self) -> Result<XYZ<i16>, I::Error> {
108        self.read_sensor_raw(RegisterAddress::OUTX_L_XL.address())
109    }
110
111    /// Returns accelerometer scaled readings \[g]
112    pub fn read_accel(&mut self) -> Result<XYZ<f32>, I::Error> {
113        let xyz = self.read_accel_raw()?;
114        let sensitivity = self.settings.accel.scale.sensitivity();
115        Ok(XYZ {
116            x: xyz.x as f32 * sensitivity,
117            y: xyz.y as f32 * sensitivity,
118            z: xyz.z as f32 * sensitivity,
119        })
120    }
121
122    /// Returns gyroscope raw readings
123    pub fn read_gyro_raw(&mut self) -> Result<XYZ<i16>, I::Error> {
124        self.read_sensor_raw(RegisterAddress::OUTX_L_G.address())
125    }
126
127    /// Returns gyroscope scaled readings [°/s]
128    pub fn read_gyro(&mut self) -> Result<XYZ<f32>, I::Error> {
129        let xyz = self.read_gyro_raw()?;
130        let sensitivity = self.settings.gyro.scale.sensitivity();
131        Ok(XYZ {
132            x: xyz.x as f32 * sensitivity,
133            y: xyz.y as f32 * sensitivity,
134            z: xyz.z as f32 * sensitivity,
135        })
136    }
137
138    /// Returns temperature sensor raw reading
139    pub fn read_temp_raw(&mut self) -> Result<i16, I::Error> {
140        let mut bytes = [0u8; 2];
141        self.interface
142            .read(RegisterAddress::OUT_TEMP_L.address(), &mut bytes)?;
143        let temp: i16 = (bytes[1] as i16) << 8 | bytes[0] as i16;
144        Ok(temp)
145    }
146
147    /// Returns temperature sensor scaled reading [°C]
148    pub fn read_temp(&mut self) -> Result<f32, I::Error> {
149        let temp = self.read_temp_raw()?;
150        Ok(temp as f32 / TEMP_SCALE + TEMP_BIAS)
151    }
152
153    /// Returns last interrupt sources
154    pub fn read_interrupt_sources(&mut self) -> Result<Vec<IrqSource>, I::Error> {
155        let mut wake_up_src = WakeUpSrc::default();
156        let mut tap_src = TapSrc::default();
157        // TODO add FUNC_SRC1 reading
158        // TODO add FUNC_SRC2 reading
159        wake_up_src = self.read_register(wake_up_src.address())?.into();
160        tap_src = self.read_register(tap_src.address())?.into();
161        let mut irq_sources = Vec::new();
162        for source in wake_up_src.get_irq_sources() {
163            irq_sources.push(source.clone());
164        }
165        for source in tap_src.get_irq_sources() {
166            irq_sources.push(source.clone());
167        }
168        Ok(irq_sources)
169    }
170
171    fn read_sensor_raw(&mut self, addr: u8) -> Result<XYZ<i16>, I::Error> {
172        let mut bytes = [0u8; 6];
173        self.interface.read(addr, &mut bytes)?;
174        let x: i16 = (bytes[1] as i16) << 8 | bytes[0] as i16;
175        let y: i16 = (bytes[3] as i16) << 8 | bytes[2] as i16;
176        let z: i16 = (bytes[5] as i16) << 8 | bytes[4] as i16;
177        Ok(XYZ { x, y, z })
178    }
179
180    fn read_register(&mut self, address: u8) -> Result<u8, I::Error> {
181        let mut value = [0u8];
182        self.interface.read(address, &mut value)?;
183        Ok(value[0])
184    }
185
186    fn write_register(&mut self, address: u8, value: u8) -> Result<(), I::Error> {
187        self.interface.write(address, value)?;
188        Ok(())
189    }
190
191    fn read_register_config(&mut self, address: u8) -> Result<RegisterConfig, I::Error> {
192        let mut value = [0u8];
193        self.interface.read(address, &mut value)?;
194        let value = value[0];
195        Ok(RegisterConfig { address, value })
196    }
197
198    fn write_register_config(&mut self, register_config: RegisterConfig) -> Result<(), I::Error> {
199        self.write_register(register_config.address, register_config.value)?;
200        Ok(())
201    }
202}
203
204/// Interrupt sources
205#[cfg_attr(feature = "defmt", derive(defmt::Format))]
206#[derive(Clone, Debug)]
207pub enum IrqSource {
208    FreeFall,
209    Sleep,
210    WakeUp,
211    WakeUpOnX,
212    WakeUpOnY,
213    WakeUpOnZ,
214    Tap,
215    SingleTap,
216    DoubleTap,
217    TapOnX,
218    TapOnY,
219    TapOnZ,
220}
221
222pub struct IrqSources(pub Vec<IrqSource>);