iaq_core/
device_impl.rs

1use crate::{hal::blocking::i2c::Read, Error, IaqCore, Measurement};
2use nb;
3
4const DEV_ADDR: u8 = 0x5A;
5
6impl<E, I2C> IaqCore<I2C>
7where
8    I2C: Read<Error = E>,
9{
10    /// Create new instance of the iAQ-Core device.
11    pub fn new(i2c: I2C) -> Self {
12        IaqCore { i2c }
13    }
14
15    /// Destroy driver instance, return I²C bus instance.
16    pub fn destroy(self) -> I2C {
17        self.i2c
18    }
19
20    /// Get all data from the sensor measurement
21    ///
22    /// Returns `nb::Error::WouldBlock` in case the device reports a busy or warm up status.
23    pub fn data(&mut self) -> nb::Result<Measurement, Error<E>> {
24        let mut data = [0; 9];
25        self.read(&mut data)?;
26        Ok(Measurement {
27            co2: (u16::from(data[0]) << 8) | u16::from(data[1]),
28            tvoc: (u16::from(data[7]) << 8) | u16::from(data[8]),
29            resistance: (u32::from(data[4]) << 16) | (u32::from(data[5]) << 8) | u32::from(data[6]),
30        })
31    }
32
33    /// Get the CO2 (ppm) equivalent prediction value
34    ///
35    /// Returns `nb::Error::WouldBlock` in case the device reports a busy or warm up status.
36    pub fn co2(&mut self) -> nb::Result<u16, Error<E>> {
37        let mut data = [0; 3];
38        self.read(&mut data)?;
39        Ok((u16::from(data[0]) << 8) | u16::from(data[1]))
40    }
41
42    /// Get the TVOC (ppb) equivalent prediction value
43    ///
44    /// Returns `nb::Error::WouldBlock` in case the device reports a busy or warm up status.
45    pub fn tvoc(&mut self) -> nb::Result<u16, Error<E>> {
46        let mut data = [0; 9];
47        self.read(&mut data)?;
48        Ok((u16::from(data[7]) << 8) | u16::from(data[8]))
49    }
50
51    /// Get the sensor resistance in Ohm
52    ///
53    /// Returns `nb::Error::WouldBlock` in case the device reports a busy or warm up status.
54    pub fn resistance(&mut self) -> nb::Result<u32, Error<E>> {
55        let mut data = [0; 7];
56        self.read(&mut data)?;
57        Ok((u32::from(data[4]) << 16) | (u32::from(data[5]) << 8) | u32::from(data[6]))
58    }
59
60    fn read(&mut self, data: &mut [u8]) -> nb::Result<(), Error<E>> {
61        self.i2c.read(DEV_ADDR, data).map_err(Error::I2C)?;
62        Self::check_status(data[2])
63    }
64
65    fn check_status(status: u8) -> nb::Result<(), Error<E>> {
66        if status == 0x80 {
67            Err(nb::Error::Other(Error::Device))
68        } else if status == 0 {
69            Ok(())
70        } else {
71            // warm up or busy
72            Err(nb::Error::WouldBlock)
73        }
74    }
75}