embassy_bme280_sensor/
calibration.rs1use 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}