3030#include " callbacks.h"
3131#include " vqf.h"
3232
33+ constexpr static bool DEBUG_ICM42688_HIRES = false ;
34+
3335namespace SlimeVR ::Sensors::SoftFusion::Drivers {
3436
3537// Driver uses acceleration range at 8g
@@ -44,16 +46,22 @@ struct ICM42688 {
4446
4547 static constexpr float GyrTs = 1.0 / 200.0 ;
4648 static constexpr float AccTs = 1.0 / 100.0 ;
47- static constexpr float TempTs = 1.0 / 500 .0 ;
49+ static constexpr float TempTs = 1.0 / 200 .0 ;
4850
4951 static constexpr float MagTs = 1.0 / 100 ;
5052
51- static constexpr float GyroSensitivity = 32 .8f ;
52- static constexpr float AccelSensitivity = 4096 .0f ;
53+ // When 20-bits data format is used, the only FSR settings that are
54+ // operational are ±2000dps for gyroscope and ±16g for accelerometer, even if the
55+ // FSR selection register settings are configured for other FSR values. The
56+ // corresponding sensitivity scale factor values are 131 LSB/dps for gyroscope and
57+ // 8192 LSB/g for accelerometer.
58+ static constexpr float GyroSensitivity = (DEBUG_ICM42688_HIRES ? 131 .0f : 32 .8f );
59+ static constexpr float AccelSensitivity
60+ = (DEBUG_ICM42688_HIRES ? 8192 .0f : 4096 .0f );
5361
5462 static constexpr float TemperatureBias = 25 .0f ;
55- static constexpr float TemperatureSensitivity = 2 . 07f ;
56-
63+ static constexpr float TemperatureSensitivity
64+ = (DEBUG_ICM42688_HIRES ? 132 . 48f : 2 . 07f );
5765 static constexpr float TemperatureZROChange = 20 .0f ;
5866
5967 static constexpr VQFParams SensorVQFParams{};
@@ -88,7 +96,9 @@ struct ICM42688 {
8896 static constexpr uint8_t reg = 0x5f ;
8997 static constexpr uint8_t value
9098 = 0b1 | (0b1 << 1 ) | (0b1 << 2 )
91- | (0b0 << 4 ); // fifo accel en=1, gyro=1, temp=1, hires=1
99+ | (DEBUG_ICM42688_HIRES ? (0b1 << 4 ) : (0b0 << 4 ));
100+ // fifo accel en=1, gyro=1, temp=1,
101+ // hires=DEBUG_ICM42688_HIRES
92102 };
93103 struct GyroConfig {
94104 static constexpr uint8_t reg = 0x4f ;
@@ -115,7 +125,7 @@ struct ICM42688 {
115125 };
116126
117127#pragma pack(push, 1)
118- struct FifoEntryAligned {
128+ struct FifoEntryAlignedHires {
119129 union {
120130 struct {
121131 int16_t accel[3 ];
@@ -128,10 +138,65 @@ struct ICM42688 {
128138 } part;
129139 uint8_t raw[19 ];
130140 };
141+
142+ void getGyro (int32_t out[3 ]) {
143+ // 6.1 Packet Structure for high resolution mode
144+ // https://invensense.tdk.com/wp-content/uploads/2020/04/ds-000347_icm-42688-p-datasheet.pdf
145+ // When 20-bits data format is used, gyroscope data consists of 19-bits
146+ // of actual data and the LSB is always set to 0
147+ out[0 ] = static_cast <int32_t >(part.gyro [0 ]) << 3 | ((part.xlsb & 0xe ) >> 1 );
148+ out[1 ] = static_cast <int32_t >(part.gyro [1 ]) << 3 | ((part.ylsb & 0xe ) >> 1 );
149+ out[2 ] = static_cast <int32_t >(part.gyro [2 ]) << 3 | ((part.zlsb & 0xe ) >> 1 );
150+ }
151+ void getAccel (int32_t out[3 ]) {
152+ // accelerometer data consists of 18-bits of actual data and the two
153+ // lowest order bits are always set to 0
154+ out[0 ] = static_cast <int32_t >(part.accel [0 ]) << 2
155+ | (static_cast <int32_t >((part.xlsb ) & 0xf0 ) >> 6 );
156+ out[1 ] = static_cast <int32_t >(part.accel [1 ]) << 2
157+ | (static_cast <int32_t >((part.ylsb ) & 0xf0 ) >> 6 );
158+ out[2 ] = static_cast <int32_t >(part.accel [2 ]) << 2
159+ | (static_cast <int32_t >((part.zlsb ) & 0xf0 ) >> 6 );
160+ }
161+ };
162+
163+ struct FifoEntryAlignedDefault {
164+ union {
165+ struct {
166+ int16_t accel[3 ];
167+ int16_t gyro[3 ];
168+ int8_t temp;
169+ uint16_t timestamp;
170+ } part;
171+ uint8_t raw[15 ];
172+ };
173+
174+ void getGyro (int32_t out[3 ]) {
175+ out[0 ] = static_cast <int32_t >(part.gyro [0 ]);
176+ out[1 ] = static_cast <int32_t >(part.gyro [1 ]);
177+ out[2 ] = static_cast <int32_t >(part.gyro [2 ]);
178+ }
179+
180+ void getAccel (int32_t out[3 ]) {
181+ out[0 ] = static_cast <int32_t >(part.accel [0 ]);
182+ out[1 ] = static_cast <int32_t >(part.accel [1 ]);
183+ out[2 ] = static_cast <int32_t >(part.accel [2 ]);
184+ }
131185 };
132186#pragma pack(pop)
133187
188+ static_assert (sizeof (FifoEntryAlignedHires) == 19 );
189+ static_assert (sizeof (FifoEntryAlignedDefault) == 15 );
190+
191+ using FifoEntryAligned = std::conditional<
192+ DEBUG_ICM42688_HIRES,
193+ FifoEntryAlignedHires,
194+ FifoEntryAlignedDefault>::type;
195+
134196 static constexpr size_t FullFifoEntrySize = sizeof (FifoEntryAligned) + 1 ;
197+ // max 4 readings in highres mode 8 readings delay too high 6 seems to be the
198+ // edge to work reliably. Tested on ESP8266 with 2 IMU
199+ static constexpr size_t MaxReadings = DEBUG_ICM42688_HIRES ? 4 : 8 ;
135200
136201 bool initialize () {
137202 // perform initialization step
@@ -155,7 +220,8 @@ struct ICM42688 {
155220 bool bulkRead (DriverCallbacks<int32_t >&& callbacks) {
156221 const auto fifo_bytes = m_RegisterInterface.readReg16 (Regs::FifoCount);
157222
158- std::array<uint8_t , FullFifoEntrySize * 8 > read_buffer; // max 8 readings
223+ std::array<uint8_t , FullFifoEntrySize * MaxReadings> read_buffer;
224+
159225 const auto bytes_to_read = std::min (
160226 static_cast <size_t >(read_buffer.size ()),
161227 static_cast <size_t >(fifo_bytes)
@@ -171,22 +237,13 @@ struct ICM42688 {
171237 sizeof (FifoEntryAligned)
172238 ); // skip fifo header
173239
174- const int32_t gyroData[3 ]{
175- static_cast <int32_t >(entry.part .gyro [0 ]) << 4 | (entry.part .xlsb & 0xf ),
176- static_cast <int32_t >(entry.part .gyro [1 ]) << 4 | (entry.part .ylsb & 0xf ),
177- static_cast <int32_t >(entry.part .gyro [2 ]) << 4 | (entry.part .zlsb & 0xf ),
178- };
240+ int32_t gyroData[3 ];
241+ entry.getGyro (gyroData);
179242 callbacks.processGyroSample (gyroData, GyrTs);
180243
181244 if (entry.part .accel [0 ] != -32768 ) {
182- const int32_t accelData[3 ]{
183- static_cast <int32_t >(entry.part .accel [0 ]) << 4
184- | (static_cast <int32_t >(entry.part .xlsb ) & 0xf0 >> 4 ),
185- static_cast <int32_t >(entry.part .accel [1 ]) << 4
186- | (static_cast <int32_t >(entry.part .ylsb ) & 0xf0 >> 4 ),
187- static_cast <int32_t >(entry.part .accel [2 ]) << 4
188- | (static_cast <int32_t >(entry.part .zlsb ) & 0xf0 >> 4 ),
189- };
245+ int32_t accelData[3 ];
246+ entry.getAccel (accelData);
190247 callbacks.processAccelSample (accelData, AccTs);
191248 }
192249
@@ -197,7 +254,6 @@ struct ICM42688 {
197254 );
198255 }
199256 }
200-
201257 return fifo_bytes > bytes_to_read;
202258 }
203259};
0 commit comments