2 * This file is part of INAV.
4 * INAV 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 * INAV 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 INAV. If not, see <http://www.gnu.org/licenses/>.
20 * Dominic Clifton - Cleanflight implementation
21 * John Ihlein - Initial FF32 code
22 * Konstantin Sharlaimov - busDevice refactoring
29 #include "build/debug.h"
31 #include "common/axis.h"
32 #include "common/maths.h"
34 #include "drivers/system.h"
35 #include "drivers/time.h"
36 #include "drivers/io.h"
37 #include "drivers/bus.h"
39 #include "drivers/sensor.h"
40 #include "drivers/accgyro/accgyro.h"
41 #include "drivers/accgyro/accgyro_mpu.h"
42 #include "drivers/accgyro/accgyro_mpu6000.h"
44 #if defined(USE_IMU_MPU6000)
47 #define BIT_H_RESET 0x80
48 #define MPU_CLK_SEL_PLLGYROX 0x01
49 #define MPU_CLK_SEL_PLLGYROZ 0x03
50 #define BIT_I2C_IF_DIS 0x10
55 // Product ID Description for MPU6000
56 // high 4 bits low 4 bits
57 // Product Name Product Revision
58 #define MPU6000ES_REV_C4 0x14
59 #define MPU6000ES_REV_C5 0x15
60 #define MPU6000ES_REV_D6 0x16
61 #define MPU6000ES_REV_D7 0x17
62 #define MPU6000ES_REV_D8 0x18
63 #define MPU6000_REV_C4 0x54
64 #define MPU6000_REV_C5 0x55
65 #define MPU6000_REV_D6 0x56
66 #define MPU6000_REV_D7 0x57
67 #define MPU6000_REV_D8 0x58
68 #define MPU6000_REV_D9 0x59
69 #define MPU6000_REV_D10 0x5A
71 static void mpu6000AccAndGyroInit(gyroDev_t
*gyro
)
73 busDevice_t
* busDev
= gyro
->busDev
;
74 const gyroFilterAndRateConfig_t
* config
= mpuChooseGyroConfig(gyro
->lpf
, 1000000 / gyro
->requestedSampleIntervalUs
);
75 gyro
->sampleRateIntervalUs
= 1000000 / config
->gyroRateHz
;
77 busSetSpeed(busDev
, BUS_SPEED_INITIALIZATION
);
80 busWrite(busDev
, MPU_RA_PWR_MGMT_1
, BIT_H_RESET
);
83 busWrite(busDev
, MPU_RA_SIGNAL_PATH_RESET
, BIT_GYRO
| BIT_ACC
| BIT_TEMP
);
86 // Clock Source PPL with Z axis gyro reference
87 busWrite(busDev
, MPU_RA_PWR_MGMT_1
, MPU_CLK_SEL_PLLGYROZ
);
88 delayMicroseconds(15);
90 // Disable Primary I2C Interface
91 busWrite(busDev
, MPU_RA_USER_CTRL
, BIT_I2C_IF_DIS
);
92 delayMicroseconds(15);
94 busWrite(busDev
, MPU_RA_PWR_MGMT_2
, 0x00);
95 delayMicroseconds(15);
97 // Accel Sample Rate 1kHz
98 // Gyroscope Output Rate = 1kHz when the DLPF is enabled
99 busWrite(busDev
, MPU_RA_SMPLRT_DIV
, config
->gyroConfigValues
[1]);
100 delayMicroseconds(15);
102 // Gyro +/- 2000 DPS Full Scale
103 busWrite(busDev
, MPU_RA_GYRO_CONFIG
, INV_FSR_2000DPS
<< 3);
104 delayMicroseconds(15);
106 // Accel +/- 16 G Full Scale
107 busWrite(busDev
, MPU_RA_ACCEL_CONFIG
, INV_FSR_16G
<< 3);
108 delayMicroseconds(15);
110 // Accel and Gyro DLPF Setting
111 busWrite(busDev
, MPU_RA_CONFIG
, config
->gyroConfigValues
[0]);
112 delayMicroseconds(1);
114 busSetSpeed(busDev
, BUS_SPEED_FAST
);
118 if (((int8_t)gyro
->gyroADCRaw
[1]) == -1 && ((int8_t)gyro
->gyroADCRaw
[0]) == -1) {
119 failureMode(FAILURE_GYRO_INIT_FAILED
);
123 static void mpu6000AccInit(accDev_t
*acc
)
125 acc
->acc_1G
= 512 * 4;
128 bool mpu6000AccDetect(accDev_t
*acc
)
130 acc
->busDev
= busDeviceOpen(BUSTYPE_ANY
, DEVHW_MPU6000
, acc
->imuSensorToUse
);
131 if (acc
->busDev
== NULL
) {
135 mpuContextData_t
* ctx
= busDeviceGetScratchpadMemory(acc
->busDev
);
136 if (ctx
->chipMagicNumber
!= 0x6860) {
140 acc
->initFn
= mpu6000AccInit
;
141 acc
->readFn
= mpuAccReadScratchpad
;
142 acc
->accAlign
= acc
->busDev
->param
;
147 static bool mpu6000DeviceDetect(busDevice_t
* busDev
)
150 uint8_t attemptsRemaining
= 5;
152 busSetSpeed(busDev
, BUS_SPEED_INITIALIZATION
);
154 busWrite(busDev
, MPU_RA_PWR_MGMT_1
, BIT_H_RESET
);
159 busRead(busDev
, MPU_RA_WHO_AM_I
, &in
);
160 if (in
== MPU6000_WHO_AM_I_CONST
) {
163 if (!attemptsRemaining
) {
166 } while (attemptsRemaining
--);
168 busRead(busDev
, MPU_RA_PRODUCT_ID
, &in
);
170 /* look for a product ID we recognise */
172 case MPU6000ES_REV_C4
:
173 case MPU6000ES_REV_C5
:
176 case MPU6000ES_REV_D6
:
177 case MPU6000ES_REV_D7
:
178 case MPU6000ES_REV_D8
:
183 case MPU6000_REV_D10
:
190 bool mpu6000GyroDetect(gyroDev_t
*gyro
)
192 gyro
->busDev
= busDeviceInit(BUSTYPE_ANY
, DEVHW_MPU6000
, gyro
->imuSensorToUse
, OWNER_MPU
);
193 if (gyro
->busDev
== NULL
) {
197 if (!mpu6000DeviceDetect(gyro
->busDev
)) {
198 busDeviceDeInit(gyro
->busDev
);
202 // Magic number for ACC detection to indicate that we have detected MPU6000 gyro
203 mpuContextData_t
* ctx
= busDeviceGetScratchpadMemory(gyro
->busDev
);
204 ctx
->chipMagicNumber
= 0x6860;
206 gyro
->initFn
= mpu6000AccAndGyroInit
;
207 gyro
->readFn
= mpuGyroReadScratchpad
;
208 gyro
->intStatusFn
= gyroCheckDataReady
;
209 gyro
->temperatureFn
= mpuTemperatureReadScratchpad
;
210 gyro
->scale
= 1.0f
/ 16.4f
; // 16.4 dps/lsb scalefactor
211 gyro
->gyroAlign
= gyro
->busDev
->param
;