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}