embassy_bme280_sensor/
calibration.rs

1use crate::{BME280_REGISTER_DIG_FIRST_LENGTH, BME280_REGISTER_DIG_SECOND_LENGTH};
2
3pub struct CalibrationRegisters {
4    pub dig_t1: u16,
5    pub dig_t2: i16,
6    pub dig_t3: i16,
7    pub dig_p1: u16,
8    pub dig_p2: i16,
9    pub dig_p3: i16,
10    pub dig_p4: i16,
11    pub dig_p5: i16,
12    pub dig_p6: i16,
13    pub dig_p7: i16,
14    pub dig_p8: i16,
15    pub dig_p9: i16,
16    pub dig_h1: u8,
17    pub dig_h2: i16,
18    pub dig_h3: u8,
19    pub dig_h4: i16,
20    pub dig_h5: i16,
21    pub dig_h6: i8,
22}
23
24impl From<[u8; BME280_REGISTER_DIG_FIRST_LENGTH + BME280_REGISTER_DIG_SECOND_LENGTH]>
25    for CalibrationRegisters
26{
27    fn from(
28        value: [u8; BME280_REGISTER_DIG_FIRST_LENGTH + BME280_REGISTER_DIG_SECOND_LENGTH],
29    ) -> Self {
30        Self {
31            dig_t1: u16::from_le_bytes([value[0], value[1]]),
32            dig_t2: i16::from_le_bytes([value[2], value[3]]),
33            dig_t3: i16::from_le_bytes([value[4], value[5]]),
34            dig_p1: u16::from_le_bytes([value[6], value[7]]),
35            dig_p2: i16::from_le_bytes([value[8], value[9]]),
36            dig_p3: i16::from_le_bytes([value[10], value[11]]),
37            dig_p4: i16::from_le_bytes([value[12], value[13]]),
38            dig_p5: i16::from_le_bytes([value[14], value[15]]),
39            dig_p6: i16::from_le_bytes([value[16], value[17]]),
40            dig_p7: i16::from_le_bytes([value[18], value[19]]),
41            dig_p8: i16::from_le_bytes([value[20], value[21]]),
42            dig_p9: i16::from_le_bytes([value[22], value[23]]),
43            dig_h1: value[25],
44            dig_h2: i16::from_le_bytes([value[26], value[27]]),
45            dig_h3: value[28],
46            dig_h4: i16::from(value[29]) << 4 | i16::from(value[30]) & 0xf,
47            dig_h5: ((i16::from(value[30]) & 0xf0) >> 4) | (i16::from(value[31]) << 4),
48            dig_h6: value[32] as i8,
49        }
50    }
51}
52
53impl CalibrationRegisters {
54    pub fn compensate_temperature(&self, adc_t: i32) -> i32 {
55        let var1 = (((adc_t >> 3) - (i32::from(self.dig_t1) << 1)) * i32::from(self.dig_t2)) >> 11;
56        let var2 = (((((adc_t >> 4) - i32::from(self.dig_t1))
57            * ((adc_t >> 4) - i32::from(self.dig_t1)))
58            >> 12)
59            * i32::from(self.dig_t3))
60            >> 14;
61
62        var1 + var2
63    }
64
65    pub fn compensate_humidity(&self, adc_h: u16, t_fine: i32) -> u32 {
66        let adc_h = i32::from(adc_h);
67
68        let v_x1_u32r: i32 = t_fine - 76_800_i32;
69        let v_x1_u32r: i32 = ((((adc_h << 14)
70            - (i32::from(self.dig_h4) << 20)
71            - (i32::from(self.dig_h5) * v_x1_u32r))
72            + (16_384_i32))
73            >> 15)
74            * (((((((v_x1_u32r * i32::from(self.dig_h6)) >> 10)
75                * (((v_x1_u32r * i32::from(self.dig_h3)) >> 11) + (32_768_i32)))
76                >> 10)
77                + (2_097_152_i32))
78                * i32::from(self.dig_h2)
79                + 8192_i32)
80                >> 14);
81        let v_x1_u32r: i32 = v_x1_u32r
82            - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * i32::from(self.dig_h1)) >> 4);
83        let v_x1_u32r = if v_x1_u32r < 0 { 0 } else { v_x1_u32r };
84        let v_x1_u32r = if v_x1_u32r > 419_430_400 {
85            419_430_400
86        } else {
87            v_x1_u32r
88        };
89
90        let humidity = v_x1_u32r >> 12;
91        humidity as u32
92    }
93
94    pub fn compensate_pressure(&self, adc_p: u32, t_fine: i32) -> u32 {
95        let var1 = i64::from(t_fine) - 128_000;
96        let var2 = var1 * var1 * i64::from(self.dig_p6);
97        let var2 = var2 + ((var1 * i64::from(self.dig_p5)) << 17);
98        let var2 = var2 + (i64::from(self.dig_p4) << 35);
99        let var1 =
100            ((var1 * var1 * i64::from(self.dig_p3)) >> 8) + ((var1 * i64::from(self.dig_p2)) << 12);
101        let var1 = ((((1_i64) << 47) + var1) * i64::from(self.dig_p1)) >> 33;
102
103        if var1 == 0 {
104            0
105        } else {
106            let var4 = 1_048_576 - i64::from(adc_p);
107            let var4 = (((var4 << 31) - var2) * 3125) / var1;
108            let var1 = (i64::from(self.dig_p9) * (var4 >> 13) * (var4 >> 13)) >> 25;
109            let var2 = (i64::from(self.dig_p8) * var4) >> 19;
110            let var5 = ((var4 + var1 + var2) >> 8) + (i64::from(self.dig_p7) << 4);
111
112            let p = var5;
113            let pressure = p as u32;
114
115            pressure
116        }
117    }
118}