Update cloud build defines (#14080)
[betaflight.git] / src / main / drivers / accgyro / accgyro_spi_icm20689.c
blobada4dadf78cff71246c2256e3c0d7155b46925a6
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <stdlib.h>
25 #include "platform.h"
27 #include "common/axis.h"
28 #include "common/maths.h"
30 #include "drivers/accgyro/accgyro.h"
31 #include "drivers/accgyro/accgyro_mpu.h"
32 #include "drivers/accgyro/accgyro_spi_icm20689.h"
33 #include "drivers/bus_spi.h"
34 #include "drivers/exti.h"
35 #include "drivers/io.h"
36 #include "drivers/sensor.h"
37 #include "drivers/time.h"
39 // 10 MHz max SPI frequency
40 #define ICM20689_MAX_SPI_CLK_HZ 8000000
42 // Register 0x37 - INT_PIN_CFG / Pin Bypass Enable Configuration
43 #define ICM20689_INT_ANYRD_2CLEAR 0x10
45 // Register 0x68 - SIGNAL_PATH_RESET / Pin Bypass Enable Configuration
46 #define ICM20689_ACCEL_RST 0x02
47 #define ICM20689_TEMP_RST 0x01
49 // Register 0x6a - USER_CTRL / User Control
50 #define ICM20689_I2C_IF_DIS 0x10
52 // Register 0x6b - PWR_MGMT_1 / Power Management 1
53 #define ICM20689_BIT_RESET 0x80
55 /* Allow CLKSEL setting time to settle when PLL is selected
57 * Not specified in the ICM-20689 datasheet, but in the ICM-20690 datasheet,
59 * https://invensense.tdk.com/wp-content/uploads/2016/10/DS-000178-ICM-20690-v1.0.pdf
61 * says (section 10.11) that the clock selection takes ~20us to settle. Testing
62 * has shown that 60us is required, so double to allow a margin
64 #define ICM20689_CLKSEL_SETTLE_US 120
66 /* Not specified in the ICM-20689 datasheet, but in the MPU-6000 datasheet,
68 * https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
70 * says (section 4.28) suggest a delay of 100ms after a reset
72 #define ICM20689_RESET_DELAY_MS 100
74 /* Not specified in the ICM-20689 datasheet, but in the MPU-6000 datasheet,
76 * https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
78 * says (section 4.28) suggest a delay of 100ms after a path reset
80 #define ICM20689_PATH_RESET_DELAY_MS 100
82 uint8_t icm20689SpiDetect(const extDevice_t *dev)
84 // Note that the following reset is being done repeatedly by each MPU6000
85 // compatible device being probed
87 // reset the device configuration
88 spiWriteReg(dev, MPU_RA_PWR_MGMT_1, ICM20689_BIT_RESET);
89 delay(ICM20689_RESET_DELAY_MS);
91 uint8_t icmDetected;
93 const uint8_t whoAmI = spiReadRegMsk(dev, MPU_RA_WHO_AM_I);
95 switch (whoAmI) {
96 case ICM20601_WHO_AM_I_CONST:
97 icmDetected = ICM_20601_SPI;
98 break;
99 case ICM20602_WHO_AM_I_CONST:
100 icmDetected = ICM_20602_SPI;
101 break;
102 case ICM20608G_WHO_AM_I_CONST:
103 icmDetected = ICM_20608_SPI;
104 break;
105 case ICM20689_WHO_AM_I_CONST:
106 icmDetected = ICM_20689_SPI;
107 break;
108 default:
109 icmDetected = MPU_NONE;
110 return icmDetected;
113 // We now know the device is recognised so it's safe to perform device
114 // specific register accesses
116 // Disable Primary I2C Interface
117 spiWriteReg(dev, MPU_RA_USER_CTRL, ICM20689_I2C_IF_DIS);
119 // Reset the device signal paths
120 spiWriteReg(dev, MPU_RA_SIGNAL_PATH_RESET, ICM20689_ACCEL_RST | ICM20689_TEMP_RST);
122 delay(ICM20689_PATH_RESET_DELAY_MS);
124 return icmDetected;
127 void icm20689AccInit(accDev_t *acc)
129 acc->acc_1G = 512 * 4;
132 bool icm20689SpiAccDetect(accDev_t *acc)
134 switch (acc->mpuDetectionResult.sensor) {
135 case ICM_20602_SPI:
136 case ICM_20689_SPI:
137 break;
138 default:
139 return false;
142 acc->initFn = icm20689AccInit;
143 acc->readFn = mpuAccReadSPI;
145 return true;
148 void icm20689GyroInit(gyroDev_t *gyro)
150 extDevice_t *dev = &gyro->dev;
152 spiSetClkDivisor(dev, spiCalculateDivider(ICM20689_MAX_SPI_CLK_HZ));
154 mpuGyroInit(gyro);
156 // Device was already reset during detection so proceed with configuration
158 spiWriteReg(dev, MPU_RA_PWR_MGMT_1, INV_CLK_PLL);
159 delayMicroseconds(ICM20689_CLKSEL_SETTLE_US);
160 spiWriteReg(dev, MPU_RA_GYRO_CONFIG, INV_FSR_2000DPS << 3);
161 spiWriteReg(dev, MPU_RA_ACCEL_CONFIG, INV_FSR_16G << 3);
162 spiWriteReg(dev, MPU_RA_CONFIG, mpuGyroDLPF(gyro));
163 spiWriteReg(dev, MPU_RA_SMPLRT_DIV, gyro->mpuDividerDrops);
165 // Data ready interrupt configuration
166 spiWriteReg(dev, MPU_RA_INT_PIN_CFG, ICM20689_INT_ANYRD_2CLEAR);
168 spiWriteReg(dev, MPU_RA_INT_ENABLE, MPU_RF_DATA_RDY_EN);
171 bool icm20689SpiGyroDetect(gyroDev_t *gyro)
173 switch (gyro->mpuDetectionResult.sensor) {
174 case ICM_20601_SPI:
175 case ICM_20602_SPI:
176 case ICM_20608_SPI:
177 case ICM_20689_SPI:
178 break;
179 default:
180 return false;
183 gyro->initFn = icm20689GyroInit;
184 gyro->readFn = mpuGyroReadSPI;
186 gyro->scale = GYRO_SCALE_2000DPS;
188 return true;