spl06_007/
lib.rs

1//! I2C driver for the SPL06-007 pressure and temperature sensor. This sensor
2//! is available as a breakout board for the Arduino platform. This driver
3//! may also work with the SPL06-001, but this has not been tested.
4//!
5//! Instantiate the Barometer struct with a reference to the I2C bus. The sensor 
6//! will then be ready to read temperature and pressure values.
7//!
8//! ```rust, no_run
9//! use spl06_007::*;
10//! use embedded_hal_mock::i2c::Mock as I2c;
11//! let mut i2c = I2c::new(&[]);
12//! 
13//! let mut barometer = Barometer::new(&mut i2c).expect("Failed to instantiate barometer");
14//! let temp = barometer.get_temperature().unwrap();
15//! let pressure = barometer.get_pressure().unwrap();
16//! let altitude = barometer.altitude(1020.0).unwrap();
17//! ```
18//!
19//! You can set the mode, sample rate, and oversampling values manually:
20//!
21//! ```rust, no_run
22//! # use spl06_007::*;
23//! # use embedded_hal_mock::i2c::Mock as I2c;
24//! # let mut i2c = I2c::new(&[]);
25//! # let mut barometer = Barometer::new(&mut i2c).expect("Failed to instantiate barometer");
26//! barometer.set_pressure_config(SampleRate::One, SampleRate::Eight);
27//! barometer.set_temperature_config(SampleRate::One, SampleRate::Eight);
28//! ```
29//!
30//! This is useful for more rapid updates, better precsion, or lower power draw.
31//!
32//! It is also possible to set the mode to `Mode::Standby` to reduce power consumption.:
33//!
34//! ```rust, no_run
35//! # use spl06_007::*;
36//! # use embedded_hal_mock::i2c::Mock as I2c;
37//! # let mut i2c = I2c::new(&[]);
38//! # let mut barometer = Barometer::new(&mut i2c).expect("Failed to instantiate barometer");
39//! barometer.set_mode(Mode::Standby);
40//! ```
41
42#![forbid(unsafe_code)]
43#![warn(missing_docs)]
44#![warn(missing_debug_implementations)]
45#![cfg_attr(not(any(test, doctest)), no_std)]
46
47extern crate embedded_hal as hal;
48extern crate libm;
49
50use embedded_hal::blocking::i2c::{Read, Write, WriteRead};
51
52const ADDR: u8 = 0x76;
53const PRS: u8 = 0x00;
54const TMP: u8 = 0x03;
55const PRS_CFG: u8 = 0x06;
56const TMP_CFG: u8 = 0x07;
57const MEAS_CFG: u8 = 0x08;
58const CFG_REG: u8 = 0x09;
59// const INT_STS: u8 = 0x0A;
60// const FIFO_STS: u8 = 0x0B;
61const RESET: u8 = 0x0C;
62const ID: u8 = 0x0D;
63const COEF: u8 = 0x10;
64
65/// Use [Barometer::set_mode] to set the mode.
66///
67/// In continuous mode, the sensor will take measurements at the rate set by
68/// [Barometer::set_pressure_config] and [Barometer::set_temperature_config]. Note that pressure
69/// readings are dependent on temperature readings, so it is not recommended to use continuous
70/// mode for pressure readings because they will be calculated using out-of-date temperature
71/// readings.
72///
73/// Temperature and Pressure modes will take a single measurement and then return to standby
74/// mode. These are used internally by the [Barometer::get_temperature] and [Barometer::get_pressure]
75/// methods and are not recommended for general use.
76#[derive(Clone, Copy, PartialEq, Eq, Debug)]
77pub enum Mode {
78    /// The default mode. The sensor will not take any measurements. It is still possible to read
79    /// the temperature and pressure, but the values will not be updated.
80    Standby = 0b000,
81    /// Take a single temperature reading and then return to standby mode.
82    Pressure = 0b001,
83    /// Take a single pressure reading and then return to standby mode.
84    Temperature = 0b010,
85    /// Take continuous pressure readings at the configured sample rate. Note that this mode is
86    /// not recommended because pressure readings are dependent on temperature readings, so
87    /// they will be calculated using out-of-date temperature readings.
88    ContinuousPressure = 0b101,
89    /// Take continuous temperature readings at the configured sample rate.
90    ContinuousTemperature = 0b110,
91    /// Take continuous pressure and temperature readings at the configured sample rate.
92    ContinuousPressureTemperature = 0b111,
93}
94
95/// Setting for the sampling and oversampling rates.
96///
97/// Use [Barometer::set_pressure_config] and [Barometer::set_temperature_config] to set the
98/// sampling and oversampling rates. The oversampling rate is the number of samples taken and
99/// averaged to produce a single reading. The sampling rate is the number of times per second
100/// that the sensor will record a new reading.
101#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
102pub enum SampleRate {
103    /// Take a single measurement per second or single oversample per measurement.
104    One = 0b000,
105    /// Two measurements per second or two oversamples per measurement. Labelled "Low Power" mode
106    /// in the datasheet.
107    Two = 0b001,
108    /// Four measurements per second or four oversamples per measurement.
109    Four = 0b010,
110    /// Eight measurements per second or eight oversamples per measurement. This is the default
111    /// value.
112    Eight = 0b011,
113    /// Sixteen measurements per second or sixteen oversamples per measurement. Labelled "Standard"
114    ///  mode in the datasheet.
115    Sixteen = 0b100,
116    /// Thirty-two measurements per second or thirty-two oversamples per measurement.
117    ThirtyTwo = 0b101,
118    /// Sixty-four measurements per second or sixty-four oversamples per measurement. Labelled
119    /// "High Precision" mode in the datasheet.
120    SixtyFour = 0b110,
121    /// One hundred twenty-eight measurements per second or one hundred twenty-eight oversamples
122    /// per measurement.
123    OneTwentyEight = 0b111,
124}
125
126// pub enum FifoStatus {
127//     Empty = 0b01,
128//     Partial = 0b00,
129//     Full = 0b10,
130// }
131
132/// The SPL06-007 barometer.
133///
134/// This struct is generic over the I2C bus type. See method documentation for details.
135#[derive(Debug)]
136pub struct Barometer<'a, I2C>
137where
138    I2C: Read + Write + WriteRead,
139{
140    i2c: &'a mut I2C,
141    calibration_data: CalibrationData,
142    temperature_oversample: SampleRate,
143    pressure_oversample: SampleRate,
144    mode: Mode,
145}
146
147impl<'a, I2C, E> Barometer<'a, I2C>
148where
149    I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
150{
151    /// Create a new instance of the barometer.
152    ///
153    /// This method will initialise the sensor with the following default settings:
154    /// - Pressure sample rate: 1
155    /// - Pressure oversample rate: 8
156    /// - Temperature oversample rate: 1
157    /// - Temperature sample rate: 8
158    /// - Mode: Continuous pressure and temperature
159    /// - FIFO disabled
160    /// - Interrupts disabled
161    pub fn new(i2c: &'a mut I2C) -> Result<Self, E> {
162        let mut barometer = Barometer {
163            i2c,
164            calibration_data: CalibrationData::default(),
165            temperature_oversample: SampleRate::Eight,
166            pressure_oversample: SampleRate::Eight,
167            mode: Mode::Standby,
168        };
169        while (barometer.read8(MEAS_CFG)? >> 7) != 1 {}
170        barometer.calibration_data = barometer.get_calibration_data()?;
171        barometer.init()?;
172        Ok(barometer)
173    }
174
175    fn init(&mut self) -> Result<(), E> {
176        self.set_pressure_config(SampleRate::One, SampleRate::Eight)?;
177        self.set_temperature_config(SampleRate::One, SampleRate::Eight)?;
178        self.set_mode(Mode::ContinuousPressureTemperature)?;
179        self.write(&[CFG_REG, 0x00])?; // disable FIFO
180        Ok(())
181    }
182
183    /// First four bits: Product ID
184    /// Last four bits: Revision ID
185    pub fn sensor_id(&mut self) -> Result<u8, E> {
186        self.read8(ID)
187    }
188
189    /// Read and calculate the temperature in degrees celsius.
190    ///
191    /// When the sensor is in standby mode or continuous pressure mode, this method will block
192    /// until a new temperature reading is available. When the sensor is in continuous temperature
193    /// mode, this method will return the latest temperature reading. In continuous mode you can
194    /// check if a new temperature reading is available using [Barometer::new_data_is_available].
195    pub fn get_temperature(&mut self) -> Result<f32, E> {
196        if self.mode == Mode::Standby || self.mode == Mode::ContinuousPressure {
197            while !self.new_data_is_available()?.0 {
198                self.set_mode(Mode::Temperature)?
199            }
200        }
201        let cal = self.calibration_data;
202        Ok(cal.c0 as f32 / 2.0 + cal.c1 as f32 * self.traw_sc()?)
203    }
204
205    /// Read and calculate the pressure in millibars
206    ///
207    /// When the sensor is in standby mode or continuous temperature mode, this method will block
208    /// until a new temperature reading is available. When the sensor is in continuous pressure
209    /// mode, this method will return the latest pressure reading. In continuous mode you can
210    /// check if a new temperature reading is available using [Barometer::new_data_is_available].
211    pub fn get_pressure(&mut self) -> Result<f32, E> {
212        if self.mode == Mode::Standby {
213            self.get_temperature()?;
214        }
215        if self.mode == Mode::Standby || self.mode == Mode::ContinuousTemperature {
216            while !self.new_data_is_available()?.1 {
217                self.set_mode(Mode::Pressure)?
218            }
219        }
220
221        let cal = self.calibration_data;
222        let traw_sc = self.traw_sc()?;
223        let praw_sc = self.praw_sc()?;
224
225        let pcomp = cal.c00 as f32
226            + praw_sc * (cal.c10 as f32 + praw_sc * (cal.c20 as f32 + praw_sc * cal.c30 as f32))
227            + traw_sc * cal.c01 as f32
228            + traw_sc * praw_sc * (cal.c11 as f32 + praw_sc * cal.c21 as f32);
229        Ok(pcomp / 100.0)
230    }
231
232    /// Read and calculate the altitude in metres
233    pub fn altitude(&mut self, sea_level_hpa: f32) -> Result<f32, E> {
234        Ok(44330.0 * (1.0 - libm::powf(self.get_pressure()? / sea_level_hpa, 0.1903)))
235    }
236
237    fn traw_sc(&mut self) -> Result<f32, E> {
238        let mut temp = self.read24(TMP)?;
239        if self.temperature_oversample > SampleRate::Eight {
240            temp <<= 1;
241        }
242        Ok(temp as f32 / self.temperature_oversample.scale_factor())
243    }
244
245    fn praw_sc(&mut self) -> Result<f32, E> {
246        let mut pressure = self.read24(PRS)?;
247        if self.pressure_oversample > SampleRate::Eight {
248            pressure <<= 1;
249        }
250        Ok(pressure as f32 / self.pressure_oversample.scale_factor())
251    }
252
253    /// Sensor data might not be available after the sensor is powered on or settings changed.
254    /// Note that you should use [Barometer::new_data_is_available] for checking if new data is available.
255    pub fn sensor_data_is_ready(&mut self) -> Result<bool, E> {
256        Ok(((self.read8(MEAS_CFG)? >> 6) & 0b1) == 1)
257    }
258
259    /// Returns a tuple of `(temperature, pressure)`. `true` if new data is available
260    pub fn new_data_is_available(&mut self) -> Result<(bool, bool), E> {
261        let byte = self.read8(MEAS_CFG)?;
262        Ok((((byte >> 5) & 1) == 1, ((byte >> 4) & 1) == 1))
263    }
264
265    // pub fn fifo_is_enabled(&mut self) -> Result<bool, E> {
266    //     let byte = self.read8(CFG_REG)? >> 1;
267    //     Ok((byte & 1) == 1)
268    // }
269
270    // pub fn fifo_status(&mut self) -> Result<FifoStatus, E> {
271    //     match self.read8(FIFO_STS)? & 0b11 {
272    //         0b01 => Ok(FifoStatus::Empty),
273    //         0b00 => Ok(FifoStatus::Partial),
274    //         0b10 => Ok(FifoStatus::Full),
275    //         _ => unreachable!("Not a valid FIFO status"),
276    //     }
277    // }
278
279    // pub fn set_fifo(&mut self, value: bool) -> Result<(), E> {
280    //     let mut reg = self.read8(CFG_REG)? & 0b11111101;
281    //     reg |= (value as u8) << 1;
282    //     self.write(&[CFG_REG, reg])
283    // }
284
285    // pub fn flush_fifo(&mut self) -> Result<(), E> {
286    //     self.write(&[RESET, 0x80])
287    // }
288
289    fn set_pressure_shift(&mut self, value: bool) -> Result<(), E> {
290        let mut reg = self.read8(CFG_REG)? & 0b11111011;
291        reg |= (value as u8) << 2;
292        self.write(&[CFG_REG, reg])
293    }
294
295    fn set_temp_shift(&mut self, value: bool) -> Result<(), E> {
296        let mut reg = self.read8(CFG_REG)? & 0b11110111;
297        reg |= (value as u8) << 3;
298        self.write(&[CFG_REG, reg])
299    }
300
301    /// Reset the sensor. This will reset all configuration registers to their default values.
302    pub fn soft_reset(&mut self) -> Result<(), E> {
303        self.write(&[RESET, 0x09])?;
304        self.init()
305    }
306
307    /// The sample rate is the number of measurements available per second.
308    /// The oversample rate is the number of individual measurements used to calculate the final
309    /// value for each final measurement. Higher oversample rates will give more accurate results.
310    pub fn set_temperature_config(
311        &mut self,
312        sample: SampleRate,
313        oversample: SampleRate,
314    ) -> Result<(), E> {
315        self.set_temp_shift(oversample > SampleRate::Eight)?;
316        self.temperature_oversample = oversample;
317        let byte = 0x80 | (sample as u8) << 4 | oversample as u8;
318        self.write(&[TMP_CFG, byte])
319    }
320
321    /// The sample rate is the number of measurements available per second.
322    /// The oversample rate is the number of individual measurements used to calculate the final
323    /// value for each final measurement. Higher oversample rates will give more accurate results.
324    ///
325    /// Note that the pressure readings are dependent on temperature readings, so the temperature
326    /// oversample rate should be equal or higher than the pressure oversample rate.
327    pub fn set_pressure_config(
328        &mut self,
329        sample: SampleRate,
330        oversample: SampleRate,
331    ) -> Result<(), E> {
332        self.set_pressure_shift(oversample > SampleRate::Eight)?;
333        self.pressure_oversample = oversample;
334        let byte = (sample as u8) << 4 | oversample as u8;
335        self.write(&[PRS_CFG, byte])
336    }
337
338    /// Set the mode of the sensor. See the [Mode] enum for more details.
339    pub fn set_mode(&mut self, mode: Mode) -> Result<(), E> {
340        self.mode = match mode {
341            Mode::Standby | Mode::Pressure | Mode::Temperature => Mode::Standby,
342            _ => mode,
343        };
344        self.write(&[MEAS_CFG, mode as u8])
345    }
346
347    fn get_calibration_data(&mut self) -> Result<CalibrationData, E> {
348        let mut data = [0; 2];
349
350        self.read(COEF, &mut data)?;
351        let mut c0 = ((data[0] as u16) << 4) | data[1] as u16 >> 4;
352        if c0 & (1 << 11) != 0 {
353            c0 |= 0xF000;
354        }
355
356        // c1
357        self.read(COEF + 1, &mut data)?;
358        let mut c1 = (((data[0] & 0xF) as u16) << 8) | data[1] as u16;
359        if c1 & (1 << 11) != 0 {
360            c1 |= 0xF000;
361        }
362
363        // c00
364        let mut data = [0; 3];
365        self.read(COEF + 3, &mut data)?;
366        let c00 = if data[0] & 0x80 != 0 { 0xFFF00000 } else { 0 }
367            | ((data[0] as u32) << 12)
368            | ((data[1] as u32) << 4)
369            | ((data[2] as u32) & 0xF0) >> 4;
370
371        // c10
372        self.read(COEF + 5, &mut data)?;
373        let c10 = if data[0] & 0x8 != 0 { 0xFFF00000 } else { 0 }
374            | ((data[0] as u32) & 0x0F) << 16
375            | (data[1] as u32) << 8
376            | data[2] as u32;
377
378        Ok(CalibrationData {
379            c0: c0 as i16,
380            c1: c1 as i16,
381            c00: c00 as i32,
382            c10: c10 as i32,
383            c01: self.read16(COEF + 8)? as i32,
384            c11: self.read16(COEF + 10)? as i32,
385            c20: self.read16(COEF + 12)? as i32,
386            c21: self.read16(COEF + 14)? as i32,
387            c30: self.read16(COEF + 16)? as i32,
388        })
389    }
390
391    fn write(&mut self, data: &[u8]) -> Result<(), E> {
392        self.i2c.write(ADDR, data)
393    }
394
395    fn read(&mut self, reg: u8, buffer: &mut [u8]) -> Result<(), E> {
396        self.i2c.write_read(ADDR, &[reg], buffer)
397    }
398
399    fn read8(&mut self, reg: u8) -> Result<u8, E> {
400        let mut buffer = [0u8];
401        match self.read(reg, &mut buffer) {
402            Ok(_) => Ok(buffer[0]),
403            Err(res) => Err(res),
404        }
405    }
406
407    fn read16(&mut self, reg: u8) -> Result<i16, E> {
408        let mut buffer = [0u8; 2];
409        match self.read(reg, &mut buffer) {
410            Ok(_) => Ok((((buffer[0] as u16) << 8) | buffer[1] as u16) as i16),
411            Err(res) => Err(res),
412        }
413    }
414
415    fn read24(&mut self, reg: u8) -> Result<i32, E> {
416        let mut buffer = [0; 3];
417        self.read(reg, &mut buffer)?;
418        let [msb, lsb, xlsb] = buffer.map(|x| x as u32);
419        let res: u32 =
420            if msb & 0x80 != 0 { 0xFF << 24 } else { 0x00 } | (msb << 16) | (lsb << 8) | xlsb;
421        Ok(res as i32)
422    }
423}
424
425#[derive(Debug, Clone, Copy, Default)]
426struct CalibrationData {
427    c0: i16,
428    c1: i16,
429    c00: i32,
430    c10: i32,
431    c01: i32,
432    c11: i32,
433    c20: i32,
434    c21: i32,
435    c30: i32,
436}
437
438impl SampleRate {
439    fn scale_factor(&self) -> f32 {
440        match self {
441            Self::One => 524288.0,
442            Self::Two => 1572864.0,
443            Self::Four => 3670016.0,
444            Self::Eight => 7864320.0,
445            Self::Sixteen => 253952.0,
446            Self::ThirtyTwo => 516096.0,
447            Self::SixtyFour => 1040384.0,
448            Self::OneTwentyEight => 2088960.0,
449        }
450    }
451}
452
453#[cfg(test)]
454mod tests {
455    use super::*;
456    use embedded_hal_mock::i2c::{Mock as I2cMock, Transaction};
457
458    fn expectations(to_add: Vec<Transaction>) -> Vec<Transaction> {
459        [
460            // Barometer::new
461            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0x80]),
462            Transaction::write_read(ADDR, vec![COEF], vec![0xc, 0xbe]),
463            Transaction::write_read(ADDR, vec![COEF + 1], vec![0xbe, 0xfc]),
464            Transaction::write_read(ADDR, vec![COEF + 3], vec![0x13, 0xd9, 0xaf]),
465            Transaction::write_read(ADDR, vec![COEF + 5], vec![0xaf, 0x2b, 0x34]),
466            Transaction::write_read(ADDR, vec![COEF + 8], vec![0xf3, 0xf7]),
467            Transaction::write_read(ADDR, vec![COEF + 10], vec![0x4, 0xff]),
468            Transaction::write_read(ADDR, vec![COEF + 12], vec![0xda, 0x5a]),
469            Transaction::write_read(ADDR, vec![COEF + 14], vec![0x0, 0xa]),
470            Transaction::write_read(ADDR, vec![COEF + 16], vec![0xfb, 0x1b]),
471            Transaction::write_read(ADDR, vec![CFG_REG], vec![0]),
472            Transaction::write(ADDR, vec![CFG_REG, 0]),
473            Transaction::write(ADDR, vec![PRS_CFG, SampleRate::Eight as u8]),
474            Transaction::write_read(ADDR, vec![CFG_REG], vec![0]),
475            Transaction::write(ADDR, vec![CFG_REG, 0]),
476            Transaction::write(ADDR, vec![TMP_CFG, 0x80 | SampleRate::Eight as u8]),
477            Transaction::write(
478                ADDR,
479                vec![MEAS_CFG, Mode::ContinuousPressureTemperature as u8],
480            ),
481            Transaction::write(ADDR, vec![CFG_REG, 0x00]),
482        ]
483        .to_vec()
484        .into_iter()
485        .chain(to_add)
486        .collect::<std::vec::Vec<_>>()
487    }
488
489    #[test]
490    fn test_barometer_new_init() {
491        let expectations = expectations(vec![]);
492        let mut i2c = I2cMock::new(&expectations);
493        Barometer::new(&mut i2c).unwrap();
494    }
495
496    #[test]
497    fn test_barometer_read() {
498        let expectations = expectations(vec![
499            Transaction::write_read(ADDR, vec![0], vec![0, 1, 2]),
500            Transaction::write_read(ADDR, vec![0], vec![0]),
501            Transaction::write_read(ADDR, vec![0], vec![0, 1]),
502            Transaction::write_read(ADDR, vec![0], vec![0, 1, 2]),
503        ]);
504        let mut i2c = I2cMock::new(&expectations);
505        let mut barometer = Barometer::new(&mut i2c).unwrap();
506
507        let mut buffer = [0; 3];
508        barometer.read(0, &mut buffer).unwrap();
509        barometer.read8(0).unwrap();
510        barometer.read16(0).unwrap();
511        barometer.read24(0).unwrap();
512        assert_eq!(buffer, [0, 1, 2]);
513    }
514
515    #[test]
516    fn test_barometer_get_calibration_data() {
517        let expectations = expectations(vec![]);
518        let mut i2c = I2cMock::new(&expectations);
519        let mut barometer = Barometer {
520            i2c: &mut i2c,
521            calibration_data: CalibrationData::default(),
522            temperature_oversample: SampleRate::Eight,
523            pressure_oversample: SampleRate::Eight,
524            mode: Mode::Standby,
525        };
526        // remainder of new
527        barometer.read8(MEAS_CFG).unwrap();
528        let cal_data = barometer.get_calibration_data().unwrap();
529        assert_eq!(cal_data.c0, 203, "c0");
530        assert_eq!(cal_data.c1, -260, "c1");
531        assert_eq!(cal_data.c00, 81306, "c00");
532        assert_eq!(cal_data.c10, -54476, "c10");
533        assert_eq!(cal_data.c01, -3081, "c01");
534        assert_eq!(cal_data.c11, 1279, "c11");
535        assert_eq!(cal_data.c20, -9638, "c20");
536        assert_eq!(cal_data.c21, 10, "c21");
537        assert_eq!(cal_data.c30, -1253, "c30");
538    }
539
540    #[test]
541    fn test_barometer_get_temperature() {
542        let expectations = expectations(vec![
543            Transaction::write_read(ADDR, vec![TMP], vec![0, 1, 2]),
544            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0]),
545            Transaction::write(ADDR, vec![MEAS_CFG, Mode::Temperature as u8]),
546            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0]),
547            Transaction::write(ADDR, vec![MEAS_CFG, Mode::Temperature as u8]),
548            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0b100000]),
549            Transaction::write_read(ADDR, vec![TMP], vec![0, 1, 2]),
550        ]);
551        let mut i2c = I2cMock::new(&expectations);
552        let mut barometer = Barometer::new(&mut i2c).unwrap();
553        barometer.mode = Mode::ContinuousPressureTemperature;
554        barometer.get_temperature().unwrap(); // TODO: test value
555        barometer.mode = Mode::Standby;
556        barometer.get_temperature().unwrap(); // TODO: test value
557    }
558
559    #[test]
560    fn test_barometer_get_pressure() {
561        let expectations = expectations(vec![
562            Transaction::write_read(ADDR, vec![TMP], vec![0, 1, 2]),
563            Transaction::write_read(ADDR, vec![PRS], vec![0, 1, 2]),
564            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0]),
565            Transaction::write(ADDR, vec![MEAS_CFG, Mode::Temperature as u8]),
566            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0]),
567            Transaction::write(ADDR, vec![MEAS_CFG, Mode::Temperature as u8]),
568            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0b100000]),
569            Transaction::write_read(ADDR, vec![TMP], vec![0, 1, 2]),
570            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0]),
571            Transaction::write(ADDR, vec![MEAS_CFG, Mode::Pressure as u8]),
572            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0b100000]),
573            Transaction::write(ADDR, vec![MEAS_CFG, Mode::Pressure as u8]),
574            Transaction::write_read(ADDR, vec![MEAS_CFG], vec![0b010000]),
575            Transaction::write_read(ADDR, vec![TMP], vec![0, 1, 2]),
576            Transaction::write_read(ADDR, vec![PRS], vec![0, 1, 2]),
577        ]);
578        let mut i2c = I2cMock::new(&expectations);
579        let mut barometer = Barometer::new(&mut i2c).unwrap();
580        barometer.mode = Mode::ContinuousPressureTemperature;
581        barometer.get_pressure().unwrap(); // TODO: test value
582        barometer.mode = Mode::Standby;
583        barometer.get_pressure().unwrap(); // TODO: test value
584    }
585
586    #[test]
587    fn test_barometer_altitude() {
588        let expectations = expectations(vec![
589            Transaction::write_read(ADDR, vec![TMP], vec![0, 1, 2]),
590            Transaction::write_read(ADDR, vec![PRS], vec![0, 1, 2]),
591        ]);
592        let mut i2c = I2cMock::new(&expectations);
593        let mut barometer = Barometer::new(&mut i2c).unwrap();
594        barometer.mode = Mode::ContinuousPressureTemperature;
595        let altitude = barometer.altitude(1000.0).unwrap();
596        assert_eq!(altitude, 1712.0905); // TODO: Use more realistic values
597    }
598}