Removed excess trailing spaces before new lines on licenses.
[betaflight.git] / src / main / drivers / barometer / barometer_bmp280.c
blob00f8f8e14c5ddf6fe8f316f7110f471bdc4d5afe
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
24 #include <platform.h>
26 #include "build/build_config.h"
27 #include "build/debug.h"
29 #include "barometer.h"
31 #include "drivers/bus.h"
32 #include "drivers/bus_i2c.h"
33 #include "drivers/bus_i2c_busdev.h"
34 #include "drivers/bus_spi.h"
35 #include "drivers/io.h"
36 #include "drivers/time.h"
38 #include "barometer_bmp280.h"
40 #if defined(USE_BARO) && (defined(USE_BARO_BMP280) || defined(USE_BARO_SPI_BMP280))
42 typedef struct bmp280_calib_param_s {
43 uint16_t dig_T1; /* calibration T1 data */
44 int16_t dig_T2; /* calibration T2 data */
45 int16_t dig_T3; /* calibration T3 data */
46 uint16_t dig_P1; /* calibration P1 data */
47 int16_t dig_P2; /* calibration P2 data */
48 int16_t dig_P3; /* calibration P3 data */
49 int16_t dig_P4; /* calibration P4 data */
50 int16_t dig_P5; /* calibration P5 data */
51 int16_t dig_P6; /* calibration P6 data */
52 int16_t dig_P7; /* calibration P7 data */
53 int16_t dig_P8; /* calibration P8 data */
54 int16_t dig_P9; /* calibration P9 data */
55 int32_t t_fine; /* calibration t_fine data */
56 } bmp280_calib_param_t;
58 static uint8_t bmp280_chip_id = 0;
59 STATIC_UNIT_TESTED bmp280_calib_param_t bmp280_cal;
60 // uncompensated pressure and temperature
61 int32_t bmp280_up = 0;
62 int32_t bmp280_ut = 0;
64 static void bmp280_start_ut(baroDev_t *baro);
65 static void bmp280_get_ut(baroDev_t *baro);
66 static void bmp280_start_up(baroDev_t *baro);
67 static void bmp280_get_up(baroDev_t *baro);
69 STATIC_UNIT_TESTED void bmp280_calculate(int32_t *pressure, int32_t *temperature);
71 void bmp280BusInit(busDevice_t *busdev)
73 #ifdef USE_BARO_SPI_BMP280
74 if (busdev->bustype == BUSTYPE_SPI) {
75 IOHi(busdev->busdev_u.spi.csnPin); // Disable
76 IOInit(busdev->busdev_u.spi.csnPin, OWNER_BARO_CS, 0);
77 IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP);
78 spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_STANDARD); // XXX
80 #else
81 UNUSED(busdev);
82 #endif
85 void bmp280BusDeinit(busDevice_t *busdev)
87 #ifdef USE_BARO_SPI_BMP280
88 if (busdev->bustype == BUSTYPE_SPI) {
89 IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_IPU);
90 IORelease(busdev->busdev_u.spi.csnPin);
91 IOInit(busdev->busdev_u.spi.csnPin, OWNER_SPI_PREINIT, 0);
93 #else
94 UNUSED(busdev);
95 #endif
98 bool bmp280Detect(baroDev_t *baro)
100 delay(20);
102 busDevice_t *busdev = &baro->busdev;
103 bool defaultAddressApplied = false;
105 bmp280BusInit(busdev);
107 if ((busdev->bustype == BUSTYPE_I2C) && (busdev->busdev_u.i2c.address == 0)) {
108 // Default address for BMP280
109 busdev->busdev_u.i2c.address = BMP280_I2C_ADDR;
110 defaultAddressApplied = true;
113 busReadRegisterBuffer(busdev, BMP280_CHIP_ID_REG, &bmp280_chip_id, 1); /* read Chip Id */
115 if (bmp280_chip_id != BMP280_DEFAULT_CHIP_ID) {
116 bmp280BusDeinit(busdev);
117 if (defaultAddressApplied) {
118 busdev->busdev_u.i2c.address = 0;
120 return false;
123 // read calibration
124 busReadRegisterBuffer(busdev, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, (uint8_t *)&bmp280_cal, 24);
126 // set oversampling + power mode (forced), and start sampling
127 busWriteRegister(busdev, BMP280_CTRL_MEAS_REG, BMP280_MODE);
129 // these are dummy as temperature is measured as part of pressure
130 baro->ut_delay = 0;
131 baro->get_ut = bmp280_get_ut;
132 baro->start_ut = bmp280_start_ut;
133 // only _up part is executed, and gets both temperature and pressure
134 baro->start_up = bmp280_start_up;
135 baro->get_up = bmp280_get_up;
136 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;
137 baro->calculate = bmp280_calculate;
139 return true;
142 static void bmp280_start_ut(baroDev_t *baro)
144 UNUSED(baro);
145 // dummy
148 static void bmp280_get_ut(baroDev_t *baro)
150 UNUSED(baro);
151 // dummy
154 static void bmp280_start_up(baroDev_t *baro)
156 // start measurement
157 // set oversampling + power mode (forced), and start sampling
158 busWriteRegister(&baro->busdev, BMP280_CTRL_MEAS_REG, BMP280_MODE);
161 static void bmp280_get_up(baroDev_t *baro)
163 uint8_t data[BMP280_DATA_FRAME_SIZE];
165 // read data from sensor
166 busReadRegisterBuffer(&baro->busdev, BMP280_PRESSURE_MSB_REG, data, BMP280_DATA_FRAME_SIZE);
167 bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));
168 bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4));
171 // Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
172 // t_fine carries fine temperature as global value
173 static int32_t bmp280_compensate_T(int32_t adc_T)
175 int32_t var1, var2, T;
177 var1 = ((((adc_T >> 3) - ((int32_t)bmp280_cal.dig_T1 << 1))) * ((int32_t)bmp280_cal.dig_T2)) >> 11;
178 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;
179 bmp280_cal.t_fine = var1 + var2;
180 T = (bmp280_cal.t_fine * 5 + 128) >> 8;
182 return T;
185 // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
186 // Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
187 static uint32_t bmp280_compensate_P(int32_t adc_P)
189 int64_t var1, var2, p;
190 var1 = ((int64_t)bmp280_cal.t_fine) - 128000;
191 var2 = var1 * var1 * (int64_t)bmp280_cal.dig_P6;
192 var2 = var2 + ((var1*(int64_t)bmp280_cal.dig_P5) << 17);
193 var2 = var2 + (((int64_t)bmp280_cal.dig_P4) << 35);
194 var1 = ((var1 * var1 * (int64_t)bmp280_cal.dig_P3) >> 8) + ((var1 * (int64_t)bmp280_cal.dig_P2) << 12);
195 var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bmp280_cal.dig_P1) >> 33;
196 if (var1 == 0)
197 return 0;
198 p = 1048576 - adc_P;
199 p = (((p << 31) - var2) * 3125) / var1;
200 var1 = (((int64_t)bmp280_cal.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
201 var2 = (((int64_t)bmp280_cal.dig_P8) * p) >> 19;
202 p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_cal.dig_P7) << 4);
203 return (uint32_t)p;
206 STATIC_UNIT_TESTED void bmp280_calculate(int32_t *pressure, int32_t *temperature)
208 // calculate
209 int32_t t;
210 uint32_t p;
211 t = bmp280_compensate_T(bmp280_ut);
212 p = bmp280_compensate_P(bmp280_up);
214 if (pressure)
215 *pressure = (int32_t)(p / 256);
216 if (temperature)
217 *temperature = t;
220 #endif