lis2dh 0.4.0

Driver crate for the ST LIS2DH12 accelerometer
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
#![doc = include_str!("../README.md")]
#![no_std]
#![deny(missing_docs)]

#[cfg(feature = "async")]
mod asynch;
mod register;
#[cfg(not(feature = "async"))]
mod sync;

pub use register::*;

/// Driver for the LIS2DH accelerometer
pub struct Lis2dh<I2C> {
    i2c: I2C,
    addr: u8,
}

/// Error type
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error<I2cError> {
    /// I2C bus error
    I2c(I2cError),
    /// Attempted to write to a read-only register
    WriteToReadOnly,
    /// Invalid parameter
    InvalidParameter,
}

/// SA0 pad connection on the board
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Sa0Pad {
    /// SA0 pad is connected to GND
    Low = 0,
    /// SA0 pad is connected to VDD
    High = 1,
}

/// Operating mode
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Mode {
    /// Low power mode (8-bit data output)
    LowPower,
    /// Normal mode (10-bit data output)
    Normal,
    /// High resolution mode (12-bit data output)
    HighResolution,
}

/// Full scale selection
#[derive(Copy, Clone)]
#[repr(u8)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FullScale {
    /// ±2 g
    Fs2g = 0x00,
    /// ±4 g
    Fs4g = 0x10,
    /// ±8 g
    Fs8g = 0x20,
    /// ±16 g
    Fs16g = 0x30,
}

/// Output data rate
#[derive(Copy, Clone)]
#[repr(u8)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OutputDataRate {
    /// Power-down mode
    PowerDown = 0x00,
    /// 1 Hz
    Hz1 = 0x10,
    /// 10 Hz
    Hz10 = 0x20,
    /// 25 Hz
    Hz25 = 0x30,
    /// 50 Hz
    Hz50 = 0x40,
    /// 100 Hz
    Hz100 = 0x50,
    /// 200 Hz
    Hz200 = 0x60,
    /// 400 Hz
    Hz400 = 0x70,
    /// 1.620 kHz in low-power mode
    /// Normal and high-resolution modes are not defined
    /// in the datasheet for this configuration
    HighSpeed = 0x80,
    /// 1.344 kHz in normal/high-resolution modes
    /// 5.376 kHz in low-power mode
    HighestSpeed = 0x90,
}

/// Status data
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Status {
    /// X-, Y- and Z-axis overrun
    pub xyz_overrun: bool,
    /// Z-axis data overrun
    pub z_overrun: bool,
    /// Y-axis data overrun
    pub y_overrun: bool,
    /// X-axis data overrun
    pub x_overrun: bool,
    /// X-, Y- and Z-axis new data available
    pub xyz_data_available: bool,
    /// Z-axis new data available
    pub z_data_available: bool,
    /// Y-axis new data available
    pub y_data_available: bool,
    /// Z-axis new data available
    pub x_data_available: bool,
    /// Temperature data overrun
    pub temp_overrun: bool,
    /// Temperature data available
    pub temp_data_available: bool,
}

/// High-pass filter mode
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum HighPassFilterMode {
    /// Normal mode (reset by reading REFERENCE register)
    NormalModeWithReset = 0x00,
    /// Reference signal for filtering
    ReferenceSignal = 0x40,
    /// Normal mode
    NormalMode = 0x80,
    /// Auto-reset on interrupt event
    AutoResetOnInterrupt = 0xC0,
}

/// High-pass filter cut-off frequency selection
///
/// See application note AN5005 table 11f for details.
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[allow(missing_docs)]
#[repr(u8)]
pub enum HighPassCutoffFrequencySelection {
    Cfg0 = 0x00,
    Cfg1 = 0x10,
    Cfg2 = 0x20,
    Cfg3 = 0x30,
}

/// Filtered data selection
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum HighPassFilterDataSelection {
    /// Internal filter bypassed
    Bypassed = 0x00,
    /// Data from internal filter sent to output register and FIFO
    SendDataFromFilter = 0x08,
}

/// High-pass filter configuration
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct HighPassFilterConfig {
    /// High-pass filter mode
    pub mode: HighPassFilterMode,
    /// High-pass filter cut-off frequency selection
    pub cutoff_frequency: HighPassCutoffFrequencySelection,
    /// Filtered data selection
    pub data_selection: HighPassFilterDataSelection,
}

/// Interrupt pin
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum IntPin {
    /// Pin INT1
    Int1,
    /// Pin INT2
    Int2,
}

/// FIFO configuration
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FifoConfig {
    /// Bypass mode
    ///
    /// FIFO remains non-operational and for this reason it
    /// remains empty
    Bypass,
    /// FIFO mode
    ///
    /// Buffer continues filling data from the accelerometer channels
    /// until it is full (a set of 32 samples stored). When the FIFO
    /// is full, it stops collecting data from the input channels and
    /// the FIFO contents remain unchanged
    Fifo,
    /// Stream mode
    ///
    /// The FIFO continues filling data from the X, Y, and Z accelerometer channels
    /// until the buffer is full (a set of 32 samples stored) at which point
    /// the FIFO buffer index restarts from the beginning and older data is replaced
    /// by the current data. The oldest values continue to be overwritten until a
    /// read operation frees the FIFO slots
    Stream {
        /// Watermark level for the watermark interrupt
        /// When the interrupt is triggered there will be N+1 values to read
        watermark: u8,
    },
    /// Stream-to-FIFO mode
    ///
    /// Data from the X, Y and Z accelerometer channels are collected in a combination
    /// of Stream mode and FIFO mode. The FIFO buffer starts operating in Stream
    /// mode and switches to FIFO mode when the selected interrupt occurs
    StreamToFifo {
        /// Interrupt pin selected to trigger the switch to FIFO mode
        pin: IntPin,
    },
}

/// FIFO status data
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FifoStatus {
    /// FIFO content exceeds watermark level
    pub watermark_exceeded: bool,
    /// FIFO is full
    pub full: bool,
    /// FIFO is empty
    pub empty: bool,
    /// Current number of unread samples in the FIFO buffer
    pub sample_count: u8,
}

/// Interrupt mode for movement interrupts
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum MovementIntMode {
    /// OR combination of interrupt events
    OrCombination = 0x00,
    /// 6-direction movement recognition
    ///
    /// An interrupt is generated when the orientation moves from an unknown
    /// zone to a known zone. The interrupt signal remains for a duration ODR
    MovementRecognition = 0x40,
    /// AND combination of interrupt events
    AndCombination = 0x80,
    /// 6-direction position recognition
    ///
    /// An interrupt is generated when the orientation is inside a known zone
    /// The interrupt signal remains while the orientation is inside the zone
    PositionRecognition = 0xC0,
}

/// Movement interrupts
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct MovementInterrupts {
    /// X-axis acceleration higher than threshold value
    pub x_high: bool,
    /// X-axis acceleration lower than threshold value
    pub x_low: bool,
    /// Y-axis acceleration higher than threshold value
    pub y_high: bool,
    /// Y-axis acceleration lower than threshold value
    pub y_low: bool,
    /// Z-axis acceleration higher than threshold value
    pub z_high: bool,
    /// Z-axis acceleration lower than threshold value
    pub z_low: bool,
}

/// Movement interrupt configuration
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct MovementIntConfig {
    /// Movement interrupt mode
    pub mode: MovementIntMode,
    /// Interrupts to enable
    pub enable: MovementInterrupts,
    /// Interrupt threshold
    pub threshold: u8,
    /// Minimum duration of the interrupt event for it to be recognized
    pub duration: u8,
    /// Latch interrupt request
    /// Cleared by reading movement interrupt source
    pub latch: bool,
    /// Enable 4D-detection: Disables the Z-axis
    pub only_4d: bool,
    /// Enable high-pass filter
    pub high_pass_filter: bool,
}

/// Click interrupts
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ClickInterrupts {
    /// Single click on X-axis
    pub x_single: bool,
    /// Double click on X-axis
    pub x_double: bool,
    /// Single click on Y-axis
    pub y_single: bool,
    /// Double click on Y-axis
    pub y_double: bool,
    /// Single click on Z-axis
    pub z_single: bool,
    /// Double click on Z-axis
    pub z_double: bool,
}

/// Click interrupt configuration
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ClickIntConfig {
    /// Interrupts to enable
    pub enable: ClickInterrupts,
    /// Interrupt threshold
    pub threshold: u8,
    /// Click time limit
    pub time_limit: u8,
    /// Click time latency
    pub time_latency: u8,
    /// Click time window
    pub time_window: u8,
    /// Latch interrupt request
    /// Cleared by reading click interrupt source
    pub latch: bool,
    /// Enable high-pass filter
    pub high_pass_filter: bool,
}

/// Click interrupt source
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ClickIntSrc {
    /// X-axis click detected
    pub x: bool,
    /// Y-axis click detected
    pub y: bool,
    /// Z-axis click detected
    pub z: bool,
    /// Click sign
    pub positive: bool,
    /// Single click detection enabled
    pub single_click_enabled: bool,
    /// Double click detection enabled
    pub double_click_enabled: bool,
}

/// Activity interrupt configuration
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ActivityIntConfig {
    /// Sleep-to-wake, return-to-sleep activation threshold in low-power mode
    /// 1 LSb = 16 mg @ FS = 2 g
    /// 1 LSb = 32 mg @ FS = 4 g
    /// 1 LSb = 62 mg @ FS = 8 g
    /// 1 LSb = 186 mg @ FS = 16 g
    pub threshold: u8,
    /// Sleep-to-wake, return-to-sleep duration
    pub duration: u8,
}

/// INT1 configuration
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Int1Config {
    /// Interrupt pin unused
    Unused,
    /// Click interrupt
    Click(ClickIntConfig),
    /// Movement interrupt 1
    MovementInt1(MovementIntConfig),
    /// Movement interrupt 2
    MovementInt2(MovementIntConfig),
    /// X-, Y- and Z-axis data available interrupt
    DataAvailableXYZ,
    /// FIFO watermark interrupt
    FifoWatermark,
    /// FIFO overrun interrupt
    FifoOverrun,
}

/// INT2 configuration
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Int2Config {
    /// Interrupt pin unused
    Unused,
    /// Click interrupt
    Click(ClickIntConfig),
    /// Movement interrupt 1
    MovementInt1(MovementIntConfig),
    /// Movement interrupt 2
    MovementInt2(MovementIntConfig),
    /// Boot
    Boot,
    /// Activity interrupt
    Activity(ActivityIntConfig),
}

/// Interrupt polarity
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum IntPolarity {
    /// Active high
    ActiveHigh,
    /// Active low
    ActiveLow,
}

/// Acceleration data
#[derive(Copy, Clone, Default)]
pub struct AccelerationData {
    /// X-axis
    pub x: i16,
    /// Y-axis
    pub y: i16,
    /// Z-axis
    pub z: i16,
}

#[cfg(feature = "defmt")]
impl defmt::Format for AccelerationData {
    fn format(&self, f: defmt::Formatter) {
        defmt::write!(f, "({}, {}, {})", self.x, self.y, self.z)
    }
}