Skip to main content

bmp390_rs/
fifo.rs

1//! This module contains FIFO-related types and functions.
2
3/// Holds all configurable parameters related to FIFO functionality of the BMP390.
4/// 
5/// This is a combination of fields from the FIFO_CONFIG_1 and FIFO_CONFIG_2 registers.
6#[derive(Copy, Clone, Debug)]
7pub struct FifoConfiguration {
8    fifo_enabled: bool,
9    pressure_enabled: bool,
10    temperature_enabled: bool,
11    time_enabled: bool,
12    full_behavior: FifoFullBehavior,
13    subsampling: u8,
14    apply_iir_filter: bool,
15}
16
17impl Default for FifoConfiguration {
18    /// Returns a default configuration that is identical to the default configuration of the BMP930.
19    fn default() -> Self {
20        Self {
21            fifo_enabled: false,
22            pressure_enabled: false,
23            temperature_enabled: false,
24            time_enabled: false,
25            full_behavior: FifoFullBehavior::Stop,
26            subsampling: 0x02,
27            apply_iir_filter: false,
28        }
29    }
30}
31
32impl FifoConfiguration {
33    
34    /// Creates a new instance of the [`FifoConfiguration`] struct with the given initial configuration.
35    pub fn new(
36        fifo_enabled: bool,
37        pressure_enabled: bool,
38        temperature_enabled: bool,
39        time_enabled: bool,
40        full_behavior: FifoFullBehavior,
41        subsampling: u8,
42        apply_iir_filter: bool)
43        -> Self {
44        Self {
45            fifo_enabled,
46            pressure_enabled,
47            temperature_enabled,
48            time_enabled,
49            full_behavior,
50            subsampling,
51            apply_iir_filter,
52        }
53    }
54
55    /// Returns true if the FIFO functionality of the BMP390 should be enabled.
56    pub fn fifo_enabled(&self) -> bool { self.fifo_enabled }
57    
58    /// Enables or disables writing measurements to FIFO.
59    /// 
60    /// If the FIFO is disabled, no measurements will be stored. It is however still possible to read from the FIFO.
61    pub fn set_fifo_enabled(mut self, enabled: bool) -> Self {
62        self.fifo_enabled = enabled;
63        
64        self
65    }
66
67    /// Returns true if pressure should be measured and stored in the FIFO.
68    pub fn pressure_enabled(&self) -> bool { self.pressure_enabled }
69    
70    /// Sets whether pressure should be measured and stored in the FIFO.
71    pub fn set_pressure_enabled(mut self, enabled: bool) -> Self {
72        self.pressure_enabled = enabled;
73        
74        self
75    }
76
77    /// Returns true if temperature should be measured and stored in the FIFO.
78    pub fn temperature_enabled(&self) -> bool { self.temperature_enabled }
79
80    /// Sets whether temperature should be measured and stored in the FIFO.
81    pub fn set_temperature_enabled(mut self, enabled: bool) -> Self {
82        self.temperature_enabled = enabled;
83        
84        self
85    }
86
87    /// Returns true if sensor timestamps should be appended to the last frame of the FIFO. (i.e., when the FIFO is fully drained)
88    pub fn time_enabled(&self) -> bool { self.time_enabled }
89
90    /// Sets whether sensor timestamps should be appended to the last frame of the FIFO. (i.e., when the FIFO is fully drained)
91    pub fn set_time_enabled(mut self, enabled: bool) -> Self {
92        self.time_enabled = enabled;
93        
94        self
95    }
96
97    /// Returns the configured behavior for when new measurements are made with a full FIFO.
98    pub fn fifo_full_behavior(&self) -> FifoFullBehavior { self.full_behavior }
99
100    /// Sets the behavior for when new measurements are made with a full FIFO.
101    pub fn set_fifo_full_behavior(mut self, behavior: FifoFullBehavior) -> Self{
102        self.full_behavior = behavior;
103        
104        self
105    }
106
107    /// Returns the level of subsampling that will be performed.
108    pub fn subsampling(&self) -> u8 { self.subsampling }
109
110    /// Set the level of subsampling that should be performed.
111    ///
112    /// This value is clamped to the range 0-7.
113    /// Read more about FIFO subsampling in the datasheet section 3.6.2
114    pub fn set_subsampling(mut self, subsampling: u8) -> Self{
115        self.subsampling = subsampling;
116        
117        self
118    }
119
120    /// Returns true if the IIR filter should be applied to FIFO measurements.
121    pub fn apply_iir_filter(&self) -> bool { self.apply_iir_filter }
122
123    /// Sets whether the IIR filter should be applied to FIFO measurements or not.
124    ///
125    /// Read more about the IIR filter in the datasheet section 3.4.3
126    pub fn set_apply_iir_filter(mut self, apply_iir_filter: bool) -> Self {
127        self.apply_iir_filter = apply_iir_filter;
128        
129        self
130    }
131}
132
133/// This enum describes the different behaviors that are configurable for when the FIFO is full.
134///
135/// It is used in conjunction with the [`FifoConfiguration`] struct and the [`Bmp390::fifo_configuration`] and [`Bmp390::set_fifo_configuration`] methods.
136#[derive(Copy, Clone, Debug, PartialEq)]
137pub enum FifoFullBehavior {
138    /// Stop writing to FIFO if it is full.
139    Stop,
140
141    /// When the FIFO is full, new measurements will overwrite the oldest one.
142    OverwriteOldest,
143}
144pub(crate) struct FifoHeader {
145    pub fh_mode: u8,
146    pub fh_param: u8,
147}
148
149impl FifoHeader {
150    pub fn is_sensor_frame(&self) -> bool {
151        self.fh_mode == 0b10
152    }
153
154    pub fn is_control_frame(&self) -> bool {
155        self.fh_mode == 0b01
156    }
157
158    pub fn sensor_time_flag(&self) -> bool {
159        (self.fh_param & 0b1000) != 0
160    }
161
162    pub fn temperature_flag(&self) -> bool {
163        (self.fh_param & 0b0100) != 0
164    }
165
166    pub fn pressure_flag(&self) -> bool {
167        (self.fh_param & 0b0001) != 0
168    }
169
170    pub fn config_error_flag(&self) -> bool {
171        self.fh_param == 1
172    }
173
174    pub fn config_change_flag(&self) -> bool {
175        self.fh_param == 2
176    }
177}
178
179impl From<u8> for FifoHeader {
180    fn from(raw: u8) -> Self {
181        FifoHeader {
182            fh_mode: (raw & 0b1100_0000) >> 6,
183            fh_param: (raw & 0b0011_1100) >> 2,
184        }
185    }
186}
187
188/// Represents the frames that can be read from the FIFO
189#[derive(PartialEq, Debug)]
190pub enum FifoFrame {
191    /// Sensor frame
192    SensorFrame(SensorFrameType),
193
194    /// Control frame
195    ControlFrame(ControlFrameType),
196}
197
198/// Represents the sensor frames that can be read from the FIFO
199#[derive(PartialEq, Debug)]
200pub enum SensorFrameType {
201    /// Sensor timestamp. This is appended to the *last* frame of the FIFO only if sensor time has been enabled.
202    SensorTime(u32),
203    /// Calibrated pressure. This frame is produced if only pressure output is enabled.
204    Pressure(f32),
205    /// Calibrated temperature. This frame is produced if only temperature output is enabled.
206    Temperature(f32),
207
208    /// Calibrated pressure and temperature. This frame is produced if *both* pressure and temperature output is enabled.
209    PressureAndTemperature {
210        /// Calibrated pressure.
211        pressure: f32,
212
213        /// Calibrated temperature.
214        temperature: f32,
215    },
216
217    /// Empty frame. This frame is returned when the FIFO is empty and sensor time is disabled.
218    Empty
219}
220
221/// Represents the control frames that can be read from the FIFO
222#[derive(PartialEq, Debug)]
223pub enum ControlFrameType {
224    /// A configuration error was detected while the FIFO is enabled.
225    ConfigError,
226    /// Changes has been made to any of these registers/fields while the FIFO is enabled:
227    /// - FIFO_CONFIG_1
228    /// - FIFO_CONFIG_2
229    /// - OSR
230    /// - ODR
231    /// - CONFIG
232    /// - PWR_CTRL (press_en/temp_en)
233    ConfigChange,
234}
235
236#[cfg(test)]
237mod tests {
238    use super::*;
239    #[test]
240    fn fifo_header_from_u8() {
241        let header = FifoHeader::from(0b1001_0100);
242        assert_eq!(header.fh_mode, 0b10);
243        assert_eq!(header.fh_param, 0b0101);
244    }
245
246    #[test]
247    fn fifo_header_is_control_frame() {
248        let header = FifoHeader::from(0b1001_0100);
249        assert!(!header.is_control_frame());
250
251        let header = FifoHeader::from(0b0101_0100);
252        assert!(header.is_control_frame());
253    }
254
255    #[test]
256    fn fifo_header_is_sensor_frame() {
257        let header = FifoHeader::from(0b0101_0100);
258        assert!(!header.is_sensor_frame());
259
260        let header = FifoHeader::from(0b1001_0100);
261        assert!(header.is_sensor_frame());
262    }
263
264    #[test]
265    fn fifo_header_config_error_flag() {
266        let header = FifoHeader::from(0b0100_0000);
267        assert!(!header.config_error_flag());
268
269        let header = FifoHeader::from(0b0100_0100);
270        assert!(header.config_error_flag());
271    }
272
273    #[test]
274    fn fifo_header_config_change_flag() {
275        let header = FifoHeader::from(0b0100_0000);
276        assert!(!header.config_change_flag());
277
278        let header = FifoHeader::from(0b0100_1000);
279        assert!(header.config_change_flag());
280    }
281
282    #[test]
283    fn fifo_header_sensor_time_flag() {
284        let header = FifoHeader::from(0b1000_0000);
285        assert!(!header.sensor_time_flag());
286
287        let header = FifoHeader::from(0b1010_0000);
288        assert!(header.sensor_time_flag());
289    }
290
291    #[test]
292    fn fifo_header_temperature_flag() {
293        let header = FifoHeader::from(0b1000_0000);
294        assert!(!header.temperature_flag());
295
296        let header = FifoHeader::from(0b1001_0000);
297        assert!(header.temperature_flag());
298    }
299
300    #[test]
301    fn fifo_header_pressure_flag() {
302        let header = FifoHeader::from(0b1000_0000);
303        assert!(!header.pressure_flag());
304
305        let header = FifoHeader::from(0b1000_0100);
306        assert!(header.pressure_flag());
307    }
308}