3636#include "drivers/sensor.h"
3737#include "drivers/time.h"
3838
39-
40-
4139// 10 MHz max SPI frequency
42- #define ICM20689_MAX_SPI_CLK_HZ 10000000
40+ #define ICM20689_MAX_SPI_CLK_HZ 8000000
4341
4442// 10 MHz max SPI frequency for intialisation
4543#define ICM20689_MAX_SPI_INIT_CLK_HZ 1000000
4644
45+ // Register 0x37 - INT_PIN_CFG / Pin Bypass Enable Configuration
46+ #define ICM20689_INT_ANYRD_2CLEAR 0x10
47+
48+ // Register 0x68 - SIGNAL_PATH_RESET / Pin Bypass Enable Configuration
49+ #define ICM20689_ACCEL_RST 0x02
50+ #define ICM20689_TEMP_RST 0x01
51+
52+ // Register 0x6a - USER_CTRL / User Control
53+ #define ICM20689_I2C_IF_DIS 0x10
54+
55+ // Register 0x6b - PWR_MGMT_1 / Power Management 1
56+ #define ICM20689_BIT_RESET 0x80
57+
58+ /* Allow CLKSEL setting time to settle when PLL is selected
59+ *
60+ * Not specified in the ICM-20689 datasheet, but in the ICM-20690 datasheet,
61+ *
62+ * https://invensense.tdk.com/wp-content/uploads/2016/10/DS-000178-ICM-20690-v1.0.pdf
63+ *
64+ * says (section 10.11) that the clock selection takes ~20us to settle. Testing
65+ * has shown that 60us is required, so double to allow a margin
66+ */
67+ #define ICM20689_CLKSEL_SETTLE_US 120
68+
69+ /* Not specified in the ICM-20689 datasheet, but in the MPU-6000 datasheet,
70+ *
71+ * https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
72+ *
73+ * says (section 4.28) suggest a delay of 100ms after a reset
74+ */
75+ #define ICM20689_RESET_DELAY_MS 100
76+
77+ /* Not specified in the ICM-20689 datasheet, but in the MPU-6000 datasheet,
78+ *
79+ * https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
80+ *
81+ * says (section 4.28) suggest a delay of 100ms after a path reset
82+ */
83+ #define ICM20689_PATH_RESET_DELAY_MS 100
84+
4785static void icm20689SpiInit (const extDevice_t * dev )
4886{
4987 static bool hardwareInitialised = false;
@@ -52,7 +90,6 @@ static void icm20689SpiInit(const extDevice_t *dev)
5290 return ;
5391 }
5492
55-
5693 spiSetClkDivisor (dev , spiCalculateDivider (ICM20689_MAX_SPI_CLK_HZ ));
5794
5895 hardwareInitialised = true;
@@ -64,13 +101,12 @@ uint8_t icm20689SpiDetect(const extDevice_t *dev)
64101
65102 spiSetClkDivisor (dev , spiCalculateDivider (ICM20689_MAX_SPI_INIT_CLK_HZ ));
66103
104+ // Note that the following reset is being done repeatedly by each MPU6000
105+ // compatible device being probed
106+
67107 // reset the device configuration
68108 spiWriteReg (dev , MPU_RA_PWR_MGMT_1 , ICM20689_BIT_RESET );
69- delay (100 );
70-
71- // reset the device signal paths
72- spiWriteReg (dev , MPU_RA_SIGNAL_PATH_RESET , 0x03 );
73- delay (100 );
109+ delay (ICM20689_RESET_DELAY_MS );
74110
75111 uint8_t icmDetected ;
76112
@@ -91,11 +127,21 @@ uint8_t icm20689SpiDetect(const extDevice_t *dev)
91127 break ;
92128 default :
93129 icmDetected = MPU_NONE ;
94- break ;
130+ return icmDetected ;
95131 }
96132
133+ // We now know the device is recognised so it's safe to perform device
134+ // specific register accesses
97135 spiSetClkDivisor (dev , spiCalculateDivider (ICM20689_MAX_SPI_CLK_HZ ));
98136
137+ // Disable Primary I2C Interface
138+ spiWriteReg (dev , MPU_RA_USER_CTRL , ICM20689_I2C_IF_DIS );
139+
140+ // Reset the device signal paths
141+ spiWriteReg (dev , MPU_RA_SIGNAL_PATH_RESET , ICM20689_ACCEL_RST | ICM20689_TEMP_RST );
142+
143+ delay (ICM20689_PATH_RESET_DELAY_MS );
144+
99145 return icmDetected ;
100146}
101147
@@ -129,24 +175,17 @@ void icm20689GyroInit(gyroDev_t *gyro)
129175 // Device was already reset during detection so proceed with configuration
130176
131177 spiWriteReg (& gyro -> dev , MPU_RA_PWR_MGMT_1 , INV_CLK_PLL );
132- delay ( 15 );
178+ delayMicroseconds ( ICM20689_CLKSEL_SETTLE_US );
133179 spiWriteReg (& gyro -> dev , MPU_RA_GYRO_CONFIG , INV_FSR_2000DPS << 3 );
134- delay (15 );
135180 spiWriteReg (& gyro -> dev , MPU_RA_ACCEL_CONFIG , INV_FSR_16G << 3 );
136- delay (15 );
137181 spiWriteReg (& gyro -> dev , MPU_RA_CONFIG , mpuGyroDLPF (gyro ));
138- delay (15 );
139- spiWriteReg (& gyro -> dev , MPU_RA_SMPLRT_DIV , gyro -> mpuDividerDrops ); // Get Divider Drops
140- delay (100 );
182+ spiWriteReg (& gyro -> dev , MPU_RA_SMPLRT_DIV , gyro -> mpuDividerDrops );
141183
142184 // Data ready interrupt configuration
143- // spiWriteReg(&gyro->dev, MPU_RA_INT_PIN_CFG, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0); // INT_ANYRD_2CLEAR, BYPASS_EN
144- spiWriteReg (& gyro -> dev , MPU_RA_INT_PIN_CFG , 0x10 ); // INT_ANYRD_2CLEAR, BYPASS_EN
145-
146- delay (15 );
185+ spiWriteReg (& gyro -> dev , MPU_RA_INT_PIN_CFG , ICM20689_INT_ANYRD_2CLEAR );
147186
148187#ifdef USE_MPU_DATA_READY_SIGNAL
149- spiWriteReg (& gyro -> dev , MPU_RA_INT_ENABLE , 0x01 ); // RAW_RDY_EN interrupt enable
188+ spiWriteReg (& gyro -> dev , MPU_RA_INT_ENABLE , MPU_RF_DATA_RDY_EN );
150189#endif
151190
152191 spiSetClkDivisor (& gyro -> dev , spiCalculateDivider (ICM20689_MAX_SPI_CLK_HZ ));
0 commit comments