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/>.
21 * Dominic Clifton - Cleanflight implementation
22 * John Ihlein - Initial FF32 code
31 #include "common/axis.h"
32 #include "common/maths.h"
41 #include "accgyro_mpu.h"
42 #include "accgyro_spi_mpu6000.h"
44 static void mpu6000AccAndGyroInit(void);
46 extern uint8_t mpuLowPassFilter
;
48 static bool mpuSpi6000InitDone
= false;
51 #define BIT_SLEEP 0x40
52 #define BIT_H_RESET 0x80
53 #define BITS_CLKSEL 0x07
54 #define MPU_CLK_SEL_PLLGYROX 0x01
55 #define MPU_CLK_SEL_PLLGYROZ 0x03
56 #define MPU_EXT_SYNC_GYROX 0x02
57 #define BITS_FS_250DPS 0x00
58 #define BITS_FS_500DPS 0x08
59 #define BITS_FS_1000DPS 0x10
60 #define BITS_FS_2000DPS 0x18
61 #define BITS_FS_2G 0x00
62 #define BITS_FS_4G 0x08
63 #define BITS_FS_8G 0x10
64 #define BITS_FS_16G 0x18
65 #define BITS_FS_MASK 0x18
66 #define BITS_DLPF_CFG_256HZ 0x00
67 #define BITS_DLPF_CFG_188HZ 0x01
68 #define BITS_DLPF_CFG_98HZ 0x02
69 #define BITS_DLPF_CFG_42HZ 0x03
70 #define BITS_DLPF_CFG_20HZ 0x04
71 #define BITS_DLPF_CFG_10HZ 0x05
72 #define BITS_DLPF_CFG_5HZ 0x06
73 #define BITS_DLPF_CFG_2100HZ_NOLPF 0x07
74 #define BITS_DLPF_CFG_MASK 0x07
75 #define BIT_INT_ANYRD_2CLEAR 0x10
76 #define BIT_RAW_RDY_EN 0x01
77 #define BIT_I2C_IF_DIS 0x10
78 #define BIT_INT_STATUS_DATA 0x01
83 // Product ID Description for MPU6000
84 // high 4 bits low 4 bits
85 // Product Name Product Revision
86 #define MPU6000ES_REV_C4 0x14
87 #define MPU6000ES_REV_C5 0x15
88 #define MPU6000ES_REV_D6 0x16
89 #define MPU6000ES_REV_D7 0x17
90 #define MPU6000ES_REV_D8 0x18
91 #define MPU6000_REV_C4 0x54
92 #define MPU6000_REV_C5 0x55
93 #define MPU6000_REV_D6 0x56
94 #define MPU6000_REV_D7 0x57
95 #define MPU6000_REV_D8 0x58
96 #define MPU6000_REV_D9 0x59
97 #define MPU6000_REV_D10 0x5A
99 #define DISABLE_MPU6000 GPIO_SetBits(MPU6000_CS_GPIO, MPU6000_CS_PIN)
100 #define ENABLE_MPU6000 GPIO_ResetBits(MPU6000_CS_GPIO, MPU6000_CS_PIN)
103 bool mpu6000WriteRegister(uint8_t reg
, uint8_t data
)
106 spiTransferByte(MPU6000_SPI_INSTANCE
, reg
);
107 spiTransferByte(MPU6000_SPI_INSTANCE
, data
);
113 bool mpu6000ReadRegister(uint8_t reg
, uint8_t length
, uint8_t *data
)
116 spiTransferByte(MPU6000_SPI_INSTANCE
, reg
| 0x80); // read transaction
117 spiTransfer(MPU6000_SPI_INSTANCE
, data
, NULL
, length
);
123 void mpu6000SpiGyroInit(uint16_t lpf
)
127 uint8_t mpuLowPassFilter
= determineMPULPF(lpf
);
129 mpu6000AccAndGyroInit();
131 spiResetErrorCounter(MPU6000_SPI_INSTANCE
);
133 spiSetDivisor(MPU6000_SPI_INSTANCE
, SPI_0_5625MHZ_CLOCK_DIVIDER
);
135 // Accel and Gyro DLPF Setting
136 mpu6000WriteRegister(MPU6000_CONFIG
, mpuLowPassFilter
);
137 delayMicroseconds(1);
142 if ((((int8_t)data
[1]) == -1 && ((int8_t)data
[0]) == -1) || spiGetErrorCounter(MPU6000_SPI_INSTANCE
) != 0) {
143 spiResetErrorCounter(MPU6000_SPI_INSTANCE
);
144 failureMode(FAILURE_GYRO_INIT_FAILED
);
148 void mpu6000SpiAccInit(void)
155 bool mpu6000SpiDetect(void)
158 uint8_t attemptsRemaining
= 5;
160 spiSetDivisor(MPU6000_SPI_INSTANCE
, SPI_0_5625MHZ_CLOCK_DIVIDER
);
162 mpu6000WriteRegister(MPU_RA_PWR_MGMT_1
, BIT_H_RESET
);
167 mpu6000ReadRegister(MPU_RA_WHO_AM_I
, 1, &in
);
168 if (in
== MPU6000_WHO_AM_I_CONST
) {
171 if (!attemptsRemaining
) {
174 } while (attemptsRemaining
--);
177 mpu6000ReadRegister(MPU_RA_PRODUCT_ID
, 1, &in
);
179 /* look for a product ID we recognise */
181 // verify product revision
183 case MPU6000ES_REV_C4
:
184 case MPU6000ES_REV_C5
:
187 case MPU6000ES_REV_D6
:
188 case MPU6000ES_REV_D7
:
189 case MPU6000ES_REV_D8
:
194 case MPU6000_REV_D10
:
201 static void mpu6000AccAndGyroInit(void) {
203 if (mpuSpi6000InitDone
) {
207 spiSetDivisor(MPU6000_SPI_INSTANCE
, SPI_0_5625MHZ_CLOCK_DIVIDER
);
210 mpu6000WriteRegister(MPU_RA_PWR_MGMT_1
, BIT_H_RESET
);
213 mpu6000WriteRegister(MPU_RA_SIGNAL_PATH_RESET
, BIT_GYRO
| BIT_ACC
| BIT_TEMP
);
216 // Clock Source PPL with Z axis gyro reference
217 mpu6000WriteRegister(MPU_RA_PWR_MGMT_1
, MPU_CLK_SEL_PLLGYROZ
);
218 delayMicroseconds(1);
220 // Disable Primary I2C Interface
221 mpu6000WriteRegister(MPU_RA_USER_CTRL
, BIT_I2C_IF_DIS
);
222 delayMicroseconds(1);
224 mpu6000WriteRegister(MPU_RA_PWR_MGMT_2
, 0x00);
225 delayMicroseconds(1);
227 // Accel Sample Rate 1kHz
228 // Gyroscope Output Rate = 1kHz when the DLPF is enabled
229 mpu6000WriteRegister(MPU_RA_SMPLRT_DIV
, 0x00);
230 delayMicroseconds(1);
232 // Gyro +/- 1000 DPS Full Scale
233 mpu6000WriteRegister(MPU_RA_GYRO_CONFIG
, INV_FSR_2000DPS
<< 3);
234 delayMicroseconds(1);
236 // Accel +/- 8 G Full Scale
237 mpu6000WriteRegister(MPU_RA_ACCEL_CONFIG
, INV_FSR_8G
<< 3);
238 delayMicroseconds(1);
241 mpu6000WriteRegister(MPU_RA_INT_PIN_CFG
, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0); // INT_ANYRD_2CLEAR
242 delayMicroseconds(1);
244 #ifdef USE_MPU_DATA_READY_SIGNAL
245 mpu6000WriteRegister(MPU_RA_INT_ENABLE
, MPU_RF_DATA_RDY_EN
);
246 delayMicroseconds(1);
249 spiSetDivisor(MPU6000_SPI_INSTANCE
, SPI_18MHZ_CLOCK_DIVIDER
); // 18 MHz SPI clock
251 mpuSpi6000InitDone
= true;
254 bool mpu6000SpiAccDetect(acc_t
*acc
)
256 if (mpuDetectionResult
.sensor
!= MPU_60x0_SPI
) {
260 acc
->init
= mpu6000SpiAccInit
;
261 acc
->read
= mpuAccRead
;
266 bool mpu6000SpiGyroDetect(gyro_t
*gyro
)
268 if (mpuDetectionResult
.sensor
!= MPU_60x0_SPI
) {
272 gyro
->init
= mpu6000SpiGyroInit
;
273 gyro
->read
= mpuGyroRead
;
275 // 16.4 dps/lsb scalefactor
276 gyro
->scale
= 1.0f
/ 16.4f
;