Skip to content

Commit 8469b6f

Browse files
fix icm42688 (#493)
* fix_icm42688 test fullscale Still issues with snapping * fix temp scale, adjust buffer * change to lowres * fix semikolon * Apply suggestions Co-Authored-By: gorbit99 <5338164+gorbit99@users.noreply.github.com> * formating --------- Co-authored-by: gorbit99 <5338164+gorbit99@users.noreply.github.com>
1 parent fcd4951 commit 8469b6f

File tree

1 file changed

+78
-22
lines changed

1 file changed

+78
-22
lines changed

src/sensors/softfusion/drivers/icm42688.h

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "callbacks.h"
3131
#include "vqf.h"
3232

33+
constexpr static bool DEBUG_ICM42688_HIRES = false;
34+
3335
namespace 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

Comments
 (0)