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/.
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
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
);
91 busWrite(gyro
->busDev
, REGG_BGW_SOFTRESET
, 0xB6);
95 busWrite(gyro
->busDev
, REGG_BW
, 0x81);
99 busWrite(gyro
->busDev
, REGG_INT_CTRL
, 0x80);
102 busSetSpeed(gyro
->busDev
, BUS_SPEED_FAST
);
105 static void bmi088AccInit(accDev_t
*acc
)
107 busSetSpeed(acc
->busDev
, BUS_SPEED_INITIALIZATION
);
110 busWrite(acc
->busDev
, REGA_SOFTRESET
, 0xB6);
114 busWrite(acc
->busDev
, REGA_PWR_CONF
, 0);
118 busWrite(acc
->busDev
, REGA_PWR_CTRL
, 0x04);
122 busWrite(acc
->busDev
, REGA_CONF
, 0x8C);
126 busWrite(acc
->busDev
, REGA_RANGE
, 0x02);
129 busSetSpeed(acc
->busDev
, BUS_SPEED_STANDARD
);
134 static bool bmi088GyroRead(gyroDev_t
*gyro
)
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);
148 static bool bmi088AccRead(accDev_t
*acc
)
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);
163 static bool gyroDeviceDetect(busDevice_t
* busDev
)
167 busSetSpeed(busDev
, BUS_SPEED_INITIALIZATION
);
169 for (attempts
= 0; attempts
< 5; attempts
++) {
173 busRead(busDev
, REGG_CHIPID
, &chipId
);
175 if (chipId
== 0x0F) {
183 static bool accDeviceDetect(busDevice_t
* busDev
)
187 busSetSpeed(busDev
, BUS_SPEED_INITIALIZATION
);
189 for (attempts
= 0; attempts
< 5; attempts
++) {
193 busRead(busDev
, REGA_CHIPID
, &chipId
);
195 if (chipId
== 0x1E) {
203 bool bmi088AccDetect(accDev_t
*acc
)
205 acc
->busDev
= busDeviceInit(BUSTYPE_ANY
, DEVHW_BMI088_ACC
, acc
->imuSensorToUse
, OWNER_MPU
);
206 if (acc
->busDev
== NULL
) {
210 if (!accDeviceDetect(acc
->busDev
)) {
211 busDeviceDeInit(acc
->busDev
);
215 acc
->initFn
= bmi088AccInit
;
216 acc
->readFn
= bmi088AccRead
;
217 acc
->accAlign
= acc
->busDev
->param
;
222 bool bmi088GyroDetect(gyroDev_t
*gyro
)
224 gyro
->busDev
= busDeviceInit(BUSTYPE_ANY
, DEVHW_BMI088_GYRO
, gyro
->imuSensorToUse
, OWNER_MPU
);
225 if (gyro
->busDev
== NULL
) {
229 if (!gyroDeviceDetect(gyro
->busDev
)) {
230 busDeviceDeInit(gyro
->busDev
);
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
;
243 #endif /* USE_IMU_BMI088 */