-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathICM20948.h
309 lines (275 loc) · 12.6 KB
/
ICM20948.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
* Code based on: https://github.com/wollewald/ICM20948_WE.
* Author: Wolfgang (Wolle) Ewald.
* License: MIT (see LICENSE file).
* Further information can be found on:
* https://wolles-elektronikkiste.de/icm-20948-9-achsensensor-teil-i (German)
* https://wolles-elektronikkiste.de/en/icm-20948-9-axis-sensor-part-i (English)
*/
#pragma once
#include "Arduino.h"
#include <Wire.h>
#include <SPI.h>
#include "IMU.h"
#include "logger.h"
/* Enums */
typedef enum ICM20948_CYCLE {
ICM20948_NO_CYCLE = 0x00,
ICM20948_GYR_CYCLE = 0x10,
ICM20948_ACC_CYCLE = 0x20,
ICM20948_ACC_GYR_CYCLE = 0x30,
ICM20948_ACC_GYR_I2C_MST_CYCLE = 0x70
} ICM20948_cycle;
typedef enum ICM20948_INT_PIN_POL {
ICM20948_ACT_HIGH, ICM20948_ACT_LOW
} ICM20948_intPinPol;
typedef enum ICM20948_INT_TYPE {
ICM20948_FSYNC_INT = 0x01,
ICM20948_WOM_INT = 0x02,
ICM20948_DMP_INT = 0x04,
ICM20948_DATA_READY_INT = 0x08,
ICM20948_FIFO_OVF_INT = 0x10,
ICM20948_FIFO_WM_INT = 0x20
} ICM20948_intType;
typedef enum ICM20948_FIFO_TYPE {
ICM20948_FIFO_ACC = 0x10,
ICM20948_FIFO_GYR = 0x0E,
ICM20948_FIFO_ACC_GYR = 0x1E
} ICM20948_fifoType;
typedef enum ICM20948_FIFO_MODE_CHOICE {
ICM20948_CONTINUOUS, ICM20948_STOP_WHEN_FULL
} ICM20948_fifoMode;
typedef enum ICM20948_GYRO_RANGE {
ICM20948_GYRO_RANGE_250, ICM20948_GYRO_RANGE_500, ICM20948_GYRO_RANGE_1000, ICM20948_GYRO_RANGE_2000
} ICM20948_gyroRange;
typedef enum ICM20948_DLPF {
ICM20948_DLPF_0, ICM20948_DLPF_1, ICM20948_DLPF_2, ICM20948_DLPF_3, ICM20948_DLPF_4, ICM20948_DLPF_5,
ICM20948_DLPF_6, ICM20948_DLPF_7, ICM20948_DLPF_OFF
} ICM20948_dlpf;
typedef enum ICM20948_GYRO_AVG_LOW_PWR {
ICM20948_GYR_AVG_1, ICM20948_GYR_AVG_2, ICM20948_GYR_AVG_4, ICM20948_GYR_AVG_8, ICM20948_GYR_AVG_16,
ICM20948_GYR_AVG_32, ICM20948_GYR_AVG_64, ICM20948_GYR_AVG_128
} ICM20948_gyroAvgLowPower;
typedef enum ICM20948_ACC_RANGE {
ICM20948_ACC_RANGE_2G, ICM20948_ACC_RANGE_4G, ICM20948_ACC_RANGE_8G, ICM20948_ACC_RANGE_16G
} ICM20948_accRange;
typedef enum ICM20948_ACC_AVG_LOW_PWR {
ICM20948_ACC_AVG_4, ICM20948_ACC_AVG_8, ICM20948_ACC_AVG_16, ICM20948_ACC_AVG_32
} ICM20948_accAvgLowPower;
typedef enum ICM20948_WOM_COMP {
ICM20948_WOM_COMP_DISABLE, ICM20948_WOM_COMP_ENABLE
} ICM20948_womCompEn;
typedef enum AK09916_OP_MODE {
AK09916_PWR_DOWN = 0x00,
AK09916_TRIGGER_MODE = 0x01,
AK09916_CONT_MODE_10HZ = 0x02,
AK09916_CONT_MODE_20HZ = 0x04,
AK09916_CONT_MODE_50HZ = 0x06,
AK09916_CONT_MODE_100HZ = 0x08
} AK09916_opMode;
class ICM20948 : public IMUInterface, public Logger
{
public:
/* constants */
static constexpr uint8_t AK09916_ADDRESS {0x0C};
/* Registers ICM20948 USER BANK 0*/
static constexpr uint8_t ICM20948_WHO_AM_I {0x00};
static constexpr uint8_t ICM20948_USER_CTRL {0x03};
static constexpr uint8_t ICM20948_LP_CONFIG {0x05};
static constexpr uint8_t ICM20948_PWR_MGMT_1 {0x06};
static constexpr uint8_t ICM20948_PWR_MGMT_2 {0x07};
static constexpr uint8_t ICM20948_INT_PIN_CFG {0x0F};
static constexpr uint8_t ICM20948_INT_ENABLE {0x10};
static constexpr uint8_t ICM20948_INT_ENABLE_1 {0x11};
static constexpr uint8_t ICM20948_INT_ENABLE_2 {0x12};
static constexpr uint8_t ICM20948_INT_ENABLE_3 {0x13};
static constexpr uint8_t ICM20948_I2C_MST_STATUS {0x17};
static constexpr uint8_t ICM20948_INT_STATUS {0x19};
static constexpr uint8_t ICM20948_INT_STATUS_1 {0x1A};
static constexpr uint8_t ICM20948_INT_STATUS_2 {0x1B};
static constexpr uint8_t ICM20948_INT_STATUS_3 {0x1C};
static constexpr uint8_t ICM20948_DELAY_TIME_H {0x28};
static constexpr uint8_t ICM20948_DELAY_TIME_L {0x29};
static constexpr uint8_t ICM20948_ACCEL_OUT {0x2D}; // accel data registers begin
static constexpr uint8_t ICM20948_GYRO_OUT {0x33}; // gyro data registers begin
static constexpr uint8_t ICM20948_TEMP_OUT {0x39};
static constexpr uint8_t ICM20948_EXT_SLV_SENS_DATA_00{0x3B};
static constexpr uint8_t ICM20948_EXT_SLV_SENS_DATA_01{0x3C};
static constexpr uint8_t ICM20948_FIFO_EN_1 {0x66};
static constexpr uint8_t ICM20948_FIFO_EN_2 {0x67};
static constexpr uint8_t ICM20948_FIFO_RST {0x68};
static constexpr uint8_t ICM20948_FIFO_MODE {0x69};
static constexpr uint8_t ICM20948_FIFO_COUNT {0x70};
static constexpr uint8_t ICM20948_FIFO_R_W {0x72};
static constexpr uint8_t ICM20948_DATA_RDY_STATUS {0x74};
static constexpr uint8_t ICM20948_FIFO_CFG {0x76};
/* Registers ICM20948 USER BANK 1*/
static constexpr uint8_t ICM20948_SELF_TEST_X_GYRO {0x02};
static constexpr uint8_t ICM20948_SELF_TEST_Y_GYRO {0x03};
static constexpr uint8_t ICM20948_SELF_TEST_Z_GYRO {0x04};
static constexpr uint8_t ICM20948_SELF_TEST_X_ACCEL {0x0E};
static constexpr uint8_t ICM20948_SELF_TEST_Y_ACCEL {0x0F};
static constexpr uint8_t ICM20948_SELF_TEST_Z_ACCEL {0x10};
static constexpr uint8_t ICM20948_XA_OFFS_H {0x14};
static constexpr uint8_t ICM20948_XA_OFFS_L {0x15};
static constexpr uint8_t ICM20948_YA_OFFS_H {0x17};
static constexpr uint8_t ICM20948_YA_OFFS_L {0x18};
static constexpr uint8_t ICM20948_ZA_OFFS_H {0x1A};
static constexpr uint8_t ICM20948_ZA_OFFS_L {0x1B};
static constexpr uint8_t ICM20948_TIMEBASE_CORR_PLL {0x28};
/* Registers ICM20948 USER BANK 2*/
static constexpr uint8_t ICM20948_GYRO_SMPLRT_DIV {0x00};
static constexpr uint8_t ICM20948_GYRO_CONFIG_1 {0x01};
static constexpr uint8_t ICM20948_GYRO_CONFIG_2 {0x02};
static constexpr uint8_t ICM20948_XG_OFFS_USRH {0x03};
static constexpr uint8_t ICM20948_XG_OFFS_USRL {0x04};
static constexpr uint8_t ICM20948_YG_OFFS_USRH {0x05};
static constexpr uint8_t ICM20948_YG_OFFS_USRL {0x06};
static constexpr uint8_t ICM20948_ZG_OFFS_USRH {0x07};
static constexpr uint8_t ICM20948_ZG_OFFS_USRL {0x08};
static constexpr uint8_t ICM20948_ODR_ALIGN_EN {0x09};
static constexpr uint8_t ICM20948_ACCEL_SMPLRT_DIV_1 {0x10};
static constexpr uint8_t ICM20948_ACCEL_SMPLRT_DIV_2 {0x11};
static constexpr uint8_t ICM20948_ACCEL_INTEL_CTRL {0x12};
static constexpr uint8_t ICM20948_ACCEL_WOM_THR {0x13};
static constexpr uint8_t ICM20948_ACCEL_CONFIG {0x14};
static constexpr uint8_t ICM20948_ACCEL_CONFIG_2 {0x15};
static constexpr uint8_t ICM20948_FSYNC_CONFIG {0x52};
static constexpr uint8_t ICM20948_TEMP_CONFIG {0x53};
static constexpr uint8_t ICM20948_MOD_CTRL_USR {0x54};
/* Registers ICM20948 USER BANK 3*/
static constexpr uint8_t ICM20948_I2C_MST_ODR_CFG {0x00};
static constexpr uint8_t ICM20948_I2C_MST_CTRL {0x01};
static constexpr uint8_t ICM20948_I2C_MST_DELAY_CTRL {0x02};
static constexpr uint8_t ICM20948_I2C_SLV0_ADDR {0x03};
static constexpr uint8_t ICM20948_I2C_SLV0_REG {0x04};
static constexpr uint8_t ICM20948_I2C_SLV0_CTRL {0x05};
static constexpr uint8_t ICM20948_I2C_SLV0_DO {0x06};
/* Registers ICM20948 ALL BANKS */
static constexpr uint8_t ICM20948_REG_BANK_SEL {0x7F};
/* Registers AK09916 */
static constexpr uint8_t AK09916_WIA_1 {0x00}; // Who I am, Company ID
static constexpr uint8_t AK09916_WIA_2 {0x01}; // Who I am, Device ID
static constexpr uint8_t AK09916_STATUS_1 {0x10};
static constexpr uint8_t AK09916_HXL {0x11};
static constexpr uint8_t AK09916_HXH {0x12};
static constexpr uint8_t AK09916_HYL {0x13};
static constexpr uint8_t AK09916_HYH {0x14};
static constexpr uint8_t AK09916_HZL {0x15};
static constexpr uint8_t AK09916_HZH {0x16};
static constexpr uint8_t AK09916_STATUS_2 {0x18};
static constexpr uint8_t AK09916_CNTL_2 {0x31};
static constexpr uint8_t AK09916_CNTL_3 {0x32};
/* Register Bits */
static constexpr uint8_t ICM20948_RESET {0x80};
static constexpr uint8_t ICM20948_I2C_MST_EN {0x20};
static constexpr uint8_t ICM20948_SLEEP {0x40};
static constexpr uint8_t ICM20948_LP_EN {0x20};
static constexpr uint8_t ICM20948_BYPASS_EN {0x02};
static constexpr uint8_t ICM20948_GYR_EN {0x07};
static constexpr uint8_t ICM20948_ACC_EN {0x38};
static constexpr uint8_t ICM20948_FIFO_EN {0x40};
static constexpr uint8_t ICM20948_INT1_ACTL {0x80};
static constexpr uint8_t ICM20948_INT_1_LATCH_EN {0x20};
static constexpr uint8_t ICM20948_ACTL_FSYNC {0x08};
static constexpr uint8_t ICM20948_INT_ANYRD_2CLEAR {0x10};
static constexpr uint8_t ICM20948_FSYNC_INT_MODE_EN {0x06};
static constexpr uint8_t AK09916_16_BIT {0x10};
static constexpr uint8_t AK09916_OVF {0x08};
static constexpr uint8_t AK09916_READ {0x80};
/* Others */
static constexpr uint16_t AK09916_WHO_AM_I_1 {0x4809};
static constexpr uint16_t AK09916_WHO_AM_I_2 {0x0948};
static constexpr uint8_t ICM20948_WHO_AM_I_CONTENT{0xEA};
static constexpr float ICM20948_ROOM_TEMP_OFFSET {0.0};
static constexpr float ICM20948_T_SENSITIVITY {333.87};
static constexpr float AK09916_MAG_LSB {0.1495};
static constexpr uint8_t ICM20948_I2C_MST_RST {0x02};
/* Constructors */
ICM20948(uint8_t addr = 0x68) : _wire{&Wire}, i2cAddress{addr}, useSPI{false} {}
ICM20948(TwoWire *w, uint8_t addr = 0x68) : _wire{w}, i2cAddress{addr}, useSPI{false} {}
ICM20948(TwoWire& w, uint8_t addr = 0x68) : _wire{&w}, i2cAddress{addr}, useSPI{false} {}
ICM20948(SPIClass& s, int cs = -1) : _spi{&s}, csPin{cs}, useSPI{true} {}
bool begin() override;
void reset() override;
uint8_t whoAmI() override;
const char* getModel() const override { return "ICM20948"; }
void enableAcc(bool enAcc);
bool setAccelRange(const AccelRange range) override;
void setAccRange(ICM20948_accRange accRange);
void setAccDLPF(ICM20948_dlpf dlpf);
void setAccSampleRateDivider(uint16_t accSplRateDiv);
void enableGyr(bool enGyr);
bool setGyroRange(const GyroRange range) override;
void setGyrRange(ICM20948_gyroRange gyroRange);
void setGyrDLPF(ICM20948_dlpf dlpf);
void setGyrSampleRateDivider(uint8_t gyrSplRateDiv);
void setTempDLPF(ICM20948_dlpf dlpf);
bool setDLPF(const DLPF dlpf) override;
void setI2CMstSampleRate(uint8_t rateExp);
void setSPIClockSpeed(unsigned long clock);
bool setRate(const Rate rate) override;
/* Results */
bool read() override;
void waitForData() override;
void getAccel(float& x, float& y, float& z) const override;
float getTemp() const override;
void getGyro(float& x, float& y, float& z) const override;
void getMag(float& x, float& y, float& z) const override;
/* Power, Sleep, Standby */
void enableCycle(ICM20948_cycle cycle);
void enableLowPower(bool enLP);
void setGyrAverageInCycleMode(ICM20948_gyroAvgLowPower avg);
void setAccAverageInCycleMode(ICM20948_accAvgLowPower avg);
void sleep(bool sleep);
/* Interrupts */
void setIntPinPolarity(ICM20948_intPinPol pol);
void enableIntLatch(bool latch);
void enableClearIntByAnyRead(bool clearByAnyRead);
void setFSyncIntPolarity(ICM20948_intPinPol pol);
void enableInterrupt(ICM20948_intType intType);
void disableInterrupt(ICM20948_intType intType);
uint8_t readAndClearInterrupts();
bool checkInterrupt(uint8_t source, ICM20948_intType type);
void setWakeOnMotionThreshold(uint8_t womThresh, ICM20948_womCompEn womCompEn);
/* FIFO */
void enableFifo(bool fifo);
void setFifoMode(ICM20948_fifoMode mode);
void startFifo(ICM20948_fifoType fifo);
void stopFifo();
void resetFifo();
int16_t getFifoCount();
int16_t getNumberOfFifoDataSets();
void findFifoBegin();
/* Magnetometer */
bool initMagnetometer();
uint16_t whoAmIMag();
void setMagOpMode(AK09916_opMode opMode);
void resetMag();
protected:
TwoWire *_wire;
SPIClass *_spi;
SPISettings mySPISettings;
uint8_t i2cAddress;
uint8_t currentBank;
uint8_t buffer[20];
uint8_t accRangeFactor;
uint8_t gyrRangeFactor;
uint8_t regVal; // intermediate storage of register values
ICM20948_fifoType fifoType;
int csPin;
bool useSPI;
void setClockToAutoSelect();
void switchBank(uint8_t newBank);
void writeRegister8(uint8_t bank, uint8_t reg, uint8_t val);
void writeRegister16(uint8_t bank, uint8_t reg, int16_t val);
uint8_t readRegister8(uint8_t bank, uint8_t reg);
int16_t readRegister16(uint8_t bank, uint8_t reg);
void readAllData(uint8_t* data);
void writeAK09916Register8(uint8_t reg, uint8_t val);
uint8_t readAK09916Register8(uint8_t reg);
int16_t readAK09916Register16(uint8_t reg);
void enableI2CMaster();
void i2cMasterReset();
void enableMagDataRead(uint8_t reg, uint8_t bytes);
};