unify `typedef struct name_s {} name_t;` naming convention
[betaflight.git] / src / main / drivers / barometer_bmp280.c
blob43de7560e1017f51d4843a61f9fe944392f978e1
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
21 #include <platform.h>
23 #include "build_config.h"
25 #include "barometer.h"
27 #include "system.h"
28 #include "bus_i2c.h"
30 #include "barometer_bmp280.h"
32 #ifdef BARO
34 // BMP280, address 0x76
36 #define BMP280_I2C_ADDR (0x76)
37 #define BMP280_DEFAULT_CHIP_ID (0x58)
39 #define BMP280_CHIP_ID_REG (0xD0) /* Chip ID Register */
40 #define BMP280_RST_REG (0xE0) /* Softreset Register */
41 #define BMP280_STAT_REG (0xF3) /* Status Register */
42 #define BMP280_CTRL_MEAS_REG (0xF4) /* Ctrl Measure Register */
43 #define BMP280_CONFIG_REG (0xF5) /* Configuration Register */
44 #define BMP280_PRESSURE_MSB_REG (0xF7) /* Pressure MSB Register */
45 #define BMP280_PRESSURE_LSB_REG (0xF8) /* Pressure LSB Register */
46 #define BMP280_PRESSURE_XLSB_REG (0xF9) /* Pressure XLSB Register */
47 #define BMP280_TEMPERATURE_MSB_REG (0xFA) /* Temperature MSB Reg */
48 #define BMP280_TEMPERATURE_LSB_REG (0xFB) /* Temperature LSB Reg */
49 #define BMP280_TEMPERATURE_XLSB_REG (0xFC) /* Temperature XLSB Reg */
50 #define BMP280_FORCED_MODE (0x01)
52 #define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG (0x88)
53 #define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH (24)
54 #define BMP280_DATA_FRAME_SIZE (6)
56 #define BMP280_OVERSAMP_SKIPPED (0x00)
57 #define BMP280_OVERSAMP_1X (0x01)
58 #define BMP280_OVERSAMP_2X (0x02)
59 #define BMP280_OVERSAMP_4X (0x03)
60 #define BMP280_OVERSAMP_8X (0x04)
61 #define BMP280_OVERSAMP_16X (0x05)
63 // configure pressure and temperature oversampling, forced sampling mode
64 #define BMP280_PRESSURE_OSR (BMP280_OVERSAMP_8X)
65 #define BMP280_TEMPERATURE_OSR (BMP280_OVERSAMP_1X)
66 #define BMP280_MODE (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_FORCED_MODE)
68 #define T_INIT_MAX (20)
69 // 20/16 = 1.25 ms
70 #define T_MEASURE_PER_OSRS_MAX (37)
71 // 37/16 = 2.3125 ms
72 #define T_SETUP_PRESSURE_MAX (10)
73 // 10/16 = 0.625 ms
75 typedef struct bmp280_calib_param_s {
76 uint16_t dig_T1; /* calibration T1 data */
77 int16_t dig_T2; /* calibration T2 data */
78 int16_t dig_T3; /* calibration T3 data */
79 uint16_t dig_P1; /* calibration P1 data */
80 int16_t dig_P2; /* calibration P2 data */
81 int16_t dig_P3; /* calibration P3 data */
82 int16_t dig_P4; /* calibration P4 data */
83 int16_t dig_P5; /* calibration P5 data */
84 int16_t dig_P6; /* calibration P6 data */
85 int16_t dig_P7; /* calibration P7 data */
86 int16_t dig_P8; /* calibration P8 data */
87 int16_t dig_P9; /* calibration P9 data */
88 int32_t t_fine; /* calibration t_fine data */
89 } bmp280_calib_param_t;
91 static uint8_t bmp280_chip_id = 0;
92 static bool bmp280InitDone = false;
93 STATIC_UNIT_TESTED bmp280_calib_param_t bmp280_cal;
94 // uncompensated pressure and temperature
95 STATIC_UNIT_TESTED int32_t bmp280_up = 0;
96 STATIC_UNIT_TESTED int32_t bmp280_ut = 0;
98 static void bmp280_start_ut(void);
99 static void bmp280_get_ut(void);
100 static void bmp280_start_up(void);
101 static void bmp280_get_up(void);
102 STATIC_UNIT_TESTED void bmp280_calculate(int32_t *pressure, int32_t *temperature);
104 bool bmp280Detect(baro_t *baro)
106 if (bmp280InitDone)
107 return true;
109 delay(20);
111 i2cRead(BMP280_I2C_ADDR, BMP280_CHIP_ID_REG, 1, &bmp280_chip_id); /* read Chip Id */
112 if (bmp280_chip_id != BMP280_DEFAULT_CHIP_ID)
113 return false;
115 // read calibration
116 i2cRead(BMP280_I2C_ADDR, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, 24, (uint8_t *)&bmp280_cal);
117 // set oversampling + power mode (forced), and start sampling
118 i2cWrite(BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE);
120 bmp280InitDone = true;
122 // these are dummy as temperature is measured as part of pressure
123 baro->ut_delay = 0;
124 baro->get_ut = bmp280_get_ut;
125 baro->start_ut = bmp280_start_ut;
127 // only _up part is executed, and gets both temperature and pressure
128 baro->up_delay = ((T_INIT_MAX + T_MEASURE_PER_OSRS_MAX * (((1 << BMP280_TEMPERATURE_OSR) >> 1) + ((1 << BMP280_PRESSURE_OSR) >> 1)) + (BMP280_PRESSURE_OSR ? T_SETUP_PRESSURE_MAX : 0) + 15) / 16) * 1000;
129 baro->start_up = bmp280_start_up;
130 baro->get_up = bmp280_get_up;
131 baro->calculate = bmp280_calculate;
133 return true;
136 static void bmp280_start_ut(void)
138 // dummy
141 static void bmp280_get_ut(void)
143 // dummy
146 static void bmp280_start_up(void)
148 // start measurement
149 // set oversampling + power mode (forced), and start sampling
150 i2cWrite(BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE);
153 static void bmp280_get_up(void)
155 uint8_t data[BMP280_DATA_FRAME_SIZE];
157 // read data from sensor
158 i2cRead(BMP280_I2C_ADDR, BMP280_PRESSURE_MSB_REG, BMP280_DATA_FRAME_SIZE, data);
159 bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));
160 bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4));
163 // Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
164 // t_fine carries fine temperature as global value
165 static int32_t bmp280_compensate_T(int32_t adc_T)
167 int32_t var1, var2, T;
169 var1 = ((((adc_T >> 3) - ((int32_t)bmp280_cal.dig_T1 << 1))) * ((int32_t)bmp280_cal.dig_T2)) >> 11;
170 var2 = (((((adc_T >> 4) - ((int32_t)bmp280_cal.dig_T1)) * ((adc_T >> 4) - ((int32_t)bmp280_cal.dig_T1))) >> 12) * ((int32_t)bmp280_cal.dig_T3)) >> 14;
171 bmp280_cal.t_fine = var1 + var2;
172 T = (bmp280_cal.t_fine * 5 + 128) >> 8;
174 return T;
177 // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
178 // Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
179 static uint32_t bmp280_compensate_P(int32_t adc_P)
181 int64_t var1, var2, p;
182 var1 = ((int64_t)bmp280_cal.t_fine) - 128000;
183 var2 = var1 * var1 * (int64_t)bmp280_cal.dig_P6;
184 var2 = var2 + ((var1*(int64_t)bmp280_cal.dig_P5) << 17);
185 var2 = var2 + (((int64_t)bmp280_cal.dig_P4) << 35);
186 var1 = ((var1 * var1 * (int64_t)bmp280_cal.dig_P3) >> 8) + ((var1 * (int64_t)bmp280_cal.dig_P2) << 12);
187 var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bmp280_cal.dig_P1) >> 33;
188 if (var1 == 0)
189 return 0;
190 p = 1048576 - adc_P;
191 p = (((p << 31) - var2) * 3125) / var1;
192 var1 = (((int64_t)bmp280_cal.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
193 var2 = (((int64_t)bmp280_cal.dig_P8) * p) >> 19;
194 p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_cal.dig_P7) << 4);
195 return (uint32_t)p;
198 STATIC_UNIT_TESTED void bmp280_calculate(int32_t *pressure, int32_t *temperature)
200 // calculate
201 int32_t t;
202 uint32_t p;
203 t = bmp280_compensate_T(bmp280_ut);
204 p = bmp280_compensate_P(bmp280_up);
206 if (pressure)
207 *pressure = (int32_t)(p / 256);
208 if (temperature)
209 *temperature = t;
212 #endif