lps25hb/
lib.rs

1//! A platform agnostic driver to interface with LPS25HB pressure sensor module.
2//!
3//! This driver allows you to:
4//! - read atmospheric pressure in hPa, see [`read_pressure()`]
5//! - read temperature in degrees Celsius, see [`read_temperature()`]
6//! - enable single-shot data acquisition, see [`enable_one_shot()`]
7//! - set data rate, see [`set_datarate()`]
8//!
9//! [`read_pressure()`]: struct.LPS25HB.html#method.read_pressure
10//! [`read_temperature()`]: struct.LPS25HB.html#method.read_temperature
11//! [`enable_one_shot()`]: struct.LPS25HB.html#method.enable_one_shot
12//! [`set_datarate()`]: struct.LPS25HB.html#method.set_datarate
13//!
14//! __NOTE__: This is an early version of the crate. Only I2C interface is supported at the moment.
15//!  
16//!
17//! ### Datasheet: [LPS25HB](https://www.st.com/resource/en/datasheet/lps25hb.pdf)
18//!
19//! ## Usage examples (see also examples folder)
20//!
21//! Please find additional examples using hardware in this repository: [examples]
22//!
23//! [examples]: https://github.com/nebelgrau77/lps25hb-rs/examples
24//!
25//! ### Read pressure and temperature
26//!
27//! ```rust
28//!
29//! use lps25hb::interface::{I2cInterface, i2c::I2cAddress};
30//! use lps25hb::*;
31//!
32//! let mut lps25 = LPS25HB.new(i2c_interface);
33//!
34//! lps25hb.sensor_on(true).unwrap();
35//!
36//! lps25.one_shot().unwrap();
37//!
38//! let pressure = lps25.read_pressure().unwrap();
39//! let temperature = lps25.read_temperature().unwrap();
40//! ```
41//!
42
43// TO DO: move MULTIBYTE into the interface, as it is different between I2C and SPI
44// 
45// TO DO (IDEA): create an init() function with a Config struct. 
46// The configuration would include: power on (bool), ODR, block data update (bool), pressure resolution, temperature resolution. 
47
48
49#![no_std]
50//#![deny(warnings, missing_docs)]
51
52pub mod sensor;
53use sensor::*;
54
55pub mod register;
56use register::*;
57
58pub mod fifo;
59use fifo::*;
60
61pub mod config;
62use config::*;
63
64pub mod interrupt;
65use interrupt::*;
66
67pub mod interface;
68use interface::Interface;
69
70/// Sensor's ID
71const WHOAMI: u8 = 0b10111101; // decimal value 189
72
73// https://www.st.com/resource/en/technical_note/dm00242307-how-to-interpret-pressure-and-temperature-readings-in-the-lps25hb-pressure-sensor-stmicroelectronics.pdf
74
75/// The output of the temperature sensor must be divided by 480, see Table 3 of the datasheet.
76const TEMP_SCALE: f32 = 480.0;
77/// An offset value must be added to the result. This is NOT mentioned in the LPS25HB datasheet, but is described in the LPS25H datasheet.
78const TEMP_OFFSET: f32 = 42.5;
79/// The output of the pressure sensor must be divided by 4096, see Table 3 of the datasheet.
80const PRESS_SCALE: f32 = 4096.0;
81
82/// Holds the driver instance with the selected interface
83pub struct LPS25HB<T> {
84    interface: T,
85}
86
87impl<T, E> LPS25HB<T>
88where
89    T: Interface<Error = E>,
90{
91    /// Create a new instance of the LPS25HB driver.
92    pub fn new(interface: T) -> Self {
93        LPS25HB { interface }
94    }
95
96    /// Destroy driver instance, return interface instance.
97    pub fn destroy(self) -> T {
98        self.interface
99    }
100
101    /// Read a byte from the given register.
102    fn read_register(&mut self, address: Registers) -> Result<u8, T::Error> {
103        let mut reg_data = [0u8];
104        self.interface.read(address.addr(), &mut reg_data)?;
105        Ok(reg_data[0])
106    }
107
108    /// Clear selected bits using a bitmask
109    fn clear_register_bit_flag(&mut self, address: Registers, bitmask: u8) -> Result<(), T::Error> {
110        let mut reg_data = [0u8];
111        self.interface.read(address.addr(), &mut reg_data)?;
112        let payload: u8 = reg_data[0] & !bitmask;
113        self.interface.write(address.addr(), payload)?;
114        Ok(())
115    }
116
117    /// Set selected bits using a bitmask
118    fn set_register_bit_flag(&mut self, address: Registers, bitmask: u8) -> Result<(), T::Error> {
119        let mut reg_data = [0u8];
120        self.interface.read(address.addr(), &mut reg_data)?;
121        let payload: u8 = reg_data[0] | bitmask;
122        self.interface.write(address.addr(), payload)?;
123        Ok(())
124    }
125
126    /// Check if specific bits are set.
127    fn is_register_bit_flag_high(
128        &mut self,
129        address: Registers,
130        bitmask: u8,
131    ) -> Result<bool, T::Error> {
132        let data = self.read_register(address)?;
133        Ok((data & bitmask) != 0)
134    }
135
136    /*
137
138    /// FOR DEBUGGING PURPOSES ONLY
139    pub fn get_mask(&mut self, mask: ODR) -> Result<u8, T::Error> {
140        Ok(mask.value())
141    }
142
143    */
144}
145
146/// Output data rate and power mode selection (ODR). (Refer to Table 20)
147#[derive(Debug, Clone, Copy)]
148pub enum ODR {
149    /// One-shot mode enabled
150    OneShot = 0b000,
151    /// 1 Hz
152    _1Hz = 0b001,
153    /// 7 Hz
154    _7Hz = 0b010,
155    /// 12.5 Hz
156    _12_5Hz = 0b011,
157    /// 25 Hz
158    _25Hz = 0b100,
159}
160
161impl ODR {
162    pub fn value(self) -> u8 {
163        (self as u8) << 4 // shifted into the right position, can be used directly
164    }
165}
166
167/// SPI interface mode
168#[derive(Debug, Clone, Copy)]
169pub enum SPI_Mode {
170    /// 4-wire mode (default)
171    _4wire,
172    /// 3-wire mode
173    _3wire,
174}
175
176/// FIFO mode selection. (Refer to Table 22)
177#[derive(Debug, Clone, Copy)]
178pub enum FIFO_MODE {
179    /// Bypass mode
180    Bypass = 0b000,
181    /// FIFO mode
182    FIFO = 0b001,
183    /// Stream mode
184    Stream = 0b010,
185    /// Stream-to-FIFO mode
186    Stream_to_FIFO = 0b011,
187    /// Bypass-to-stream mode
188    Bypass_to_stream = 0b100,
189    /// FIFO Mean mode
190    FIFO_Mean = 0b110,
191    /// Bypass-to-FIFO mode
192    Bypass_to_FIFO = 0b111,
193}
194
195impl FIFO_MODE {
196    pub fn value(self) -> u8 {
197        (self as u8) << 5 // shifted into the right position, can be used directly
198    }
199}
200
201/// FIFO Mean mode running average sample size. (Refer to Table 23)
202#[derive(Debug, Clone, Copy)]
203pub enum FIFO_MEAN {
204    /// 2-sample moving average
205    _2sample = 0b00001,
206    /// 4-sample moving average
207    _4sample = 0b00011,
208    /// 8-sample moving average
209    _8sample = 0b00111,
210    /// 16-sample moving average
211    _16sample = 0b01111,
212    /// 32-sample moving average
213    _32sample = 0b11111,
214}
215
216impl FIFO_MEAN {
217    pub fn value(self) -> u8 {
218        self as u8 // no need to shift, bits 0:4
219    }
220}
221
222/// INT_DRDY pin configuration. (Refer to Table 21)
223#[derive(Debug, Clone, Copy)]
224pub enum INT_DRDY {
225    /// Data signal (see CTRL_REG4)
226    DataSignal = 0b00,
227    /// Pressure high
228    P_high = 0b01,
229    /// Pressure low
230    P_low = 0b10,
231    /// Pressure low or high
232    P_low_or_high = 0b011,
233}
234
235impl INT_DRDY {
236    pub fn value(self) -> u8 {
237        self as u8 // no need to shift, bits 0:1
238    }
239}
240
241/// Interrupt active setting for the INT_DRDY pin: active high (default) or active low
242#[derive(Debug, Clone, Copy)]
243pub enum INT_ACTIVE {
244    /// Active high
245    High,
246    /// Active low
247    Low,
248}
249
250/// Interrupt pad setting for INT_DRDY pin: push-pull (default) or open-drain.
251#[derive(Debug, Clone, Copy)]
252pub enum INT_PIN {
253    /// Push-pull
254    PushPull,
255    /// Open drain
256    OpenDrain,
257}
258
259/// Temperature resolution configuration, number of internal average(Refer to Table 18)
260#[derive(Debug, Clone, Copy)]
261pub enum TEMP_RES {
262    /// Nr. internal average 8
263    _8 = 0b00,
264    /// Nr. internal average 16
265    _16 = 0b01,
266    /// Nr. internal average 32
267    _32 = 0b10,
268    /// Nr. internal average 64
269    _64 = 0b11,
270}
271
272impl TEMP_RES {
273    pub fn value(self) -> u8 {
274        (self as u8) << 2 // shifted into the right position, can be used directly
275    }
276}
277
278/// Pressure resolution configuration, number of internal average(Refer to Table 19)
279#[derive(Debug, Clone, Copy)]
280pub enum PRESS_RES {
281    /// Nr. internal average 8
282    _8 = 0b00,
283    /// Nr. internal average 32
284    _32 = 0b01,
285    /// Nr. internal average 128
286    _128 = 0b10,
287    /// Nr. internal average 512
288    _512 = 0b11,
289}
290
291impl PRESS_RES {
292    pub fn value(self) -> u8 {
293        self as u8 // no need to shift
294    }
295}