Create set-home.md
[u360gts.git] / src / main / drivers / accgyro_spi_mpu6000.c
blobb216975aaeddfd156af944e5403151f76117a296
1 /*
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/>.
20 * Authors:
21 * Dominic Clifton - Cleanflight implementation
22 * John Ihlein - Initial FF32 code
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stdlib.h>
29 #include "platform.h"
31 #include "common/axis.h"
32 #include "common/maths.h"
34 #include "system.h"
35 #include "gpio.h"
36 #include "exti.h"
37 #include "bus_spi.h"
39 #include "sensor.h"
40 #include "accgyro.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;
50 // Bits
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
79 #define BIT_GYRO 3
80 #define BIT_ACC 2
81 #define BIT_TEMP 1
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)
105 ENABLE_MPU6000;
106 spiTransferByte(MPU6000_SPI_INSTANCE, reg);
107 spiTransferByte(MPU6000_SPI_INSTANCE, data);
108 DISABLE_MPU6000;
110 return true;
113 bool mpu6000ReadRegister(uint8_t reg, uint8_t length, uint8_t *data)
115 ENABLE_MPU6000;
116 spiTransferByte(MPU6000_SPI_INSTANCE, reg | 0x80); // read transaction
117 spiTransfer(MPU6000_SPI_INSTANCE, data, NULL, length);
118 DISABLE_MPU6000;
120 return true;
123 void mpu6000SpiGyroInit(uint16_t lpf)
125 mpuIntExtiInit();
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);
139 int16_t data[3];
140 mpuGyroRead(data);
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)
150 mpuIntExtiInit();
152 acc_1G = 512 * 8;
155 bool mpu6000SpiDetect(void)
157 uint8_t in;
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);
164 do {
165 delay(150);
167 mpu6000ReadRegister(MPU_RA_WHO_AM_I, 1, &in);
168 if (in == MPU6000_WHO_AM_I_CONST) {
169 break;
171 if (!attemptsRemaining) {
172 return false;
174 } while (attemptsRemaining--);
177 mpu6000ReadRegister(MPU_RA_PRODUCT_ID, 1, &in);
179 /* look for a product ID we recognise */
181 // verify product revision
182 switch (in) {
183 case MPU6000ES_REV_C4:
184 case MPU6000ES_REV_C5:
185 case MPU6000_REV_C4:
186 case MPU6000_REV_C5:
187 case MPU6000ES_REV_D6:
188 case MPU6000ES_REV_D7:
189 case MPU6000ES_REV_D8:
190 case MPU6000_REV_D6:
191 case MPU6000_REV_D7:
192 case MPU6000_REV_D8:
193 case MPU6000_REV_D9:
194 case MPU6000_REV_D10:
195 return true;
198 return false;
201 static void mpu6000AccAndGyroInit(void) {
203 if (mpuSpi6000InitDone) {
204 return;
207 spiSetDivisor(MPU6000_SPI_INSTANCE, SPI_0_5625MHZ_CLOCK_DIVIDER);
209 // Device Reset
210 mpu6000WriteRegister(MPU_RA_PWR_MGMT_1, BIT_H_RESET);
211 delay(150);
213 mpu6000WriteRegister(MPU_RA_SIGNAL_PATH_RESET, BIT_GYRO | BIT_ACC | BIT_TEMP);
214 delay(150);
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);
247 #endif
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) {
257 return false;
260 acc->init = mpu6000SpiAccInit;
261 acc->read = mpuAccRead;
263 return true;
266 bool mpu6000SpiGyroDetect(gyro_t *gyro)
268 if (mpuDetectionResult.sensor != MPU_60x0_SPI) {
269 return false;
272 gyro->init = mpu6000SpiGyroInit;
273 gyro->read = mpuGyroRead;
275 // 16.4 dps/lsb scalefactor
276 gyro->scale = 1.0f / 16.4f;
278 return true;