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}