New SPI API supporting DMA
[betaflight.git] / src / main / drivers / barometer / barometer_bmp280.c
blobd6e641620e3bc2cc6affbb5b2e6de6eed79effb0
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 // 10 MHz max SPI frequency
41 #define BMP280_MAX_SPI_CLK_HZ 10000000
43 #if defined(USE_BARO) && (defined(USE_BARO_BMP280) || defined(USE_BARO_SPI_BMP280))
46 #define BMP280_I2C_ADDR (0x76)
47 #define BMP280_DEFAULT_CHIP_ID (0x58)
48 #define BME280_DEFAULT_CHIP_ID (0x60)
50 #define BMP280_CHIP_ID_REG (0xD0) /* Chip ID Register */
51 #define BMP280_RST_REG (0xE0) /* Softreset Register */
52 #define BMP280_STAT_REG (0xF3) /* Status Register */
53 #define BMP280_CTRL_MEAS_REG (0xF4) /* Ctrl Measure Register */
54 #define BMP280_CONFIG_REG (0xF5) /* Configuration Register */
55 #define BMP280_PRESSURE_MSB_REG (0xF7) /* Pressure MSB Register */
56 #define BMP280_PRESSURE_LSB_REG (0xF8) /* Pressure LSB Register */
57 #define BMP280_PRESSURE_XLSB_REG (0xF9) /* Pressure XLSB Register */
58 #define BMP280_TEMPERATURE_MSB_REG (0xFA) /* Temperature MSB Reg */
59 #define BMP280_TEMPERATURE_LSB_REG (0xFB) /* Temperature LSB Reg */
60 #define BMP280_TEMPERATURE_XLSB_REG (0xFC) /* Temperature XLSB Reg */
61 #define BMP280_FORCED_MODE (0x01)
63 #define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG (0x88)
64 #define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH (24)
65 #define BMP280_DATA_FRAME_SIZE (6)
67 #define BMP280_OVERSAMP_SKIPPED (0x00)
68 #define BMP280_OVERSAMP_1X (0x01)
69 #define BMP280_OVERSAMP_2X (0x02)
70 #define BMP280_OVERSAMP_4X (0x03)
71 #define BMP280_OVERSAMP_8X (0x04)
72 #define BMP280_OVERSAMP_16X (0x05)
74 // configure pressure and temperature oversampling, forced sampling mode
75 #define BMP280_PRESSURE_OSR (BMP280_OVERSAMP_8X)
76 #define BMP280_TEMPERATURE_OSR (BMP280_OVERSAMP_1X)
77 #define BMP280_MODE (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_FORCED_MODE)
79 #define T_INIT_MAX (20)
80 // 20/16 = 1.25 ms
81 #define T_MEASURE_PER_OSRS_MAX (37)
82 // 37/16 = 2.3125 ms
83 #define T_SETUP_PRESSURE_MAX (10)
84 // 10/16 = 0.625 ms
86 typedef struct bmp280_calib_param_s {
87 uint16_t dig_T1; /* calibration T1 data */
88 int16_t dig_T2; /* calibration T2 data */
89 int16_t dig_T3; /* calibration T3 data */
90 uint16_t dig_P1; /* calibration P1 data */
91 int16_t dig_P2; /* calibration P2 data */
92 int16_t dig_P3; /* calibration P3 data */
93 int16_t dig_P4; /* calibration P4 data */
94 int16_t dig_P5; /* calibration P5 data */
95 int16_t dig_P6; /* calibration P6 data */
96 int16_t dig_P7; /* calibration P7 data */
97 int16_t dig_P8; /* calibration P8 data */
98 int16_t dig_P9; /* calibration P9 data */
99 } __attribute__((packed)) bmp280_calib_param_t; // packed as we read directly from the device into this structure.
101 STATIC_ASSERT(sizeof(bmp280_calib_param_t) == BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH, bmp280_calibration_structure_incorrectly_packed);
103 STATIC_UNIT_TESTED int32_t t_fine; /* calibration t_fine data */
105 static uint8_t bmp280_chip_id = 0;
106 STATIC_UNIT_TESTED bmp280_calib_param_t bmp280_cal;
107 // uncompensated pressure and temperature
108 int32_t bmp280_up = 0;
109 int32_t bmp280_ut = 0;
110 static DMA_DATA_ZERO_INIT uint8_t sensor_data[BMP280_DATA_FRAME_SIZE];
112 static void bmp280StartUT(baroDev_t *baro);
113 static bool bmp280ReadUT(baroDev_t *baro);
114 static bool bmp280GetUT(baroDev_t *baro);
115 static void bmp280StartUP(baroDev_t *baro);
116 static bool bmp280ReadUP(baroDev_t *baro);
117 static bool bmp280GetUP(baroDev_t *baro);
119 STATIC_UNIT_TESTED void bmp280Calculate(int32_t *pressure, int32_t *temperature);
121 void bmp280BusInit(const extDevice_t *dev)
123 #ifdef USE_BARO_SPI_BMP280
124 if (dev->bus->busType == BUS_TYPE_SPI) {
125 IOHi(dev->busType_u.spi.csnPin); // Disable
126 IOInit(dev->busType_u.spi.csnPin, OWNER_BARO_CS, 0);
127 IOConfigGPIO(dev->busType_u.spi.csnPin, IOCFG_OUT_PP);
128 spiSetClkDivisor(dev, spiCalculateDivider(BMP280_MAX_SPI_CLK_HZ));
130 #else
131 UNUSED(dev);
132 #endif
135 void bmp280BusDeinit(const extDevice_t *dev)
137 #ifdef USE_BARO_SPI_BMP280
138 if (dev->bus->busType == BUS_TYPE_SPI) {
139 spiPreinitByIO(dev->busType_u.spi.csnPin);
141 #else
142 UNUSED(dev);
143 #endif
146 #include "drivers/time.h"
148 bool bmp280Detect(baroDev_t *baro)
150 delay(20);
152 extDevice_t *dev = &baro->dev;
153 bool defaultAddressApplied = false;
155 bmp280BusInit(dev);
157 if ((dev->bus->busType == BUS_TYPE_I2C) && (dev->busType_u.i2c.address == 0)) {
158 // Default address for BMP280
159 dev->busType_u.i2c.address = BMP280_I2C_ADDR;
160 defaultAddressApplied = true;
163 busReadRegisterBuffer(dev, BMP280_CHIP_ID_REG, &bmp280_chip_id, 1); /* read Chip Id */
165 if ((bmp280_chip_id != BMP280_DEFAULT_CHIP_ID) && (bmp280_chip_id != BME280_DEFAULT_CHIP_ID)) {
166 bmp280BusDeinit(dev);
167 if (defaultAddressApplied) {
168 dev->busType_u.i2c.address = 0;
170 return false;
173 busDeviceRegister(dev);
175 // read calibration
176 busReadRegisterBuffer(dev, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, (uint8_t *)&bmp280_cal, sizeof(bmp280_calib_param_t));
178 // set oversampling + power mode (forced), and start sampling
179 busWriteRegister(dev, BMP280_CTRL_MEAS_REG, BMP280_MODE);
181 // these are dummy as temperature is measured as part of pressure
182 baro->combined_read = true;
183 baro->ut_delay = 0;
184 baro->start_ut = bmp280StartUT;
185 baro->get_ut = bmp280GetUT;
186 baro->read_ut = bmp280ReadUT;
187 // only _up part is executed, and gets both temperature and pressure
188 baro->start_up = bmp280StartUP;
189 baro->get_up = bmp280GetUP;
190 baro->read_up = bmp280ReadUP;
191 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;
192 baro->calculate = bmp280Calculate;
194 return true;
197 static void bmp280StartUT(baroDev_t *baro)
199 UNUSED(baro);
200 // dummy
203 static bool bmp280ReadUT(baroDev_t *baro)
205 UNUSED(baro);
206 // dummy
207 return true;
210 static bool bmp280GetUT(baroDev_t *baro)
212 UNUSED(baro);
213 // dummy
214 return true;
217 static void bmp280StartUP(baroDev_t *baro)
219 // start measurement
220 // set oversampling + power mode (forced), and start sampling
221 busWriteRegisterStart(&baro->dev, BMP280_CTRL_MEAS_REG, BMP280_MODE);
224 static bool bmp280ReadUP(baroDev_t *baro)
226 if (busBusy(&baro->dev, NULL)) {
227 return false;
230 // read data from sensor
231 busReadRegisterBufferStart(&baro->dev, BMP280_PRESSURE_MSB_REG, sensor_data, BMP280_DATA_FRAME_SIZE);
233 return true;
236 static bool bmp280GetUP(baroDev_t *baro)
238 if (busBusy(&baro->dev, NULL)) {
239 return false;
242 bmp280_up = (int32_t)(sensor_data[0] << 12 | sensor_data[1] << 4 | sensor_data[2] >> 4);
243 bmp280_ut = (int32_t)(sensor_data[3] << 12 | sensor_data[4] << 4 | sensor_data[5] >> 4);
245 return true;
248 // Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
249 // t_fine carries fine temperature as global value
250 static int32_t bmp280CompensateTemperature(int32_t adc_T)
252 int32_t var1, var2, T;
254 var1 = ((((adc_T >> 3) - ((int32_t)bmp280_cal.dig_T1 << 1))) * ((int32_t)bmp280_cal.dig_T2)) >> 11;
255 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;
256 t_fine = var1 + var2;
257 T = (t_fine * 5 + 128) >> 8;
259 return T;
262 // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
263 // Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
264 static uint32_t bmp280CompensatePressure(int32_t adc_P)
266 int64_t var1, var2, p;
267 var1 = ((int64_t)t_fine) - 128000;
268 var2 = var1 * var1 * (int64_t)bmp280_cal.dig_P6;
269 var2 = var2 + ((var1*(int64_t)bmp280_cal.dig_P5) << 17);
270 var2 = var2 + (((int64_t)bmp280_cal.dig_P4) << 35);
271 var1 = ((var1 * var1 * (int64_t)bmp280_cal.dig_P3) >> 8) + ((var1 * (int64_t)bmp280_cal.dig_P2) << 12);
272 var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bmp280_cal.dig_P1) >> 33;
273 if (var1 == 0)
274 return 0;
275 p = 1048576 - adc_P;
276 p = (((p << 31) - var2) * 3125) / var1;
277 var1 = (((int64_t)bmp280_cal.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
278 var2 = (((int64_t)bmp280_cal.dig_P8) * p) >> 19;
279 p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_cal.dig_P7) << 4);
280 return (uint32_t)p;
283 STATIC_UNIT_TESTED void bmp280Calculate(int32_t *pressure, int32_t *temperature)
285 // calculate
286 int32_t t;
287 uint32_t p;
288 t = bmp280CompensateTemperature(bmp280_ut);
289 p = bmp280CompensatePressure(bmp280_up);
291 if (pressure)
292 *pressure = (int32_t)(p / 256);
293 if (temperature)
294 *temperature = t;
297 #endif