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}