bme280_multibus/
lib.rs

1//! BME280 driver with support for I2C and SPI buses.
2//!
3//! # Example
4//!
5//! ```
6//! # let i2c = ehm::eh0::i2c::Mock::new(&[
7//! #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
8//! #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
9//! #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF2, 0b100]),
10//! #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF4, 0b10010011]),
11//! #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF5, 0b10110000]),
12//! #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xF7], vec![0; 8]),
13//! # ]);
14//! use bme280_multibus::{Address, Bme280, Sample, Standby};
15//!
16//! const SETTINGS: bme280_multibus::Settings = bme280_multibus::Settings {
17//!     config: bme280_multibus::Config::RESET
18//!         .set_standby_time(bme280_multibus::Standby::Millis1000)
19//!         .set_filter(bme280_multibus::Filter::X16),
20//!     ctrl_meas: bme280_multibus::CtrlMeas::RESET
21//!         .set_osrs_t(bme280_multibus::Oversampling::X8)
22//!         .set_osrs_p(bme280_multibus::Oversampling::X8)
23//!         .set_mode(bme280_multibus::Mode::Normal),
24//!     ctrl_hum: bme280_multibus::Oversampling::X8,
25//! };
26//!
27//! let mut bme: Bme280<_> = Bme280::from_i2c0(i2c, Address::SdoGnd)?;
28//! bme.settings(&SETTINGS)?;
29//! let sample: Sample = bme.sample().unwrap();
30//! # bme.free().free().done();
31//! # Ok::<(), ehm::eh0::MockError>(())
32//! ```
33//!
34//! # Features
35//!
36//! * `serde`: Implement `Serialize` and `Deserialize` for `Sample`.
37#![no_std]
38#![cfg_attr(docsrs, feature(doc_cfg), feature(doc_auto_cfg))]
39#![allow(async_fn_in_trait)] // https://github.com/rust-embedded/embedded-hal/pull/515#issuecomment-1763525962
40#![warn(missing_docs)]
41#![forbid(unsafe_code)]
42
43use core::time::Duration;
44
45pub use eh0;
46pub use eh1;
47pub use eha1;
48
49/// BME280 I2C bus implementation with embedded-hal version 0.2
50pub mod i2c0;
51/// BME280 I2C bus implementation with embedded-hal version 1
52pub mod i2c1;
53/// BME280 SPI bus implementation with embedded-hal version 0.2
54pub mod spi0;
55/// BME280 SPI bus implementation with embedded-hal version 1
56pub mod spi1;
57
58/// BME280 chip ID.
59pub const CHIP_ID: u8 = 0x60;
60
61const NUM_CALIB_REG: usize = 33;
62const NUM_MEAS_REG: usize = 8;
63
64/// Maximum SPI bus frequency in hertz.
65pub const SPI_MAX_FREQ: u32 = 10_000_000;
66
67/// BME280 calibration data.
68#[derive(Debug)]
69#[allow(missing_docs)]
70pub struct Calibration {
71    t1: u16, // 0x88..0x89 buf[00:01]
72    t2: i16, // 0x8A..0x8B buf[02:03]
73    t3: i16, // 0x8C..0x8D buf[04:05]
74    p1: u16, // 0x8E..0x8F buf[06:07]
75    p2: i16, // 0x90..0x91 buf[08:09]
76    p3: i16, // 0x92..0x93 buf[10:11]
77    p4: i16, // 0x94..0x95 buf[12:13]
78    p5: i16, // 0x96..0x97 buf[14:15]
79    p6: i16, // 0x98..0x99 buf[16:17]
80    p7: i16, // 0x9A..0x9B buf[18:19]
81    p8: i16, // 0x9C..0x9D buf[20:21]
82    p9: i16, // 0x9E..0x9F buf[22:23]
83    // INTENTIONAL ONE BYTE GAP (see datasheet)
84    h1: u8,  // 0xA1       buf[25]
85    h2: i16, // 0xE1..0xE2 buf[26:27]
86    h3: u8,  // 0xE3       buf[28]
87    h4: i16, // 0xE4..0xE5[3:0] = H4 [11:4]..[3:0]
88    h5: i16, // 0xE5[7:4]..0xE6 = H5 [3:0]..[11:4]
89    h6: i8,  // 0xE7       buf[32]
90}
91
92impl From<[u8; NUM_CALIB_REG]> for Calibration {
93    fn from(buf: [u8; NUM_CALIB_REG]) -> Self {
94        Calibration {
95            t1: u16::from_le_bytes([buf[0], buf[1]]),
96            t2: i16::from_le_bytes([buf[2], buf[3]]),
97            t3: i16::from_le_bytes([buf[4], buf[5]]),
98            p1: u16::from_le_bytes([buf[6], buf[7]]),
99            p2: i16::from_le_bytes([buf[8], buf[9]]),
100            p3: i16::from_le_bytes([buf[10], buf[11]]),
101            p4: i16::from_le_bytes([buf[12], buf[13]]),
102            p5: i16::from_le_bytes([buf[14], buf[15]]),
103            p6: i16::from_le_bytes([buf[16], buf[17]]),
104            p7: i16::from_le_bytes([buf[18], buf[19]]),
105            p8: i16::from_le_bytes([buf[20], buf[21]]),
106            p9: i16::from_le_bytes([buf[22], buf[23]]),
107            // INTENTIONAL ONE BYTE GAP (see datasheet)
108            h1: buf[25],
109            h2: i16::from_le_bytes([buf[26], buf[27]]),
110            h3: buf[28],
111            h4: ((buf[29] as i8 as i16) << 4 | (buf[30] as i8 as i16) & 0xF),
112            h5: (((buf[30] as i8 as i16) & 0xF0) >> 4) | ((buf[31] as i8 as i16) << 4),
113            h6: buf[32] as i8,
114        }
115    }
116}
117
118const RESET_MAGIC: u8 = 0xB6;
119
120/// Register addresses.
121///
122/// from Table 18: Memory Map
123#[allow(dead_code)]
124mod reg {
125    pub const HUM_LSB: u8 = 0xFE;
126    pub const HUM_MSB: u8 = 0xFB;
127    pub const TEMP_XLSB: u8 = 0xFC;
128    pub const TEMP_LSB: u8 = 0xFB;
129    pub const TEMP_MSB: u8 = 0xFA;
130    pub const PRESS_XLSB: u8 = 0xF9;
131    pub const PRESS_LSB: u8 = 0xF8;
132    pub const PRESS_MSB: u8 = 0xF7;
133    pub const CONFIG: u8 = 0xF5;
134    pub const CTRL_MEAS: u8 = 0xF4;
135    pub const STATUS: u8 = 0xF3;
136    pub const CTRL_HUM: u8 = 0xF2;
137    pub const CALIB_41: u8 = 0xF0;
138    pub const CALIB_40: u8 = 0xEF;
139    pub const CALIB_39: u8 = 0xEE;
140    pub const CALIB_38: u8 = 0xED;
141    pub const CALIB_37: u8 = 0xEC;
142    pub const CALIB_36: u8 = 0xEB;
143    pub const CALIB_35: u8 = 0xEA;
144    pub const CALIB_34: u8 = 0xE9;
145    pub const CALIB_33: u8 = 0xE8;
146    pub const CALIB_32: u8 = 0xE7;
147    pub const CALIB_31: u8 = 0xE6;
148    pub const CALIB_30: u8 = 0xE5;
149    pub const CALIB_29: u8 = 0xE4;
150    pub const CALIB_28: u8 = 0xE3;
151    pub const CALIB_27: u8 = 0xE2;
152    pub const CALIB_26: u8 = 0xE1;
153    pub const RESET: u8 = 0xE0;
154    pub const ID: u8 = 0xD0;
155    pub const CALIB_25: u8 = 0xA1;
156    pub const CALIB_24: u8 = 0xA0;
157    pub const CALIB_23: u8 = 0x9F;
158    pub const CALIB_22: u8 = 0x9E;
159    pub const CALIB_21: u8 = 0x9D;
160    pub const CALIB_20: u8 = 0x9C;
161    pub const CALIB_19: u8 = 0x9B;
162    pub const CALIB_18: u8 = 0x9A;
163    pub const CALIB_17: u8 = 0x99;
164    pub const CALIB_16: u8 = 0x98;
165    pub const CALIB_15: u8 = 0x97;
166    pub const CALIB_14: u8 = 0x96;
167    pub const CALIB_13: u8 = 0x95;
168    pub const CALIB_12: u8 = 0x94;
169    pub const CALIB_11: u8 = 0x93;
170    pub const CALIB_10: u8 = 0x92;
171    pub const CALIB_09: u8 = 0x91;
172    pub const CALIB_08: u8 = 0x90;
173    pub const CALIB_07: u8 = 0x8F;
174    pub const CALIB_06: u8 = 0x8E;
175    pub const CALIB_05: u8 = 0x8D;
176    pub const CALIB_04: u8 = 0x8C;
177    pub const CALIB_03: u8 = 0x8B;
178    pub const CALIB_02: u8 = 0x8A;
179    pub const CALIB_01: u8 = 0x89;
180    pub const CALIB_00: u8 = 0x88;
181}
182
183/// Oversampling settings for temperature, pressure, and humidity data.
184#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
185#[repr(u8)]
186pub enum Oversampling {
187    /// Skipped, output set to `0x80000`.
188    Skip = 0b000,
189    /// Oversampling × 1
190    X1 = 0b001,
191    /// Oversampling × 2
192    X2 = 0b010,
193    /// Oversampling × 4
194    X4 = 0b011,
195    /// Oversampling × 8
196    X8 = 0b100,
197    /// Oversampling × 16
198    X16 = 0b101,
199}
200
201impl From<Oversampling> for u8 {
202    fn from(x: Oversampling) -> Self {
203        x as u8
204    }
205}
206
207impl Oversampling {
208    /// Reset value of the osrs fields.
209    ///
210    /// # Example
211    ///
212    /// ```
213    /// use bme280_multibus::Oversampling;
214    ///
215    /// assert_eq!(Oversampling::RESET, Oversampling::Skip);
216    /// ```
217    pub const RESET: Self = Self::Skip;
218}
219
220impl Default for Oversampling {
221    fn default() -> Self {
222        Oversampling::RESET
223    }
224}
225
226/// Sensor mode.
227#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
228#[repr(u8)]
229pub enum Mode {
230    /// Sleep mode.
231    Sleep = 0b00,
232    /// Forced mode.
233    Forced = 0b01,
234    /// Normal mode.
235    Normal = 0b11,
236}
237
238impl From<Mode> for u8 {
239    fn from(x: Mode) -> Self {
240        x as u8
241    }
242}
243
244impl Mode {
245    /// Reset value of the mode field in the [`CtrlMeas`] register.
246    ///
247    /// # Example
248    ///
249    /// ```
250    /// use bme280_multibus::Mode;
251    ///
252    /// assert_eq!(Mode::RESET, Mode::Sleep);
253    /// ```
254    pub const RESET: Self = Mode::Sleep;
255}
256
257impl Default for Mode {
258    fn default() -> Self {
259        Mode::RESET
260    }
261}
262
263/// t<sub>standby</sub> settings.
264#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
265#[repr(u8)]
266pub enum Standby {
267    /// 0.5 ms
268    Micros500 = 0b000,
269    /// 62.5 ms
270    Micros62500 = 0b001,
271    /// 125 ms
272    Millis125 = 0b010,
273    /// 250 ms
274    Millis250 = 0b011,
275    /// 500 ms
276    Millis500 = 0b100,
277    /// 1000 ms
278    Millis1000 = 0b101,
279    /// 10 ms
280    Millis10 = 0b110,
281    /// 20 ms
282    Millis20 = 0b111,
283}
284
285impl Standby {
286    /// Reset value of the standby field in the [`Config`] register.
287    ///
288    /// # Example
289    ///
290    /// ```
291    /// use bme280_multibus::Standby;
292    ///
293    /// assert_eq!(Standby::RESET, Standby::Micros500);
294    /// ```
295    pub const RESET: Self = Standby::Micros500;
296
297    /// Convert the standby enumeration to a duration.
298    ///
299    /// # Example
300    ///
301    /// ```
302    /// use bme280_multibus::Standby;
303    /// use core::time::Duration;
304    ///
305    /// assert_eq!(Standby::Micros500.duration(), Duration::from_micros(500));
306    /// assert_eq!(
307    ///     Standby::Micros62500.duration(),
308    ///     Duration::from_micros(62500)
309    /// );
310    /// assert_eq!(Standby::Millis125.duration(), Duration::from_millis(125));
311    /// assert_eq!(Standby::Millis250.duration(), Duration::from_millis(250));
312    /// assert_eq!(Standby::Millis500.duration(), Duration::from_millis(500));
313    /// assert_eq!(Standby::Millis1000.duration(), Duration::from_millis(1000));
314    /// assert_eq!(Standby::Millis10.duration(), Duration::from_millis(10));
315    /// assert_eq!(Standby::Millis20.duration(), Duration::from_millis(20));
316    /// ```
317    pub const fn duration(&self) -> Duration {
318        match self {
319            Standby::Micros500 => Duration::from_micros(500),
320            Standby::Micros62500 => Duration::from_micros(62500),
321            Standby::Millis125 => Duration::from_millis(125),
322            Standby::Millis250 => Duration::from_millis(250),
323            Standby::Millis500 => Duration::from_millis(500),
324            Standby::Millis1000 => Duration::from_millis(1000),
325            Standby::Millis10 => Duration::from_millis(10),
326            Standby::Millis20 => Duration::from_millis(20),
327        }
328    }
329}
330
331impl From<&Standby> for Duration {
332    fn from(s: &Standby) -> Self {
333        s.duration()
334    }
335}
336
337impl From<Standby> for Duration {
338    fn from(s: Standby) -> Self {
339        s.duration()
340    }
341}
342
343impl PartialOrd for Standby {
344    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
345        Some(self.duration().cmp(&other.duration()))
346    }
347}
348
349impl Ord for Standby {
350    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
351        self.duration().cmp(&other.duration())
352    }
353}
354
355impl Default for Standby {
356    fn default() -> Self {
357        Standby::RESET
358    }
359}
360
361/// Filter settings.
362#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
363#[repr(u8)]
364pub enum Filter {
365    /// Filter off.
366    Off = 0b000,
367    /// Filter coefficient of 2.
368    X2 = 0b001,
369    /// Filter coefficient of 4.
370    X4 = 0b010,
371    /// Filter coefficient of 8.
372    X8 = 0b011,
373    /// Filter coefficient of 16.
374    X16 = 0b100,
375}
376
377impl Filter {
378    /// Reset value of the filter field in the [`Config`] register.
379    ///
380    /// # Example
381    ///
382    /// ```
383    /// use bme280_multibus::Filter;
384    ///
385    /// assert_eq!(Filter::RESET, Filter::Off);
386    /// ```
387    pub const RESET: Self = Filter::Off;
388}
389
390impl Default for Filter {
391    fn default() -> Self {
392        Filter::RESET
393    }
394}
395
396impl From<Filter> for u8 {
397    fn from(x: Filter) -> Self {
398        x as u8
399    }
400}
401
402/// Config register.
403///
404/// This register sets the rate, filter, and interface options of the device.
405/// Writes to the config register in normal mode may be ignored.
406/// In sleep mode writes are not ignored.
407///
408/// All methods on this struct are constant so that you can create a
409/// configuration value at compile time.
410///
411/// # Example
412///
413/// ```
414/// use bme280_multibus::{Config, Filter, Standby};
415///
416/// const CONFIG: Config = Config::RESET
417///     .set_standby_time(Standby::Millis1000)
418///     .set_filter(Filter::X16)
419///     .set_spi3w_en(false);
420/// ```
421#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
422pub struct Config(u8);
423
424impl Config {
425    /// Get the reset value of the config register.
426    ///
427    /// # Example
428    ///
429    /// ```
430    /// use bme280_multibus::Config;
431    ///
432    /// assert_eq!(Config::RESET, Config::default());
433    /// ```
434    pub const RESET: Self = Config(0x00);
435
436    /// Set the inactive duration t<sub>standby</sub> in normal mode.
437    ///
438    /// See [`Standby`] for settings, and chapter 3.3.4 in the [datasheet] for
439    /// details.
440    ///
441    /// # Example
442    ///
443    /// ```
444    /// use bme280_multibus::{Config, Standby};
445    ///
446    /// let mut cfg: Config = Config::default();
447    /// assert_eq!(cfg.standby_time(), Standby::default());
448    /// cfg = cfg.set_standby_time(Standby::Micros500);
449    /// assert_eq!(cfg.standby_time(), Standby::Micros500);
450    /// cfg = cfg.set_standby_time(Standby::Micros62500);
451    /// assert_eq!(cfg.standby_time(), Standby::Micros62500);
452    /// cfg = cfg.set_standby_time(Standby::Millis125);
453    /// assert_eq!(cfg.standby_time(), Standby::Millis125);
454    /// cfg = cfg.set_standby_time(Standby::Millis250);
455    /// assert_eq!(cfg.standby_time(), Standby::Millis250);
456    /// cfg = cfg.set_standby_time(Standby::Millis500);
457    /// assert_eq!(cfg.standby_time(), Standby::Millis500);
458    /// cfg = cfg.set_standby_time(Standby::Millis1000);
459    /// assert_eq!(cfg.standby_time(), Standby::Millis1000);
460    /// cfg = cfg.set_standby_time(Standby::Millis10);
461    /// assert_eq!(cfg.standby_time(), Standby::Millis10);
462    /// cfg = cfg.set_standby_time(Standby::Millis20);
463    /// assert_eq!(cfg.standby_time(), Standby::Millis20);
464    /// ```
465    ///
466    /// [datasheet]: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
467    #[must_use = "set_standby_time returns a modified Config"]
468    pub const fn set_standby_time(self, s: Standby) -> Config {
469        Config((self.0 & 0x1F) | ((s as u8) << 5))
470    }
471
472    /// Get the standby time.
473    pub const fn standby_time(&self) -> Standby {
474        match self.0 >> 5 {
475            0b000 => Standby::Micros500,
476            0b001 => Standby::Micros62500,
477            0b010 => Standby::Millis125,
478            0b011 => Standby::Millis250,
479            0b100 => Standby::Millis500,
480            0b101 => Standby::Millis1000,
481            0b110 => Standby::Millis10,
482            _ => Standby::Millis20,
483        }
484    }
485
486    /// Set the time constant of the IIR filter.
487    ///
488    /// See [`Filter`] for settings, and chapter 3.4.4 in the [datasheet] for
489    /// details.
490    ///
491    /// # Example
492    ///
493    /// ```
494    /// use bme280_multibus::{Config, Filter};
495    ///
496    /// let mut cfg: Config = Config::default();
497    /// assert_eq!(cfg.filter(), Filter::default());
498    /// cfg = cfg.set_filter(Filter::Off);
499    /// assert_eq!(cfg.filter(), Filter::Off);
500    /// cfg = cfg.set_filter(Filter::X2);
501    /// assert_eq!(cfg.filter(), Filter::X2);
502    /// cfg = cfg.set_filter(Filter::X4);
503    /// assert_eq!(cfg.filter(), Filter::X4);
504    /// cfg = cfg.set_filter(Filter::X8);
505    /// assert_eq!(cfg.filter(), Filter::X8);
506    /// cfg = cfg.set_filter(Filter::X16);
507    /// assert_eq!(cfg.filter(), Filter::X16);
508    /// ```
509    ///
510    /// [datasheet]: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
511    #[must_use = "set_filter returns a modified Config"]
512    pub const fn set_filter(self, f: Filter) -> Config {
513        Config((self.0 & 0b11100011) | ((f as u8) << 2))
514    }
515
516    /// Get the filter coefficient.
517    pub const fn filter(&self) -> Filter {
518        match (self.0 >> 2) & 0b111 {
519            0b000 => Filter::Off,
520            0b001 => Filter::X2,
521            0b010 => Filter::X4,
522            0b011 => Filter::X8,
523            _ => Filter::X16,
524        }
525    }
526
527    /// Enables the 3-wire SPI itnerface when enabled.
528    ///
529    /// See chapter 6.3 in the [datasheet] for details.
530    ///
531    /// # Example
532    ///
533    /// ```
534    /// use bme280_multibus::Config;
535    ///
536    /// let mut cfg: Config = Config::default();
537    /// assert_eq!(cfg.spi3w_en(), false);
538    /// cfg = cfg.set_spi3w_en(true);
539    /// assert_eq!(cfg.spi3w_en(), true);
540    /// cfg = cfg.set_spi3w_en(false);
541    /// assert_eq!(cfg.spi3w_en(), false);
542    /// ```
543    ///
544    /// [datasheet]: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
545    #[must_use = "set_spi3w_en returns a modified Config"]
546    pub const fn set_spi3w_en(self, en: bool) -> Config {
547        if en {
548            Config(self.0 | 0b1)
549        } else {
550            Config(self.0 & !0b1)
551        }
552    }
553
554    /// Returns `true` if 3-wire SPI is enabled.
555    pub const fn spi3w_en(&self) -> bool {
556        self.0 & 0b1 == 0b1
557    }
558}
559
560impl Default for Config {
561    fn default() -> Self {
562        Config::RESET
563    }
564}
565
566/// Measurement control register.
567///
568/// This configures the pressure and temperature data acquisition options of the
569/// device.
570#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
571pub struct CtrlMeas(u8);
572
573impl CtrlMeas {
574    /// Get the reset value of the ctrl_meas register.
575    ///
576    /// # Example
577    ///
578    /// ```
579    /// use bme280_multibus::CtrlMeas;
580    ///
581    /// assert_eq!(CtrlMeas::RESET, CtrlMeas::default());
582    /// ```
583    pub const RESET: Self = CtrlMeas(0x00);
584
585    /// Set the oversampling for temperature data.
586    ///
587    /// See [`Oversampling`] for settings, and chapter 3.4.3 in the [datasheet]
588    /// for details.
589    ///
590    /// # Example
591    ///
592    /// ```
593    /// use bme280_multibus::{CtrlMeas, Oversampling};
594    ///
595    /// let mut ctrl_meas: CtrlMeas = CtrlMeas::default();
596    /// assert_eq!(ctrl_meas.osrs_t(), Oversampling::default());
597    /// ctrl_meas = ctrl_meas.set_osrs_t(Oversampling::Skip);
598    /// assert_eq!(ctrl_meas.osrs_t(), Oversampling::Skip);
599    /// ctrl_meas = ctrl_meas.set_osrs_t(Oversampling::X1);
600    /// assert_eq!(ctrl_meas.osrs_t(), Oversampling::X1);
601    /// ctrl_meas = ctrl_meas.set_osrs_t(Oversampling::X2);
602    /// assert_eq!(ctrl_meas.osrs_t(), Oversampling::X2);
603    /// ctrl_meas = ctrl_meas.set_osrs_t(Oversampling::X4);
604    /// assert_eq!(ctrl_meas.osrs_t(), Oversampling::X4);
605    /// ctrl_meas = ctrl_meas.set_osrs_t(Oversampling::X8);
606    /// assert_eq!(ctrl_meas.osrs_t(), Oversampling::X8);
607    /// ctrl_meas = ctrl_meas.set_osrs_t(Oversampling::X16);
608    /// assert_eq!(ctrl_meas.osrs_t(), Oversampling::X16);
609    /// ```
610    ///
611    /// [datasheet]: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
612    #[must_use = "set_osrs_t returns a modified CtrlMeas"]
613    pub const fn set_osrs_t(self, os: Oversampling) -> CtrlMeas {
614        CtrlMeas((self.0 & 0b00011111) | ((os as u8) << 5))
615    }
616
617    /// Get the temperature data oversampling.
618    pub const fn osrs_t(&self) -> Oversampling {
619        match (self.0 >> 5) & 0b111 {
620            0b000 => Oversampling::Skip,
621            0b001 => Oversampling::X1,
622            0b010 => Oversampling::X2,
623            0b011 => Oversampling::X4,
624            0b100 => Oversampling::X8,
625            _ => Oversampling::X16,
626        }
627    }
628
629    /// Set the oversampling for pressure data.
630    ///
631    /// See [`Oversampling`] for settings, and chapter 3.4.2 in the [datasheet]
632    /// for details.
633    ///
634    /// # Example
635    ///
636    /// ```
637    /// use bme280_multibus::{CtrlMeas, Oversampling};
638    ///
639    /// let mut ctrl_meas: CtrlMeas = CtrlMeas::default();
640    /// assert_eq!(ctrl_meas.osrs_p(), Oversampling::default());
641    /// ctrl_meas = ctrl_meas.set_osrs_p(Oversampling::Skip);
642    /// assert_eq!(ctrl_meas.osrs_p(), Oversampling::Skip);
643    /// ctrl_meas = ctrl_meas.set_osrs_p(Oversampling::X1);
644    /// assert_eq!(ctrl_meas.osrs_p(), Oversampling::X1);
645    /// ctrl_meas = ctrl_meas.set_osrs_p(Oversampling::X2);
646    /// assert_eq!(ctrl_meas.osrs_p(), Oversampling::X2);
647    /// ctrl_meas = ctrl_meas.set_osrs_p(Oversampling::X4);
648    /// assert_eq!(ctrl_meas.osrs_p(), Oversampling::X4);
649    /// ctrl_meas = ctrl_meas.set_osrs_p(Oversampling::X8);
650    /// assert_eq!(ctrl_meas.osrs_p(), Oversampling::X8);
651    /// ctrl_meas = ctrl_meas.set_osrs_p(Oversampling::X16);
652    /// assert_eq!(ctrl_meas.osrs_p(), Oversampling::X16);
653    /// ```
654    ///
655    /// [datasheet]: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
656    #[must_use = "set_osrs_p returns a modified CtrlMeas"]
657    pub const fn set_osrs_p(self, os: Oversampling) -> CtrlMeas {
658        CtrlMeas((self.0 & 0b11100011) | ((os as u8) << 2))
659    }
660
661    /// Get the pressure data oversampling.
662    pub const fn osrs_p(&self) -> Oversampling {
663        match (self.0 >> 2) & 0b111 {
664            0b000 => Oversampling::Skip,
665            0b001 => Oversampling::X1,
666            0b010 => Oversampling::X2,
667            0b011 => Oversampling::X4,
668            0b100 => Oversampling::X8,
669            _ => Oversampling::X16,
670        }
671    }
672
673    /// Set the sensor mode for the device.
674    ///
675    /// See [`Mode`] for setting, and chapter 3.3 in the [datasheet] for details.
676    ///
677    /// # Example
678    ///
679    /// ```
680    /// use bme280_multibus::{CtrlMeas, Mode};
681    ///
682    /// let mut ctrl_meas: CtrlMeas = CtrlMeas::default();
683    /// assert_eq!(ctrl_meas.mode(), Mode::default());
684    /// ctrl_meas = ctrl_meas.set_mode(Mode::Sleep);
685    /// assert_eq!(ctrl_meas.mode(), Mode::Sleep);
686    /// ctrl_meas = ctrl_meas.set_mode(Mode::Forced);
687    /// assert_eq!(ctrl_meas.mode(), Mode::Forced);
688    /// ctrl_meas = ctrl_meas.set_mode(Mode::Normal);
689    /// assert_eq!(ctrl_meas.mode(), Mode::Normal);
690    /// ```
691    ///
692    /// [datasheet]: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
693    #[must_use = "set_osrs_p returns a modified CtrlMeas"]
694    pub const fn set_mode(self, m: Mode) -> CtrlMeas {
695        CtrlMeas((self.0 & 0xFC) | (m as u8))
696    }
697
698    /// Get the mode.
699    pub const fn mode(&self) -> Mode {
700        match self.0 & 0b11 {
701            0b00 => Mode::Sleep,
702            0b11 => Mode::Normal,
703            _ => Mode::Forced,
704        }
705    }
706}
707
708impl Default for CtrlMeas {
709    fn default() -> Self {
710        CtrlMeas::RESET
711    }
712}
713
714/// Status register
715#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
716pub struct Status(u8);
717
718impl Status {
719    /// Get the reset value of the ctrl_meas register.
720    ///
721    /// # Example
722    ///
723    /// ```
724    /// use bme280_multibus::Status;
725    ///
726    /// assert_eq!(Status::RESET, Status::default());
727    /// ```
728    pub const RESET: Self = Status(0x00);
729
730    /// Measuring field.
731    ///
732    /// Automatically set to `true` whenever a conversion is running and back to
733    /// `false` when the results have been transferred to the data registers.
734    ///
735    /// # Example
736    ///
737    /// ```
738    /// assert!(!bme280_multibus::Status::RESET.measuring());
739    /// ```
740    pub const fn measuring(&self) -> bool {
741        self.0 & (1 << 3) != 0
742    }
743
744    /// im_update field.
745    ///
746    /// Automatically set to `true` when the NVM data are being copied to image
747    /// registers and back to `false` when the copying is done.
748    /// The data is copied at power-on-reset and before every conversion.
749    ///
750    /// # Example
751    ///
752    /// ```
753    /// assert!(!bme280_multibus::Status::RESET.im_update());
754    /// ```
755    pub const fn im_update(&self) -> bool {
756        self.0 & 1 != 0
757    }
758}
759
760impl core::fmt::Display for Status {
761    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
762        f.debug_struct("Status")
763            .field("measuring", &self.measuring())
764            .field("im_update", &self.im_update())
765            .finish()
766    }
767}
768
769impl Default for Status {
770    fn default() -> Self {
771        Status::RESET
772    }
773}
774
775/// BME280 initialization settings.
776#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
777pub struct Settings {
778    /// `config` register value.
779    pub config: Config,
780    /// `ctrl_meas` register value.
781    pub ctrl_meas: CtrlMeas,
782    /// `ctrl_hum` register value.
783    pub ctrl_hum: Oversampling,
784}
785
786impl Settings {
787    /// Create a new settings structure.
788    ///
789    /// # Example
790    ///
791    /// ```
792    /// use bme280_multibus::{Config, CtrlMeas, Filter, Mode, Oversampling, Settings, Standby};
793    ///
794    /// const SETTINGS: Settings = Settings {
795    ///     config: Config::RESET
796    ///         .set_standby_time(Standby::Millis1000)
797    ///         .set_filter(Filter::X16),
798    ///     ctrl_meas: CtrlMeas::RESET
799    ///         .set_osrs_t(Oversampling::X16)
800    ///         .set_osrs_p(Oversampling::X16)
801    ///         .set_mode(Mode::Normal),
802    ///     ctrl_hum: Oversampling::X16,
803    /// };
804    /// ```
805    pub const fn new() -> Settings {
806        Settings {
807            config: Config::RESET,
808            ctrl_meas: CtrlMeas::RESET,
809            ctrl_hum: Oversampling::RESET,
810        }
811    }
812}
813
814impl Default for Settings {
815    fn default() -> Self {
816        Settings::new()
817    }
818}
819
820/// A sensor sample from the BME280.
821#[derive(Debug, Clone, Copy)]
822#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
823pub struct Sample {
824    /// Temperature reading in celsius.
825    pub temperature: f32,
826    /// Pressure reading in pascal.
827    pub pressure: f32,
828    /// Humidity in perfect relative.
829    pub humidity: f32,
830}
831
832impl Sample {
833    fn from_raw<B>(buf: &[u8; NUM_MEAS_REG], cal: &Calibration) -> Result<Self, Error<B>> {
834        // The magical math and magical numbers come from the datasheet.
835        // I am not to blame for this.
836
837        // msb [7:0] = p[19:12]
838        // lsb [7:0] = p[11:4]
839        // xlsb[7:4] = p[3:0]
840        let p: u32 = ((buf[0] as u32) << 12) | ((buf[1] as u32) << 4) | ((buf[2] as u32) >> 4);
841        // msb [7:0] = t[19:12]
842        // lsb [7:0] = t[11:4]
843        // xlsb[7:4] = t[3:0]
844        let t: u32 = ((buf[3] as u32) << 12) | ((buf[4] as u32) << 4) | ((buf[5] as u32) >> 4);
845        // msb [7:0] = h[15:8]
846        // lsb [7:0] = h[7:0]
847        let h: u32 = ((buf[6] as u32) << 8) | (buf[7] as u32);
848
849        if t == 0x80000000 || p == 0x80000000 || h == 0x8000 {
850            return Err(Error::Sample);
851        }
852
853        let p: i32 = p as i32;
854        let t: i32 = t as i32;
855        let h: i32 = h as i32;
856
857        let var1: i32 = (((t >> 3) - ((cal.t1 as i32) << 1)) * (cal.t2 as i32)) >> 11;
858        let var2: i32 = (((((t >> 4) - (cal.t1 as i32)) * ((t >> 4) - (cal.t1 as i32))) >> 12)
859            * (cal.t3 as i32))
860            >> 14;
861
862        let t_fine: i32 = var1 + var2;
863
864        let temperatue: i32 = (t_fine * 5 + 128) >> 8;
865        let temperature: f32 = (temperatue as f32) / 100.0;
866
867        let var1: i64 = (t_fine as i64) - 128000;
868        let var2: i64 = var1 * var1 * (cal.p6 as i64);
869        let var2: i64 = var2 + ((var1 * (cal.p5 as i64)) << 17);
870        let var2: i64 = var2 + ((cal.p4 as i64) << 35);
871        let var1: i64 = ((var1 * var1 * (cal.p3 as i64)) >> 8) + ((var1 * (cal.p2 as i64)) << 12);
872        let var1: i64 = ((((1i64) << 47) + var1) * (cal.p1 as i64)) >> 33;
873        let pressure: f32 = if var1 == 0 {
874            0.0
875        } else {
876            let var3: i64 = 1048576 - (p as i64);
877            let var3: i64 = (((var3 << 31) - var2) * 3125) / var1;
878            let var1: i64 = ((cal.p9 as i64) * (var3 >> 13) * (var3 >> 13)) >> 25;
879            let var2: i64 = ((cal.p8 as i64) * var3) >> 19;
880
881            let var3: i64 = ((var3 + var1 + var2) >> 8) + ((cal.p7 as i64) << 4);
882            (var3 as f32) / 256.0
883        };
884
885        let var1: i32 = t_fine - 76800i32;
886        let var1: i32 =
887            ((((h << 14) - ((cal.h4 as i32) << 20) - ((cal.h5 as i32) * var1)) + 16384i32) >> 15)
888                * (((((((var1 * (cal.h6 as i32)) >> 10)
889                    * (((var1 * (cal.h3 as i32)) >> 11) + (32768i32)))
890                    >> 10)
891                    + (2097152i32))
892                    * (cal.h2 as i32)
893                    + 8192)
894                    >> 14);
895        let var1: i32 = var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * (cal.h1 as i32)) >> 4);
896        let var1: i32 = if var1 < 0 { 0 } else { var1 };
897        let var1: i32 = if var1 > 419430400 { 419430400 } else { var1 };
898        let humidity: f32 = ((var1 >> 12) as f32) / 1024.0;
899
900        Ok(Sample {
901            temperature,
902            pressure,
903            humidity,
904        })
905    }
906}
907
908/// I2C device address.
909#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
910#[repr(u8)]
911pub enum Address {
912    /// SDO pin is connected to GND.
913    SdoGnd = 0x76,
914    /// SDO pin is connected to V<sub>DDIO</sub>
915    SdoVddio = 0x77,
916}
917
918/// Sampling error.
919#[derive(Debug, PartialEq, Eq)]
920pub enum Error<B> {
921    /// Bus error.
922    Bus(B),
923    /// Sample error.
924    ///
925    /// This is returned when the sample registers hold the reset value.
926    /// This may indicate:
927    /// * The power-on-time delay was not observed.
928    /// * [`Oversampling::Skip`] was used for humidity, temperature, or pressure.
929    /// * The BME280 was not configured.
930    Sample,
931}
932
933/// BME280 bus.
934pub trait Bme280Bus {
935    /// BME280 bus error.
936    type Error;
937
938    /// Read from the BME280.
939    ///
940    /// # I2C
941    ///
942    /// ```text
943    /// Read example (BME280 Datasheet Figure 10: I2C multiple byte read)
944    /// +-------+---------------+----+------+------------------+------+
945    /// | Start | Slave Address | RW | ACKS | Register Address | ACKS |
946    /// +-------+---------------+----+------+------------------+------+
947    /// | S     | 111011x       |  0 |      | xxxxxxxx         |      |
948    /// +-------+---------------+----+------+------------------+------+
949    ///
950    ///     +-------+---------------+----+------+---------------+------+---------------+--------+------+
951    /// ... | Start | Slave Address | RW | ACKS | Register Data | ACKM | Register Data | NOACKM | Stop |
952    ///     +-------+---------------+----+------+---------------+------+---------------+--------+------+
953    /// ... | S     | 111011x       |  1 |      | xxxxxxxx      |      | xxxxxxxx      |        | P    |
954    ///     +-------+---------------+----+------+---------------+------+---------------+--------+------+
955    /// ```
956    ///
957    /// # SPI
958    ///
959    /// ```text
960    /// Read example (BME280 Datasheet Figure 13: SPI multiple byte read)
961    /// +-------+----+------------------+---------------+
962    /// | Start | RW | Register Address | Register Data |
963    /// +-------+----+------------------+---------------+
964    /// | CSB=0 |  1 | xxxxxxx          | xxxxxxxx      |
965    /// +-------+----+------------------+---------------+
966    ///
967    ///     +---------------+-------+
968    /// ... | Register Data | Stop  |
969    ///     +---------------+-------+
970    /// ... | xxxxxxxx      | CSB=0 |
971    ///     +---------------+-------+
972    /// ```
973    fn read_regs(&mut self, reg: u8, buf: &mut [u8]) -> Result<(), Self::Error>;
974
975    /// Write a single register to the BME280.
976    ///
977    /// # I2C
978    ///
979    /// ```text
980    /// Write example (BME280 Datasheet Figure 9: I2C multiple byte write)
981    /// +-------+---------------+----+------+------------------+------+---------------+------+
982    /// | Start | Slave Address | RW | ACKS | Register Address | ACKS | Register Data | ACKS |
983    /// +-------+---------------+----+------+------------------+------+---------------+------+
984    /// | S     | 111011x       |  0 |      | xxxxxxxx         |      | xxxxxxxx      |      |
985    /// +-------+---------------+----+------+------------------+------+---------------+------+
986    ///
987    ///     +------------------+------+---------------+------+------+
988    /// ... | Register Address | ACKS | Register Data | ACKS | Stop |
989    ///     +------------------+------+---------------+------+------+
990    /// ... | xxxxxxxx         |      | xxxxxxxx      |      | P    |
991    ///     +------------------+------+---------------+------+------+
992    /// ```
993    ///
994    /// # SPI
995    ///
996    /// ```text
997    /// Write example (BME280 Datasheet Figure 12: SPI multiple byte write)
998    /// +-------+----+------------------+---------------+
999    /// | Start | RW | Register Address | Register Data |
1000    /// +-------+----+------------------+---------------+
1001    /// | CSB=0 |  0 | xxxxxxx          | xxxxxxxx      |
1002    /// +-------+----+------------------+---------------+
1003    ///
1004    ///     +----+------------------+---------------+-------+
1005    /// ... | RW | Register Address | Register Data | Stop  |
1006    ///     +----+------------------+---------------+-------+
1007    /// ... |  0 | xxxxxxx          | xxxxxxxx      | CSB=0 |
1008    ///     +----+------------------+---------------+-------+
1009    /// ```
1010    fn write_reg(&mut self, reg: u8, data: u8) -> Result<(), Self::Error>;
1011
1012    /// Read the calibration from the chip.
1013    fn calibration(&mut self) -> Result<Calibration, Self::Error> {
1014        const FIRST: usize = (reg::CALIB_25 - reg::CALIB_00 + 1) as usize;
1015        debug_assert_eq!(FIRST, 26);
1016        const SECOND: usize = (reg::CALIB_32 - reg::CALIB_26 + 1) as usize;
1017        debug_assert_eq!((FIRST + SECOND), NUM_CALIB_REG);
1018
1019        let mut buf: [u8; NUM_CALIB_REG] = [0; NUM_CALIB_REG];
1020        self.read_regs(reg::CALIB_00, &mut buf[0..FIRST])?;
1021        self.read_regs(reg::CALIB_26, &mut buf[FIRST..(FIRST + SECOND)])?;
1022
1023        Ok(buf.into())
1024    }
1025}
1026
1027/// Asynchronous BME280 bus.
1028pub trait Bme280BusAsync {
1029    /// BME280 bus error.
1030    type Error;
1031
1032    /// Read from the BME280.
1033    ///
1034    /// See [`Bme280Bus::read_regs`] for more information.
1035    async fn read_regs(&mut self, reg: u8, buf: &mut [u8]) -> Result<(), Self::Error>;
1036
1037    /// Write a single register to the BME280.
1038    ///
1039    /// See [`Bme280Bus::write_reg`] for more information.
1040    async fn write_reg(&mut self, reg: u8, data: u8) -> Result<(), Self::Error>;
1041
1042    /// Read the calibration from the chip.
1043    async fn calibration(&mut self) -> Result<crate::Calibration, Self::Error> {
1044        const FIRST: usize = (crate::reg::CALIB_25 - crate::reg::CALIB_00 + 1) as usize;
1045        debug_assert_eq!(FIRST, 26);
1046        const SECOND: usize = (crate::reg::CALIB_32 - crate::reg::CALIB_26 + 1) as usize;
1047        debug_assert_eq!((FIRST + SECOND), crate::NUM_CALIB_REG);
1048
1049        let mut buf: [u8; crate::NUM_CALIB_REG] = [0; crate::NUM_CALIB_REG];
1050
1051        self.read_regs(crate::reg::CALIB_00, &mut buf[0..FIRST])
1052            .await?;
1053        self.read_regs(crate::reg::CALIB_26, &mut buf[FIRST..(FIRST + SECOND)])
1054            .await?;
1055
1056        Ok(buf.into())
1057    }
1058}
1059
1060/// BME280 driver.
1061#[derive(Debug)]
1062pub struct Bme280<B> {
1063    bus: B,
1064    cal: Calibration,
1065}
1066
1067impl<I2C, E> Bme280<crate::i2c0::Bme280Bus<I2C>>
1068where
1069    I2C: eh0::blocking::i2c::Write<Error = E> + eh0::blocking::i2c::WriteRead<Error = E>,
1070{
1071    /// Creates a new `Bme280` driver from a I2C peripheral, and an I2C
1072    /// device address.
1073    ///
1074    /// # Example
1075    ///
1076    /// ```
1077    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1078    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1079    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1080    /// # ]);
1081    /// use bme280_multibus::{Address, Bme280};
1082    ///
1083    /// let mut bme: Bme280<_> = Bme280::from_i2c0(i2c, Address::SdoGnd)?;
1084    /// # bme.free().free().done();
1085    /// # Ok::<(), ehm::eh0::MockError>(())
1086    /// ```
1087    pub fn from_i2c0(i2c: I2C, address: crate::Address) -> Result<Self, E> {
1088        let bus = crate::i2c0::Bme280Bus::new(i2c, address);
1089        Self::new(bus)
1090    }
1091}
1092
1093impl<I2C, E> Bme280<crate::i2c1::Bme280Bus<I2C>>
1094where
1095    I2C: eh1::i2c::I2c<Error = E>,
1096{
1097    /// Creates a new `Bme280` driver from a I2C peripheral, and an I2C
1098    /// device address.
1099    ///
1100    /// # Example
1101    ///
1102    /// ```
1103    /// # let i2c = ehm::eh1::i2c::Mock::new(&[
1104    /// #   ehm::eh1::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1105    /// #   ehm::eh1::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1106    /// # ]);
1107    /// use bme280_multibus::{i2c1::Address, Bme280};
1108    ///
1109    /// let mut bme: Bme280<_> = Bme280::from_i2c1(i2c, Address::SdoGnd)?;
1110    /// # bme.free().free().done();
1111    /// # Ok::<(), eh1::i2c::ErrorKind>(())
1112    /// ```
1113    pub fn from_i2c1(i2c: I2C, address: crate::i2c1::Address) -> Result<Self, E> {
1114        let bus = crate::i2c1::Bme280Bus::new(i2c, address);
1115        Self::new(bus)
1116    }
1117}
1118
1119impl<SPI, CS, SpiError, PinError> Bme280<crate::spi0::Bme280Bus<SPI, CS>>
1120where
1121    SPI: eh0::blocking::spi::Transfer<u8, Error = SpiError>
1122        + eh0::blocking::spi::Write<u8, Error = SpiError>,
1123    CS: eh0::digital::v2::OutputPin<Error = PinError>,
1124{
1125    /// Creates a new `Bme280` driver from an embedded-hal version 0.2 SPI
1126    /// peripheral and a chip select digital I/O pin.
1127    ///
1128    /// # Safety
1129    ///
1130    /// The chip select pin must be high before being passed to this function.
1131    ///
1132    /// # Example
1133    ///
1134    /// ```
1135    /// # let spi = ehm::eh0::spi::Mock::new(&[
1136    /// #   ehm::eh0::spi::Transaction::write(vec![0x88]),
1137    /// #   ehm::eh0::spi::Transaction::transfer(vec![0; 26], vec![0; 26]),
1138    /// #   ehm::eh0::spi::Transaction::write(vec![0xE1]),
1139    /// #   ehm::eh0::spi::Transaction::transfer(vec![0; 7], vec![0; 7]),
1140    /// # ]);
1141    /// # let mut pin = ehm::eh0::pin::Mock::new(&[
1142    /// #    ehm::eh0::pin::Transaction::set(ehm::eh0::pin::State::High),
1143    /// #    ehm::eh0::pin::Transaction::set(ehm::eh0::pin::State::Low),
1144    /// #    ehm::eh0::pin::Transaction::set(ehm::eh0::pin::State::High),
1145    /// #    ehm::eh0::pin::Transaction::set(ehm::eh0::pin::State::Low),
1146    /// #    ehm::eh0::pin::Transaction::set(ehm::eh0::pin::State::High),
1147    /// # ]);
1148    /// use bme280_multibus::Bme280;
1149    /// use eh0::digital::v2::OutputPin;
1150    ///
1151    /// pin.set_high()?;
1152    /// let mut bme: Bme280<_> = Bme280::from_spi0(spi, pin)?;
1153    /// # let (mut spi, mut pin) = bme.free().free();
1154    /// # spi.done(); pin.done();
1155    /// # Ok::<(), bme280_multibus::spi0::Error<ehm::eh0::MockError, ehm::eh0::MockError>>(())
1156    /// ```
1157    #[allow(clippy::unnecessary_safety_doc)]
1158    pub fn from_spi0(spi: SPI, cs: CS) -> Result<Self, crate::spi0::Error<SpiError, PinError>> {
1159        let bus = crate::spi0::Bme280Bus::new(spi, cs);
1160        Self::new(bus)
1161    }
1162}
1163
1164impl<SPI, E> Bme280<crate::spi1::Bme280Bus<SPI>>
1165where
1166    SPI: eh1::spi::SpiDevice<Error = E>,
1167{
1168    /// Creates a new `Bme280` driver from an embedded-hal version 1 SPI device.
1169    ///
1170    /// # Example
1171    ///
1172    /// ```
1173    /// # let spi = ehm::eh1::spi::Mock::new(&[
1174    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1175    /// #   ehm::eh1::spi::Transaction::write(0x88),
1176    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1177    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1178    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1179    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1180    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1181    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1182    /// # ]);
1183    /// use bme280_multibus::Bme280;
1184    ///
1185    /// let mut bme: Bme280<_> = Bme280::from_spi1(spi)?;
1186    /// # bme.free().free().done();
1187    /// # Ok::<(), eh1::spi::ErrorKind>(())
1188    /// ```
1189    pub fn from_spi1(spi: SPI) -> Result<Self, E> {
1190        let bus: crate::spi1::Bme280Bus<SPI> = crate::spi1::Bme280Bus::new(spi);
1191        Self::new(bus)
1192    }
1193}
1194
1195impl<SPI, E> Bme280<crate::spi1::Bme280Bus<SPI>>
1196where
1197    SPI: eha1::spi::SpiDevice<Error = E>,
1198{
1199    /// Creates a new `Bme280` driver from an embedded-hal-async SPI device.
1200    ///
1201    /// # Example
1202    ///
1203    /// ```
1204    /// # #[tokio::main(flavor = "current_thread")]
1205    /// # async fn main() -> Result<(), eh1::spi::ErrorKind> {
1206    /// # let spi = ehm::eh1::spi::Mock::new(&[
1207    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1208    /// #   ehm::eh1::spi::Transaction::write(0x88),
1209    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1210    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1211    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1212    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1213    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1214    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1215    /// # ]);
1216    /// use bme280_multibus::Bme280;
1217    ///
1218    /// let bme: Bme280<_> = Bme280::from_spia0a(spi).await?;
1219    /// # bme.free().free().done(); Ok(()) }
1220    /// ```
1221    pub async fn from_spia0a(spi: SPI) -> Result<Self, E> {
1222        let bus = crate::spi1::Bme280Bus::new(spi);
1223        Self::new_async(bus).await
1224    }
1225}
1226
1227impl<B, E> Bme280<B>
1228where
1229    B: Bme280BusAsync<Error = E>,
1230{
1231    /// Create a new BME280 from a [`Bme280BusAsync`].
1232    ///
1233    /// # Example
1234    ///
1235    /// ```
1236    /// # #[tokio::main(flavor = "current_thread")]
1237    /// # async fn main() -> Result<(), eh1::spi::ErrorKind> {
1238    /// # let spi = ehm::eh1::spi::Mock::new(&[
1239    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1240    /// #   ehm::eh1::spi::Transaction::write(0x88),
1241    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1242    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1243    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1244    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1245    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1246    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1247    /// # ]);
1248    /// use bme280_multibus::{spi1::Bme280Bus, Bme280};
1249    ///
1250    /// let bus: Bme280Bus<_> = Bme280Bus::new(spi);
1251    /// let bme: Bme280<_> = Bme280::new_async(bus).await?;
1252    /// # bme.free().free().done(); Ok(()) }
1253    /// ```
1254    pub async fn new_async(mut bus: B) -> Result<Self, E> {
1255        let cal: Calibration = bus.calibration().await?;
1256        Ok(Self { bus, cal })
1257    }
1258
1259    /// BME280 chip ID.
1260    ///
1261    /// The return value is a constant, [`CHIP_ID`].
1262    ///
1263    /// This register is useful as a sanity check to ensure communications are
1264    /// working with the BME280.
1265    ///
1266    /// # Example
1267    ///
1268    /// ```
1269    /// # #[tokio::main(flavor = "current_thread")]
1270    /// # async fn main() -> Result<(), eh1::spi::ErrorKind> {
1271    /// # let spi = ehm::eh1::spi::Mock::new(&[
1272    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1273    /// #   ehm::eh1::spi::Transaction::write(0x88),
1274    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1275    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1276    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1277    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1278    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1279    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1280    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1281    /// #   ehm::eh1::spi::Transaction::write(0xD0),
1282    /// #   ehm::eh1::spi::Transaction::read(0x60),
1283    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1284    /// # ]);
1285    /// use bme280_multibus::{spi1::Bme280Bus, Bme280, CHIP_ID};
1286    ///
1287    /// let mut bme: Bme280<_> = Bme280::from_spia0a(spi).await?;
1288    /// let chip_id: u8 = bme.chip_id_async().await?;
1289    /// assert_eq!(chip_id, CHIP_ID);
1290    /// # bme.free().free().done(); Ok(()) }
1291    /// ```
1292    pub async fn chip_id_async(&mut self) -> Result<u8, E> {
1293        let mut buf: [u8; 1] = [0];
1294        self.bus.read_regs(reg::ID, &mut buf).await?;
1295        Ok(buf[0])
1296    }
1297
1298    /// Reset the BME280.
1299    ///
1300    /// # Example
1301    ///
1302    /// ```
1303    /// # #[tokio::main(flavor = "current_thread")]
1304    /// # async fn main() -> Result<(), eh1::spi::ErrorKind> {
1305    /// # let spi = ehm::eh1::spi::Mock::new(&[
1306    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1307    /// #   ehm::eh1::spi::Transaction::write(0x88),
1308    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1309    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1310    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1311    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1312    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1313    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1314    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1315    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0xE0 & !0x80, 0xB6]),
1316    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1317    /// # ]);
1318    /// use bme280_multibus::{spi1::Bme280Bus, Bme280};
1319    ///
1320    /// let mut bme: Bme280<_> = Bme280::from_spia0a(spi).await?;
1321    /// bme.reset_async().await?;
1322    /// # bme.free().free().done(); Ok(()) }
1323    /// ```
1324    pub async fn reset_async(&mut self) -> Result<(), E> {
1325        self.bus.write_reg(reg::RESET, RESET_MAGIC).await
1326    }
1327
1328    /// Get the status of the device.
1329    ///
1330    /// # Example
1331    ///
1332    /// ```
1333    /// # #[tokio::main(flavor = "current_thread")]
1334    /// # async fn main() -> Result<(), eh1::spi::ErrorKind> {
1335    /// # let spi = ehm::eh1::spi::Mock::new(&[
1336    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1337    /// #   ehm::eh1::spi::Transaction::write(0x88),
1338    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1339    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1340    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1341    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1342    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1343    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1344    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1345    /// #   ehm::eh1::spi::Transaction::write(0xF3),
1346    /// #   ehm::eh1::spi::Transaction::read(0x00),
1347    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1348    /// # ]);
1349    /// use bme280_multibus::{spi1::Bme280Bus, Bme280, Status};
1350    ///
1351    /// let mut bme: Bme280<_> = Bme280::from_spia0a(spi).await?;
1352    /// let status: Status = bme.status_async().await?;
1353    /// # bme.free().free().done(); Ok(()) }
1354    /// ```
1355    pub async fn status_async(&mut self) -> Result<Status, E> {
1356        let mut buf: [u8; 1] = [0];
1357        self.bus.read_regs(reg::STATUS, &mut buf).await?;
1358        Ok(Status(buf[0]))
1359    }
1360
1361    /// Configure the BME280 settings.
1362    ///
1363    /// # Example
1364    ///
1365    /// ```
1366    /// # #[tokio::main(flavor = "current_thread")]
1367    /// # async fn main() -> Result<(), eh1::spi::ErrorKind> {
1368    /// # let spi = ehm::eh1::spi::Mock::new(&[
1369    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1370    /// #   ehm::eh1::spi::Transaction::write(0x88),
1371    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1372    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1373    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1374    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1375    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1376    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1377    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1378    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0xF2 & !0x80, 0b100]),
1379    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1380    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1381    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0xF4 & !0x80, 0b10010011]),
1382    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1383    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1384    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0xF5 & !0x80, 0b10110000]),
1385    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1386    /// # ]);
1387    /// use bme280_multibus::{
1388    ///     spi1::Bme280Bus, Bme280, Config, CtrlMeas, Filter, Mode, Oversampling, Settings, Standby,
1389    /// };
1390    ///
1391    /// const SETTINGS: Settings = Settings {
1392    ///     config: Config::RESET
1393    ///         .set_standby_time(Standby::Millis1000)
1394    ///         .set_filter(Filter::X16),
1395    ///     ctrl_meas: CtrlMeas::RESET
1396    ///         .set_osrs_t(Oversampling::X8)
1397    ///         .set_osrs_p(Oversampling::X8)
1398    ///         .set_mode(Mode::Normal),
1399    ///     ctrl_hum: Oversampling::X8,
1400    /// };
1401    ///
1402    /// let mut bme: Bme280<_> = Bme280::from_spia0a(spi).await?;
1403    /// bme.settings_async(&SETTINGS).await?;
1404    /// # bme.free().free().done(); Ok(()) }
1405    /// ```
1406    pub async fn settings_async(&mut self, settings: &Settings) -> Result<(), E> {
1407        self.bus
1408            .write_reg(reg::CTRL_HUM, settings.ctrl_hum as u8)
1409            .await?;
1410        self.bus
1411            .write_reg(reg::CTRL_MEAS, settings.ctrl_meas.0)
1412            .await?;
1413        self.bus.write_reg(reg::CONFIG, settings.config.0).await
1414    }
1415
1416    /// Read a sample from the BME280.
1417    ///
1418    /// ```
1419    /// # #[tokio::main(flavor = "current_thread")]
1420    /// # async fn main() -> Result<(), eh1::spi::ErrorKind> {
1421    /// # let spi = ehm::eh1::spi::Mock::new(&[
1422    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1423    /// #   ehm::eh1::spi::Transaction::write(0x88),
1424    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 26]),
1425    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1426    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1427    /// #   ehm::eh1::spi::Transaction::write(0xE1),
1428    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 7]),
1429    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1430    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1431    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0xF2 & !0x80, 0b100]),
1432    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1433    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1434    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0xF4 & !0x80, 0b10010011]),
1435    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1436    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1437    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0xF5 & !0x80, 0b10110000]),
1438    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1439    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1440    /// #   ehm::eh1::spi::Transaction::write(0xF7),
1441    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0; 8]),
1442    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1443    /// # ]);
1444    /// use bme280_multibus::{
1445    ///     spi1::Bme280Bus, Bme280, Config, CtrlMeas, Filter, Mode, Oversampling, Sample, Settings,
1446    ///     Standby,
1447    /// };
1448    ///
1449    /// const SETTINGS: bme280_multibus::Settings = bme280_multibus::Settings {
1450    ///     config: bme280_multibus::Config::RESET
1451    ///         .set_standby_time(bme280_multibus::Standby::Millis1000)
1452    ///         .set_filter(bme280_multibus::Filter::X16),
1453    ///     ctrl_meas: bme280_multibus::CtrlMeas::RESET
1454    ///         .set_osrs_t(bme280_multibus::Oversampling::X8)
1455    ///         .set_osrs_p(bme280_multibus::Oversampling::X8)
1456    ///         .set_mode(bme280_multibus::Mode::Normal),
1457    ///     ctrl_hum: bme280_multibus::Oversampling::X8,
1458    /// };
1459    ///
1460    /// let mut bme: Bme280<_> = Bme280::from_spia0a(spi).await?;
1461    /// bme.settings_async(&SETTINGS).await?;
1462    /// let sample: Sample = bme.sample_async().await.unwrap();
1463    /// # bme.free().free().done(); Ok(()) }
1464    /// ```
1465    pub async fn sample_async(&mut self) -> Result<Sample, Error<E>> {
1466        let mut buf: [u8; NUM_MEAS_REG] = [0; NUM_MEAS_REG];
1467        self.bus
1468            .read_regs(reg::PRESS_MSB, &mut buf)
1469            .await
1470            .map_err(Error::Bus)?;
1471
1472        Sample::from_raw(&buf, &self.cal)
1473    }
1474}
1475
1476impl<B, E> Bme280<B>
1477where
1478    B: Bme280Bus<Error = E>,
1479{
1480    /// Create a new BME280 from a [`spi0::Bme280Bus`] or
1481    /// a [`i2c0::Bme280Bus`].
1482    ///
1483    /// # Example
1484    ///
1485    /// ```
1486    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1487    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1488    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1489    /// # ]);
1490    /// use bme280_multibus::{
1491    ///     i2c0::{Address, Bme280Bus},
1492    ///     Bme280,
1493    /// };
1494    ///
1495    /// let bus: Bme280Bus<_> = Bme280Bus::new(i2c, Address::SdoGnd);
1496    /// let bme: Bme280<_> = Bme280::new(bus)?;
1497    /// # bme.free().free().done();
1498    /// # Ok::<(), ehm::eh0::MockError>(())
1499    /// ```
1500    pub fn new(mut bus: B) -> Result<Self, E> {
1501        let cal: Calibration = bus.calibration()?;
1502        Ok(Self { bus, cal })
1503    }
1504
1505    /// Free the I2C bus from the BME280.
1506    ///
1507    /// # Example
1508    ///
1509    /// ```
1510    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1511    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1512    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1513    /// # ]);
1514    /// use bme280_multibus::{
1515    ///     i2c0::{Address, Bme280Bus},
1516    ///     Bme280,
1517    /// };
1518    ///
1519    /// let bus: Bme280Bus<_> = Bme280Bus::new(i2c, Address::SdoGnd);
1520    /// let bme: Bme280<_> = Bme280::new(bus)?;
1521    /// let bus: Bme280Bus<_> = bme.free();
1522    /// # bus.free().done();
1523    /// # Ok::<(), ehm::eh0::MockError>(())
1524    /// ```
1525    #[inline]
1526    pub fn free(self) -> B {
1527        self.bus
1528    }
1529
1530    /// BME280 chip ID.
1531    ///
1532    /// The return value is a constant, [`CHIP_ID`].
1533    ///
1534    /// This register is useful as a sanity check to ensure communications are
1535    /// working with the BME280.
1536    ///
1537    /// # Example
1538    ///
1539    /// ```
1540    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1541    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1542    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1543    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xD0], vec![0x60]),
1544    /// # ]);
1545    /// use bme280_multibus::{Address, Bme280, CHIP_ID};
1546    ///
1547    /// let mut bme: Bme280<_> = Bme280::from_i2c0(i2c, Address::SdoGnd)?;
1548    /// let chip_id: u8 = bme.chip_id()?;
1549    /// assert_eq!(chip_id, CHIP_ID);
1550    /// # bme.free().free().done();
1551    /// # Ok::<(), ehm::eh0::MockError>(())
1552    /// ```
1553    pub fn chip_id(&mut self) -> Result<u8, E> {
1554        let mut buf: [u8; 1] = [0];
1555        self.bus.read_regs(reg::ID, &mut buf)?;
1556        Ok(buf[0])
1557    }
1558
1559    /// Reset the BME280.
1560    ///
1561    /// # Example
1562    ///
1563    /// ```
1564    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1565    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1566    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1567    /// #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xE0, 0xB6]),
1568    /// # ]);
1569    /// use bme280_multibus::{Address, Bme280};
1570    ///
1571    /// let mut bme: Bme280<_> = Bme280::from_i2c0(i2c, Address::SdoGnd)?;
1572    /// bme.reset()?;
1573    /// # bme.free().free().done();
1574    /// # Ok::<(), ehm::eh0::MockError>(())
1575    /// ```
1576    pub fn reset(&mut self) -> Result<(), E> {
1577        self.bus.write_reg(reg::RESET, RESET_MAGIC)
1578    }
1579
1580    /// Get the status of the device.
1581    ///
1582    /// # Example
1583    ///
1584    /// Check if a conversion is running.
1585    ///
1586    /// ```
1587    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1588    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1589    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1590    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xF3], vec![0]),
1591    /// # ]);
1592    /// use bme280_multibus::{Address, Bme280, Status};
1593    ///
1594    /// let mut bme: Bme280<_> = Bme280::from_i2c0(i2c, Address::SdoGnd)?;
1595    /// let status: Status = bme.status()?;
1596    /// # bme.free().free().done();
1597    /// # Ok::<(), ehm::eh0::MockError>(())
1598    /// ```
1599    pub fn status(&mut self) -> Result<Status, E> {
1600        let mut buf: [u8; 1] = [0];
1601        self.bus.read_regs(reg::STATUS, &mut buf)?;
1602        Ok(Status(buf[0]))
1603    }
1604
1605    /// Configure the BME280 settings.
1606    ///
1607    /// # Example
1608    ///
1609    /// ```
1610    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1611    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1612    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1613    /// #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF2, 0b100]),
1614    /// #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF4, 0b10010011]),
1615    /// #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF5, 0b10110000]),
1616    /// # ]);
1617    /// use bme280_multibus::{
1618    ///     Address, Bme280, Config, CtrlMeas, Filter, Mode, Oversampling, Settings, Standby,
1619    /// };
1620    ///
1621    /// const SETTINGS: Settings = Settings {
1622    ///     config: Config::RESET
1623    ///         .set_standby_time(Standby::Millis1000)
1624    ///         .set_filter(Filter::X16),
1625    ///     ctrl_meas: CtrlMeas::RESET
1626    ///         .set_osrs_t(Oversampling::X8)
1627    ///         .set_osrs_p(Oversampling::X8)
1628    ///         .set_mode(Mode::Normal),
1629    ///     ctrl_hum: Oversampling::X8,
1630    /// };
1631    ///
1632    /// let mut bme: Bme280<_> = Bme280::from_i2c0(i2c, Address::SdoGnd)?;
1633    /// bme.settings(&SETTINGS)?;
1634    /// # bme.free().free().done();
1635    /// # Ok::<(), ehm::eh0::MockError>(())
1636    /// ```
1637    pub fn settings(&mut self, settings: &Settings) -> Result<(), E> {
1638        self.bus.write_reg(reg::CTRL_HUM, settings.ctrl_hum as u8)?;
1639        self.bus.write_reg(reg::CTRL_MEAS, settings.ctrl_meas.0)?;
1640        self.bus.write_reg(reg::CONFIG, settings.config.0)
1641    }
1642
1643    /// Read a sample from the BME280.
1644    ///
1645    /// # Example
1646    ///
1647    /// ```
1648    /// # let i2c = ehm::eh0::i2c::Mock::new(&[
1649    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0x88], vec![0; 26]),
1650    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xE1], vec![0; 7]),
1651    /// #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF2, 0b100]),
1652    /// #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF4, 0b10010011]),
1653    /// #   ehm::eh0::i2c::Transaction::write(0x76, vec![0xF5, 0b10110000]),
1654    /// #   ehm::eh0::i2c::Transaction::write_read(0x76, vec![0xF7], vec![0; 8]),
1655    /// # ]);
1656    /// use bme280_multibus::{Address, Bme280, Sample};
1657    ///
1658    /// const SETTINGS: bme280_multibus::Settings = bme280_multibus::Settings {
1659    ///     config: bme280_multibus::Config::RESET
1660    ///         .set_standby_time(bme280_multibus::Standby::Millis1000)
1661    ///         .set_filter(bme280_multibus::Filter::X16),
1662    ///     ctrl_meas: bme280_multibus::CtrlMeas::RESET
1663    ///         .set_osrs_t(bme280_multibus::Oversampling::X8)
1664    ///         .set_osrs_p(bme280_multibus::Oversampling::X8)
1665    ///         .set_mode(bme280_multibus::Mode::Normal),
1666    ///     ctrl_hum: bme280_multibus::Oversampling::X8,
1667    /// };
1668    ///
1669    /// let mut bme: Bme280<_> = Bme280::from_i2c0(i2c, Address::SdoGnd)?;
1670    /// bme.settings(&SETTINGS)?;
1671    /// let sample: Sample = bme.sample().unwrap();
1672    /// # bme.free().free().done();
1673    /// # Ok::<(), ehm::eh0::MockError>(())
1674    /// ```
1675    pub fn sample(&mut self) -> Result<Sample, Error<E>> {
1676        let mut buf: [u8; NUM_MEAS_REG] = [0; NUM_MEAS_REG];
1677        self.bus
1678            .read_regs(reg::PRESS_MSB, &mut buf)
1679            .map_err(Error::Bus)?;
1680
1681        Sample::from_raw(&buf, &self.cal)
1682    }
1683}