Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / barometer / barometer_bmp085.c
blob70065b85c17e6d6bf97e52f8a3772181041fc7c5
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/build_config.h"
24 #include "common/utils.h"
26 #include "drivers/barometer/barometer.h"
28 #include "drivers/time.h"
29 #include "drivers/bus.h"
30 #include "drivers/nvic.h"
31 #include "drivers/io.h"
33 #include "drivers/barometer/barometer_bmp085.h"
35 #if defined(USE_BARO_BMP085)
37 #define BMP085_I2C_ADDR 0x77
38 #define BMP085_CHIP_ID 0x55
40 typedef struct {
41 int16_t ac1;
42 int16_t ac2;
43 int16_t ac3;
44 uint16_t ac4;
45 uint16_t ac5;
46 uint16_t ac6;
47 int16_t b1;
48 int16_t b2;
49 int16_t mb;
50 int16_t mc;
51 int16_t md;
52 } bmp085_smd500_calibration_param_t;
54 typedef struct {
55 bmp085_smd500_calibration_param_t cal_param;
56 int32_t param_b5;
57 int16_t oversampling_setting;
58 } bmp085_t;
60 #define BOSCH_PRESSURE_BMP085 85
61 #define BMP085_CHIP_ID_REG 0xD0
62 #define BMP085_VERSION_REG 0xD1
63 #define E_SENSOR_NOT_DETECTED (char) 0
64 #define BMP085_PROM_START__ADDR 0xaa
65 #define BMP085_PROM_DATA__LEN 22
66 #define BMP085_T_MEASURE 0x2E // temperature measurent
67 #define BMP085_P_MEASURE 0x34 // pressure measurement
68 #define BMP085_CTRL_MEAS_REG 0xF4
69 #define BMP085_ADC_OUT_MSB_REG 0xF6
70 #define BMP085_ADC_OUT_LSB_REG 0xF7
71 #define BMP085_CHIP_ID__POS 0
72 #define BMP085_CHIP_ID__MSK 0xFF
73 #define BMP085_CHIP_ID__LEN 8
74 #define BMP085_CHIP_ID__REG BMP085_CHIP_ID_REG
76 #define BMP085_ML_VERSION__POS 0
77 #define BMP085_ML_VERSION__LEN 4
78 #define BMP085_ML_VERSION__MSK 0x0F
79 #define BMP085_ML_VERSION__REG BMP085_VERSION_REG
81 #define BMP085_AL_VERSION__POS 4
82 #define BMP085_AL_VERSION__LEN 4
83 #define BMP085_AL_VERSION__MSK 0xF0
84 #define BMP085_AL_VERSION__REG BMP085_VERSION_REG
86 #define BMP085_GET_BITSLICE(regvar, bitname) ((regvar & bitname##__MSK) >> bitname##__POS)
87 #define BMP085_SET_BITSLICE(regvar, bitname, val) ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
89 #define SMD500_PARAM_MG 3038 //calibration parameter
90 #define SMD500_PARAM_MH -7357 //calibration parameter
91 #define SMD500_PARAM_MI 3791 //calibration parameter
93 STATIC_UNIT_TESTED bmp085_t bmp085;
95 #define UT_DELAY 6000 // 1.5ms margin according to the spec (4.5ms T conversion time)
96 #define UP_DELAY 27000 // 6000+21000=27000 1.5ms margin according to the spec (25.5ms P conversion time with OSS=3)
98 STATIC_UNIT_TESTED uint16_t bmp085_ut; // static result of temperature measurement
99 STATIC_UNIT_TESTED uint32_t bmp085_up; // static result of pressure measurement
101 static void bmp085_get_cal_param(baroDev_t *baro)
103 uint8_t data[BMP085_PROM_DATA__LEN];
104 busReadBuf(baro->busDev, BMP085_PROM_START__ADDR, data, BMP085_PROM_DATA__LEN);
106 /* parameters AC1-AC6 */
107 bmp085.cal_param.ac1 = (data[0] << 8) | data[1];
108 bmp085.cal_param.ac2 = (data[2] << 8) | data[3];
109 bmp085.cal_param.ac3 = (data[4] << 8) | data[5];
110 bmp085.cal_param.ac4 = (data[6] << 8) | data[7];
111 bmp085.cal_param.ac5 = (data[8] << 8) | data[9];
112 bmp085.cal_param.ac6 = (data[10] << 8) | data[11];
114 /* parameters B1,B2 */
115 bmp085.cal_param.b1 = (data[12] << 8) | data[13];
116 bmp085.cal_param.b2 = (data[14] << 8) | data[15];
118 /* parameters MB,MC,MD */
119 bmp085.cal_param.mb = (data[16] << 8) | data[17];
120 bmp085.cal_param.mc = (data[18] << 8) | data[19];
121 bmp085.cal_param.md = (data[20] << 8) | data[21];
124 static int32_t bmp085_get_temperature(uint32_t ut)
126 int32_t temperature;
127 int32_t x1, x2;
129 x1 = (((int32_t) ut - (int32_t) bmp085.cal_param.ac6) * (int32_t) bmp085.cal_param.ac5) >> 15;
130 x2 = ((int32_t) bmp085.cal_param.mc << 11) / (x1 + bmp085.cal_param.md);
131 bmp085.param_b5 = x1 + x2;
132 temperature = ((bmp085.param_b5 * 10 + 8) >> 4); // temperature in 0.01 C (make same as MS5611)
134 return temperature;
137 static int32_t bmp085_get_pressure(uint32_t up)
139 int32_t pressure, x1, x2, x3, b3, b6;
140 uint32_t b4, b7;
142 b6 = bmp085.param_b5 - 4000;
143 // *****calculate B3************
144 x1 = (b6 * b6) >> 12;
145 x1 *= bmp085.cal_param.b2;
146 x1 >>= 11;
148 x2 = (bmp085.cal_param.ac2 * b6);
149 x2 >>= 11;
151 x3 = x1 + x2;
153 b3 = (((((int32_t) bmp085.cal_param.ac1) * 4 + x3) << bmp085.oversampling_setting) + 2) >> 2;
155 // *****calculate B4************
156 x1 = (bmp085.cal_param.ac3 * b6) >> 13;
157 x2 = (bmp085.cal_param.b1 * ((b6 * b6) >> 12)) >> 16;
158 x3 = ((x1 + x2) + 2) >> 2;
159 b4 = (bmp085.cal_param.ac4 * (uint32_t)(x3 + 32768)) >> 15;
161 b7 = ((uint32_t)(up - b3) * (50000 >> bmp085.oversampling_setting));
162 if (b7 < 0x80000000) {
163 pressure = (b7 << 1) / b4;
164 } else {
165 pressure = (b7 / b4) << 1;
168 x1 = pressure >> 8;
169 x1 *= x1;
170 x1 = (x1 * SMD500_PARAM_MG) >> 16;
171 x2 = (pressure * SMD500_PARAM_MH) >> 16;
172 pressure += (x1 + x2 + SMD500_PARAM_MI) >> 4; // pressure in Pa
174 return pressure;
177 static bool bmp085_start_ut(baroDev_t *baro)
179 bool ack = busWrite(baro->busDev, BMP085_CTRL_MEAS_REG, BMP085_T_MEASURE);
180 return ack;
183 static bool bmp085_get_ut(baroDev_t *baro)
185 uint8_t data[2];
186 bool ack = busReadBuf(baro->busDev, BMP085_ADC_OUT_MSB_REG, data, 2);
187 if (ack) {
188 bmp085_ut = (data[0] << 8) | data[1];
191 return ack;
194 static bool bmp085_start_up(baroDev_t *baro)
196 uint8_t ctrl_reg_data = BMP085_P_MEASURE + (bmp085.oversampling_setting << 6);
197 bool ack = busWrite(baro->busDev, BMP085_CTRL_MEAS_REG, ctrl_reg_data);
198 return ack;
201 /** read out up for pressure conversion
202 depending on the oversampling ratio setting up can be 16 to 19 bit
203 \return up parameter that represents the uncompensated pressure value
205 static bool bmp085_get_up(baroDev_t *baro)
207 uint8_t data[3];
208 bool ack = busReadBuf(baro->busDev, BMP085_ADC_OUT_MSB_REG, data, 3);
210 if (ack) {
211 bmp085_up = (((uint32_t) data[0] << 16) | ((uint32_t) data[1] << 8) | (uint32_t) data[2]) >> (8 - bmp085.oversampling_setting);
214 return ack;
217 STATIC_UNIT_TESTED bool bmp085_calculate(baroDev_t *baro, int32_t *pressure, int32_t *temperature)
219 UNUSED(baro);
220 int32_t temp, press;
222 temp = bmp085_get_temperature(bmp085_ut);
223 press = bmp085_get_pressure(bmp085_up);
224 if (pressure)
225 *pressure = press;
226 if (temperature)
227 *temperature = temp;
228 return true;
232 #define DETECTION_MAX_RETRY_COUNT 5
233 static bool deviceDetect(busDevice_t * busDev)
235 for (int retry = 0; retry < DETECTION_MAX_RETRY_COUNT; retry++) {
236 uint8_t chipId = 0;
238 delay(10);
240 bool ack = busRead(busDev, BMP085_CHIP_ID__REG, &chipId);
241 if (ack && BMP085_GET_BITSLICE(chipId, BMP085_CHIP_ID) == BMP085_CHIP_ID) {
242 return true;
246 return false;
249 bool bmp085Detect(baroDev_t *baro)
251 baro->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_BMP085, 0, OWNER_BARO);
252 if (baro->busDev == NULL) {
253 return false;
256 if (!deviceDetect(baro->busDev)) {
257 busDeviceDeInit(baro->busDev);
258 return false;
261 bmp085.oversampling_setting = 3;
262 bmp085_get_cal_param(baro); /* readout bmp085 calibparam structure */
264 baro->ut_delay = UT_DELAY;
265 baro->start_ut = bmp085_start_ut;
266 baro->get_ut = bmp085_get_ut;
268 baro->up_delay = UP_DELAY;
269 baro->start_up = bmp085_start_up;
270 baro->get_up = bmp085_get_up;
272 baro->calculate = bmp085_calculate;
274 return true;
277 #endif /* BARO */