Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / barometer / barometer_lps25h.c
blob5ea6bbb0a91bfccee03bbcc0d213a7fbbe0d3557
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/>.
17 ******************************************************************************
18 * @brief contains definitions from the ST MEMS team
19 * @author MEMS Application Team
20 * @version V1.0.0
21 * @date 11-February-2015
22 ******************************************************************************
23 * @attention
25 * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
26 * */
28 #include <stdbool.h>
29 #include <stdint.h>
30 #include <math.h>
32 #include <platform.h>
33 #include "build/build_config.h"
34 #include "build/debug.h"
35 #include "common/utils.h"
37 #include "drivers/time.h"
38 #include "drivers/io.h"
39 #include "drivers/bus.h"
40 #include "drivers/barometer/barometer.h"
41 #include "drivers/barometer/barometer_lps25h.h"
43 #if defined(USE_BARO_LPS25H)
45 #define LPS25HB_WHO_AM_I_ADDR 0x0F
46 #define LPS25HB_RES_CONF_ADDR 0x10
47 #define LPS25HB_CTRL_REG1_ADDR 0x20
48 #define LPS25HB_CTRL_REG2_ADDR 0x21
49 #define LPS25HB_STATUS_REG_ADDR 0x27
50 #define LPS25HB_PRESS_POUT_XL_ADDR 0x28
51 #define LPS25HB_PRESS_OUT_L_ADDR 0x29
52 #define LPS25HB_PRESS_OUT_H_ADDR 0x2A
53 #define LPS25HB_TEMP_OUT_L_ADDR 0x2B
54 #define LPS25HB_TEMP_OUT_H_ADDR 0x2C
56 #define LPS25HB_I2C_MULTIPLEBYTE_CMD 0x80
57 #define LPS25HB_SPI_MULTIPLEBYTE_CMD 0x40
59 #define TEMPERATURE_READY_MASK (1 << 0)
60 #define PRESSURE_READY_MASK (1 << 1)
62 #define I_AM_LPS25HB 0xBD
64 #define LPS25HB_MODE_MASK 0x80
65 #define LPS25HB_MODE_POWERDOWN 0x00
66 #define LPS25HB_MODE_ACTIVE 0x80
68 #define LPS25HB_ODR_MASK 0x70
69 #define LPS25HB_ODR_ONE_SHOT 0x00
70 #define LPS25HB_ODR_1Hz 0x10
71 #define LPS25HB_ODR_7Hz 0x20
72 #define LPS25HB_ODR_12_5Hz 0x30
73 #define LPS25HB_ODR_25Hz 0x40
75 #define LPS25HB_DIFF_EN_MASK 0x08
76 #define LPS25HB_DIFF_DISABLE 0x00
77 #define LPS25HB_DIFF_ENABLE 0x08
79 #define LPS25HB_BDU_MASK 0x04
80 #define LPS25HB_BDU_CONT 0x00
81 #define LPS25HB_BDU_READ 0x04
84 #define LPS25HB_RESET_MEMORY_MASK 0x80
85 #define LPS25HB_NORMAL_MODE 0x00
86 #define LPS25HB_RESET_MEMORY 0x80
89 #define LPS25HB_P_RES_MASK 0x03
90 #define LPS25HB_P_RES_AVG_8 0x00
91 #define LPS25HB_P_RES_AVG_32 0x01
92 #define LPS25HB_P_RES_AVG_128 0x02
93 #define LPS25HB_P_RES_AVG_512 0x03
95 #define LPS25HB_T_RES_MASK 0x0C
96 #define LPS25HB_T_RES_AVG_8 0x00
97 #define LPS25HB_T_RES_AVG_16 0x04
98 #define LPS25HB_T_RES_AVG_32 0x08
99 #define LPS25HB_T_RES_AVG_64 0x0C
101 #define LPS25H_CHIP_ID 0xBD
103 static int32_t pressureRaw;
104 static int32_t temperatureRaw;
106 static bool lps25hbRebootCmd(baroDev_t * baro)
108 uint8_t tmpreg;
110 /* Read CTRL_REG5 register */
111 bool ack = busRead(baro->busDev, LPS25HB_CTRL_REG2_ADDR, &tmpreg);
112 if (!ack) {
113 return false;
116 /* Enable or Disable the reboot memory */
117 tmpreg |= LPS25HB_RESET_MEMORY;
119 /* Write value to MEMS CTRL_REG5 regsister */
120 ack = busWrite(baro->busDev, LPS25HB_CTRL_REG2_ADDR, tmpreg);
121 if (!ack) {
122 return false;
125 return true;
128 static bool lps25hbPower(baroDev_t * baro, bool enable)
130 uint8_t tmpreg;
132 /* Read the register content */
133 bool ack = busRead(baro->busDev, LPS25HB_CTRL_REG1_ADDR, &tmpreg);
134 if (!ack) {
135 return false;
138 tmpreg &= ~LPS25HB_MODE_MASK;
140 if (enable) {
141 tmpreg |= LPS25HB_MODE_ACTIVE;
143 else {
144 tmpreg |= LPS25HB_MODE_POWERDOWN;
147 /* Write register */
148 ack = busWrite(baro->busDev, LPS25HB_CTRL_REG1_ADDR, tmpreg);
149 if (!ack) {
150 return false;
153 return true;
156 static bool lps25hbInit(baroDev_t * baro)
158 uint8_t tmp1 = 0x00;
160 /* Configure the low level interface ---------------------------------------*/
161 if (!lps25hbRebootCmd(baro)) {
162 return false;
165 delay(100);
167 if (!lps25hbPower(baro, false)) {
168 return false;
171 bool ack = busRead(baro->busDev, LPS25HB_CTRL_REG1_ADDR, &tmp1);
172 if (!ack) {
173 return false;
176 /* Output Data Rate selection */
177 tmp1 = (tmp1 & (~(LPS25HB_ODR_MASK))) | LPS25HB_ODR_25Hz;
179 /* Interrupt circuit selection */
180 tmp1 = (tmp1 & (~(LPS25HB_DIFF_EN_MASK))) | LPS25HB_DIFF_ENABLE;
182 /* Block Data Update selection - continuous mode */
183 tmp1 = (tmp1 & (~(LPS25HB_BDU_MASK))) | LPS25HB_BDU_CONT;
185 ack = busWrite(baro->busDev, LPS25HB_CTRL_REG1_ADDR, tmp1);
186 if (!ack) {
187 return false;
190 tmp1 = 0;
191 ack = busRead(baro->busDev, LPS25HB_RES_CONF_ADDR, &tmp1);
192 if (!ack) {
193 return false;
196 // PressureResolution
197 tmp1 = (tmp1 & (~(LPS25HB_P_RES_MASK))) | LPS25HB_P_RES_AVG_512;
199 // TemperatureResolution
200 tmp1 = (tmp1 & (~(LPS25HB_T_RES_MASK))) | LPS25HB_T_RES_AVG_32;
202 ack = busWrite(baro->busDev, LPS25HB_RES_CONF_ADDR, tmp1);
203 if (!ack) {
204 return false;
207 if (!lps25hbPower(baro, true)) {
208 return false;
211 return true;
215 // check the status register bit to be present
216 static bool isDataReady(baroDev_t * baro, uint8_t bitMask)
218 uint8_t tmp = 0;
220 bool ack = busRead(baro->busDev, LPS25HB_STATUS_REG_ADDR, &tmp);
221 if (!ack) {
222 return false;
225 return (tmp & bitMask);
228 static bool lps25h_start_up(baroDev_t * baro)
230 UNUSED(baro);
231 return true;
234 static bool lps25h_get_up(baroDev_t * baro)
236 uint8_t buffer[3] = {0};
238 if (isDataReady(baro, PRESSURE_READY_MASK)) {
239 if (baro->busDev->busType == BUSTYPE_SPI) {
240 busReadBuf(baro->busDev, LPS25HB_SPI_MULTIPLEBYTE_CMD | LPS25HB_PRESS_POUT_XL_ADDR, buffer, sizeof(buffer));
242 else {
243 busReadBuf(baro->busDev, LPS25HB_I2C_MULTIPLEBYTE_CMD | LPS25HB_PRESS_POUT_XL_ADDR, buffer, sizeof(buffer));
246 pressureRaw = (int32_t)((uint32_t)buffer[2] << 16 | (uint32_t)buffer[1] << 8 | (uint32_t)buffer[0]);
249 return true;
252 static bool lps25h_start_ut(baroDev_t * baro)
254 UNUSED(baro);
255 return true;
258 static bool lps25h_get_ut(baroDev_t * baro)
260 uint8_t data[2] = {0};
262 if (isDataReady(baro, TEMPERATURE_READY_MASK)) {
263 if (baro->busDev->busType == BUSTYPE_SPI) {
264 busReadBuf(baro->busDev, LPS25HB_SPI_MULTIPLEBYTE_CMD | LPS25HB_TEMP_OUT_L_ADDR, data, sizeof(data));
266 else {
267 busReadBuf(baro->busDev, LPS25HB_I2C_MULTIPLEBYTE_CMD | LPS25HB_TEMP_OUT_L_ADDR, data, sizeof(data));
270 temperatureRaw = (int16_t)((uint16_t)data[1] << 8 | (uint16_t)data[0]);
273 return true;
276 #define DETECTION_MAX_RETRY_COUNT 5
277 static bool deviceDetect(busDevice_t * busDev)
279 for (int retry = 0; retry < DETECTION_MAX_RETRY_COUNT; retry++) {
280 uint8_t chipId = 0;
282 delay(100);
284 bool ack = busRead(busDev, LPS25HB_WHO_AM_I_ADDR, &chipId);
285 // verified: id is 189 (0xBD)
287 if (ack && chipId == LPS25H_CHIP_ID) {
288 return true;
292 return false;
295 STATIC_UNIT_TESTED bool lps25h_calculate(baroDev_t * baro, int32_t * pressure, int32_t * temperature)
297 UNUSED(baro);
299 if (pressure) {
300 // Pout(hPa) = PRESS_OUT / 4096
301 // Pout(Pa) = Pout(hPa) * 100
302 *pressure = pressureRaw * 100 / 4096;
305 if (temperature) {
306 // We need temperature in 0.01 degC
307 *temperature = 4250 + temperatureRaw * 100 / 480;
310 return true;
313 bool lps25hDetect(baroDev_t *baro)
315 baro->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_LPS25H, 0, OWNER_BARO);
316 if (baro->busDev == NULL) {
317 return false;
320 busSetSpeed(baro->busDev, BUS_SPEED_STANDARD);
322 if (!deviceDetect(baro->busDev)) {
323 busDeviceDeInit(baro->busDev);
324 return false;
327 lps25hbInit(baro);
329 baro->ut_delay = 0;
330 baro->get_ut = lps25h_get_ut;
331 baro->start_ut = lps25h_start_ut;
333 baro->up_delay = 1000;
334 baro->start_up = lps25h_start_up;
335 baro->get_up = lps25h_get_up;
337 baro->calculate = lps25h_calculate;
339 return true;
343 #endif