1use crate::config::{Configuration, HeaterProfile, IIRFilter, Oversampling, SensorMode};
2use bitfield::bitfield;
3use core::time::Duration;
4
5bitfield! {
6 pub struct RawConfig([u8]);
7 impl Debug;
8 u8;
9 pub from into IIRFilter, filter, set_filter : calc_position(4, 4), calc_position(2, 4);
11 pub mode, set_mode: calc_position(1, 3), calc_position(0, 3);
13 pub from into Oversampling, pressure_oversampling, set_pressure_oversampling : calc_position(4, 3), calc_position(2, 3);
15 pub from into Oversampling, temperature_oversampling, set_temperature_oversampling: calc_position(7, 3), calc_position(5, 3);
17 pub from into Oversampling, humidity_oversampling, set_humidity_oversampling: calc_position(2, 1), calc_position(0, 1);
19 pub from into HeaterProfile, heater_profile, set_heater_profile: calc_position(3, 0), calc_position(0, 0);
21 pub run_gas, set_run_gas: calc_position(4, 0);
23}
24
25impl RawConfig<[u8; 5]> {
26 pub fn apply_config(&mut self, config: &Configuration) {
31 let config = config.clone();
33 if let Some(temperature_oversampling) = config.temperature_oversampling {
34 self.set_temperature_oversampling(temperature_oversampling);
35 }
36 if let Some(pressure_oversampling) = config.pressure_oversampling {
37 self.set_pressure_oversampling(pressure_oversampling);
38 }
39 if let Some(humidity_oversampling) = config.humidity_oversampling {
40 self.set_humidity_oversampling(humidity_oversampling);
41 }
42 if let Some(filter) = config.filter {
43 self.set_filter(filter);
44 }
45 if let Some(_gas_config) = config.gas_config {
46 self.set_run_gas(true);
47 self.set_heater_profile(HeaterProfile::Profile0);
50 }
51 }
52
53}
54
55bitfield! {
56 pub struct RawGasConfig([u8]);
57 impl Debug;
58 u8;
59 pub res_heat, _: 7, 0;
60 pub from into GasWaitDuration, gas_wait, _: calc_position(7, 1), calc_position(0, 1);
61}
62#[derive(Debug)]
63pub struct GasWaitDuration(Duration);
64impl From<u8> for GasWaitDuration {
65 fn from(val: u8) -> Self {
66 Self(Duration::from_millis(val as u64))
67 }
68}
69
70impl From<GasWaitDuration> for Duration {
71 fn from(value: GasWaitDuration) -> Self {
72 value.0
73 }
74}
75
76bitfield! {
78 pub struct CtrlMeasurment(u8);
79 impl Debug;
80 u8;
81 pub from into Oversampling, temperature_os, set_temperature_os: 7, 5;
82 pub from into Oversampling, pressure_os, set_pressure_os: 4, 2;
83 pub from into SensorMode, mode, set_mode: 1, 0;
84}
85
86bitfield! {
87 pub struct MeasurmentStatus(u8);
88 impl Debug;
89 u8;
90 pub bool, new_data, _: 7;
91 pub bool, gas_measuring, _: 6;
92 pub bool, measuring, _: 5;
93 pub gas_meas_index, _: 3, 0;
94}
95
96bitfield! {
113 pub struct RawData([u8]);
114 impl Debug;
115
116 pub u8, gas_range, _: calc_position(3, 14), calc_position(0, 14);
117 pub bool, gas_valid, _: calc_position(5, 14);
120 pub bool, heater_sable, _: calc_position(4, 14);
122 pub u16, from into GasADC, gas_adc, _: calc_position(7, 14), calc_position(0, 13);
123 pub u16, from into Humidity, humidity_adc, _: calc_position(7, 9), calc_position(0, 8);
124 pub u32, from into Measurment, temperature_adc, _: calc_position(7, 7), calc_position(0, 5);
125 pub u32, from into Measurment, pressure_adc, _: calc_position(7, 4), calc_position(0, 2);
126 pub u8, gas_meas_index, _: calc_position(3, 0), calc_position(0, 0);
129 pub bool, measuring, _: calc_position(5, 0);
131 pub bool, gas_measuring, _: calc_position(6, 0);
133 pub bool, new_data, _: calc_position(7, 0);
135}
136
137#[derive(Debug)]
139pub struct Measurment(pub u32);
140impl From<u32> for Measurment {
141 fn from(value: u32) -> Self {
142 let measurment_value = u32::from_be(value) >> 12;
143 Measurment(measurment_value)
144 }
145}
146
147#[derive(Debug)]
149pub struct Humidity(pub u16);
150impl From<u16> for Humidity {
151 fn from(value: u16) -> Self {
152 let humidity = u16::from_be(value);
154 Humidity(humidity)
155 }
156}
157
158#[derive(Debug)]
160pub struct GasADC(pub u16);
161impl From<u16> for GasADC {
162 fn from(value: u16) -> Self {
163 let [gas_r_msb, gas_r_lsb] = value.to_le_bytes();
165 let mut gas_adc: u16 = gas_r_msb.into();
166 gas_adc <<= 2;
168 gas_adc |= (gas_r_lsb >> 6) as u16;
169 GasADC(gas_adc)
170 }
171}
172
173fn calc_position(bit_position: usize, byte_offset: usize) -> usize {
175 byte_offset * 8 + bit_position
176}
177#[cfg(test)]
178mod tests {
179 extern crate std;
180 use crate::config::Configuration;
181 use std::println;
182
183 use super::{calc_position, Humidity, Measurment, RawConfig, RawData};
184 use bitfield::bitfield;
185
186 bitfield! {
187 pub struct SampleData([u8]);
188 impl Debug;
189 pub u32, from into Measurment, m, _: calc_position(7, 2), calc_position(0, 0);
190 pub u16, from into Humidity, h, _: calc_position(7,4), calc_position(0, 3);
191 }
192
193 #[test]
194 fn test_raw_data() {
195 let data = [
196 0b1_0_0_0_0000u8,
198 0,
200 0b00101001,
202 0b10110011,
204 0b1111_0000,
206 0b00101001,
208 0b10110011,
210 0b1111_0000,
212 0b10110011,
214 0b00101001,
216 0,
218 0,
219 0,
220 0b10000001,
222 0b11_1_1_0011,
224 ];
225 let expected_new_data = true;
226 let expected_gas_measuring = false;
227 let expected_measuring = false;
228 let expected_gas_meas_index = 0u8;
229 let expected_pressure = 0b0000_00000000_00101001_10110011_1111_u32;
230 let expected_temperature = 0b0000_00000000_00101001_10110011_1111_u32;
231 let expected_humidity = 0b10110011_00101001_u16;
232 let expected_gas_adc = 0b10000001_11u16;
233 let expected_gas_range = 0b011u8;
234 let expected_gas_valid = true;
235 let expected_heater_stable = true;
236 let raw_data = RawData(data);
237 assert!(raw_data.new_data() == expected_new_data);
238 assert!(raw_data.gas_measuring() == expected_gas_measuring);
239 assert!(raw_data.measuring() == expected_measuring);
240 assert!(raw_data.gas_meas_index() == expected_gas_meas_index);
241 assert!(raw_data.pressure_adc().0 == expected_pressure);
242 assert!(raw_data.temperature_adc().0 == expected_temperature);
243 assert!(raw_data.humidity_adc().0 == expected_humidity);
244 assert!(raw_data.gas_adc().0 == expected_gas_adc);
245 assert!(raw_data.gas_valid() == expected_gas_valid);
246 assert!(raw_data.heater_sable() == expected_heater_stable);
247 assert!(raw_data.gas_range() == expected_gas_range);
248 }
249
250 #[test]
251 fn test_measurment_and_humidty() {
252 let data = [0b00101001, 0b10110011, 0b1111_0000, 0b10110011, 0b00101001];
254 let expected_measurment_value = 0b0000_00000000_00101001_10110011_1111_u32;
255 let expected_humidity = 0b10110011_00101001_u16;
256 let measurment = SampleData(data);
257 assert!(expected_measurment_value == measurment.m().0);
258 assert!(expected_humidity == measurment.h().0);
259 }
260 #[test]
261 fn test_assemble() {
262 let mut result = 0;
263 let xlsb: u32 = 0b1111_0000;
264 let lsb = 0b10110011;
265 let msb = 0b00101001;
266 let expected_value = 0b101001_10110011_1111;
267 result |= xlsb >> 4;
268 println!("Adding xlsb {xlsb:b} results in: {result:b}");
269 result |= lsb << 4;
270 println!("Adding lsb {lsb:b} results in: {result:b}");
271 result |= msb << 12;
272 println!("Adding msb {msb:b} results in: {result:b}");
273 assert!(result == expected_value);
274 }
275 #[test]
276 fn test_raw_config() {
277 let mut raw_config = RawConfig([0u8; 5]);
278 let default_user_config = Configuration::default();
279 raw_config.apply_config(&default_user_config);
280 let raw_data = raw_config.0;
281 let expected_raw_data = [
282 0b_000_1_0000u8,
284 0b_0_0_000_001,
286 0b0,
288 0b_010_101_00,
290 0b000_001_00,
292 ];
293 println!("Expeced data: {expected_raw_data:?}");
294 println!("Actual raw data: {raw_data:?}");
295 assert!(expected_raw_data == raw_data);
296 }
297}