Skip to content

Commit b73253c

Browse files
committed
Honor requested gyro sample rate instead of hard-coding 1kHz
Add a rate-config table (mirroring ICM42605's) so the driver selects GYRO_CONFIG0/ACCEL_CONFIG0 ODR from gyro->requestedSampleIntervalUs instead of always running at 1kHz, which would have silently capped the PID loop rate on any board using this chip. Also document why the ICM42605-style INT_CONFIG1/ASYNC_RESET clear step is omitted: that register isn't present in the ICM-40609-D register map.
1 parent 21bf312 commit b73253c

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

src/main/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@ main_sources(COMMON_SRC
8585
drivers/accgyro/accgyro_fake.h
8686
drivers/accgyro/accgyro_icm20689.c
8787
drivers/accgyro/accgyro_icm20689.h
88+
drivers/accgyro/accgyro_icm40609d.c
89+
drivers/accgyro/accgyro_icm40609d.h
8890
drivers/accgyro/accgyro_icm42605.c
8991
drivers/accgyro/accgyro_icm42605.h
9092
drivers/accgyro/accgyro_icm45686.c
9193
drivers/accgyro/accgyro_icm45686.h
92-
drivers/accgyro/accgyro_icm40609d.c
93-
drivers/accgyro/accgyro_icm40609d.h
9494
drivers/accgyro/accgyro_mpu.c
9595
drivers/accgyro/accgyro_mpu.h
9696
drivers/accgyro/accgyro_mpu6000.c

src/main/drivers/accgyro/accgyro_icm40609d.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,10 @@
5656

5757
// GYRO_FS_SEL = 0 -> +/-2000dps, 16.4 LSB/(deg/s)
5858
#define ICM40609D_GYRO_FS_SEL_2000DPS (0 << 5)
59-
#define ICM40609D_GYRO_ODR_1KHZ 6
6059

6160
// ACCEL_FS_SEL = 1 -> +/-16g, 2048 LSB/g (FS_SEL=0 is +/-32g on this chip,
6261
// unlike ICM42605 where 0 is the narrowest common range)
6362
#define ICM40609D_ACCEL_FS_SEL_16G (1 << 5)
64-
#define ICM40609D_ACCEL_ODR_1KHZ 6
6563

6664
// Low-latency UI filter bandwidth select, both fields set to the "trivial"
6765
// low-latency option (verified numeric meaning against the same bit layout
@@ -80,6 +78,20 @@
8078
#define ICM40609D_RA_INT_SOURCE0 0x65
8179
#define ICM40609D_UI_DRDY_INT1_EN_ENABLED (1 << 3)
8280

81+
// ODR select values (bits[3:0] of GYRO_CONFIG0/ACCEL_CONFIG0) verified
82+
// against the datasheet's ODR tables -- identical encoding to ICM42605
83+
// for these five rates, so reusing the same gyroFilterAndRateConfig_t
84+
// mechanism and DLPF tag (unused here; this driver doesn't vary the UI
85+
// filter bandwidth by requested LPF, see icm40609dAccAndGyroInit).
86+
static const gyroFilterAndRateConfig_t icm40609dGyroConfigs[] = {
87+
/* DLPF ODR */
88+
{ GYRO_LPF_256HZ, 8000, { 0, 3 } },
89+
{ GYRO_LPF_256HZ, 4000, { 0, 4 } },
90+
{ GYRO_LPF_256HZ, 2000, { 0, 5 } },
91+
{ GYRO_LPF_256HZ, 1000, { 0, 6 } },
92+
{ GYRO_LPF_256HZ, 500, { 0, 15 } },
93+
};
94+
8395
static void icm40609dAccInit(accDev_t *acc)
8496
{
8597
acc->acc_1G = 512 * 4; // 2048 LSB/g, matches ACCEL_FS_SEL=1 (+/-16g)
@@ -123,18 +135,19 @@ bool icm40609dAccDetect(accDev_t *acc)
123135
static void icm40609dAccAndGyroInit(gyroDev_t *gyro)
124136
{
125137
busDevice_t * dev = gyro->busDev;
126-
127-
gyro->sampleRateIntervalUs = 1000; // 1kHz ODR
138+
const gyroFilterAndRateConfig_t * config = chooseGyroConfig(gyro->lpf, 1000000 / gyro->requestedSampleIntervalUs,
139+
&icm40609dGyroConfigs[0], ARRAYLEN(icm40609dGyroConfigs));
140+
gyro->sampleRateIntervalUs = 1000000 / config->gyroRateHz;
128141

129142
busSetSpeed(dev, BUS_SPEED_INITIALIZATION);
130143

131144
busWrite(dev, ICM40609D_RA_PWR_MGMT0, ICM40609D_PWR_MGMT0_TEMP_DISABLE_OFF | ICM40609D_PWR_MGMT0_ACCEL_MODE_LN | ICM40609D_PWR_MGMT0_GYRO_MODE_LN);
132145
delay(15);
133146

134-
busWrite(dev, ICM40609D_RA_GYRO_CONFIG0, ICM40609D_GYRO_FS_SEL_2000DPS | ICM40609D_GYRO_ODR_1KHZ);
147+
busWrite(dev, ICM40609D_RA_GYRO_CONFIG0, ICM40609D_GYRO_FS_SEL_2000DPS | (config->gyroConfigValues[1] & 0x0F));
135148
delay(15);
136149

137-
busWrite(dev, ICM40609D_RA_ACCEL_CONFIG0, ICM40609D_ACCEL_FS_SEL_16G | ICM40609D_ACCEL_ODR_1KHZ);
150+
busWrite(dev, ICM40609D_RA_ACCEL_CONFIG0, ICM40609D_ACCEL_FS_SEL_16G | (config->gyroConfigValues[1] & 0x0F));
138151
delay(15);
139152

140153
// Low latency, same convention as ICM42605
@@ -144,6 +157,11 @@ static void icm40609dAccAndGyroInit(gyroDev_t *gyro)
144157
busWrite(dev, ICM40609D_RA_INT_CONFIG, ICM40609D_INT1_MODE_PULSED | ICM40609D_INT1_DRIVE_CIRCUIT_PP | ICM40609D_INT1_POLARITY_ACTIVE_HIGH);
145158
delay(15);
146159

160+
// Unlike ICM42605, this chip's Bank 0 register map has no INT_CONFIG1
161+
// (0x64) / ASYNC_RESET bit -- confirmed absent from DS-000272 rev 0.8
162+
// (register map jumps from INT_CONFIG0 at 0x63 straight to INT_SOURCE0
163+
// at 0x65). ICM42605's "clear ASYNC_RESET for proper INT1/INT2
164+
// operation" erratum step is therefore intentionally omitted here.
147165
busWrite(dev, ICM40609D_RA_INT_CONFIG0, ICM40609D_UI_DRDY_INT_CLEAR_ON_SBR);
148166
delay(100);
149167

0 commit comments

Comments
 (0)