1use self::i2c_helper::I2CHelper;
2use crate::config::{Configuration, SensorMode, Variant};
3use crate::data::CalibrationData;
4use crate::BmeError;
5use crate::DeviceAddress;
6use crate::MeasurmentData;
7use embedded_hal_async::{
8 delay::DelayNs,
9 i2c::{I2c, SevenBitAddress},
10};
11mod i2c_helper;
12
13pub struct AsyncBme680<I2C, D> {
29 i2c: I2CHelper<I2C, D>,
31 state: Option<State>,
32}
33
34struct State {
35 calibration_data: CalibrationData,
37 current_sensor_config: Configuration,
39 variant: Variant,
41}
42
43impl<I2C, D> AsyncBme680<I2C, D>
44where
45 I2C: I2c<SevenBitAddress>,
46 D: DelayNs,
47{
48 pub fn new(
66 i2c_interface: I2C,
67 device_address: DeviceAddress,
68 delayer: D,
69 ambient_temperature: i32,
70 ) -> Self {
71 let i2c = I2CHelper::new(i2c_interface, device_address, delayer, ambient_temperature);
72
73 Self { i2c, state: None }
74 }
75
76 pub async fn initialize(&mut self, sensor_config: &Configuration) -> Result<(), BmeError<I2C>> {
77 self.i2c.init().await?;
78 let calibration_data = self.i2c.get_calibration_data().await?;
79 self.i2c
80 .set_config(sensor_config, &calibration_data)
81 .await?;
82 let variant = self.i2c.get_variant_id().await?;
83 self.state = Some(State {
84 calibration_data,
85 current_sensor_config: sensor_config.clone(),
86 variant,
87 });
88 Ok(())
89 }
90 pub async fn put_to_sleep(&mut self) -> Result<(), BmeError<I2C>> {
91 self.i2c.set_mode(SensorMode::Sleep).await
92 }
93 pub fn into_inner(self) -> I2C {
95 self.i2c.into_inner()
96 }
97
98 pub async fn set_configuration(&mut self, config: &Configuration) -> Result<(), BmeError<I2C>> {
99 let state = self.state.as_mut().ok_or(BmeError::Uninitialized)?;
100 self.i2c.set_mode(SensorMode::Sleep).await?;
101 self.i2c.set_config(config, &state.calibration_data).await?;
102 state.current_sensor_config = config.clone();
104 Ok(())
105 }
106 pub async fn measure(&mut self) -> Result<MeasurmentData, BmeError<I2C>> {
113 let state = self.state.as_mut().ok_or(BmeError::Uninitialized)?;
114 self.i2c.set_mode(SensorMode::Forced).await?;
115 let delay_period = state.current_sensor_config.calculate_delay_period_us();
116
117 self.i2c.delay(delay_period).await;
118 for _i in 0..5 {
120 let raw_data = self.i2c.get_field_data().await?;
121 match MeasurmentData::from_raw(raw_data, &state.calibration_data, &state.variant) {
122 Some(data) => {
123 self.i2c.ambient_temperature = data.temperature as i32;
125 return Ok(data);
126 }
127 None => self.i2c.delay(delay_period).await,
128 }
129 }
130 Err(BmeError::MeasuringTimeOut)
132 }
133
134 pub fn get_calibration_data(&self) -> Result<&CalibrationData, BmeError<I2C>> {
135 Ok(&self
136 .state
137 .as_ref()
138 .ok_or(BmeError::Uninitialized)?
139 .calibration_data)
140 }
141}
142
143#[cfg(test)]
144mod library_tests {
145 extern crate std;
146
147 use std::vec;
148 use std::vec::Vec;
149
150 use crate::constants::{
151 ADDR_CHIP_ID, ADDR_CONFIG, ADDR_CONTROL_MODE, ADDR_GAS_WAIT_0, ADDR_REG_COEFF1,
152 ADDR_REG_COEFF2, ADDR_REG_COEFF3, ADDR_RES_HEAT_0, ADDR_SOFT_RESET, ADDR_VARIANT_ID,
153 CHIP_ID, CMD_SOFT_RESET, LEN_COEFF1, LEN_COEFF2, LEN_COEFF3,
154 };
155 use crate::i2c_helper::extract_calibration_data;
156
157 const CALIBRATION_DATA: [u8; 42] = [
158 179, 193, 176, 188, 21, 51, 11, 29, 222, 179, 184, 1, 230, 47, 209, 22, 154, 34, 237, 70,
159 148, 134, 44, 13, 204, 61, 206, 69, 18, 43, 124, 164, 92, 132, 19, 63, 29, 28, 201, 140,
160 70, 24,
161 ];
162
163 use super::*;
164 use crate::bitfields::RawConfig;
165 use embedded_hal_mock::eh1::delay::NoopDelay;
166 use embedded_hal_mock::eh1::i2c::{Mock as I2cMock, Transaction as I2cTransaction};
167
168 fn setup_transactions() -> Vec<I2cTransaction> {
169 let mut transactions = vec![];
170 let calibration_data_1 = CALIBRATION_DATA[0..LEN_COEFF1].to_vec();
171 let calibration_data_2 = CALIBRATION_DATA[LEN_COEFF1..LEN_COEFF1 + LEN_COEFF2].to_vec();
172 let calibration_data_3 = CALIBRATION_DATA
173 [LEN_COEFF1 + LEN_COEFF2..LEN_COEFF1 + LEN_COEFF2 + LEN_COEFF3]
174 .to_vec();
175 assert_eq!(calibration_data_1.len(), LEN_COEFF1);
176 assert_eq!(calibration_data_2.len(), LEN_COEFF2);
177 assert_eq!(calibration_data_3.len(), LEN_COEFF3);
178 transactions.push(I2cTransaction::write(
180 DeviceAddress::Primary.into(),
181 vec![ADDR_SOFT_RESET, CMD_SOFT_RESET],
182 ));
183 transactions.push(I2cTransaction::write_read(
185 DeviceAddress::Primary.into(),
186 vec![ADDR_CHIP_ID],
187 vec![CHIP_ID],
188 ));
189 transactions.push(I2cTransaction::write_read(
191 DeviceAddress::Primary.into(),
192 vec![ADDR_REG_COEFF1],
193 calibration_data_1,
194 ));
195 transactions.push(I2cTransaction::write_read(
196 DeviceAddress::Primary.into(),
197 vec![ADDR_REG_COEFF2],
198 calibration_data_2,
199 ));
200 transactions.push(I2cTransaction::write_read(
201 DeviceAddress::Primary.into(),
202 vec![ADDR_REG_COEFF3],
203 calibration_data_3,
204 ));
205 let default_config = [0u8; 5];
212 transactions.push(I2cTransaction::write_read(
213 DeviceAddress::Primary.into(),
214 vec![ADDR_CONFIG],
215 default_config.into(),
216 ));
217 let user_config = Configuration::default();
219 let mut raw_config = RawConfig(default_config);
220 raw_config.apply_config(&user_config);
221 raw_config
223 .0
224 .into_iter()
225 .enumerate()
226 .for_each(|(register_offset, register_content)| {
227 transactions.push(I2cTransaction::write(
228 DeviceAddress::Primary.into(),
229 vec![ADDR_CONFIG + register_offset as u8, register_content],
230 ));
231 });
232 let gas_config = user_config.gas_config.unwrap();
234 let gas_wait_0 = gas_config.calc_gas_wait();
235 let res_heat_0 = gas_config.calc_res_heat(&extract_calibration_data(CALIBRATION_DATA), 20);
236 transactions.push(I2cTransaction::write(
237 DeviceAddress::Primary.into(),
238 vec![ADDR_GAS_WAIT_0, gas_wait_0],
239 ));
240 transactions.push(I2cTransaction::write(
241 DeviceAddress::Primary.into(),
242 vec![ADDR_RES_HEAT_0, res_heat_0],
243 ));
244 transactions.push(I2cTransaction::write_read(
246 DeviceAddress::Primary.into(),
247 vec![ADDR_VARIANT_ID],
248 vec![0],
249 ));
250 transactions
251 }
252 fn add_sleep_to_sleep_transactions(transactions: &mut Vec<I2cTransaction>) {
253 transactions.push(I2cTransaction::write_read(
254 DeviceAddress::Primary.into(),
255 vec![ADDR_CONTROL_MODE],
256 vec![0b101011_00],
258 ));
259 }
260 #[tokio::test]
261 async fn test_setup() {
262 let transactions = setup_transactions();
263 let i2c_interface = I2cMock::new(&transactions);
264 let mut bme = AsyncBme680::new(i2c_interface, DeviceAddress::Primary, NoopDelay::new(), 20);
265 bme.initialize(&Configuration::default()).await.unwrap();
266 bme.into_inner().done();
267 }
268
269 #[tokio::test]
270 async fn test_set_mode_forced_to_sleep() {
271 let mut transactions = setup_transactions();
272 transactions.push(I2cTransaction::write_read(
273 DeviceAddress::Primary.into(),
274 vec![ADDR_CONTROL_MODE],
275 vec![0b101011_01],
277 ));
278 transactions.push(I2cTransaction::write(
279 DeviceAddress::Primary.into(),
280 vec![ADDR_CONTROL_MODE, 0b101011_00],
281 ));
282 transactions.push(I2cTransaction::write_read(
283 DeviceAddress::Primary.into(),
284 vec![ADDR_CONTROL_MODE],
285 vec![0b101011_00],
287 ));
288 let i2c_interface = I2cMock::new(&transactions);
290 let mut bme = AsyncBme680::new(i2c_interface, DeviceAddress::Primary, NoopDelay::new(), 20);
291 bme.initialize(&Configuration::default()).await.unwrap();
292 bme.put_to_sleep().await.unwrap();
293 bme.into_inner().done();
294 }
295 #[tokio::test]
296 async fn test_set_mode_sleep_to_sleep() {
297 let mut transactions = setup_transactions();
298 add_sleep_to_sleep_transactions(&mut transactions);
299 let i2c_interface = I2cMock::new(&transactions);
300 let mut bme = AsyncBme680::new(i2c_interface, DeviceAddress::Primary, NoopDelay::new(), 20);
301 bme.initialize(&Configuration::default()).await.unwrap();
302 bme.put_to_sleep().await.unwrap();
303 bme.into_inner().done();
304 }
305}