1use crate::hal::{delay::DelayNs, digital::OutputPin};
2use crate::{
3 hal, mode, ActionInProgress, BitFlags, Ccs811, Ccs811Awake, Ccs811Device, Error, ErrorAwake,
4 FirmwareMode, ModeChangeError, Register, SlaveAddr,
5};
6use core::marker::PhantomData;
7
8impl<I2C, NWAKE, WAKEDELAY> Ccs811<I2C, NWAKE, WAKEDELAY, mode::Boot> {
9 pub fn new(i2c: I2C, address: SlaveAddr, n_wake_pin: NWAKE, wake_delay: WAKEDELAY) -> Self {
13 Self::create(i2c, address.addr(), n_wake_pin, wake_delay)
14 }
15}
16
17impl<I2C, NWAKE, WAKEDELAY, MODE> Ccs811<I2C, NWAKE, WAKEDELAY, MODE> {
18 pub(crate) fn create(i2c: I2C, address: u8, n_wake_pin: NWAKE, wake_delay: WAKEDELAY) -> Self {
19 Self::from_awake_dev(Ccs811Awake::create(i2c, address), n_wake_pin, wake_delay)
20 }
21
22 pub(crate) fn from_awake_dev(
23 dev: Ccs811Awake<I2C, MODE>,
24 n_wake_pin: NWAKE,
25 wake_delay: WAKEDELAY,
26 ) -> Self {
27 Ccs811 {
28 dev,
29 n_wake_pin,
30 wake_delay,
31 _mode: PhantomData,
32 }
33 }
34}
35
36impl<I2C> Ccs811Awake<I2C, mode::Boot> {
37 pub fn new(i2c: I2C, address: SlaveAddr) -> Self {
39 Self::create(i2c, address.addr())
40 }
41}
42
43impl<I2C, MODE> Ccs811Awake<I2C, MODE> {
44 pub(crate) fn create(i2c: I2C, address: u8) -> Self {
45 Ccs811Awake {
46 i2c,
47 address,
48 meas_mode_reg: 0,
49 in_progress: ActionInProgress::None,
50 _mode: PhantomData,
51 }
52 }
53}
54
55impl<I2C, E, MODE> Ccs811Awake<I2C, MODE>
56where
57 I2C: hal::i2c::I2c<Error = E>,
58{
59 pub fn destroy(self) -> I2C {
61 self.i2c
62 }
63}
64impl<I2C, E, MODE> Ccs811Awake<I2C, MODE>
65where
66 I2C: hal::i2c::I2c<Error = E>,
67{
68 pub(crate) fn write_sw_reset(&mut self) -> Result<(), ErrorAwake<E>> {
69 self.i2c
70 .write(self.address, &[Register::SW_RESET, 0x11, 0xE5, 0x72, 0x8A])
71 .map_err(ErrorAwake::I2C)
72 }
73}
74
75impl<I2C, CommE, PinE, NWAKE, WAKEDELAY, MODE> Ccs811<I2C, NWAKE, WAKEDELAY, MODE>
76where
77 I2C: hal::i2c::I2c<Error = CommE>,
78 NWAKE: OutputPin<Error = PinE>,
79 WAKEDELAY: DelayNs,
80{
81 pub fn destroy(self) -> (I2C, NWAKE, WAKEDELAY) {
84 (self.dev.destroy(), self.n_wake_pin, self.wake_delay)
85 }
86
87 pub(crate) fn on_awaken<T, F>(&mut self, f: F) -> Result<T, Error<CommE, PinE>>
88 where
89 F: FnOnce(&mut Self) -> Result<T, ErrorAwake<CommE>>,
90 {
91 self.n_wake_pin.set_low().map_err(Error::Pin)?;
92 self.wake_delay.delay_us(50);
93 let result = match f(self) {
94 Ok(v) => Ok(v),
95 Err(e) => Err(e.into()),
96 };
97 self.n_wake_pin.set_high().map_err(Error::Pin)?;
98 self.wake_delay.delay_us(20);
99 result
100 }
101
102 pub(crate) fn on_awaken_nb<T, F>(&mut self, f: F) -> nb::Result<T, Error<CommE, PinE>>
103 where
104 F: FnOnce(&mut Self) -> nb::Result<T, ErrorAwake<CommE>>,
105 {
106 self.n_wake_pin
107 .set_low()
108 .map_err(Error::Pin)
109 .map_err(nb::Error::Other)?;
110 self.wake_delay.delay_us(50);
111 let result = match f(self) {
112 Ok(v) => Ok(v),
113 Err(nb::Error::Other(e)) => Err(nb::Error::Other(e.into())),
114 Err(nb::Error::WouldBlock) => Err(nb::Error::WouldBlock),
115 };
116 self.n_wake_pin
117 .set_high()
118 .map_err(Error::Pin)
119 .map_err(nb::Error::Other)?;
120 self.wake_delay.delay_us(20);
121 result
122 }
123
124 #[allow(clippy::type_complexity)]
128 pub(crate) fn wrap_mode_change<TMODE, F>(
129 mut self,
130 f: F,
131 ) -> Result<Ccs811<I2C, NWAKE, WAKEDELAY, TMODE>, ModeChangeError<Error<CommE, PinE>, Self>>
132 where
133 F: FnOnce(
134 Ccs811Awake<I2C, MODE>,
135 ) -> Result<
136 Ccs811Awake<I2C, TMODE>,
137 ModeChangeError<ErrorAwake<CommE>, Ccs811Awake<I2C, MODE>>,
138 >,
139 {
140 if let Err(e) = self.n_wake_pin.set_low() {
141 return Err(ModeChangeError::new(self, Error::Pin(e)));
142 }
143 self.wake_delay.delay_us(50);
144 let Ccs811 {
145 dev,
146 mut n_wake_pin,
147 mut wake_delay,
148 ..
149 } = self;
150 let result = f(dev);
151 if let Err(e) = n_wake_pin.set_high() {
152 return match result {
153 Ok(Ccs811Awake { i2c, address, .. }) => Err(ModeChangeError {
154 dev: Ccs811::create(i2c, address, n_wake_pin, wake_delay),
155 error: Error::Pin(e),
156 }),
157 Err(ModeChangeError { dev, error }) => Err(ModeChangeError {
158 dev: Ccs811::from_awake_dev(dev, n_wake_pin, wake_delay),
159 error: error.into(),
160 }),
161 };
162 }
163 wake_delay.delay_us(20);
164 match result {
165 Ok(dev) => Ok(Ccs811::from_awake_dev(dev, n_wake_pin, wake_delay)),
166 Err(ModeChangeError { dev, error }) => Err(ModeChangeError {
167 dev: Ccs811::from_awake_dev(dev, n_wake_pin, wake_delay),
168 error: error.into(),
169 }),
170 }
171 }
172}
173
174impl<I2C, E, MODE> Ccs811Device for Ccs811Awake<I2C, MODE>
175where
176 I2C: hal::i2c::I2c<Error = E>,
177{
178 type Error = ErrorAwake<E>;
179
180 fn firmware_mode(&mut self) -> Result<FirmwareMode, Self::Error> {
181 let status = self.read_status()?;
182 let mode = if (status & BitFlags::FW_MODE) != 0 {
183 FirmwareMode::Application
184 } else {
185 FirmwareMode::Boot
186 };
187 Ok(mode)
188 }
189
190 fn has_valid_app(&mut self) -> Result<bool, Self::Error> {
191 let status = self.read_status()?;
192 Ok((status & BitFlags::APP_VALID) != 0)
193 }
194
195 fn hardware_id(&mut self) -> Result<u8, Self::Error> {
196 self.read_register_1byte(Register::HW_ID)
197 }
198
199 fn hardware_version(&mut self) -> Result<(u8, u8), Self::Error> {
200 let version = self.read_register_1byte(Register::HW_VERSION)?;
201 Ok(((version & 0xF0) >> 4, version & 0xF))
202 }
203
204 fn firmware_bootloader_version(&mut self) -> Result<(u8, u8, u8), Self::Error> {
205 let version = self.read_register_2bytes(Register::FW_BOOT_VERSION)?;
206 Ok(((version[0] & 0xF0) >> 4, version[0] & 0xF, version[1]))
207 }
208
209 fn firmware_application_version(&mut self) -> Result<(u8, u8, u8), Self::Error> {
210 let version = self.read_register_2bytes(Register::FW_APP_VERSION)?;
211 Ok(((version[0] & 0xF0) >> 4, version[0] & 0xF, version[1]))
212 }
213}
214
215impl<I2C, CommE, PinE, NWAKE, WAKEDELAY, MODE> Ccs811Device for Ccs811<I2C, NWAKE, WAKEDELAY, MODE>
216where
217 I2C: hal::i2c::I2c<Error = CommE>,
218 NWAKE: OutputPin<Error = PinE>,
219 WAKEDELAY: DelayNs,
220{
221 type Error = Error<CommE, PinE>;
222
223 fn firmware_mode(&mut self) -> Result<FirmwareMode, Self::Error> {
224 self.on_awaken(|s| s.dev.firmware_mode())
225 }
226
227 fn has_valid_app(&mut self) -> Result<bool, Self::Error> {
228 self.on_awaken(|s| s.dev.has_valid_app())
229 }
230
231 fn hardware_id(&mut self) -> Result<u8, Self::Error> {
232 self.on_awaken(|s| s.dev.hardware_id())
233 }
234
235 fn hardware_version(&mut self) -> Result<(u8, u8), Self::Error> {
236 self.on_awaken(|s| s.dev.hardware_version())
237 }
238
239 fn firmware_bootloader_version(&mut self) -> Result<(u8, u8, u8), Self::Error> {
240 self.on_awaken(|s| s.dev.firmware_bootloader_version())
241 }
242
243 fn firmware_application_version(&mut self) -> Result<(u8, u8, u8), Self::Error> {
244 self.on_awaken(|s| s.dev.firmware_application_version())
245 }
246}