Merge pull request #11297 from SteveCEvans/baro_state
[betaflight.git] / src / main / drivers / barometer / barometer_bmp388.c
blob6a647ba4cd2e41f822409302bb788c7796eb0625
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/>.
20 * BMP388 Driver author: Dominic Clifton
23 #include <math.h>
24 #include <stdbool.h>
25 #include <stdint.h>
27 #include "platform.h"
29 #if defined(USE_BARO) && (defined(USE_BARO_BMP388) || defined(USE_BARO_SPI_BMP388))
31 #include "build/build_config.h"
33 #include "build/debug.h"
35 #include "drivers/barometer/barometer.h"
36 #include "drivers/bus.h"
37 #include "drivers/bus_i2c.h"
38 #include "drivers/bus_i2c_busdev.h"
39 #include "drivers/bus_spi.h"
40 #include "drivers/io.h"
41 #include "drivers/nvic.h"
42 #include "drivers/time.h"
44 #include "barometer_bmp388.h"
46 // 10 MHz max SPI frequency
47 #define BMP388_MAX_SPI_CLK_HZ 10000000
49 #define BMP388_I2C_ADDR (0x76) // same as BMP280/BMP180
50 #define BMP388_DEFAULT_CHIP_ID (0x50) // from https://github.com/BoschSensortec/BMP3-Sensor-API/blob/master/bmp3_defs.h#L130
52 #define BMP388_CMD_REG (0x7E)
53 #define BMP388_RESERVED_UPPER_REG (0x7D)
54 // everything between BMP388_RESERVED_UPPER_REG and BMP388_RESERVED_LOWER_REG is reserved.
55 #define BMP388_RESERVED_LOWER_REG (0x20)
56 #define BMP388_CONFIG_REG (0x1F)
57 #define BMP388_RESERVED_0x1E_REG (0x1E)
58 #define BMP388_ODR_REG (0x1D)
59 #define BMP388_OSR_REG (0x1C)
60 #define BMP388_PWR_CTRL_REG (0x1B)
61 #define BMP388_IF_CONFIG_REG (0x1A)
62 #define BMP388_INT_CTRL_REG (0x19)
63 #define BMP388_FIFO_CONFIG_2_REG (0x18)
64 #define BMP388_FIFO_CONFIG_1_REG (0x17)
65 #define BMP388_FIFO_WTM_1_REG (0x16)
66 #define BMP388_FIFO_WTM_0_REG (0x15)
67 #define BMP388_FIFO_DATA_REG (0x14)
68 #define BMP388_FIFO_LENGTH_1_REG (0x13)
69 #define BMP388_FIFO_LENGTH_0_REG (0x12)
70 #define BMP388_INT_STATUS_REG (0x11)
71 #define BMP388_EVENT_REG (0x10)
72 #define BMP388_SENSORTIME_3_REG (0x0F) // BME780 only
73 #define BMP388_SENSORTIME_2_REG (0x0E)
74 #define BMP388_SENSORTIME_1_REG (0x0D)
75 #define BMP388_SENSORTIME_0_REG (0x0C)
76 #define BMP388_RESERVED_0x0B_REG (0x0B)
77 #define BMP388_RESERVED_0x0A_REG (0x0A)
79 // see friendly register names below
80 #define BMP388_DATA_5_REG (0x09)
81 #define BMP388_DATA_4_REG (0x08)
82 #define BMP388_DATA_3_REG (0x07)
83 #define BMP388_DATA_2_REG (0x06)
84 #define BMP388_DATA_1_REG (0x05)
85 #define BMP388_DATA_0_REG (0x04)
87 #define BMP388_STATUS_REG (0x03)
88 #define BMP388_ERR_REG (0x02)
89 #define BMP388_RESERVED_0x01_REG (0x01)
90 #define BMP388_CHIP_ID_REG (0x00)
92 // friendly register names, from datasheet 4.3.4
93 #define BMP388_PRESS_MSB_23_16_REG BMP388_DATA_2_REG
94 #define BMP388_PRESS_LSB_15_8_REG BMP388_DATA_1_REG
95 #define BMP388_PRESS_XLSB_7_0_REG BMP388_DATA_0_REG
97 // friendly register names, from datasheet 4.3.5
98 #define BMP388_TEMP_MSB_23_16_REG BMP388_DATA_5_REG
99 #define BMP388_TEMP_LSB_15_8_REG BMP388_DATA_4_REG
100 #define BMP388_TEMP_XLSB_7_0_REG BMP388_DATA_3_REG
102 #define BMP388_DATA_FRAME_SIZE ((BMP388_DATA_5_REG - BMP388_DATA_0_REG) + 1) // +1 for inclusive
104 // from Datasheet 3.3
105 #define BMP388_MODE_SLEEP (0x00)
106 #define BMP388_MODE_FORCED (0x01)
107 #define BMP388_MODE_NORMAL (0x02)
109 #define BMP388_CALIRATION_LOWER_REG (0x30) // See datasheet 4.3.19, "calibration data"
110 #define BMP388_TRIMMING_NVM_PAR_T1_LSB_REG (0x31) // See datasheet 3.11.1 "Memory map trimming coefficients"
111 #define BMP388_TRIMMING_NVM_PAR_P11_REG (0x45) // See datasheet 3.11.1 "Memory map trimming coefficients"
112 #define BMP388_CALIRATION_UPPER_REG (0x57)
114 #define BMP388_TRIMMING_DATA_LENGTH ((BMP388_TRIMMING_NVM_PAR_P11_REG - BMP388_TRIMMING_NVM_PAR_T1_LSB_REG) + 1) // +1 for inclusive
116 #define BMP388_OVERSAMP_1X (0x00)
117 #define BMP388_OVERSAMP_2X (0x01)
118 #define BMP388_OVERSAMP_4X (0x02)
119 #define BMP388_OVERSAMP_8X (0x03)
120 #define BMP388_OVERSAMP_16X (0x04)
121 #define BMP388_OVERSAMP_32X (0x05)
123 // INT_CTRL register
124 #define BMP388_INT_OD_BIT 0
125 #define BMP388_INT_LEVEL_BIT 1
126 #define BMP388_INT_LATCH_BIT 2
127 #define BMP388_INT_FWTM_EN_BIT 3
128 #define BMP388_INT_FFULL_EN_BIT 4
129 #define BMP388_INT_RESERVED_5_BIT 5
130 #define BMP388_INT_DRDY_EN_BIT 6
131 #define BMP388_INT_RESERVED_7_BIT 7
133 // OSR register
134 #define BMP388_OSR_P_BIT 0 // to 2
135 #define BMP388_OSR4_T_BIT 3 // to 5
136 #define BMP388_OSR_P_MASK (0x03) // -----111
137 #define BMP388_OSR4_T_MASK (0x38) // --111---
139 // configure pressure and temperature oversampling, forced sampling mode
140 #define BMP388_PRESSURE_OSR (BMP388_OVERSAMP_8X)
141 #define BMP388_TEMPERATURE_OSR (BMP388_OVERSAMP_1X)
143 // see Datasheet 3.11.1 Memory Map Trimming Coefficients
144 typedef struct bmp388_calib_param_s {
145 uint16_t T1;
146 uint16_t T2;
147 int8_t T3;
148 int16_t P1;
149 int16_t P2;
150 int8_t P3;
151 int8_t P4;
152 uint16_t P5;
153 uint16_t P6;
154 int8_t P7;
155 int8_t P8;
156 int16_t P9;
157 int8_t P10;
158 int8_t P11;
159 } __attribute__((packed)) bmp388_calib_param_t;
161 STATIC_ASSERT(sizeof(bmp388_calib_param_t) == BMP388_TRIMMING_DATA_LENGTH, bmp388_calibration_structure_incorrectly_packed);
163 static uint8_t bmp388_chip_id = 0;
164 STATIC_UNIT_TESTED bmp388_calib_param_t bmp388_cal;
165 // uncompensated pressure and temperature
166 uint32_t bmp388_up = 0;
167 uint32_t bmp388_ut = 0;
168 static DMA_DATA_ZERO_INIT uint8_t sensor_data[BMP388_DATA_FRAME_SIZE];
170 STATIC_UNIT_TESTED int64_t t_lin = 0;
172 static void bmp388StartUT(baroDev_t *baro);
173 static bool bmp388GetUT(baroDev_t *baro);
174 static bool bmp388ReadUT(baroDev_t *baro);
175 static void bmp388StartUP(baroDev_t *baro);
176 static bool bmp388GetUP(baroDev_t *baro);
177 static bool bmp388ReadUP(baroDev_t *baro);
179 STATIC_UNIT_TESTED void bmp388Calculate(int32_t *pressure, int32_t *temperature);
181 #ifdef USE_EXTI
182 void bmp388_extiHandler(extiCallbackRec_t* cb)
184 #ifdef DEBUG
185 static uint32_t bmp388ExtiCallbackCounter = 0;
187 bmp388ExtiCallbackCounter++;
188 #endif
190 baroDev_t *baro = container_of(cb, baroDev_t, exti);
192 uint8_t intStatus = 0;
193 busReadRegisterBuffer(&baro->dev, BMP388_INT_STATUS_REG, &intStatus, 1);
195 #endif
197 void bmp388BusInit(const extDevice_t *dev)
199 #ifdef USE_BARO_SPI_BMP388
200 if (dev->bus->busType == BUS_TYPE_SPI) {
201 IOHi(dev->busType_u.spi.csnPin); // Disable
202 IOInit(dev->busType_u.spi.csnPin, OWNER_BARO_CS, 0);
203 IOConfigGPIO(dev->busType_u.spi.csnPin, IOCFG_OUT_PP);
204 spiSetClkDivisor(dev, spiCalculateDivider(BMP388_MAX_SPI_CLK_HZ));
206 #else
207 UNUSED(dev);
208 #endif
211 void bmp388BusDeinit(const extDevice_t *dev)
213 #ifdef USE_BARO_SPI_BMP388
214 if (dev->bus->busType == BUS_TYPE_SPI) {
215 spiPreinitByIO(dev->busType_u.spi.csnPin);
217 #else
218 UNUSED(dev);
219 #endif
222 void bmp388BeginForcedMeasurement(const extDevice_t *dev)
224 // enable pressure measurement, temperature measurement, set power mode and start sampling
225 uint8_t mode = BMP388_MODE_FORCED << 4 | 1 << 1 | 1 << 0;
226 busWriteRegisterStart(dev, BMP388_PWR_CTRL_REG, mode);
229 bool bmp388Detect(const bmp388Config_t *config, baroDev_t *baro)
231 delay(20);
233 #ifdef USE_EXTI
234 IO_t baroIntIO = IOGetByTag(config->eocTag);
235 if (baroIntIO) {
236 IOInit(baroIntIO, OWNER_BARO_EOC, 0);
237 EXTIHandlerInit(&baro->exti, bmp388_extiHandler);
238 EXTIConfig(baroIntIO, &baro->exti, NVIC_PRIO_BARO_EXTI, IOCFG_IN_FLOATING, BETAFLIGHT_EXTI_TRIGGER_RISING);
239 EXTIEnable(baroIntIO, true);
241 #else
242 UNUSED(config);
243 #endif
245 extDevice_t *dev = &baro->dev;
246 bool defaultAddressApplied = false;
248 bmp388BusInit(dev);
250 if ((dev->bus->busType == BUS_TYPE_I2C) && (dev->busType_u.i2c.address == 0)) {
251 // Default address for BMP388
252 dev->busType_u.i2c.address = BMP388_I2C_ADDR;
253 defaultAddressApplied = true;
256 busReadRegisterBuffer(dev, BMP388_CHIP_ID_REG, &bmp388_chip_id, 1);
258 if (bmp388_chip_id != BMP388_DEFAULT_CHIP_ID) {
259 bmp388BusDeinit(dev);
260 if (defaultAddressApplied) {
261 dev->busType_u.i2c.address = 0;
263 return false;
266 busDeviceRegister(dev);
268 #ifdef USE_EXTI
269 if (baroIntIO) {
270 uint8_t intCtrlValue = 1 << BMP388_INT_DRDY_EN_BIT |
271 0 << BMP388_INT_FFULL_EN_BIT |
272 0 << BMP388_INT_FWTM_EN_BIT |
273 0 << BMP388_INT_LATCH_BIT |
274 1 << BMP388_INT_LEVEL_BIT |
275 0 << BMP388_INT_OD_BIT;
276 busWriteRegister(dev, BMP388_INT_CTRL_REG, intCtrlValue);
278 #endif
280 // read calibration
281 busReadRegisterBuffer(dev, BMP388_TRIMMING_NVM_PAR_T1_LSB_REG, (uint8_t *)&bmp388_cal, sizeof(bmp388_calib_param_t));
284 // set oversampling
285 busWriteRegister(dev, BMP388_OSR_REG,
286 ((BMP388_PRESSURE_OSR << BMP388_OSR_P_BIT) & BMP388_OSR_P_MASK) |
287 ((BMP388_TEMPERATURE_OSR << BMP388_OSR4_T_BIT) & BMP388_OSR4_T_MASK)
290 bmp388BeginForcedMeasurement(dev);
292 // these are dummy as temperature is measured as part of pressure
293 baro->ut_delay = 0;
294 baro->start_ut = bmp388StartUT;
295 baro->get_ut = bmp388GetUT;
296 baro->read_ut = bmp388ReadUT;
297 // only _up part is executed, and gets both temperature and pressure
298 baro->start_up = bmp388StartUP;
299 baro->get_up = bmp388GetUP;
300 baro->read_up = bmp388ReadUP;
302 // See datasheet 3.9.2 "Measurement rate in forced mode and normal mode"
303 baro->up_delay = 234 +
304 (392 + (powf(2, BMP388_PRESSURE_OSR + 1) * 2000)) +
305 (313 + (powf(2, BMP388_TEMPERATURE_OSR + 1) * 2000));
307 baro->calculate = bmp388Calculate;
309 while (busBusy(&baro->dev, NULL));
311 return true;
314 static void bmp388StartUT(baroDev_t *baro)
316 UNUSED(baro);
317 // dummy
320 static bool bmp388ReadUT(baroDev_t *baro)
322 UNUSED(baro);
323 // dummy
324 return true;
327 static bool bmp388GetUT(baroDev_t *baro)
329 UNUSED(baro);
330 // dummy
331 return true;
334 static void bmp388StartUP(baroDev_t *baro)
336 // start measurement
337 bmp388BeginForcedMeasurement(&baro->dev);
340 static bool bmp388ReadUP(baroDev_t *baro)
342 if (busBusy(&baro->dev, NULL)) {
343 return false;
346 // read data from sensor
347 busReadRegisterBufferStart(&baro->dev, BMP388_DATA_0_REG, sensor_data, BMP388_DATA_FRAME_SIZE);
349 return true;
352 static bool bmp388GetUP(baroDev_t *baro)
354 if (busBusy(&baro->dev, NULL)) {
355 return false;
358 bmp388_up = sensor_data[0] << 0 | sensor_data[1] << 8 | sensor_data[2] << 16;
359 bmp388_ut = sensor_data[3] << 0 | sensor_data[4] << 8 | sensor_data[5] << 16;
360 return true;
363 // Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
364 static int64_t bmp388CompensateTemperature(uint32_t uncomp_temperature)
366 uint64_t partial_data1;
367 uint64_t partial_data2;
368 uint64_t partial_data3;
369 int64_t partial_data4;
370 int64_t partial_data5;
371 int64_t partial_data6;
372 int64_t comp_temp;
374 partial_data1 = uncomp_temperature - (256 * bmp388_cal.T1);
375 partial_data2 = bmp388_cal.T2 * partial_data1;
376 partial_data3 = partial_data1 * partial_data1;
377 partial_data4 = (int64_t)partial_data3 * bmp388_cal.T3;
378 partial_data5 = ((int64_t)(partial_data2 * 262144) + partial_data4);
379 partial_data6 = partial_data5 / 4294967296;
380 /* Update t_lin, needed for pressure calculation */
381 t_lin = partial_data6;
382 comp_temp = (int64_t)((partial_data6 * 25) / 16384);
384 return comp_temp;
387 static uint64_t bmp388CompensatePressure(uint32_t uncomp_pressure)
389 int64_t partial_data1;
390 int64_t partial_data2;
391 int64_t partial_data3;
392 int64_t partial_data4;
393 int64_t partial_data5;
394 int64_t partial_data6;
395 int64_t offset;
396 int64_t sensitivity;
397 uint64_t comp_press;
399 partial_data1 = t_lin * t_lin;
400 partial_data2 = partial_data1 / 64;
401 partial_data3 = (partial_data2 * t_lin) / 256;
402 partial_data4 = (bmp388_cal.P8 * partial_data3) / 32;
403 partial_data5 = (bmp388_cal.P7 * partial_data1) * 16;
404 partial_data6 = (bmp388_cal.P6 * t_lin) * 4194304;
405 offset = (bmp388_cal.P5 * 140737488355328) + partial_data4 + partial_data5 + partial_data6;
407 partial_data2 = (bmp388_cal.P4 * partial_data3) / 32;
408 partial_data4 = (bmp388_cal.P3 * partial_data1) * 4;
409 partial_data5 = (bmp388_cal.P2 - 16384) * t_lin * 2097152;
410 sensitivity = ((bmp388_cal.P1 - 16384) * 70368744177664) + partial_data2 + partial_data4
411 + partial_data5;
413 partial_data1 = (sensitivity / 16777216) * uncomp_pressure;
414 partial_data2 = bmp388_cal.P10 * t_lin;
415 partial_data3 = partial_data2 + (65536 * bmp388_cal.P9);
416 partial_data4 = (partial_data3 * uncomp_pressure) / 8192;
417 partial_data5 = (partial_data4 * uncomp_pressure) / 512;
418 partial_data6 = (int64_t)((uint64_t)uncomp_pressure * (uint64_t)uncomp_pressure);
419 partial_data2 = (bmp388_cal.P11 * partial_data6) / 65536;
420 partial_data3 = (partial_data2 * uncomp_pressure) / 128;
421 partial_data4 = (offset / 4) + partial_data1 + partial_data5 + partial_data3;
422 comp_press = (((uint64_t)partial_data4 * 25) / (uint64_t)1099511627776);
424 #ifdef DEBUG_BARO_BMP388
425 debug[1] = ((comp_press & 0xFFFF0000) >> 32);
426 debug[2] = ((comp_press & 0x0000FFFF) >> 0);
427 #endif
428 return comp_press;
431 STATIC_UNIT_TESTED void bmp388Calculate(int32_t *pressure, int32_t *temperature)
433 // calculate
434 int64_t t;
435 int64_t p;
437 t = bmp388CompensateTemperature(bmp388_ut);
438 p = bmp388CompensatePressure(bmp388_up);
440 if (pressure)
441 *pressure = (int32_t)(p / 256);
442 if (temperature)
443 *temperature = t;
446 #endif