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/>.
24 #include "common/axis.h"
25 #include "common/maths.h"
27 #include "drivers/system.h"
28 #include "drivers/time.h"
30 #include "drivers/sensor.h"
31 #include "drivers/accgyro/accgyro.h"
32 #include "drivers/accgyro/accgyro_mpu.h"
33 #include "drivers/accgyro/accgyro_mpu6500.h"
35 #if defined(USE_IMU_MPU6500)
37 #define MPU6500_BIT_RESET (0x80)
38 #define MPU6500_BIT_INT_ANYRD_2CLEAR (1 << 4)
39 #define MPU6500_BIT_BYPASS_EN (1 << 0)
40 #define MPU6500_BIT_I2C_IF_DIS (1 << 4)
41 #define MPU6500_BIT_RAW_RDY_EN (0x01)
43 static void mpu6500AccInit(accDev_t
*acc
)
45 acc
->acc_1G
= 512 * 4;
48 bool mpu6500AccDetect(accDev_t
*acc
)
50 acc
->busDev
= busDeviceOpen(BUSTYPE_ANY
, DEVHW_MPU6500
, acc
->imuSensorToUse
);
51 if (acc
->busDev
== NULL
) {
55 mpuContextData_t
* ctx
= busDeviceGetScratchpadMemory(acc
->busDev
);
56 if (ctx
->chipMagicNumber
!= 0x6500) {
60 acc
->initFn
= mpu6500AccInit
;
61 acc
->readFn
= mpuAccReadScratchpad
;
62 acc
->accAlign
= acc
->busDev
->param
;
67 static void mpu6500AccAndGyroInit(gyroDev_t
*gyro
)
69 busDevice_t
* dev
= gyro
->busDev
;
70 const gyroFilterAndRateConfig_t
* config
= mpuChooseGyroConfig(gyro
->lpf
, 1000000 / gyro
->requestedSampleIntervalUs
);
71 gyro
->sampleRateIntervalUs
= 1000000 / config
->gyroRateHz
;
73 busSetSpeed(dev
, BUS_SPEED_INITIALIZATION
);
75 busWrite(dev
, MPU_RA_PWR_MGMT_1
, MPU6500_BIT_RESET
);
78 busWrite(dev
, MPU_RA_SIGNAL_PATH_RESET
, 0x07); // BIT_GYRO | BIT_ACC | BIT_TEMP
81 busWrite(dev
, MPU_RA_PWR_MGMT_1
, 0);
84 busWrite(dev
, MPU_RA_PWR_MGMT_1
, INV_CLK_PLL
);
87 busWrite(dev
, MPU_RA_GYRO_CONFIG
, INV_FSR_2000DPS
<< 3 | FCB_DISABLED
);
90 busWrite(dev
, MPU_RA_ACCEL_CONFIG
, INV_FSR_16G
<< 3);
93 busWrite(dev
, MPU_RA_CONFIG
, config
->gyroConfigValues
[0]);
96 busWrite(dev
, MPU_RA_SMPLRT_DIV
, config
->gyroConfigValues
[1]);
99 busSetSpeed(dev
, BUS_SPEED_FAST
);
102 static bool mpu6500DeviceDetect(busDevice_t
* dev
)
105 uint8_t attemptsRemaining
= 5;
107 busSetSpeed(dev
, BUS_SPEED_INITIALIZATION
);
109 busWrite(dev
, MPU_RA_PWR_MGMT_1
, MPU6500_BIT_RESET
);
114 busRead(dev
, MPU_RA_WHO_AM_I
, &tmp
);
117 case MPU6500_WHO_AM_I_CONST
:
118 case ICM20608G_WHO_AM_I_CONST
:
119 case ICM20601_WHO_AM_I_CONST
:
120 case ICM20602_WHO_AM_I_CONST
:
121 case ICM20689_WHO_AM_I_CONST
:
122 // Compatible chip detected
129 } while (attemptsRemaining
--);
134 bool mpu6500GyroDetect(gyroDev_t
*gyro
)
136 gyro
->busDev
= busDeviceInit(BUSTYPE_ANY
, DEVHW_MPU6500
, gyro
->imuSensorToUse
, OWNER_MPU
);
137 if (gyro
->busDev
== NULL
) {
141 if (!mpu6500DeviceDetect(gyro
->busDev
)) {
142 busDeviceDeInit(gyro
->busDev
);
146 // Magic number for ACC detection to indicate that we have detected MPU6500 gyro
147 mpuContextData_t
* ctx
= busDeviceGetScratchpadMemory(gyro
->busDev
);
148 ctx
->chipMagicNumber
= 0x6500;
150 gyro
->initFn
= mpu6500AccAndGyroInit
;
151 gyro
->readFn
= mpuGyroReadScratchpad
;
152 gyro
->intStatusFn
= gyroCheckDataReady
;
153 gyro
->temperatureFn
= mpuTemperatureReadScratchpad
;
154 gyro
->scale
= 1.0f
/ 16.4f
; // 16.4 dps/lsb scalefactor
155 gyro
->gyroAlign
= gyro
->busDev
->param
;