Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / accgyro / accgyro_bmi088.c
blob7f219f212bdf6c3d39194eb623ff4b869c65b3cd
1 /*
2 * This file is part of INAV.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
6 * You can obtain one at http://mozilla.org/MPL/2.0/.
8 * Alternatively, the contents of this file may be used under the terms
9 * of the GNU General Public License Version 3, as described below:
11 * This file is free software: you may copy, redistribute and/or modify
12 * it under the terms of the GNU General Public License as published by the
13 * Free Software Foundation, either version 3 of the License, or (at your
14 * option) any later version.
16 * This file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 * Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see http://www.gnu.org/licenses/.
25 #include <stdbool.h>
26 #include <stdint.h>
28 #include "platform.h"
29 #include "build/debug.h"
31 #include "common/axis.h"
32 #include "common/maths.h"
33 #include "common/utils.h"
35 #include "drivers/system.h"
36 #include "drivers/time.h"
37 #include "drivers/io.h"
38 #include "drivers/bus.h"
40 #include "drivers/sensor.h"
41 #include "drivers/accgyro/accgyro.h"
42 #include "drivers/accgyro/accgyro_bmi088.h"
45 #if defined(USE_IMU_BMI088)
48 device registers, names follow datasheet conventions, with REGA_
49 prefix for accel, and REGG_ prefix for gyro
51 #define REGA_CHIPID 0x00
52 #define REGA_ERR_REG 0x02
53 #define REGA_STATUS 0x03
54 #define REGA_X_LSB 0x12
55 #define REGA_INT_STATUS_1 0x1D
56 #define REGA_TEMP_LSB 0x22
57 #define REGA_TEMP_MSB 0x23
58 #define REGA_CONF 0x40
59 #define REGA_RANGE 0x41
60 #define REGA_PWR_CONF 0x7C
61 #define REGA_PWR_CTRL 0x7D
62 #define REGA_SOFTRESET 0x7E
63 #define REGA_FIFO_CONFIG0 0x48
64 #define REGA_FIFO_CONFIG1 0x49
65 #define REGA_FIFO_DOWNS 0x45
66 #define REGA_FIFO_DATA 0x26
67 #define REGA_FIFO_LEN0 0x24
68 #define REGA_FIFO_LEN1 0x25
70 #define REGG_CHIPID 0x00
71 #define REGG_RATE_X_LSB 0x02
72 #define REGG_INT_CTRL 0x15
73 #define REGG_INT_STATUS_1 0x0A
74 #define REGG_INT_STATUS_2 0x0B
75 #define REGG_INT_STATUS_3 0x0C
76 #define REGG_FIFO_STATUS 0x0E
77 #define REGG_RANGE 0x0F
78 #define REGG_BW 0x10
79 #define REGG_LPM1 0x11
80 #define REGG_RATE_HBW 0x13
81 #define REGG_BGW_SOFTRESET 0x14
82 #define REGG_FIFO_CONFIG_1 0x3E
83 #define REGG_FIFO_DATA 0x3F
86 static void bmi088GyroInit(gyroDev_t *gyro)
88 busSetSpeed(gyro->busDev, BUS_SPEED_INITIALIZATION);
90 // Soft reset
91 busWrite(gyro->busDev, REGG_BGW_SOFTRESET, 0xB6);
92 delay(100);
94 // ODR 2kHz, BW 532Hz
95 busWrite(gyro->busDev, REGG_BW, 0x81);
96 delay(1);
98 // Enable sampling
99 busWrite(gyro->busDev, REGG_INT_CTRL, 0x80);
100 delay(1);
102 busSetSpeed(gyro->busDev, BUS_SPEED_FAST);
105 static void bmi088AccInit(accDev_t *acc)
107 busSetSpeed(acc->busDev, BUS_SPEED_INITIALIZATION);
109 // Soft reset
110 busWrite(acc->busDev, REGA_SOFTRESET, 0xB6);
111 delay(100);
113 // Active mode
114 busWrite(acc->busDev, REGA_PWR_CONF, 0);
115 delay(100);
117 // ACC ON
118 busWrite(acc->busDev, REGA_PWR_CTRL, 0x04);
119 delay(100);
121 // OSR4, ODR 1600Hz
122 busWrite(acc->busDev, REGA_CONF, 0x8C);
123 delay(1);
125 // Range 12g
126 busWrite(acc->busDev, REGA_RANGE, 0x02);
127 delay(1);
129 busSetSpeed(acc->busDev, BUS_SPEED_STANDARD);
131 acc->acc_1G = 2048;
134 static bool bmi088GyroRead(gyroDev_t *gyro)
136 uint8_t gyroRaw[6];
138 if (busReadBuf(gyro->busDev, REGG_RATE_X_LSB, gyroRaw, 6)) {
139 gyro->gyroADCRaw[X] = (float) int16_val_little_endian(gyroRaw, 0);
140 gyro->gyroADCRaw[Y] = (float) int16_val_little_endian(gyroRaw, 1);
141 gyro->gyroADCRaw[Z] = (float) int16_val_little_endian(gyroRaw, 2);
142 return true;
145 return false;
148 static bool bmi088AccRead(accDev_t *acc)
150 uint8_t buffer[7];
152 if (busReadBuf(acc->busDev, REGA_STATUS, buffer, 2) && (buffer[1] & 0x80) && busReadBuf(acc->busDev, REGA_X_LSB, buffer, 7)) {
153 // first byte is discarded, see datasheet
154 acc->ADCRaw[X] = (float)(((int16_t)(buffer[2] << 8) | buffer[1]) * 3 / 4);
155 acc->ADCRaw[Y] = (float)(((int16_t)(buffer[4] << 8) | buffer[3]) * 3 / 4);
156 acc->ADCRaw[Z] = (float)(((int16_t)(buffer[6] << 8) | buffer[5]) * 3 / 4);
157 return true;
160 return false;
163 static bool gyroDeviceDetect(busDevice_t * busDev)
165 uint8_t attempts;
167 busSetSpeed(busDev, BUS_SPEED_INITIALIZATION);
169 for (attempts = 0; attempts < 5; attempts++) {
170 uint8_t chipId;
172 delay(100);
173 busRead(busDev, REGG_CHIPID, &chipId);
175 if (chipId == 0x0F) {
176 return true;
180 return false;
183 static bool accDeviceDetect(busDevice_t * busDev)
185 uint8_t attempts;
187 busSetSpeed(busDev, BUS_SPEED_INITIALIZATION);
189 for (attempts = 0; attempts < 5; attempts++) {
190 uint8_t chipId;
192 delay(100);
193 busRead(busDev, REGA_CHIPID, &chipId);
195 if (chipId == 0x1E) {
196 return true;
200 return false;
203 bool bmi088AccDetect(accDev_t *acc)
205 acc->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_BMI088_ACC, acc->imuSensorToUse, OWNER_MPU);
206 if (acc->busDev == NULL) {
207 return false;
210 if (!accDeviceDetect(acc->busDev)) {
211 busDeviceDeInit(acc->busDev);
212 return false;
215 acc->initFn = bmi088AccInit;
216 acc->readFn = bmi088AccRead;
217 acc->accAlign = acc->busDev->param;
219 return true;
222 bool bmi088GyroDetect(gyroDev_t *gyro)
224 gyro->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_BMI088_GYRO, gyro->imuSensorToUse, OWNER_MPU);
225 if (gyro->busDev == NULL) {
226 return false;
229 if (!gyroDeviceDetect(gyro->busDev)) {
230 busDeviceDeInit(gyro->busDev);
231 return false;
234 gyro->initFn = bmi088GyroInit;
235 gyro->readFn = bmi088GyroRead;
236 gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb
237 gyro->intStatusFn = gyroCheckDataReady;
238 gyro->gyroAlign = gyro->busDev->param;
240 return true;
243 #endif /* USE_IMU_BMI088 */