embedded_ccs811/
types.rs

1use core::convert::From;
2
3/// All possible errors generated when using the `Ccs811` type.
4#[derive(Debug)]
5pub enum Error<CommE, PinE> {
6    /// I²C bus error
7    I2C(CommE),
8    /// nWAKE pin set error
9    Pin(PinE),
10    /// Errors reported by device
11    ///
12    /// This can contain several errors at the same time.
13    /// You can index this list by `DeviceError` to see if an specific error variant
14    /// has been reported. See the documentation for usage examples.
15    Device(DeviceErrors),
16    /// No valid application loaded
17    NoValidApp,
18    /// Invalid input data provided to function
19    InvalidInputData,
20}
21
22/// All possible errors when using an the `Ccs811Awake` type.
23#[derive(Debug)]
24pub enum ErrorAwake<E> {
25    /// I²C bus error
26    I2C(E),
27    /// Errors reported by device
28    ///
29    /// This can contain several errors at the same time.
30    /// You can index this list by `DeviceError` to see if an specific error variant
31    /// has been reported. See the documentation for usage examples.
32    Device(DeviceErrors),
33    /// No valid application loaded
34    NoValidApp,
35    /// Invalid input data provided to function
36    InvalidInputData,
37}
38
39impl<CommE, PinE> From<ErrorAwake<CommE>> for Error<CommE, PinE> {
40    fn from(error: ErrorAwake<CommE>) -> Self {
41        match error {
42            ErrorAwake::I2C(e) => Error::I2C(e),
43            ErrorAwake::Device(e) => Error::Device(e),
44            ErrorAwake::NoValidApp => Error::NoValidApp,
45            ErrorAwake::InvalidInputData => Error::InvalidInputData,
46        }
47    }
48}
49
50/// Errors reported by the device.
51#[derive(Debug, Clone, Copy, PartialEq, Default)]
52pub struct DeviceErrors {
53    /// I2C write to an invalid register reported by device.
54    pub invalid_register_write: bool,
55    /// I2C read from an invalid register reported by device.
56    pub invalid_register_read: bool,
57    /// Invalid measurement reported by device.
58    pub invalid_measurement: bool,
59    /// Sensor resistance measurement reached or exceeded the maximum range reported by device.
60    pub max_resistance: bool,
61    /// Heater current not in range reported by device.
62    pub heater_fault: bool,
63    /// Heater current not applied correctly reported by device.
64    pub heater_supply: bool,
65}
66
67/// Error type for mode changes when using `Ccs811`.
68///
69/// This allows to retrieve the unchanged device in case of an error.
70#[derive(Debug)]
71pub struct ModeChangeError<E, DEV> {
72    /// Unchanged device.
73    pub dev: DEV,
74    /// Error occurred.
75    pub error: E,
76}
77
78impl<E, DEV> ModeChangeError<E, DEV> {
79    pub(crate) fn new(dev: DEV, error: E) -> Self {
80        ModeChangeError { dev, error }
81    }
82}
83
84/// Measurement modes.
85///
86/// NOTE: When changing to a new mode with a lower sample rate,
87/// place the device in `Idle` mode for at least 10 minutes before
88/// enabling the new mode.
89#[derive(Debug, Clone, Copy, PartialEq)]
90pub enum MeasurementMode {
91    /// Idle. Measurements are disabled. (Mode 0)
92    Idle,
93    /// Constant power mode. IAQ measurement every second. (Mode 1)
94    ConstantPower1s,
95    /// Pulse heating mode. IAQ measurement every 10 seconds. (Mode 2)
96    PulseHeating10s,
97    /// Low power pulse heating mode. IAQ measurement every 60 seconds. (Mode 3)
98    LowPowerPulseHeating60s,
99    /// Constant power mode. IAQ measurement every 250ms. (Mode 4)
100    ConstantPower250ms,
101}
102
103/// Firmware mode
104#[derive(Debug, Clone, Copy, PartialEq)]
105pub enum FirmwareMode {
106    /// Boot mode. New firmware can be loaded.
107    Boot,
108    /// Application mode. CCS811 can take measurements
109    Application,
110}
111
112/// Interrupt generation modes.
113#[derive(Debug, Clone, Copy, PartialEq)]
114pub enum InterruptMode {
115    /// Disable interrupt generation
116    Disabled,
117    /// Generate an interrupt every time there is new data ready.
118    OnDataReady,
119    /// Generate an interrupt if the measurement crosses a threshold by more
120    /// than 50 ppm. (See `set_eco2_thresholds()`).
121    OnThresholdCrossed,
122}
123
124/// Algorithm result
125#[derive(Debug, Clone, Copy, PartialEq, Default)]
126pub struct AlgorithmResult {
127    /// eCO2 result in ppm
128    pub eco2: u16,
129    /// eTVOC result in ppb
130    pub etvoc: u16,
131    /// Raw sensor current in uA
132    pub raw_current: u8,
133    /// Raw sensor voltage (1023 = 1.65V)
134    pub raw_voltage: u16,
135}
136
137/// Possible slave addresses
138#[derive(Debug, Clone, Copy)]
139pub enum SlaveAddr {
140    /// Default slave address
141    Default,
142    /// Alternative slave address providing bit value for the ADDR pin
143    Alternative(bool),
144}
145
146impl Default for SlaveAddr {
147    /// Default slave address
148    fn default() -> Self {
149        SlaveAddr::Default
150    }
151}
152
153impl SlaveAddr {
154    pub(crate) fn addr(self) -> u8 {
155        match self {
156            SlaveAddr::Default => 0x5A,
157            SlaveAddr::Alternative(false) => 0x5A,
158            SlaveAddr::Alternative(true) => 0x5B,
159        }
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn can_get_default_address() {
169        let addr = SlaveAddr::default();
170        assert_eq!(0x5A, addr.addr());
171    }
172
173    #[test]
174    fn can_generate_alternative_addresses() {
175        assert_eq!(0x5A, SlaveAddr::Alternative(false).addr());
176        assert_eq!(0x5B, SlaveAddr::Alternative(true).addr());
177    }
178}