JeVois  1.22
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Loading...
Searching...
No Matches
ICM_20948_C.c
Go to the documentation of this file.
1#include "ICM_20948_C.h"
3#include "AK09916_REGISTERS.h"
4
5/*
6 * Icm20948 device require a DMP image to be loaded on init
7 * Provide such images by mean of a byte array
8*/
9#if defined(ICM_20948_USE_DMP) // Only include the 14301 Bytes of DMP if ICM_20948_USE_DMP is defined
10
11#if defined(ARDUINO_ARCH_MBED) // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM
12const uint8_t dmp3_image[] = {
13#elif (defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) || defined(ESP8266)) && !defined(__linux__) // Store the DMP firmware in PROGMEM on older AVR (ATmega) platforms
14#define ICM_20948_USE_PROGMEM_FOR_DMP
15#include <avr/pgmspace.h>
16const uint8_t dmp3_image[] PROGMEM = {
17#else
18const uint8_t dmp3_image[] = {
19#endif
20
21#include "icm20948_img.dmp3a.h"
22};
23#endif
24
25// ICM-20948 data is big-endian. We need to make it little-endian when writing into icm_20948_DMP_data_t
27 {
28 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 13, 12 // Also used for Geomag
29};
31 {
32 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8 // Also used for Gyro_Calibr, Compass_Calibr
33};
35 {
36 1, 0, 3, 2, 5, 4 // Also used for Raw_Accel, Compass
37};
39 {
40 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10};
47
49 {
50 // Data output control 1 register bit definition
51 // 16-bit accel 0x8000
52 // 16-bit gyro 0x4000
53 // 16-bit compass 0x2000
54 // 16-bit ALS 0x1000
55 // 32-bit 6-axis quaternion 0x0800
56 // 32-bit 9-axis quaternion + heading accuracy 0x0400
57 // 16-bit pedometer quaternion 0x0200
58 // 32-bit Geomag rv + heading accuracy 0x0100
59 // 16-bit Pressure 0x0080
60 // 32-bit calibrated gyro 0x0040
61 // 32-bit calibrated compass 0x0020
62 // Pedometer Step Detector 0x0010
63 // Header 2 0x0008
64 // Pedometer Step Indicator Bit 2 0x0004
65 // Pedometer Step Indicator Bit 1 0x0002
66 // Pedometer Step Indicator Bit 0 0x0001
67 // Unsupported Sensors are 0xFFFF
68
69 0xFFFF, // 0 Meta Data
70 0x8008, // 1 Accelerometer
71 0x0028, // 2 Magnetic Field
72 0x0408, // 3 Orientation
73 0x4048, // 4 Gyroscope
74 0x1008, // 5 Light
75 0x0088, // 6 Pressure
76 0xFFFF, // 7 Temperature
77 0xFFFF, // 8 Proximity <----------- fixme
78 0x0808, // 9 Gravity
79 0x8808, // 10 Linear Acceleration
80 0x0408, // 11 Rotation Vector
81 0xFFFF, // 12 Humidity
82 0xFFFF, // 13 Ambient Temperature
83 0x2008, // 14 Magnetic Field Uncalibrated
84 0x0808, // 15 Game Rotation Vector
85 0x4008, // 16 Gyroscope Uncalibrated
86 0x0000, // 17 Significant Motion
87 0x0018, // 18 Step Detector
88 0x0010, // 19 Step Counter <----------- fixme
89 0x0108, // 20 Geomagnetic Rotation Vector
90 0xFFFF, // 21 ANDROID_SENSOR_HEART_RATE,
91 0xFFFF, // 22 ANDROID_SENSOR_PROXIMITY,
92
93 0x8008, // 23 ANDROID_SENSOR_WAKEUP_ACCELEROMETER,
94 0x0028, // 24 ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD,
95 0x0408, // 25 ANDROID_SENSOR_WAKEUP_ORIENTATION,
96 0x4048, // 26 ANDROID_SENSOR_WAKEUP_GYROSCOPE,
97 0x1008, // 27 ANDROID_SENSOR_WAKEUP_LIGHT,
98 0x0088, // 28 ANDROID_SENSOR_WAKEUP_PRESSURE,
99 0x0808, // 29 ANDROID_SENSOR_WAKEUP_GRAVITY,
100 0x8808, // 30 ANDROID_SENSOR_WAKEUP_LINEAR_ACCELERATION,
101 0x0408, // 31 ANDROID_SENSOR_WAKEUP_ROTATION_VECTOR,
102 0xFFFF, // 32 ANDROID_SENSOR_WAKEUP_RELATIVE_HUMIDITY,
103 0xFFFF, // 33 ANDROID_SENSOR_WAKEUP_AMBIENT_TEMPERATURE,
104 0x2008, // 34 ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD_UNCALIBRATED,
105 0x0808, // 35 ANDROID_SENSOR_WAKEUP_GAME_ROTATION_VECTOR,
106 0x4008, // 36 ANDROID_SENSOR_WAKEUP_GYROSCOPE_UNCALIBRATED,
107 0x0018, // 37 ANDROID_SENSOR_WAKEUP_STEP_DETECTOR,
108 0x0010, // 38 ANDROID_SENSOR_WAKEUP_STEP_COUNTER,
109 0x0108, // 39 ANDROID_SENSOR_WAKEUP_GEOMAGNETIC_ROTATION_VECTOR
110 0xFFFF, // 40 ANDROID_SENSOR_WAKEUP_HEART_RATE,
111 0x0000, // 41 ANDROID_SENSOR_WAKEUP_TILT_DETECTOR,
112 0x8008, // 42 Raw Acc
113 0x4048, // 43 Raw Gyr
114};
115
117 NULL, // write
118 NULL, // read
119 NULL, // user
120};
121
122// Private function prototypes
123
124// Function definitions
126{
127 // Initialize all elements by 0 except for _last_bank
128 // Initialize _last_bank to 4 (invalid bank number)
129 // so ICM_20948_set_bank function does not skip issuing bank change operation
130 static const ICM_20948_Device_t init_device = { ._last_bank = 4 };
131 *pdev = init_device;
132 return ICM_20948_Stat_Ok;
133}
134
136{
137 if (s == NULL)
138 {
140 }
141 if (pdev == NULL)
142 {
144 }
145 pdev->_serif = s;
146 return ICM_20948_Stat_Ok;
147}
148
149ICM_20948_Status_e ICM_20948_execute_w(ICM_20948_Device_t *pdev, uint8_t regaddr, uint8_t *pdata, uint32_t len)
150{
151 if (pdev->_serif->write == NULL)
152 {
154 }
155 return (*pdev->_serif->write)(regaddr, pdata, len, pdev->_serif->user);
156}
157
158ICM_20948_Status_e ICM_20948_execute_r(ICM_20948_Device_t *pdev, uint8_t regaddr, uint8_t *pdata, uint32_t len)
159{
160 if (pdev->_serif->read == NULL)
161 {
163 }
164 return (*pdev->_serif->read)(regaddr, pdata, len, pdev->_serif->user);
165}
166
167//Transact directly with an I2C device, one byte at a time
168//Used to configure a device before it is setup into a normal 0-3 peripheral slot
169ICM_20948_Status_e ICM_20948_i2c_controller_periph4_txn(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len, bool Rw, bool send_reg_addr)
170{
171 // Thanks MikeFair! // https://github.com/kriswiner/MPU9250/issues/86
173
174 addr = (((Rw) ? 0x80 : 0x00) | addr);
175
176 retval = ICM_20948_set_bank(pdev, 3);
177 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_ADDR, (uint8_t *)&addr, 1);
178 if (retval != ICM_20948_Stat_Ok)
179 {
180 return retval;
181 }
182
183 retval = ICM_20948_set_bank(pdev, 3);
184 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_REG, (uint8_t *)&reg, 1);
185 if (retval != ICM_20948_Stat_Ok)
186 {
187 return retval;
188 }
189
191 ctrl.EN = 1;
192 ctrl.INT_EN = false;
193 ctrl.DLY = 0;
194 ctrl.REG_DIS = !send_reg_addr;
195
196 ICM_20948_I2C_MST_STATUS_t i2c_mst_status;
197 bool txn_failed = false;
198 uint16_t nByte = 0;
199
200 while (nByte < len)
201 {
202 if (!Rw)
203 {
204 retval = ICM_20948_set_bank(pdev, 3);
205 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_DO, (uint8_t *)&(data[nByte]), 1);
206 if (retval != ICM_20948_Stat_Ok)
207 {
208 return retval;
209 }
210 }
211
212 // Kick off txn
213 retval = ICM_20948_set_bank(pdev, 3);
214 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_PERIPH4_CTRL_t));
215 if (retval != ICM_20948_Stat_Ok)
216 {
217 return retval;
218 }
219
220 // long tsTimeout = millis() + 3000; // Emergency timeout for txn (hard coded to 3 secs)
221 uint32_t max_cycles = 1000;
222 uint32_t count = 0;
223 bool peripheral4Done = false;
224 while (!peripheral4Done)
225 {
226 retval = ICM_20948_set_bank(pdev, 0);
227 retval = ICM_20948_execute_r(pdev, AGB0_REG_I2C_MST_STATUS, (uint8_t *)&i2c_mst_status, 1);
228
229 peripheral4Done = (i2c_mst_status.I2C_PERIPH4_DONE /*| (millis() > tsTimeout) */); //Avoid forever-loops
230 peripheral4Done |= (count >= max_cycles);
231 count++;
232 }
233 txn_failed = (i2c_mst_status.I2C_PERIPH4_NACK /*| (millis() > tsTimeout) */);
234 txn_failed |= (count >= max_cycles);
235 if (txn_failed)
236 break;
237
238 if (Rw)
239 {
240 retval = ICM_20948_set_bank(pdev, 3);
241 retval = ICM_20948_execute_r(pdev, AGB3_REG_I2C_PERIPH4_DI, &data[nByte], 1);
242 }
243
244 nByte++;
245 }
246
247 if (txn_failed)
248 {
249 //We often fail here if mag is stuck
250 return ICM_20948_Stat_Err;
251 }
252
253 return retval;
254}
255
256ICM_20948_Status_e ICM_20948_i2c_master_single_w(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data)
257{
258 return ICM_20948_i2c_controller_periph4_txn(pdev, addr, reg, data, 1, false, true);
259}
260
261ICM_20948_Status_e ICM_20948_i2c_master_single_r(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data)
262{
263 return ICM_20948_i2c_controller_periph4_txn(pdev, addr, reg, data, 1, true, true);
264}
265
267{
268 if (bank > 3)
269 {
271 } // Only 4 possible banks
272
273 if (bank == pdev->_last_bank) // Do we need to change bank?
274 return ICM_20948_Stat_Ok; // Bail if we don't need to change bank to avoid unnecessary bus traffic
275
276 pdev->_last_bank = bank; // Store the requested bank (before we bit-shift)
277 bank = (bank << 4) & 0x30; // bits 5:4 of REG_BANK_SEL
278 return ICM_20948_execute_w(pdev, REG_BANK_SEL, &bank, 1);
279}
280
282{
285
286 ICM_20948_set_bank(pdev, 0); // Must be in the right bank
287
288 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
289 if (retval != ICM_20948_Stat_Ok)
290 {
291 return retval;
292 }
293
294 reg.DEVICE_RESET = 1;
295
296 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
297 if (retval != ICM_20948_Stat_Ok)
298 {
299 return retval;
300 }
301 return retval;
302}
303
305{
308
309 ICM_20948_set_bank(pdev, 0); // Must be in the right bank
310
311 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
312 if (retval != ICM_20948_Stat_Ok)
313 {
314 return retval;
315 }
316
317 if (on)
318 {
319 reg.SLEEP = 1;
320 }
321 else
322 {
323 reg.SLEEP = 0;
324 }
325
326 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
327 if (retval != ICM_20948_Stat_Ok)
328 {
329 return retval;
330 }
331 return retval;
332}
333
335{
338
339 ICM_20948_set_bank(pdev, 0); // Must be in the right bank
340
341 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
342 if (retval != ICM_20948_Stat_Ok)
343 {
344 return retval;
345 }
346
347 if (on)
348 {
349 reg.LP_EN = 1;
350 }
351 else
352 {
353 reg.LP_EN = 0;
354 }
355
356 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
357 if (retval != ICM_20948_Stat_Ok)
358 {
359 return retval;
360 }
361 return retval;
362}
363
365{
368
369 ICM_20948_set_bank(pdev, 0); // Must be in the right bank
370
371 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
372 if (retval != ICM_20948_Stat_Ok)
373 {
374 return retval;
375 }
376
377 reg.CLKSEL = source;
378
379 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)&reg, sizeof(ICM_20948_PWR_MGMT_1_t));
380 if (retval != ICM_20948_Stat_Ok)
381 {
382 return retval;
383 }
384 return retval;
385}
386
388{
389 if (whoami == NULL)
390 {
392 }
393 ICM_20948_set_bank(pdev, 0); // Must be in the right bank
394 return ICM_20948_execute_r(pdev, AGB0_REG_WHO_AM_I, whoami, 1);
395}
396
398{
400 uint8_t whoami = 0x00;
401 retval = ICM_20948_get_who_am_i(pdev, &whoami);
402 if (retval != ICM_20948_Stat_Ok)
403 {
404 return retval;
405 }
406 if (whoami != ICM_20948_WHOAMI)
407 {
409 }
410 return retval;
411}
412
414{
417 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank
418 if (retval != ICM_20948_Stat_Ok)
419 {
420 return retval;
421 }
422 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_STATUS_1, (uint8_t *)&reg, sizeof(ICM_20948_INT_STATUS_1_t));
423 if (retval != ICM_20948_Stat_Ok)
424 {
425 return retval;
426 }
427 if (!reg.RAW_DATA_0_RDY_INT)
428 {
429 retval = ICM_20948_Stat_NoData;
430 }
431 return retval;
432}
433
434// Interrupt Configuration
436{
438 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank
439 if (write != NULL)
440 { // write first, if available
441 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)write, sizeof(ICM_20948_INT_PIN_CFG_t));
442 if (retval != ICM_20948_Stat_Ok)
443 {
444 return retval;
445 }
446 }
447 if (read != NULL)
448 { // then read, to allow for verification
449 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)read, sizeof(ICM_20948_INT_PIN_CFG_t));
450 if (retval != ICM_20948_Stat_Ok)
451 {
452 return retval;
453 }
454 }
455 return retval;
456}
457
459{
461
466
467 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank
468
469 if (write != NULL)
470 { // If the write pointer is not NULL then write to the registers BEFORE reading
471 en_0.I2C_MST_INT_EN = write->I2C_MST_INT_EN;
472 en_0.DMP_INT1_EN = write->DMP_INT1_EN;
473 en_0.PLL_READY_EN = write->PLL_RDY_EN;
474 en_0.WOM_INT_EN = write->WOM_INT_EN;
475 en_0.reserved_0 = 0; // Clear RAM garbage
476 en_0.REG_WOF_EN = write->REG_WOF_EN;
478 en_1.reserved_0 = 0; // Clear RAM garbage
484 en_2.individual.reserved_0 = 0; // Clear RAM garbage
490 en_3.individual.reserved_0 = 0; // Clear RAM garbage
491
492 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE, (uint8_t *)&en_0, sizeof(ICM_20948_INT_ENABLE_t));
493 if (retval != ICM_20948_Stat_Ok)
494 {
495 return retval;
496 }
497 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE_1, (uint8_t *)&en_1, sizeof(ICM_20948_INT_ENABLE_1_t));
498 if (retval != ICM_20948_Stat_Ok)
499 {
500 return retval;
501 }
502 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE_2, (uint8_t *)&en_2, sizeof(ICM_20948_INT_ENABLE_2_t));
503 if (retval != ICM_20948_Stat_Ok)
504 {
505 return retval;
506 }
507 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE_3, (uint8_t *)&en_3, sizeof(ICM_20948_INT_ENABLE_3_t));
508 if (retval != ICM_20948_Stat_Ok)
509 {
510 return retval;
511 }
512 }
513
514 if (read != NULL)
515 { // If read pointer is not NULL then read the registers (if write is not NULL then this should read back the results of write into read)
516 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE, (uint8_t *)&en_0, sizeof(ICM_20948_INT_ENABLE_t));
517 if (retval != ICM_20948_Stat_Ok)
518 {
519 return retval;
520 }
521 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE_1, (uint8_t *)&en_1, sizeof(ICM_20948_INT_ENABLE_1_t));
522 if (retval != ICM_20948_Stat_Ok)
523 {
524 return retval;
525 }
526 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE_2, (uint8_t *)&en_2, sizeof(ICM_20948_INT_ENABLE_2_t));
527 if (retval != ICM_20948_Stat_Ok)
528 {
529 return retval;
530 }
531 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE_3, (uint8_t *)&en_3, sizeof(ICM_20948_INT_ENABLE_3_t));
532 if (retval != ICM_20948_Stat_Ok)
533 {
534 return retval;
535 }
536
537 read->I2C_MST_INT_EN = en_0.I2C_MST_INT_EN;
538 read->DMP_INT1_EN = en_0.DMP_INT1_EN;
539 read->PLL_RDY_EN = en_0.PLL_READY_EN;
540 read->WOM_INT_EN = en_0.WOM_INT_EN;
541 read->REG_WOF_EN = en_0.REG_WOF_EN;
542 read->RAW_DATA_0_RDY_EN = en_1.RAW_DATA_0_RDY_EN;
543 read->FIFO_OVERFLOW_EN_4 = en_2.individual.FIFO_OVERFLOW_EN_4;
544 read->FIFO_OVERFLOW_EN_3 = en_2.individual.FIFO_OVERFLOW_EN_3;
545 read->FIFO_OVERFLOW_EN_2 = en_2.individual.FIFO_OVERFLOW_EN_2;
546 read->FIFO_OVERFLOW_EN_1 = en_2.individual.FIFO_OVERFLOW_EN_1;
547 read->FIFO_OVERFLOW_EN_0 = en_2.individual.FIFO_OVERFLOW_EN_0;
548 read->FIFO_WM_EN_4 = en_3.individual.FIFO_WM_EN_4;
549 read->FIFO_WM_EN_3 = en_3.individual.FIFO_WM_EN_3;
550 read->FIFO_WM_EN_2 = en_3.individual.FIFO_WM_EN_2;
551 read->FIFO_WM_EN_1 = en_3.individual.FIFO_WM_EN_1;
552 read->FIFO_WM_EN_0 = en_3.individual.FIFO_WM_EN_0;
553 }
554
555 return retval;
556}
557
559{
561
563
564 retval = ICM_20948_set_bank(pdev, 2); // Must be in the right bank
565
566 if (write != NULL)
567 { // If the write pointer is not NULL then write to the registers BEFORE reading
568 ctrl.ACCEL_INTEL_EN = write->ACCEL_INTEL_EN;
570
571 retval = ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_INTEL_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_ACCEL_INTEL_CTRL_t));
572 if (retval != ICM_20948_Stat_Ok)
573 {
574 return retval;
575 }
576 }
577
578 if (read != NULL)
579 { // If read pointer is not NULL then read the registers (if write is not NULL then this should read back the results of write into read)
580 retval = ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_INTEL_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_ACCEL_INTEL_CTRL_t));
581 if (retval != ICM_20948_Stat_Ok)
582 {
583 return retval;
584 }
585
586 read->ACCEL_INTEL_EN = ctrl.ACCEL_INTEL_EN;
587 read->ACCEL_INTEL_MODE_INT = ctrl.ACCEL_INTEL_MODE_INT;
588 }
589
590 return retval;
591}
592
594{
596
598
599 retval = ICM_20948_set_bank(pdev, 2); // Must be in the right bank
600
601 if (write != NULL)
602 { // If the write pointer is not NULL then write to the registers BEFORE reading
603 thr.WOM_THRESHOLD = write->WOM_THRESHOLD;
604
605 retval = ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_WOM_THR, (uint8_t *)&thr, sizeof(ICM_20948_ACCEL_WOM_THR_t));
606 if (retval != ICM_20948_Stat_Ok)
607 {
608 return retval;
609 }
610 }
611
612 if (read != NULL)
613 { // If read pointer is not NULL then read the registers (if write is not NULL then this should read back the results of write into read)
614 retval = ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_WOM_THR, (uint8_t *)&thr, sizeof(ICM_20948_ACCEL_WOM_THR_t));
615 if (retval != ICM_20948_Stat_Ok)
616 {
617 return retval;
618 }
619
620 read->WOM_THRESHOLD = thr.WOM_THRESHOLD;
621 }
622
623 return retval;
624}
625
627{
630
632 {
634 }
635
636 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank
637 if (retval != ICM_20948_Stat_Ok)
638 {
639 return retval;
640 }
641 retval = ICM_20948_execute_r(pdev, AGB0_REG_LP_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_LP_CONFIG_t));
642 if (retval != ICM_20948_Stat_Ok)
643 {
644 return retval;
645 }
646
647 if (sensors & ICM_20948_Internal_Acc)
648 {
649 reg.ACCEL_CYCLE = mode;
650 } // Set all desired sensors to this setting
651 if (sensors & ICM_20948_Internal_Gyr)
652 {
653 reg.GYRO_CYCLE = mode;
654 }
655 if (sensors & ICM_20948_Internal_Mst)
656 {
657 reg.I2C_MST_CYCLE = mode;
658 }
659
660 retval = ICM_20948_execute_w(pdev, AGB0_REG_LP_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_LP_CONFIG_t));
661 if (retval != ICM_20948_Stat_Ok)
662 {
663 return retval;
664 }
665
666 // Check the data was written correctly
667 retval = ICM_20948_execute_r(pdev, AGB0_REG_LP_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_LP_CONFIG_t));
668 if (retval != ICM_20948_Stat_Ok)
669 {
670 return retval;
671 }
672 if (sensors & ICM_20948_Internal_Acc)
673 {
674 if (reg.ACCEL_CYCLE != mode) retval = ICM_20948_Stat_Err;
675 }
676 if (sensors & ICM_20948_Internal_Gyr)
677 {
678 if (reg.GYRO_CYCLE != mode) retval = ICM_20948_Stat_Err;
679 }
680 if (sensors & ICM_20948_Internal_Mst)
681 {
682 if (reg.I2C_MST_CYCLE != mode) retval = ICM_20948_Stat_Err;
683 }
684
685 return retval;
686}
687
689{
691
693 {
695 }
696
697 if (sensors & ICM_20948_Internal_Acc)
698 {
700 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
701 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
702 reg.ACCEL_FS_SEL = fss.a;
703 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
704 // Check the data was written correctly
705 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
706 if (reg.ACCEL_FS_SEL != fss.a) retval |= ICM_20948_Stat_Err;
707 }
708 if (sensors & ICM_20948_Internal_Gyr)
709 {
711 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
712 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
713 reg.GYRO_FS_SEL = fss.g;
714 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
715 // Check the data was written correctly
716 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
717 if (reg.GYRO_FS_SEL != fss.g) retval |= ICM_20948_Stat_Err;
718 }
719 return retval;
720}
721
723{
725
727 {
729 }
730
731 if (sensors & ICM_20948_Internal_Acc)
732 {
734 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
735 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
736 reg.ACCEL_DLPFCFG = cfg.a;
737 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
738 // Check the data was written correctly
739 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
740 if (reg.ACCEL_DLPFCFG != cfg.a) retval |= ICM_20948_Stat_Err;
741 }
742 if (sensors & ICM_20948_Internal_Gyr)
743 {
745 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
746 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
747 reg.GYRO_DLPFCFG = cfg.g;
748 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
749 // Check the data was written correctly
750 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
751 if (reg.GYRO_DLPFCFG != cfg.g) retval |= ICM_20948_Stat_Err;
752 }
753 return retval;
754}
755
757{
759
761 {
763 }
764
765 if (sensors & ICM_20948_Internal_Acc)
766 {
768 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
769 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
770 if (enable)
771 {
772 reg.ACCEL_FCHOICE = 1;
773 }
774 else
775 {
776 reg.ACCEL_FCHOICE = 0;
777 }
778 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
779 // Check the data was written correctly
780 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_ACCEL_CONFIG_t));
781 if (enable)
782 {
783 if (reg.ACCEL_FCHOICE != 1) retval |= ICM_20948_Stat_Err;
784 }
785 else
786 {
787 if (reg.ACCEL_FCHOICE != 0) retval |= ICM_20948_Stat_Err;
788 }
789 }
790 if (sensors & ICM_20948_Internal_Gyr)
791 {
793 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
794 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
795 if (enable)
796 {
797 reg.GYRO_FCHOICE = 1;
798 }
799 else
800 {
801 reg.GYRO_FCHOICE = 0;
802 }
803 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
804 // Check the data was written correctly
805 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&reg, sizeof(ICM_20948_GYRO_CONFIG_1_t));
806 if (enable)
807 {
808 if (reg.GYRO_FCHOICE != 1) retval |= ICM_20948_Stat_Err;
809 }
810 else
811 {
812 if (reg.GYRO_FCHOICE != 0) retval |= ICM_20948_Stat_Err;
813 }
814 }
815 return retval;
816}
817
819{
821
823 {
825 }
826
827 if (sensors & ICM_20948_Internal_Acc)
828 {
829 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
830 uint8_t div1 = (smplrt.a >> 8); // Thank you @yanivamichy #109
831 uint8_t div2 = (smplrt.a & 0xFF);
832 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_SMPLRT_DIV_1, &div1, 1);
833 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_SMPLRT_DIV_2, &div2, 1);
834 }
835 if (sensors & ICM_20948_Internal_Gyr)
836 {
837 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank
838 uint8_t div = (smplrt.g);
839 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_SMPLRT_DIV, &div, 1);
840 }
841 return retval;
842}
843
844// Interface Things
846{
848
850 retval = ICM_20948_set_bank(pdev, 0);
851 if (retval != ICM_20948_Stat_Ok)
852 {
853 return retval;
854 }
855 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_INT_PIN_CFG_t));
856 if (retval != ICM_20948_Stat_Ok)
857 {
858 return retval;
859 }
860 reg.BYPASS_EN = passthrough;
861 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)&reg, sizeof(ICM_20948_INT_PIN_CFG_t));
862 if (retval != ICM_20948_Stat_Ok)
863 {
864 return retval;
865 }
866
867 return retval;
868}
869
871{
873
874 // Disable BYPASS_EN
875 retval = ICM_20948_i2c_master_passthrough(pdev, false);
876 if (retval != ICM_20948_Stat_Ok)
877 {
878 return retval;
879 }
880
882 retval = ICM_20948_set_bank(pdev, 3);
883 if (retval != ICM_20948_Stat_Ok)
884 {
885 return retval;
886 }
887 retval = ICM_20948_execute_r(pdev, AGB3_REG_I2C_MST_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_MST_CTRL_t));
888 if (retval != ICM_20948_Stat_Ok)
889 {
890 return retval;
891 }
892 ctrl.I2C_MST_CLK = 0x07; // corresponds to 345.6 kHz, good for up to 400 kHz
893 ctrl.I2C_MST_P_NSR = 1;
894 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_MST_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_MST_CTRL_t));
895 if (retval != ICM_20948_Stat_Ok)
896 {
897 return retval;
898 }
899
901 retval = ICM_20948_set_bank(pdev, 0);
902 if (retval != ICM_20948_Stat_Ok)
903 {
904 return retval;
905 }
906 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&reg, sizeof(ICM_20948_USER_CTRL_t));
907 if (retval != ICM_20948_Stat_Ok)
908 {
909 return retval;
910 }
911 if (enable)
912 {
913 reg.I2C_MST_EN = 1;
914 }
915 else
916 {
917 reg.I2C_MST_EN = 0;
918 }
919 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&reg, sizeof(ICM_20948_USER_CTRL_t));
920 if (retval != ICM_20948_Stat_Ok)
921 {
922 return retval;
923 }
924
925 return retval;
926}
927
929{
931
933 retval = ICM_20948_set_bank(pdev, 0);
934 if (retval != ICM_20948_Stat_Ok)
935 {
936 return retval;
937 }
938
939 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
940 if (retval != ICM_20948_Stat_Ok)
941 {
942 return retval;
943 }
944
945 ctrl.I2C_MST_RST = 1; //Reset!
946
947 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
948 if (retval != ICM_20948_Stat_Ok)
949 {
950 return retval;
951 }
952 return retval;
953}
954
955ICM_20948_Status_e ICM_20948_i2c_controller_configure_peripheral(ICM_20948_Device_t *pdev, uint8_t peripheral, uint8_t addr, uint8_t reg, uint8_t len, bool Rw, bool enable, bool data_only, bool grp, bool swap, uint8_t dataOut)
956{
958
959 uint8_t periph_addr_reg;
960 uint8_t periph_reg_reg;
961 uint8_t periph_ctrl_reg;
962 uint8_t periph_do_reg;
963
964 switch (peripheral)
965 {
966 case 0:
967 periph_addr_reg = AGB3_REG_I2C_PERIPH0_ADDR;
968 periph_reg_reg = AGB3_REG_I2C_PERIPH0_REG;
969 periph_ctrl_reg = AGB3_REG_I2C_PERIPH0_CTRL;
970 periph_do_reg = AGB3_REG_I2C_PERIPH0_DO;
971 break;
972 case 1:
973 periph_addr_reg = AGB3_REG_I2C_PERIPH1_ADDR;
974 periph_reg_reg = AGB3_REG_I2C_PERIPH1_REG;
975 periph_ctrl_reg = AGB3_REG_I2C_PERIPH1_CTRL;
976 periph_do_reg = AGB3_REG_I2C_PERIPH1_DO;
977 break;
978 case 2:
979 periph_addr_reg = AGB3_REG_I2C_PERIPH2_ADDR;
980 periph_reg_reg = AGB3_REG_I2C_PERIPH2_REG;
981 periph_ctrl_reg = AGB3_REG_I2C_PERIPH2_CTRL;
982 periph_do_reg = AGB3_REG_I2C_PERIPH2_DO;
983 break;
984 case 3:
985 periph_addr_reg = AGB3_REG_I2C_PERIPH3_ADDR;
986 periph_reg_reg = AGB3_REG_I2C_PERIPH3_REG;
987 periph_ctrl_reg = AGB3_REG_I2C_PERIPH3_CTRL;
988 periph_do_reg = AGB3_REG_I2C_PERIPH3_DO;
989 break;
990 default:
992 }
993
994 retval = ICM_20948_set_bank(pdev, 3);
995 if (retval != ICM_20948_Stat_Ok)
996 {
997 return retval;
998 }
999
1000 // Set the peripheral address and the Rw flag
1002 address.ID = addr;
1003 if (Rw)
1004 {
1005 address.RNW = 1;
1006 }
1007 else
1008 {
1009 address.RNW = 0; // Make sure bit is clear (just in case there is any garbage in that RAM location)
1010 }
1011 retval = ICM_20948_execute_w(pdev, periph_addr_reg, (uint8_t *)&address, sizeof(ICM_20948_I2C_PERIPHX_ADDR_t));
1012 if (retval != ICM_20948_Stat_Ok)
1013 {
1014 return retval;
1015 }
1016
1017 // If we are setting up a write, configure the Data Out register too
1018 if (!Rw)
1019 {
1020 ICM_20948_I2C_PERIPHX_DO_t dataOutByte;
1021 dataOutByte.DO = dataOut;
1022 retval = ICM_20948_execute_w(pdev, periph_do_reg, (uint8_t *)&dataOutByte, sizeof(ICM_20948_I2C_PERIPHX_DO_t));
1023 if (retval != ICM_20948_Stat_Ok)
1024 {
1025 return retval;
1026 }
1027 }
1028
1029 // Set the peripheral sub-address (register address)
1030 ICM_20948_I2C_PERIPHX_REG_t subaddress;
1031 subaddress.REG = reg;
1032 retval = ICM_20948_execute_w(pdev, periph_reg_reg, (uint8_t *)&subaddress, sizeof(ICM_20948_I2C_PERIPHX_REG_t));
1033 if (retval != ICM_20948_Stat_Ok)
1034 {
1035 return retval;
1036 }
1037
1038 // Set up the control info
1040 ctrl.LENG = len;
1041 ctrl.EN = enable;
1042 ctrl.REG_DIS = data_only;
1043 ctrl.GRP = grp;
1044 ctrl.BYTE_SW = swap;
1045 retval = ICM_20948_execute_w(pdev, periph_ctrl_reg, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_PERIPHX_CTRL_t));
1046 if (retval != ICM_20948_Stat_Ok)
1047 {
1048 return retval;
1049 }
1050
1051 return retval;
1052}
1053
1054// Higher Level
1056{
1057 if (pagmt == NULL)
1058 {
1060 }
1061
1063 const uint8_t numbytes = 14 + 9; //Read Accel, gyro, temp, and 9 bytes of mag
1064 uint8_t buff[numbytes];
1065
1066 // Get readings
1067 retval |= ICM_20948_set_bank(pdev, 0);
1068 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB0_REG_ACCEL_XOUT_H, buff, numbytes);
1069
1070 pagmt->acc.axes.x = ((buff[0] << 8) | (buff[1] & 0xFF));
1071 pagmt->acc.axes.y = ((buff[2] << 8) | (buff[3] & 0xFF));
1072 pagmt->acc.axes.z = ((buff[4] << 8) | (buff[5] & 0xFF));
1073
1074 pagmt->gyr.axes.x = ((buff[6] << 8) | (buff[7] & 0xFF));
1075 pagmt->gyr.axes.y = ((buff[8] << 8) | (buff[9] & 0xFF));
1076 pagmt->gyr.axes.z = ((buff[10] << 8) | (buff[11] & 0xFF));
1077
1078 pagmt->tmp.val = ((buff[12] << 8) | (buff[13] & 0xFF));
1079
1080 pagmt->magStat1 = buff[14];
1081 pagmt->mag.axes.x = ((buff[16] << 8) | (buff[15] & 0xFF)); //Mag data is read little endian
1082 pagmt->mag.axes.y = ((buff[18] << 8) | (buff[17] & 0xFF));
1083 pagmt->mag.axes.z = ((buff[20] << 8) | (buff[19] & 0xFF));
1084 pagmt->magStat2 = buff[22];
1085
1086 // Get settings to be able to compute scaled values
1087 retval |= ICM_20948_set_bank(pdev, 2);
1089 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB2_REG_ACCEL_CONFIG, (uint8_t *)&acfg, 1 * sizeof(acfg));
1090 pagmt->fss.a = acfg.ACCEL_FS_SEL; // Worth noting that without explicitly setting the FS range of the accelerometer it was showing the register value for +/- 2g but the reported values were actually scaled to the +/- 16g range
1091 // Wait a minute... now it seems like this problem actually comes from the digital low-pass filter. When enabled the value is 1/8 what it should be...
1092 retval |= ICM_20948_set_bank(pdev, 2);
1094 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&gcfg1, 1 * sizeof(gcfg1));
1095 pagmt->fss.g = gcfg1.GYRO_FS_SEL;
1097 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB2_REG_ACCEL_CONFIG_2, (uint8_t *)&acfg2, 1 * sizeof(acfg2));
1098
1099 return retval;
1100}
1101
1102// FIFO
1103
1105{
1107
1109 retval = ICM_20948_set_bank(pdev, 0);
1110 if (retval != ICM_20948_Stat_Ok)
1111 {
1112 return retval;
1113 }
1114
1115 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
1116 if (retval != ICM_20948_Stat_Ok)
1117 {
1118 return retval;
1119 }
1120
1121 if (enable)
1122 ctrl.FIFO_EN = 1;
1123 else
1124 ctrl.FIFO_EN = 0;
1125
1126 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
1127 if (retval != ICM_20948_Stat_Ok)
1128 {
1129 return retval;
1130 }
1131 return retval;
1132}
1133
1135{
1137
1139 retval = ICM_20948_set_bank(pdev, 0);
1140 if (retval != ICM_20948_Stat_Ok)
1141 {
1142 return retval;
1143 }
1144
1145 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_RST, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_RST_t));
1146 if (retval != ICM_20948_Stat_Ok)
1147 {
1148 return retval;
1149 }
1150
1151 ctrl.FIFO_RESET = 0x1F; // Datasheet says "FIFO_RESET[4:0]"
1152
1153 retval = ICM_20948_execute_w(pdev, AGB0_REG_FIFO_RST, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_RST_t));
1154 if (retval != ICM_20948_Stat_Ok)
1155 {
1156 return retval;
1157 }
1158
1159 //delay ???
1160
1161 ctrl.FIFO_RESET = 0x1E; // The InvenSense Nucleo examples write 0x1F followed by 0x1E
1162
1163 retval = ICM_20948_execute_w(pdev, AGB0_REG_FIFO_RST, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_RST_t));
1164 if (retval != ICM_20948_Stat_Ok)
1165 {
1166 return retval;
1167 }
1168
1169 return retval;
1170}
1171
1173{
1175
1177 retval = ICM_20948_set_bank(pdev, 0);
1178 if (retval != ICM_20948_Stat_Ok)
1179 {
1180 return retval;
1181 }
1182
1183 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_MODE, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_MODE_t));
1184 if (retval != ICM_20948_Stat_Ok)
1185 {
1186 return retval;
1187 }
1188
1189 if (snapshot)
1190 ctrl.FIFO_MODE = 0x1F; // Datasheet says "FIFO_MODE[4:0]"
1191 else
1192 ctrl.FIFO_MODE = 0;
1193
1194 retval = ICM_20948_execute_w(pdev, AGB0_REG_FIFO_MODE, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_MODE_t));
1195 if (retval != ICM_20948_Stat_Ok)
1196 {
1197 return retval;
1198 }
1199 return retval;
1200}
1201
1203{
1205
1208 retval = ICM_20948_set_bank(pdev, 0);
1209 if (retval != ICM_20948_Stat_Ok)
1210 {
1211 return retval;
1212 }
1213
1214 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_COUNT_H, (uint8_t *)&ctrlh, sizeof(ICM_20948_FIFO_COUNTH_t));
1215 if (retval != ICM_20948_Stat_Ok)
1216 {
1217 return retval;
1218 }
1219
1220 ctrlh.FIFO_COUNTH &= 0x1F; // Datasheet says "FIFO_CNT[12:8]"
1221
1222 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_COUNT_L, (uint8_t *)&ctrll, sizeof(ICM_20948_FIFO_COUNTL_t));
1223 if (retval != ICM_20948_Stat_Ok)
1224 {
1225 return retval;
1226 }
1227
1228 *count = (((uint16_t)ctrlh.FIFO_COUNTH) << 8) | (uint16_t)ctrll.FIFO_COUNTL;
1229
1230 return retval;
1231}
1232
1234{
1236
1237 retval = ICM_20948_set_bank(pdev, 0);
1238 if (retval != ICM_20948_Stat_Ok)
1239 {
1240 return retval;
1241 }
1242
1243 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_R_W, data, len);
1244 if (retval != ICM_20948_Stat_Ok)
1245 {
1246 return retval;
1247 }
1248
1249 return retval;
1250}
1251
1252// DMP
1253
1255{
1257
1259 retval = ICM_20948_set_bank(pdev, 0);
1260 if (retval != ICM_20948_Stat_Ok)
1261 {
1262 return retval;
1263 }
1264
1265 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
1266 if (retval != ICM_20948_Stat_Ok)
1267 {
1268 return retval;
1269 }
1270
1271 if (enable)
1272 ctrl.DMP_EN = 1;
1273 else
1274 ctrl.DMP_EN = 0;
1275
1276 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
1277 if (retval != ICM_20948_Stat_Ok)
1278 {
1279 return retval;
1280 }
1281 return retval;
1282}
1283
1285{
1287
1289 retval = ICM_20948_set_bank(pdev, 0);
1290 if (retval != ICM_20948_Stat_Ok)
1291 {
1292 return retval;
1293 }
1294
1295 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
1296 if (retval != ICM_20948_Stat_Ok)
1297 {
1298 return retval;
1299 }
1300
1301 ctrl.DMP_RST = 1;
1302
1303 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t));
1304 if (retval != ICM_20948_Stat_Ok)
1305 {
1306 return retval;
1307 }
1308 return retval;
1309}
1310
1312{
1313#if defined(ICM_20948_USE_DMP)
1314 return (inv_icm20948_firmware_load(pdev, dmp3_image, sizeof(dmp3_image), DMP_LOAD_START));
1315#else
1317#endif
1318}
1319
1320/** @brief Loads the DMP firmware from SRAM
1321* @param[in] data pointer where the image
1322* @param[in] size size if the image
1323* @param[in] load_addr address to loading the image
1324* @return 0 in case of success, -1 for any error
1325*/
1326ICM_20948_Status_e inv_icm20948_firmware_load(ICM_20948_Device_t *pdev, const unsigned char *data_start, unsigned short size_start, unsigned short load_addr)
1327{
1328 int write_size;
1330 unsigned short memaddr;
1331 const unsigned char *data;
1332 unsigned short size;
1333 unsigned char data_cmp[INV_MAX_SERIAL_READ];
1334 int flag = 0;
1335
1336 if (pdev->_dmp_firmware_available == false)
1338
1339 if (pdev->_firmware_loaded)
1340 return ICM_20948_Stat_Ok; // Bail with no error if firmware is already loaded
1341
1342 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake
1343 if (result != ICM_20948_Stat_Ok)
1344 {
1345 return result;
1346 }
1347
1348 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state
1349 if (result != ICM_20948_Stat_Ok)
1350 {
1351 return result;
1352 }
1353
1354 // Write DMP memory
1355
1356 data = data_start;
1357 size = size_start;
1358 memaddr = load_addr;
1359 #ifdef ICM_20948_USE_PROGMEM_FOR_DMP
1360 unsigned char data_not_pg[INV_MAX_SERIAL_READ]; // Suggested by @HyperKokichi in Issue #63
1361 #endif
1362 while (size > 0)
1363 {
1364 //write_size = min(size, INV_MAX_SERIAL_WRITE); // Write in chunks of INV_MAX_SERIAL_WRITE
1365 if (size <= INV_MAX_SERIAL_WRITE) // Write in chunks of INV_MAX_SERIAL_WRITE
1366 write_size = size;
1367 else
1368 write_size = INV_MAX_SERIAL_WRITE;
1369 if ((memaddr & 0xff) + write_size > 0x100)
1370 {
1371 // Moved across a bank
1372 write_size = (memaddr & 0xff) + write_size - 0x100;
1373 }
1374#ifdef ICM_20948_USE_PROGMEM_FOR_DMP
1375 memcpy_P(data_not_pg, data, write_size); // Suggested by @HyperKokichi in Issue #63
1376 result = inv_icm20948_write_mems(pdev, memaddr, write_size, (unsigned char *)data_not_pg);
1377#else
1378 result = inv_icm20948_write_mems(pdev, memaddr, write_size, (unsigned char *)data);
1379#endif
1380 if (result != ICM_20948_Stat_Ok)
1381 return result;
1382 data += write_size;
1383 size -= write_size;
1384 memaddr += write_size;
1385 }
1386
1387 // Verify DMP memory
1388
1389 data = data_start;
1390 size = size_start;
1391 memaddr = load_addr;
1392 while (size > 0)
1393 {
1394 //write_size = min(size, INV_MAX_SERIAL_READ); // Read in chunks of INV_MAX_SERIAL_READ
1395 if (size <= INV_MAX_SERIAL_READ) // Read in chunks of INV_MAX_SERIAL_READ
1396 write_size = size;
1397 else
1398 write_size = INV_MAX_SERIAL_READ;
1399 if ((memaddr & 0xff) + write_size > 0x100)
1400 {
1401 // Moved across a bank
1402 write_size = (memaddr & 0xff) + write_size - 0x100;
1403 }
1404 result = inv_icm20948_read_mems(pdev, memaddr, write_size, data_cmp);
1405 if (result != ICM_20948_Stat_Ok)
1406 flag++; // Error, DMP not written correctly
1407#ifdef ICM_20948_USE_PROGMEM_FOR_DMP
1408 memcpy_P(data_not_pg, data, write_size); // Suggested by @HyperKokichi in Issue #63
1409 if (memcmp(data_cmp, data_not_pg, write_size))
1410#else
1411 if (memcmp(data_cmp, data, write_size)) // Compare the data
1412#endif
1414 data += write_size;
1415 size -= write_size;
1416 memaddr += write_size;
1417 }
1418
1419 //Enable LP_EN since we disabled it at begining of this function.
1420 result = ICM_20948_low_power(pdev, true); // Put chip into low power state
1421 if (result != ICM_20948_Stat_Ok)
1422 return result;
1423
1424 if (!flag)
1425 {
1426 //Serial.println("DMP Firmware was updated successfully..");
1427 pdev->_firmware_loaded = true;
1428 }
1429
1430 return result;
1431}
1432
1434{
1436
1437 if (pdev->_dmp_firmware_available == false)
1439
1440 unsigned char start_address[2];
1441
1442 start_address[0] = (unsigned char)(address >> 8);
1443 start_address[1] = (unsigned char)(address & 0xff);
1444
1445 // result = ICM_20948_sleep(pdev, false); // Make sure chip is awake
1446 // if (result != ICM_20948_Stat_Ok)
1447 // {
1448 // return result;
1449 // }
1450 //
1451 // result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state
1452 // if (result != ICM_20948_Stat_Ok)
1453 // {
1454 // return result;
1455 // }
1456
1457 result = ICM_20948_set_bank(pdev, 2); // Set bank 2
1458 if (result != ICM_20948_Stat_Ok)
1459 {
1460 return result;
1461 }
1462
1463 // Write the sensor control bits into memory address AGB2_REG_PRGM_START_ADDRH
1464 result = ICM_20948_execute_w(pdev, AGB2_REG_PRGM_START_ADDRH, (uint8_t *)start_address, 2);
1465
1466 return result;
1467}
1468
1469/**
1470* @brief Write data to a register in DMP memory
1471* @param[in] DMP memory address
1472* @param[in] number of byte to be written
1473* @param[out] output data from the register
1474* @return 0 if successful.
1475*/
1476ICM_20948_Status_e inv_icm20948_write_mems(ICM_20948_Device_t *pdev, unsigned short reg, unsigned int length, const unsigned char *data)
1477{
1479 unsigned int bytesWritten = 0;
1480 unsigned int thisLen;
1481 unsigned char lBankSelected;
1482 unsigned char lStartAddrSelected;
1483
1484 if (!data)
1485 {
1486 return ICM_20948_Stat_NoData;
1487 }
1488
1489 result = ICM_20948_set_bank(pdev, 0); // Set bank 0
1490 if (result != ICM_20948_Stat_Ok)
1491 {
1492 return result;
1493 }
1494
1495 lBankSelected = (reg >> 8);
1496
1497 if (lBankSelected != pdev->_last_mems_bank)
1498 {
1499 pdev->_last_mems_bank = lBankSelected;
1500 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_BANK_SEL, &lBankSelected, 1);
1501 if (result != ICM_20948_Stat_Ok)
1502 {
1503 return result;
1504 }
1505 }
1506
1507 while (bytesWritten < length)
1508 {
1509 lStartAddrSelected = (reg & 0xff);
1510
1511 /* Sets the starting read or write address for the selected memory, inside of the selected page (see MEM_SEL Register).
1512 Contents are changed after read or write of the selected memory.
1513 This register must be written prior to each access to initialize the register to the proper starting address.
1514 The address will auto increment during burst transactions. Two consecutive bursts without re-initializing the start address would skip one address. */
1515
1516 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_START_ADDR, &lStartAddrSelected, 1);
1517 if (result != ICM_20948_Stat_Ok)
1518 {
1519 return result;
1520 }
1521
1522 if (length - bytesWritten <= INV_MAX_SERIAL_WRITE)
1523 thisLen = length - bytesWritten;
1524 else
1525 thisLen = INV_MAX_SERIAL_WRITE;
1526
1527 /* Write data */
1528
1529 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_R_W, (uint8_t *)&data[bytesWritten], thisLen);
1530 if (result != ICM_20948_Stat_Ok)
1531 {
1532 return result;
1533 }
1534
1535 bytesWritten += thisLen;
1536 reg += thisLen;
1537 }
1538
1539 return result;
1540}
1541
1542/**
1543* @brief Read data from a register in DMP memory
1544* @param[in] DMP memory address
1545* @param[in] number of byte to be read
1546* @param[in] input data from the register
1547* @return 0 if successful.
1548*/
1549ICM_20948_Status_e inv_icm20948_read_mems(ICM_20948_Device_t *pdev, unsigned short reg, unsigned int length, unsigned char *data)
1550{
1552 unsigned int bytesRead = 0;
1553 unsigned int thisLen;
1554 unsigned char lBankSelected;
1555 unsigned char lStartAddrSelected;
1556
1557 if (!data)
1558 {
1559 return ICM_20948_Stat_NoData;
1560 }
1561
1562 result = ICM_20948_set_bank(pdev, 0); // Set bank 0
1563 if (result != ICM_20948_Stat_Ok)
1564 {
1565 return result;
1566 }
1567
1568 lBankSelected = (reg >> 8);
1569
1570 if (lBankSelected != pdev->_last_mems_bank)
1571 {
1572 pdev->_last_mems_bank = lBankSelected;
1573 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_BANK_SEL, &lBankSelected, 1);
1574 if (result != ICM_20948_Stat_Ok)
1575 {
1576 return result;
1577 }
1578 }
1579
1580 while (bytesRead < length)
1581 {
1582 lStartAddrSelected = (reg & 0xff);
1583
1584 /* Sets the starting read or write address for the selected memory, inside of the selected page (see MEM_SEL Register).
1585 Contents are changed after read or write of the selected memory.
1586 This register must be written prior to each access to initialize the register to the proper starting address.
1587 The address will auto increment during burst transactions. Two consecutive bursts without re-initializing the start address would skip one address. */
1588
1589 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_START_ADDR, &lStartAddrSelected, 1);
1590 if (result != ICM_20948_Stat_Ok)
1591 {
1592 return result;
1593 }
1594
1595 if (length - bytesRead <= INV_MAX_SERIAL_READ)
1596 thisLen = length - bytesRead;
1597 else
1598 thisLen = INV_MAX_SERIAL_READ;
1599
1600 /* Read data */
1601
1602 result = ICM_20948_execute_r(pdev, AGB0_REG_MEM_R_W, &data[bytesRead], thisLen);
1603 if (result != ICM_20948_Stat_Ok)
1604 {
1605 return result;
1606 }
1607
1608 bytesRead += thisLen;
1609 reg += thisLen;
1610 }
1611
1612 return result;
1613}
1614
1616{
1617 // Set the ODR registers and clear the ODR counter
1618
1619 // In order to set an ODR for a given sensor data, write 2-byte value to DMP using key defined above for a particular sensor.
1620 // Setting value can be calculated as follows:
1621 // Value = (DMP running rate (225Hz) / ODR ) - 1
1622 // E.g. For a 25Hz ODR rate, value= (225/25) -1 = 8.
1623
1624 // During run-time, if an ODR is changed, the corresponding rate counter must be reset.
1625 // To reset, write 2-byte {0,0} to DMP using keys below for a particular sensor:
1626
1629
1630 if (pdev->_dmp_firmware_available == false)
1632
1633 unsigned char odr_reg_val[2];
1634 odr_reg_val[0] = (unsigned char)(interval >> 8);
1635 odr_reg_val[1] = (unsigned char)(interval & 0xff);
1636
1637 unsigned char odr_count_zero[2] = {0x00, 0x00};
1638
1639 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake
1640 if (result != ICM_20948_Stat_Ok)
1641 {
1642 return result;
1643 }
1644
1645 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state
1646 if (result != ICM_20948_Stat_Ok)
1647 {
1648 return result;
1649 }
1650
1651 switch (odr_reg)
1652 {
1654 {
1655 result = inv_icm20948_write_mems(pdev, ODR_CPASS_CALIBR, 2, (const unsigned char *)&odr_reg_val);
1656 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_CPASS_CALIBR, 2, (const unsigned char *)&odr_count_zero);
1657 }
1658 break;
1660 {
1661 result = inv_icm20948_write_mems(pdev, ODR_GYRO_CALIBR, 2, (const unsigned char *)&odr_reg_val);
1662 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_GYRO_CALIBR, 2, (const unsigned char *)&odr_count_zero);
1663 }
1664 break;
1666 {
1667 result = inv_icm20948_write_mems(pdev, ODR_PRESSURE, 2, (const unsigned char *)&odr_reg_val);
1668 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_PRESSURE, 2, (const unsigned char *)&odr_count_zero);
1669 }
1670 break;
1671 case DMP_ODR_Reg_Geomag:
1672 {
1673 result = inv_icm20948_write_mems(pdev, ODR_GEOMAG, 2, (const unsigned char *)&odr_reg_val);
1674 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_GEOMAG, 2, (const unsigned char *)&odr_count_zero);
1675 }
1676 break;
1677 case DMP_ODR_Reg_PQuat6:
1678 {
1679 result = inv_icm20948_write_mems(pdev, ODR_PQUAT6, 2, (const unsigned char *)&odr_reg_val);
1680 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_PQUAT6, 2, (const unsigned char *)&odr_count_zero);
1681 }
1682 break;
1683 case DMP_ODR_Reg_Quat9:
1684 {
1685 result = inv_icm20948_write_mems(pdev, ODR_QUAT9, 2, (const unsigned char *)&odr_reg_val);
1686 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_QUAT9, 2, (const unsigned char *)&odr_count_zero);
1687 }
1688 break;
1689 case DMP_ODR_Reg_Quat6:
1690 {
1691 result = inv_icm20948_write_mems(pdev, ODR_QUAT6, 2, (const unsigned char *)&odr_reg_val);
1692 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_QUAT6, 2, (const unsigned char *)&odr_count_zero);
1693 }
1694 break;
1695 case DMP_ODR_Reg_ALS:
1696 {
1697 result = inv_icm20948_write_mems(pdev, ODR_ALS, 2, (const unsigned char *)&odr_reg_val);
1698 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_ALS, 2, (const unsigned char *)&odr_count_zero);
1699 }
1700 break;
1701 case DMP_ODR_Reg_Cpass:
1702 {
1703 result = inv_icm20948_write_mems(pdev, ODR_CPASS, 2, (const unsigned char *)&odr_reg_val);
1704 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_CPASS, 2, (const unsigned char *)&odr_count_zero);
1705 }
1706 break;
1707 case DMP_ODR_Reg_Gyro:
1708 {
1709 result = inv_icm20948_write_mems(pdev, ODR_GYRO, 2, (const unsigned char *)&odr_reg_val);
1710 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_GYRO, 2, (const unsigned char *)&odr_count_zero);
1711 }
1712 break;
1713 case DMP_ODR_Reg_Accel:
1714 {
1715 result = inv_icm20948_write_mems(pdev, ODR_ACCEL, 2, (const unsigned char *)&odr_reg_val);
1716 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_ACCEL, 2, (const unsigned char *)&odr_count_zero);
1717 }
1718 break;
1719 default:
1721 break;
1722 }
1723
1724 result = ICM_20948_low_power(pdev, true); // Put chip into low power state
1725 if (result != ICM_20948_Stat_Ok)
1726 return result;
1727
1728 if (result2 > result)
1729 result = result2; // Return the highest error
1730
1731 return result;
1732}
1733
1735{
1737
1738 uint16_t inv_event_control = 0; // Use this to store the value for MOTION_EVENT_CTL
1739 uint16_t data_rdy_status = 0; // Use this to store the value for DATA_RDY_STATUS
1740
1741 if (pdev->_dmp_firmware_available == false)
1742 return ICM_20948_Stat_DMPNotSupported; // Bail if DMP is not supported
1743
1744 uint8_t androidSensor = sensor_type_2_android_sensor(sensor); // Convert sensor from enum inv_icm20948_sensor to Android numbering
1745
1746 if (androidSensor >= ANDROID_SENSOR_NUM_MAX)
1747 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported (TO DO: Support B2S etc)
1748
1749 // Convert the Android sensor into a bit mask for DATA_OUT_CTL1
1750 uint16_t delta = inv_androidSensor_to_control_bits[androidSensor];
1751 if (delta == 0xFFFF)
1752 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported
1753
1754 // Convert the Android sensor number into a bitmask and set or clear that bit in _enabled_Android_0 / _enabled_Android_1
1755 unsigned long androidSensorAsBitMask;
1756 if (androidSensor < 32) // Sensors 0-31
1757 {
1758 androidSensorAsBitMask = 1L << androidSensor;
1759 if (state == 0) // Should we disable the sensor?
1760 {
1761 pdev->_enabled_Android_0 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor
1762 }
1763 else
1764 {
1765 pdev->_enabled_Android_0 |= androidSensorAsBitMask; // Set the bit to enable the sensor
1766 }
1767 }
1768 else // Sensors 32-
1769 {
1770 androidSensorAsBitMask = 1L << (androidSensor - 32);
1771 if (state == 0) // Should we disable the sensor?
1772 {
1773 pdev->_enabled_Android_1 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor
1774 }
1775 else
1776 {
1777 pdev->_enabled_Android_1 |= androidSensorAsBitMask; // Set the bit to enable the sensor
1778 }
1779 }
1780
1781 // Now we know androidSensor is valid, reconstruct the value for DATA_OUT_CTL1 from _enabled_Android_0 and _enabled_Android_0
1782 delta = 0; // Clear delta
1783 for (int i = 0; i < 32; i++)
1784 {
1785 androidSensorAsBitMask = 1L << i;
1786 if ((pdev->_enabled_Android_0 & androidSensorAsBitMask) > 0) // Check if the Android sensor (0-31) is enabled
1787 {
1788 delta |= inv_androidSensor_to_control_bits[i]; // If it is, or the required bits into delta
1789 }
1790 if ((pdev->_enabled_Android_1 & androidSensorAsBitMask) > 0) // Check if the Android sensor (32-) is enabled
1791 {
1792 delta |= inv_androidSensor_to_control_bits[i + 32]; // If it is, or the required bits into delta
1793 }
1794 // Also check which bits need to be set in the Data Ready Status and Motion Event Control registers
1795 // Compare to INV_NEEDS_ACCEL_MASK, INV_NEEDS_GYRO_MASK and INV_NEEDS_COMPASS_MASK
1796 if (((androidSensorAsBitMask & INV_NEEDS_ACCEL_MASK) > 0) || ((androidSensorAsBitMask & INV_NEEDS_ACCEL_MASK1) > 0))
1797 {
1798 data_rdy_status |= DMP_Data_ready_Accel;
1799 inv_event_control |= DMP_Motion_Event_Control_Accel_Calibr;
1800 }
1801 if (((androidSensorAsBitMask & INV_NEEDS_GYRO_MASK) > 0) || ((androidSensorAsBitMask & INV_NEEDS_GYRO_MASK1) > 0))
1802 {
1803 data_rdy_status |= DMP_Data_ready_Gyro;
1804 inv_event_control |= DMP_Motion_Event_Control_Gyro_Calibr;
1805 }
1806 if (((androidSensorAsBitMask & INV_NEEDS_COMPASS_MASK) > 0) || ((androidSensorAsBitMask & INV_NEEDS_COMPASS_MASK1) > 0))
1807 {
1808 data_rdy_status |= DMP_Data_ready_Secondary_Compass;
1809 inv_event_control |= DMP_Motion_Event_Control_Compass_Calibr;
1810 }
1811 }
1812
1813 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake
1814 if (result != ICM_20948_Stat_Ok)
1815 {
1816 return result;
1817 }
1818
1819 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state
1820 if (result != ICM_20948_Stat_Ok)
1821 {
1822 return result;
1823 }
1824
1825 // Check if Accel, Gyro/Gyro_Calibr or Compass_Calibr/Quat9/GeoMag/Compass are to be enabled. If they are then we need to request the accuracy data via header2.
1826 uint16_t delta2 = 0;
1827 if ((delta & DMP_Data_Output_Control_1_Accel) > 0)
1828 {
1830 }
1831 if (((delta & DMP_Data_Output_Control_1_Gyro_Calibr) > 0) || ((delta & DMP_Data_Output_Control_1_Gyro) > 0))
1832 {
1834 }
1836 {
1838 }
1839 // TO DO: Add DMP_Data_Output_Control_2_Pickup etc. if required
1840
1841 // Write the sensor control bits into memory address DATA_OUT_CTL1
1842 unsigned char data_output_control_reg[2];
1843 data_output_control_reg[0] = (unsigned char)(delta >> 8);
1844 data_output_control_reg[1] = (unsigned char)(delta & 0xff);
1845 pdev->_dataOutCtl1 = delta; // Diagnostics
1846 result = inv_icm20948_write_mems(pdev, DATA_OUT_CTL1, 2, (const unsigned char *)&data_output_control_reg);
1847 if (result != ICM_20948_Stat_Ok)
1848 {
1849 return result;
1850 }
1851
1852 // Write the 'header2' sensor control bits into memory address DATA_OUT_CTL2
1853 data_output_control_reg[0] = (unsigned char)(delta2 >> 8);
1854 data_output_control_reg[1] = (unsigned char)(delta2 & 0xff);
1855 pdev->_dataOutCtl2 = delta2; // Diagnostics
1856 result = inv_icm20948_write_mems(pdev, DATA_OUT_CTL2, 2, (const unsigned char *)&data_output_control_reg);
1857 if (result != ICM_20948_Stat_Ok)
1858 {
1859 return result;
1860 }
1861
1862 // Set the DATA_RDY_STATUS register
1863 data_output_control_reg[0] = (unsigned char)(data_rdy_status >> 8);
1864 data_output_control_reg[1] = (unsigned char)(data_rdy_status & 0xff);
1865 pdev->_dataRdyStatus = data_rdy_status; // Diagnostics
1866 result = inv_icm20948_write_mems(pdev, DATA_RDY_STATUS, 2, (const unsigned char *)&data_output_control_reg);
1867 if (result != ICM_20948_Stat_Ok)
1868 {
1869 return result;
1870 }
1871
1872 // Check which extra bits need to be set in the Motion Event Control register
1873 if ((delta & DMP_Data_Output_Control_1_Quat9) > 0)
1874 {
1875 inv_event_control |= DMP_Motion_Event_Control_9axis;
1876 }
1878 {
1880 }
1881 if ((delta & DMP_Data_Output_Control_1_Geomag) > 0)
1882 {
1883 inv_event_control |= DMP_Motion_Event_Control_Geomag;
1884 }
1885
1886 // Set the MOTION_EVENT_CTL register
1887 data_output_control_reg[0] = (unsigned char)(inv_event_control >> 8);
1888 data_output_control_reg[1] = (unsigned char)(inv_event_control & 0xff);
1889 pdev->_motionEventCtl = inv_event_control; // Diagnostics
1890 result = inv_icm20948_write_mems(pdev, MOTION_EVENT_CTL, 2, (const unsigned char *)&data_output_control_reg);
1891 if (result != ICM_20948_Stat_Ok)
1892 {
1893 return result;
1894 }
1895
1896 result = ICM_20948_low_power(pdev, true); // Put chip into low power state
1897 if (result != ICM_20948_Stat_Ok)
1898 return result;
1899
1900 return result;
1901}
1902
1904{
1906
1907 if (pdev->_dmp_firmware_available == false)
1908 return ICM_20948_Stat_DMPNotSupported; // Bail if DMP is not supported
1909
1910 uint8_t androidSensor = sensor_type_2_android_sensor(sensor); // Convert sensor from enum inv_icm20948_sensor to Android numbering
1911
1912 if (androidSensor > ANDROID_SENSOR_NUM_MAX)
1913 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported
1914
1915 // Convert the Android sensor into a bit mask for DATA_OUT_CTL1
1916 uint16_t delta = inv_androidSensor_to_control_bits[androidSensor];
1917 if (delta == 0xFFFF)
1918 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported
1919
1920 // Convert the Android sensor number into a bitmask and set or clear that bit in _enabled_Android_intr_0 / _enabled_Android_intr_1
1921 unsigned long androidSensorAsBitMask;
1922 if (androidSensor < 32) // Sensors 0-31
1923 {
1924 androidSensorAsBitMask = 1L << androidSensor;
1925 if (state == 0) // Should we disable the sensor interrupt?
1926 {
1927 pdev->_enabled_Android_intr_0 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor interrupt
1928 }
1929 else
1930 {
1931 pdev->_enabled_Android_intr_0 |= androidSensorAsBitMask; // Set the bit to enable the sensor interrupt
1932 }
1933 }
1934 else // Sensors 32-
1935 {
1936 androidSensorAsBitMask = 1L << (androidSensor - 32);
1937 if (state == 0) // Should we disable the sensor?
1938 {
1939 pdev->_enabled_Android_intr_1 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor interrupt
1940 }
1941 else
1942 {
1943 pdev->_enabled_Android_intr_1 |= androidSensorAsBitMask; // Set the bit to enable the sensor interrupt
1944 }
1945 }
1946
1947 // Now we know androidSensor is valid, reconstruct the value for DATA_INTR_CTL from _enabled_Android_intr_0 and _enabled_Android_intr_0
1948 delta = 0; // Clear delta
1949 for (int i = 0; i < 32; i++)
1950 {
1951 androidSensorAsBitMask = 1L << i;
1952 if ((pdev->_enabled_Android_intr_0 & androidSensorAsBitMask) > 0) // Check if the Android sensor (0-31) interrupt is enabled
1953 {
1954 delta |= inv_androidSensor_to_control_bits[i]; // If it is, or the required bits into delta
1955 }
1956 if ((pdev->_enabled_Android_intr_1 & androidSensorAsBitMask) > 0) // Check if the Android sensor (32-) interrupt is enabled
1957 {
1958 delta |= inv_androidSensor_to_control_bits[i + 32]; // If it is, or the required bits into delta
1959 }
1960 }
1961
1962 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake
1963 if (result != ICM_20948_Stat_Ok)
1964 {
1965 return result;
1966 }
1967
1968 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state
1969 if (result != ICM_20948_Stat_Ok)
1970 {
1971 return result;
1972 }
1973
1974 unsigned char data_intr_ctl[2];
1975
1976 data_intr_ctl[0] = (unsigned char)(delta >> 8);
1977 data_intr_ctl[1] = (unsigned char)(delta & 0xff);
1978 pdev->_dataIntrCtl = delta; // Diagnostics
1979
1980 // Write the interrupt control bits into memory address DATA_INTR_CTL
1981 result = inv_icm20948_write_mems(pdev, DATA_INTR_CTL, 2, (const unsigned char *)&data_intr_ctl);
1982
1983 result = ICM_20948_low_power(pdev, true); // Put chip into low power state
1984 if (result != ICM_20948_Stat_Ok)
1985 return result;
1986
1987 return result;
1988}
1989
1991{
1993 uint8_t fifoBytes[icm_20948_DMP_Maximum_Bytes]; // Interim storage for the FIFO data
1994
1995 if (pdev->_dmp_firmware_available == false)
1997
1998 // Check how much data is in the FIFO
1999 uint16_t fifo_count;
2000 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2001 if (result != ICM_20948_Stat_Ok)
2002 return result;
2003
2004 if (fifo_count < icm_20948_DMP_Header_Bytes) // Has a 2-byte header arrived?
2005 return ICM_20948_Stat_FIFONoDataAvail; // Bail if no header is available
2006
2007 // Read the header (2 bytes)
2008 data->header = 0; // Clear the existing header
2009 uint16_t aShort = 0;
2010 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Header_Bytes);
2011 if (result != ICM_20948_Stat_Ok)
2012 return result;
2013 for (int i = 0; i < icm_20948_DMP_Header_Bytes; i++)
2014 {
2015 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); // MSB first
2016 }
2017 data->header = aShort; // Store the header in data->header
2018 fifo_count -= icm_20948_DMP_Header_Bytes; // Decrement the count
2019
2020 // If the header indicates a header2 is present then read that now
2021 data->header2 = 0; // Clear the existing header2
2022 if ((data->header & DMP_header_bitmap_Header2) > 0) // If the header2 bit is set
2023 {
2024 if (fifo_count < icm_20948_DMP_Header2_Bytes) // Check if we need to read the FIFO count again
2025 {
2026 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2027 if (result != ICM_20948_Stat_Ok)
2028 return result;
2029 }
2030 if (fifo_count < icm_20948_DMP_Header2_Bytes)
2031 return ICM_20948_Stat_FIFOIncompleteData; // Bail if no header2 is available
2032 // Read the header (2 bytes)
2033 aShort = 0;
2034 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Header2_Bytes);
2035 if (result != ICM_20948_Stat_Ok)
2036 return result;
2037 for (int i = 0; i < icm_20948_DMP_Header2_Bytes; i++)
2038 {
2039 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8));
2040 }
2041 data->header2 = aShort; // Store the header2 in data->header2
2042 fifo_count -= icm_20948_DMP_Header2_Bytes; // Decrement the count
2043 }
2044
2045 if ((data->header & DMP_header_bitmap_Accel) > 0) // case DMP_header_bitmap_Accel:
2046 {
2047 if (fifo_count < icm_20948_DMP_Raw_Accel_Bytes) // Check if we need to read the FIFO count again
2048 {
2049 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2050 if (result != ICM_20948_Stat_Ok)
2051 return result;
2052 }
2053 if (fifo_count < icm_20948_DMP_Raw_Accel_Bytes)
2054 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2055 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Raw_Accel_Bytes);
2056 if (result != ICM_20948_Stat_Ok)
2057 return result;
2058 for (int i = 0; i < icm_20948_DMP_Raw_Accel_Bytes; i++)
2059 {
2060 data->Raw_Accel.Bytes[DMP_PQuat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2061 }
2062 fifo_count -= icm_20948_DMP_Raw_Accel_Bytes; // Decrement the count
2063 }
2064
2065 if ((data->header & DMP_header_bitmap_Gyro) > 0) // case DMP_header_bitmap_Gyro:
2066 {
2067 if (fifo_count < (icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes)) // Check if we need to read the FIFO count again
2068 {
2069 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2070 if (result != ICM_20948_Stat_Ok)
2071 return result;
2072 }
2074 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2076 if (result != ICM_20948_Stat_Ok)
2077 return result;
2079 {
2080 data->Raw_Gyro.Bytes[DMP_Raw_Gyro_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2081 }
2082 fifo_count -= (icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes); // Decrement the count
2083 }
2084
2085 if ((data->header & DMP_header_bitmap_Compass) > 0) // case DMP_header_bitmap_Compass:
2086 {
2087 if (fifo_count < icm_20948_DMP_Compass_Bytes) // Check if we need to read the FIFO count again
2088 {
2089 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2090 if (result != ICM_20948_Stat_Ok)
2091 return result;
2092 }
2093 if (fifo_count < icm_20948_DMP_Compass_Bytes)
2094 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2095 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Compass_Bytes);
2096 if (result != ICM_20948_Stat_Ok)
2097 return result;
2098 for (int i = 0; i < icm_20948_DMP_Compass_Bytes; i++)
2099 {
2100 data->Compass.Bytes[DMP_PQuat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2101 }
2102 fifo_count -= icm_20948_DMP_Compass_Bytes; // Decrement the count
2103 }
2104
2105 if ((data->header & DMP_header_bitmap_ALS) > 0) // case DMP_header_bitmap_ALS:
2106 {
2107 if (fifo_count < icm_20948_DMP_ALS_Bytes) // Check if we need to read the FIFO count again
2108 {
2109 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2110 if (result != ICM_20948_Stat_Ok)
2111 return result;
2112 }
2113 if (fifo_count < icm_20948_DMP_ALS_Bytes)
2114 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2115 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_ALS_Bytes);
2116 if (result != ICM_20948_Stat_Ok)
2117 return result;
2118 for (int i = 0; i < icm_20948_DMP_ALS_Bytes; i++)
2119 {
2120 data->ALS[i] = fifoBytes[i];
2121 }
2122 fifo_count -= icm_20948_DMP_ALS_Bytes; // Decrement the count
2123 }
2124
2125 if ((data->header & DMP_header_bitmap_Quat6) > 0) // case DMP_header_bitmap_Quat6:
2126 {
2127 if (fifo_count < icm_20948_DMP_Quat6_Bytes) // Check if we need to read the FIFO count again
2128 {
2129 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2130 if (result != ICM_20948_Stat_Ok)
2131 return result;
2132 }
2133 if (fifo_count < icm_20948_DMP_Quat6_Bytes)
2134 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2135 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Quat6_Bytes);
2136 if (result != ICM_20948_Stat_Ok)
2137 return result;
2138 for (int i = 0; i < icm_20948_DMP_Quat6_Bytes; i++)
2139 {
2140 data->Quat6.Bytes[DMP_Quat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2141 }
2142 fifo_count -= icm_20948_DMP_Quat6_Bytes; // Decrement the count
2143 }
2144
2145 if ((data->header & DMP_header_bitmap_Quat9) > 0) // case DMP_header_bitmap_Quat9:
2146 {
2147 if (fifo_count < icm_20948_DMP_Quat9_Bytes) // Check if we need to read the FIFO count again
2148 {
2149 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2150 if (result != ICM_20948_Stat_Ok)
2151 return result;
2152 }
2153 if (fifo_count < icm_20948_DMP_Quat9_Bytes)
2154 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2155 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Quat9_Bytes);
2156 if (result != ICM_20948_Stat_Ok)
2157 return result;
2158 for (int i = 0; i < icm_20948_DMP_Quat9_Bytes; i++)
2159 {
2160 data->Quat9.Bytes[DMP_Quat9_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2161 }
2162 fifo_count -= icm_20948_DMP_Quat9_Bytes; // Decrement the count
2163 }
2164
2165 if ((data->header & DMP_header_bitmap_PQuat6) > 0) // case DMP_header_bitmap_PQuat6:
2166 {
2167 if (fifo_count < icm_20948_DMP_PQuat6_Bytes) // Check if we need to read the FIFO count again
2168 {
2169 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2170 if (result != ICM_20948_Stat_Ok)
2171 return result;
2172 }
2173 if (fifo_count < icm_20948_DMP_PQuat6_Bytes)
2174 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2175 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_PQuat6_Bytes);
2176 if (result != ICM_20948_Stat_Ok)
2177 return result;
2178 for (int i = 0; i < icm_20948_DMP_PQuat6_Bytes; i++)
2179 {
2180 data->PQuat6.Bytes[DMP_PQuat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2181 }
2182 fifo_count -= icm_20948_DMP_PQuat6_Bytes; // Decrement the count
2183 }
2184
2185 if ((data->header & DMP_header_bitmap_Geomag) > 0) // case DMP_header_bitmap_Geomag:
2186 {
2187 if (fifo_count < icm_20948_DMP_Geomag_Bytes) // Check if we need to read the FIFO count again
2188 {
2189 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2190 if (result != ICM_20948_Stat_Ok)
2191 return result;
2192 }
2193 if (fifo_count < icm_20948_DMP_Geomag_Bytes)
2194 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2195 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Geomag_Bytes);
2196 if (result != ICM_20948_Stat_Ok)
2197 return result;
2198 for (int i = 0; i < icm_20948_DMP_Geomag_Bytes; i++)
2199 {
2200 data->Geomag.Bytes[DMP_Quat9_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2201 }
2202 fifo_count -= icm_20948_DMP_Geomag_Bytes; // Decrement the count
2203 }
2204
2205 if ((data->header & DMP_header_bitmap_Pressure) > 0) // case DMP_header_bitmap_Pressure:
2206 {
2207 if (fifo_count < icm_20948_DMP_Pressure_Bytes) // Check if we need to read the FIFO count again
2208 {
2209 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2210 if (result != ICM_20948_Stat_Ok)
2211 return result;
2212 }
2213 if (fifo_count < icm_20948_DMP_Pressure_Bytes)
2214 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2215 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Pressure_Bytes);
2216 if (result != ICM_20948_Stat_Ok)
2217 return result;
2218 for (int i = 0; i < icm_20948_DMP_Pressure_Bytes; i++)
2219 {
2220 data->Pressure[i] = fifoBytes[i];
2221 }
2222 fifo_count -= icm_20948_DMP_Pressure_Bytes; // Decrement the count
2223 }
2224
2225 if ((data->header & DMP_header_bitmap_Gyro_Calibr) > 0) // case DMP_header_bitmap_Gyro_Calibr:
2226 {
2227 // lcm20948MPUFifoControl.c suggests icm_20948_DMP_Gyro_Calibr_Bytes is not supported
2228 // and looking at DMP frames which have the Gyro_Calibr bit set, that certainly seems to be true.
2229 // So, we'll skip this...:
2230 /*
2231 if (fifo_count < icm_20948_DMP_Gyro_Calibr_Bytes) // Check if we need to read the FIFO count again
2232 {
2233 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2234 if (result != ICM_20948_Stat_Ok)
2235 return result;
2236 }
2237 if (fifo_count < icm_20948_DMP_Gyro_Calibr_Bytes)
2238 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2239 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Gyro_Calibr_Bytes);
2240 if (result != ICM_20948_Stat_Ok)
2241 return result;
2242 for (int i = 0; i < icm_20948_DMP_Gyro_Calibr_Bytes; i++)
2243 {
2244 data->Gyro_Calibr.Bytes[DMP_Quat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2245 }
2246 fifo_count -= icm_20948_DMP_Gyro_Calibr_Bytes; // Decrement the count
2247 */
2248 }
2249
2250 if ((data->header & DMP_header_bitmap_Compass_Calibr) > 0) // case DMP_header_bitmap_Compass_Calibr:
2251 {
2252 if (fifo_count < icm_20948_DMP_Compass_Calibr_Bytes) // Check if we need to read the FIFO count again
2253 {
2254 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2255 if (result != ICM_20948_Stat_Ok)
2256 return result;
2257 }
2258 if (fifo_count < icm_20948_DMP_Compass_Calibr_Bytes)
2259 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2260 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Compass_Calibr_Bytes);
2261 if (result != ICM_20948_Stat_Ok)
2262 return result;
2263 for (int i = 0; i < icm_20948_DMP_Compass_Calibr_Bytes; i++)
2264 {
2265 data->Compass_Calibr.Bytes[DMP_Quat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian)
2266 }
2267 fifo_count -= icm_20948_DMP_Compass_Calibr_Bytes; // Decrement the count
2268 }
2269
2270 if ((data->header & DMP_header_bitmap_Step_Detector) > 0) // case DMP_header_bitmap_Step_Detector:
2271 {
2272 if (fifo_count < icm_20948_DMP_Step_Detector_Bytes) // Check if we need to read the FIFO count again
2273 {
2274 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2275 if (result != ICM_20948_Stat_Ok)
2276 return result;
2277 }
2278 if (fifo_count < icm_20948_DMP_Step_Detector_Bytes)
2279 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2280 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Step_Detector_Bytes);
2281 if (result != ICM_20948_Stat_Ok)
2282 return result;
2283 uint32_t aWord = 0;
2284 for (int i = 0; i < icm_20948_DMP_Step_Detector_Bytes; i++)
2285 {
2286 aWord |= ((uint32_t)fifoBytes[i]) << (24 - (i * 8)); // MSB first
2287 }
2288 data->Pedometer_Timestamp = aWord;
2289 fifo_count -= icm_20948_DMP_Step_Detector_Bytes; // Decrement the count
2290 }
2291
2292 // Now check for header2 features
2293
2294 if ((data->header2 & DMP_header2_bitmap_Accel_Accuracy) > 0) // case DMP_header2_bitmap_Accel_Accuracy:
2295 {
2296 if (fifo_count < icm_20948_DMP_Accel_Accuracy_Bytes) // Check if we need to read the FIFO count again
2297 {
2298 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2299 if (result != ICM_20948_Stat_Ok)
2300 return result;
2301 }
2302 if (fifo_count < icm_20948_DMP_Accel_Accuracy_Bytes)
2303 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2304 aShort = 0;
2305 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Accel_Accuracy_Bytes);
2306 if (result != ICM_20948_Stat_Ok)
2307 return result;
2308 for (int i = 0; i < icm_20948_DMP_Accel_Accuracy_Bytes; i++)
2309 {
2310 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8));
2311 }
2312 data->Accel_Accuracy = aShort;
2313 fifo_count -= icm_20948_DMP_Accel_Accuracy_Bytes; // Decrement the count
2314 }
2315
2316 if ((data->header2 & DMP_header2_bitmap_Gyro_Accuracy) > 0) // case DMP_header2_bitmap_Gyro_Accuracy:
2317 {
2318 if (fifo_count < icm_20948_DMP_Gyro_Accuracy_Bytes) // Check if we need to read the FIFO count again
2319 {
2320 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2321 if (result != ICM_20948_Stat_Ok)
2322 return result;
2323 }
2324 if (fifo_count < icm_20948_DMP_Gyro_Accuracy_Bytes)
2325 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2326 aShort = 0;
2327 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Gyro_Accuracy_Bytes);
2328 if (result != ICM_20948_Stat_Ok)
2329 return result;
2330 for (int i = 0; i < icm_20948_DMP_Gyro_Accuracy_Bytes; i++)
2331 {
2332 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8));
2333 }
2334 data->Gyro_Accuracy = aShort;
2335 fifo_count -= icm_20948_DMP_Gyro_Accuracy_Bytes; // Decrement the count
2336 }
2337
2338 if ((data->header2 & DMP_header2_bitmap_Compass_Accuracy) > 0) // case DMP_header2_bitmap_Compass_Accuracy:
2339 {
2340 if (fifo_count < icm_20948_DMP_Compass_Accuracy_Bytes) // Check if we need to read the FIFO count again
2341 {
2342 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2343 if (result != ICM_20948_Stat_Ok)
2344 return result;
2345 }
2346 if (fifo_count < icm_20948_DMP_Compass_Accuracy_Bytes)
2347 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2348 aShort = 0;
2349 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Compass_Accuracy_Bytes);
2350 if (result != ICM_20948_Stat_Ok)
2351 return result;
2352 for (int i = 0; i < icm_20948_DMP_Compass_Accuracy_Bytes; i++)
2353 {
2354 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8));
2355 }
2356 data->Compass_Accuracy = aShort;
2357 fifo_count -= icm_20948_DMP_Compass_Accuracy_Bytes; // Decrement the count
2358 }
2359
2360 if ((data->header2 & DMP_header2_bitmap_Fsync) > 0) // case DMP_header2_bitmap_Fsync:
2361 {
2362 // lcm20948MPUFifoControl.c suggests icm_20948_DMP_Fsync_Detection_Bytes is not supported.
2363 // So, we'll skip this just in case...:
2364 /*
2365 if (fifo_count < icm_20948_DMP_Fsync_Detection_Bytes) // Check if we need to read the FIFO count again
2366 {
2367 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2368 if (result != ICM_20948_Stat_Ok)
2369 return result;
2370 }
2371 if (fifo_count < icm_20948_DMP_Fsync_Detection_Bytes)
2372 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2373 aShort = 0;
2374 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Fsync_Detection_Bytes);
2375 if (result != ICM_20948_Stat_Ok)
2376 return result;
2377 for (int i = 0; i < icm_20948_DMP_Fsync_Detection_Bytes; i++)
2378 {
2379 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8));
2380 }
2381 data->Fsync_Delay_Time = aShort;
2382 fifo_count -= icm_20948_DMP_Fsync_Detection_Bytes; // Decrement the count
2383 */
2384 }
2385
2386 if ((data->header2 & DMP_header2_bitmap_Pickup) > 0) // case DMP_header2_bitmap_Pickup:
2387 {
2388 if (fifo_count < icm_20948_DMP_Pickup_Bytes) // Check if we need to read the FIFO count again
2389 {
2390 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2391 if (result != ICM_20948_Stat_Ok)
2392 return result;
2393 }
2394 if (fifo_count < icm_20948_DMP_Pickup_Bytes)
2395 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2396 aShort = 0;
2397 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Pickup_Bytes);
2398 if (result != ICM_20948_Stat_Ok)
2399 return result;
2400 for (int i = 0; i < icm_20948_DMP_Pickup_Bytes; i++)
2401 {
2402 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8));
2403 }
2404 data->Pickup = aShort;
2405 fifo_count -= icm_20948_DMP_Pickup_Bytes; // Decrement the count
2406 }
2407
2408 if ((data->header2 & DMP_header2_bitmap_Activity_Recog) > 0) // case DMP_header2_bitmap_Activity_Recog:
2409 {
2410 if (fifo_count < icm_20948_DMP_Activity_Recognition_Bytes) // Check if we need to read the FIFO count again
2411 {
2412 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2413 if (result != ICM_20948_Stat_Ok)
2414 return result;
2415 }
2417 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2419 if (result != ICM_20948_Stat_Ok)
2420 return result;
2421 for (int i = 0; i < icm_20948_DMP_Activity_Recognition_Bytes; i++)
2422 {
2424 }
2425 fifo_count -= icm_20948_DMP_Activity_Recognition_Bytes; // Decrement the count
2426 }
2427
2428 if ((data->header2 & DMP_header2_bitmap_Secondary_On_Off) > 0) // case DMP_header2_bitmap_Secondary_On_Off:
2429 {
2430 if (fifo_count < icm_20948_DMP_Secondary_On_Off_Bytes) // Check if we need to read the FIFO count again
2431 {
2432 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2433 if (result != ICM_20948_Stat_Ok)
2434 return result;
2435 }
2436 if (fifo_count < icm_20948_DMP_Secondary_On_Off_Bytes)
2437 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2438 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Secondary_On_Off_Bytes);
2439 if (result != ICM_20948_Stat_Ok)
2440 return result;
2441 for (int i = 0; i < icm_20948_DMP_Secondary_On_Off_Bytes; i++)
2442 {
2444 }
2445 fifo_count -= icm_20948_DMP_Secondary_On_Off_Bytes; // Decrement the count
2446 }
2447
2448 // Finally, extract the footer (gyro count)
2449 if (fifo_count < icm_20948_DMP_Footer_Bytes) // Check if we need to read the FIFO count again
2450 {
2451 result = ICM_20948_get_FIFO_count(pdev, &fifo_count);
2452 if (result != ICM_20948_Stat_Ok)
2453 return result;
2454 }
2455 if (fifo_count < icm_20948_DMP_Footer_Bytes)
2456 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available
2457 aShort = 0;
2458 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Footer_Bytes);
2459 if (result != ICM_20948_Stat_Ok)
2460 return result;
2461 for (int i = 0; i < icm_20948_DMP_Footer_Bytes; i++)
2462 {
2463 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8));
2464 }
2465 data->Footer = aShort;
2466 fifo_count -= icm_20948_DMP_Footer_Bytes; // Decrement the count
2467
2468 if (fifo_count > 0) // Check if there is still data waiting to be read
2470
2471 return result;
2472}
2473
2475{
2476 switch (sensor)
2477 {
2479 return ANDROID_SENSOR_ACCELEROMETER; // 1
2481 return ANDROID_SENSOR_GYROSCOPE; // 4
2485 return ANDROID_SENSOR_RAW_GYROSCOPE; // 43
2493 return ANDROID_SENSOR_STEP_DETECTOR; // 18
2495 return ANDROID_SENSOR_STEP_COUNTER; // 19
2499 return ANDROID_SENSOR_ROTATION_VECTOR; // 11
2507 return ANDROID_SENSOR_FLIP_PICKUP; // 46
2511 return ANDROID_SENSOR_GRAVITY; // 9
2515 return ANDROID_SENSOR_ORIENTATION; // 3
2517 return ANDROID_SENSOR_B2S; // 45
2518 default:
2520 }
2521}
2522
2524{
2525 switch (sensor)
2526 {
2565 case ANDROID_SENSOR_B2S:
2567 default:
2569 }
2570}
2571
2572ICM_20948_Status_e inv_icm20948_set_gyro_sf(ICM_20948_Device_t *pdev, unsigned char div, int gyro_level)
2573{
2575
2576 if (pdev->_dmp_firmware_available == false)
2578
2579 // gyro_level should be set to 4 regardless of fullscale, due to the addition of API dmp_icm20648_set_gyro_fsr()
2580 gyro_level = 4;
2581
2582 // First read the TIMEBASE_CORRECTION_PLL register from Bank 1
2583 int8_t pll; // Signed. Typical value is 0x18
2584 result = ICM_20948_set_bank(pdev, 1);
2585 result = ICM_20948_execute_r(pdev, AGB1_REG_TIMEBASE_CORRECTION_PLL, (uint8_t *)&pll, 1);
2586 if (result != ICM_20948_Stat_Ok)
2587 {
2588 return result;
2589 }
2590
2591 pdev->_gyroSFpll = pll; // Record the PLL value so we can debug print it
2592
2593 // Now calculate the Gyro SF using code taken from the InvenSense example (inv_icm20948_set_gyro_sf)
2594
2595 long gyro_sf;
2596
2597 unsigned long long const MagicConstant = 264446880937391LL;
2598 unsigned long long const MagicConstantScale = 100000LL;
2599 unsigned long long ResultLL;
2600
2601 if (pll & 0x80)
2602 {
2603 ResultLL = (MagicConstant * (long long)(1ULL << gyro_level) * (1 + div) / (1270 - (pll & 0x7F)) / MagicConstantScale);
2604 }
2605 else
2606 {
2607 ResultLL = (MagicConstant * (long long)(1ULL << gyro_level) * (1 + div) / (1270 + pll) / MagicConstantScale);
2608 }
2609 /*
2610 In above deprecated FP version, worst case arguments can produce a result that overflows a signed long.
2611 Here, for such cases, we emulate the FP behavior of setting the result to the maximum positive value, as
2612 the compiler's conversion of a u64 to an s32 is simple truncation of the u64's high half, sadly....
2613 */
2614 if (ResultLL > 0x7FFFFFFF)
2615 gyro_sf = 0x7FFFFFFF;
2616 else
2617 gyro_sf = (long)ResultLL;
2618
2619 pdev->_gyroSF = gyro_sf; // Record value so we can debug print it
2620
2621 // Finally, write the value to the DMP GYRO_SF register
2622 unsigned char gyro_sf_reg[4];
2623 gyro_sf_reg[0] = (unsigned char)(gyro_sf >> 24);
2624 gyro_sf_reg[1] = (unsigned char)(gyro_sf >> 16);
2625 gyro_sf_reg[2] = (unsigned char)(gyro_sf >> 8);
2626 gyro_sf_reg[3] = (unsigned char)(gyro_sf & 0xff);
2627 result = inv_icm20948_write_mems(pdev, GYRO_SF, 4, (const unsigned char*)&gyro_sf_reg);
2628
2629 return result;
2630}
2631
2632
#define DMP_LOAD_START
ICM_20948_Status_e ICM_20948_reset_DMP(ICM_20948_Device_t *pdev)
ICM_20948_Status_e ICM_20948_i2c_master_reset(ICM_20948_Device_t *pdev)
ICM_20948_Status_e ICM_20948_enable_FIFO(ICM_20948_Device_t *pdev, bool enable)
uint8_t sensor_type_2_android_sensor(enum inv_icm20948_sensor sensor)
ICM_20948_Status_e inv_icm20948_write_mems(ICM_20948_Device_t *pdev, unsigned short reg, unsigned int length, const unsigned char *data)
Write data to a register in DMP memory.
const int DMP_Secondary_On_Off_Byte_Ordering[icm_20948_DMP_Secondary_On_Off_Bytes]
Definition ICM_20948_C.c:44
ICM_20948_Status_e ICM_20948_sleep(ICM_20948_Device_t *pdev, bool on)
ICM_20948_Status_e inv_icm20948_read_dmp_data(ICM_20948_Device_t *pdev, icm_20948_DMP_data_t *data)
ICM_20948_Status_e ICM_20948_wom_threshold(ICM_20948_Device_t *pdev, ICM_20948_ACCEL_WOM_THR_t *write, ICM_20948_ACCEL_WOM_THR_t *read)
ICM_20948_Status_e inv_icm20948_enable_dmp_sensor_int(ICM_20948_Device_t *pdev, enum inv_icm20948_sensor sensor, int state)
ICM_20948_Status_e ICM_20948_set_FIFO_mode(ICM_20948_Device_t *pdev, bool snapshot)
ICM_20948_Status_e inv_icm20948_set_gyro_sf(ICM_20948_Device_t *pdev, unsigned char div, int gyro_level)
ICM_20948_Status_e ICM_20948_set_clock_source(ICM_20948_Device_t *pdev, ICM_20948_PWR_MGMT_1_CLKSEL_e source)
ICM_20948_Status_e ICM_20948_set_sample_rate(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, ICM_20948_smplrt_t smplrt)
const int DMP_Raw_Gyro_Byte_Ordering[icm_20948_DMP_Raw_Gyro_Bytes+icm_20948_DMP_Gyro_Bias_Bytes]
Definition ICM_20948_C.c:38
ICM_20948_Status_e ICM_20948_set_full_scale(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, ICM_20948_fss_t fss)
ICM_20948_Status_e ICM_20948_int_pin_cfg(ICM_20948_Device_t *pdev, ICM_20948_INT_PIN_CFG_t *write, ICM_20948_INT_PIN_CFG_t *read)
ICM_20948_Status_e ICM_20948_get_who_am_i(ICM_20948_Device_t *pdev, uint8_t *whoami)
ICM_20948_Status_e ICM_20948_i2c_controller_periph4_txn(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len, bool Rw, bool send_reg_addr)
ICM_20948_Status_e ICM_20948_int_enable(ICM_20948_Device_t *pdev, ICM_20948_INT_enable_t *write, ICM_20948_INT_enable_t *read)
enum inv_icm20948_sensor inv_icm20948_sensor_android_2_sensor_type(int sensor)
ICM_20948_Status_e ICM_20948_get_agmt(ICM_20948_Device_t *pdev, ICM_20948_AGMT_t *pagmt)
ICM_20948_Status_e ICM_20948_check_id(ICM_20948_Device_t *pdev)
const ICM_20948_Serif_t NullSerif
ICM_20948_Status_e ICM_20948_data_ready(ICM_20948_Device_t *pdev)
ICM_20948_Status_e inv_icm20948_set_dmp_sensor_period(ICM_20948_Device_t *pdev, enum DMP_ODR_Registers odr_reg, uint16_t interval)
ICM_20948_Status_e inv_icm20948_read_mems(ICM_20948_Device_t *pdev, unsigned short reg, unsigned int length, unsigned char *data)
Read data from a register in DMP memory.
const uint16_t inv_androidSensor_to_control_bits[ANDROID_SENSOR_NUM_MAX]
Definition ICM_20948_C.c:48
ICM_20948_Status_e ICM_20948_get_FIFO_count(ICM_20948_Device_t *pdev, uint16_t *count)
ICM_20948_Status_e ICM_20948_set_dmp_start_address(ICM_20948_Device_t *pdev, unsigned short address)
ICM_20948_Status_e ICM_20948_i2c_master_passthrough(ICM_20948_Device_t *pdev, bool passthrough)
ICM_20948_Status_e ICM_20948_read_FIFO(ICM_20948_Device_t *pdev, uint8_t *data, uint8_t len)
ICM_20948_Status_e inv_icm20948_enable_dmp_sensor(ICM_20948_Device_t *pdev, enum inv_icm20948_sensor sensor, int state)
ICM_20948_Status_e ICM_20948_execute_r(ICM_20948_Device_t *pdev, uint8_t regaddr, uint8_t *pdata, uint32_t len)
ICM_20948_Status_e ICM_20948_i2c_controller_configure_peripheral(ICM_20948_Device_t *pdev, uint8_t peripheral, uint8_t addr, uint8_t reg, uint8_t len, bool Rw, bool enable, bool data_only, bool grp, bool swap, uint8_t dataOut)
ICM_20948_Status_e ICM_20948_set_dlpf_cfg(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, ICM_20948_dlpcfg_t cfg)
ICM_20948_Status_e ICM_20948_i2c_master_enable(ICM_20948_Device_t *pdev, bool enable)
const int DMP_PQuat6_Byte_Ordering[icm_20948_DMP_PQuat6_Bytes]
Definition ICM_20948_C.c:34
ICM_20948_Status_e ICM_20948_enable_dlpf(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, bool enable)
ICM_20948_Status_e inv_icm20948_firmware_load(ICM_20948_Device_t *pdev, const unsigned char *data_start, unsigned short size_start, unsigned short load_addr)
Loads the DMP firmware from SRAM.
ICM_20948_Status_e ICM_20948_execute_w(ICM_20948_Device_t *pdev, uint8_t regaddr, uint8_t *pdata, uint32_t len)
ICM_20948_Status_e ICM_20948_sw_reset(ICM_20948_Device_t *pdev)
ICM_20948_Status_e ICM_20948_set_sample_mode(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, ICM_20948_LP_CONFIG_CYCLE_e mode)
ICM_20948_Status_e ICM_20948_firmware_load(ICM_20948_Device_t *pdev)
ICM_20948_Status_e ICM_20948_i2c_master_single_r(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data)
ICM_20948_Status_e ICM_20948_i2c_master_single_w(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data)
const int DMP_Activity_Recognition_Byte_Ordering[icm_20948_DMP_Activity_Recognition_Bytes]
Definition ICM_20948_C.c:41
ICM_20948_Status_e ICM_20948_reset_FIFO(ICM_20948_Device_t *pdev)
const int DMP_Quat9_Byte_Ordering[icm_20948_DMP_Quat9_Bytes]
Definition ICM_20948_C.c:26
ICM_20948_Status_e ICM_20948_init_struct(ICM_20948_Device_t *pdev)
ICM_20948_Status_e ICM_20948_low_power(ICM_20948_Device_t *pdev, bool on)
const int DMP_Quat6_Byte_Ordering[icm_20948_DMP_Quat6_Bytes]
Definition ICM_20948_C.c:30
ICM_20948_Status_e ICM_20948_set_bank(ICM_20948_Device_t *pdev, uint8_t bank)
ICM_20948_Status_e ICM_20948_enable_DMP(ICM_20948_Device_t *pdev, bool enable)
ICM_20948_Status_e ICM_20948_link_serif(ICM_20948_Device_t *pdev, const ICM_20948_Serif_t *s)
ICM_20948_Status_e ICM_20948_wom_logic(ICM_20948_Device_t *pdev, ICM_20948_ACCEL_INTEL_CTRL_t *write, ICM_20948_ACCEL_INTEL_CTRL_t *read)
int memcmp(const void *, const void *, size_t)
#define INV_MAX_SERIAL_WRITE
Max size that can be written across I2C or SPI data lines.
Definition ICM_20948_C.h:47
#define INV_MAX_SERIAL_READ
Max size that can be read across I2C or SPI data lines.
Definition ICM_20948_C.h:45
ICM_20948_InternalSensorID_bm
Definition ICM_20948_C.h:73
@ ICM_20948_Internal_Acc
Definition ICM_20948_C.h:74
@ ICM_20948_Internal_Gyr
Definition ICM_20948_C.h:75
@ ICM_20948_Internal_Mst
Definition ICM_20948_C.h:78
ICM_20948_Status_e
Definition ICM_20948_C.h:50
@ ICM_20948_Stat_InvalDMPRegister
Definition ICM_20948_C.h:66
@ ICM_20948_Stat_NoData
Definition ICM_20948_C.h:57
@ ICM_20948_Stat_ParamErr
Definition ICM_20948_C.h:54
@ ICM_20948_Stat_FIFONoDataAvail
Definition ICM_20948_C.h:61
@ ICM_20948_Stat_FIFOIncompleteData
Definition ICM_20948_C.h:62
@ ICM_20948_Stat_WrongID
Definition ICM_20948_C.h:55
@ ICM_20948_Stat_FIFOMoreDataAvail
Definition ICM_20948_C.h:63
@ ICM_20948_Stat_NotImpl
Definition ICM_20948_C.h:53
@ ICM_20948_Stat_Ok
Definition ICM_20948_C.h:51
@ ICM_20948_Stat_DMPNotSupported
Definition ICM_20948_C.h:59
@ ICM_20948_Stat_DMPVerifyFail
Definition ICM_20948_C.h:60
@ ICM_20948_Stat_Err
Definition ICM_20948_C.h:52
@ ICM_20948_Stat_SensorNotSupported
Definition ICM_20948_C.h:58
#define ICM_20948_WHOAMI
Definition ICM_20948_C.h:38
#define icm_20948_DMP_Gyro_Bias_Bytes
#define icm_20948_DMP_Header2_Bytes
#define ODR_CNTR_ALS
#define INV_NEEDS_GYRO_MASK
#define INV_NEEDS_ACCEL_MASK1
#define DATA_INTR_CTL
#define ODR_PRESSURE
#define icm_20948_DMP_Gyro_Accuracy_Bytes
#define icm_20948_DMP_Secondary_On_Off_Bytes
#define ODR_CNTR_PQUAT6
#define ODR_CPASS_CALIBR
#define icm_20948_DMP_Pickup_Bytes
#define icm_20948_DMP_Pressure_Bytes
@ DMP_Motion_Event_Control_Pedometer_Interrupt
@ DMP_Motion_Event_Control_Compass_Calibr
@ DMP_Motion_Event_Control_Accel_Calibr
@ DMP_Motion_Event_Control_Gyro_Calibr
@ DMP_Motion_Event_Control_9axis
@ DMP_Motion_Event_Control_Geomag
#define ODR_QUAT9
#define icm_20948_DMP_Compass_Bytes
#define ODR_ALS
@ DMP_Data_Output_Control_1_Step_Detector
@ DMP_Data_Output_Control_1_Quat9
@ DMP_Data_Output_Control_1_Accel
@ DMP_Data_Output_Control_1_Compass_Calibr
@ DMP_Data_Output_Control_1_Gyro
@ DMP_Data_Output_Control_1_Compass
@ DMP_Data_Output_Control_1_Step_Ind_0
@ DMP_Data_Output_Control_1_Step_Ind_1
@ DMP_Data_Output_Control_1_Geomag
@ DMP_Data_Output_Control_1_Gyro_Calibr
@ DMP_Data_Output_Control_1_Step_Ind_2
@ DMP_header2_bitmap_Accel_Accuracy
@ DMP_header2_bitmap_Secondary_On_Off
@ DMP_header2_bitmap_Fsync
@ DMP_header2_bitmap_Pickup
@ DMP_header2_bitmap_Gyro_Accuracy
@ DMP_header2_bitmap_Compass_Accuracy
@ DMP_header2_bitmap_Activity_Recog
#define ODR_CNTR_ACCEL
#define DATA_RDY_STATUS
#define icm_20948_DMP_Quat6_Bytes
#define ODR_CNTR_CPASS_CALIBR
#define icm_20948_DMP_Compass_Calibr_Bytes
#define ODR_GYRO
#define MOTION_EVENT_CTL
#define icm_20948_DMP_Accel_Accuracy_Bytes
#define INV_NEEDS_ACCEL_MASK
#define ODR_CNTR_QUAT6
#define ODR_GYRO_CALIBR
#define DATA_OUT_CTL1
#define DATA_OUT_CTL2
#define icm_20948_DMP_Raw_Accel_Bytes
@ DMP_header_bitmap_Header2
@ DMP_header_bitmap_Quat9
@ DMP_header_bitmap_Pressure
@ DMP_header_bitmap_ALS
@ DMP_header_bitmap_Geomag
@ DMP_header_bitmap_Gyro_Calibr
@ DMP_header_bitmap_Step_Detector
@ DMP_header_bitmap_Quat6
@ DMP_header_bitmap_Accel
@ DMP_header_bitmap_Gyro
@ DMP_header_bitmap_Compass
@ DMP_header_bitmap_PQuat6
@ DMP_header_bitmap_Compass_Calibr
#define ODR_CPASS
#define ODR_CNTR_GYRO
#define ODR_CNTR_GEOMAG
#define icm_20948_DMP_Quat9_Bytes
#define ODR_CNTR_CPASS
#define ODR_ACCEL
@ DMP_Data_ready_Gyro
@ DMP_Data_ready_Accel
@ DMP_Data_ready_Secondary_Compass
#define icm_20948_DMP_PQuat6_Bytes
#define icm_20948_DMP_Footer_Bytes
#define INV_NEEDS_GYRO_MASK1
#define ODR_CNTR_GYRO_CALIBR
@ ANDROID_SENSOR_GYROSCOPE
@ ANDROID_SENSOR_LINEAR_ACCELERATION
@ ANDROID_SENSOR_NUM_MAX
@ ANDROID_SENSOR_GRAVITY
@ ANDROID_SENSOR_ACTIVITY_CLASSIFICATON
@ ANDROID_SENSOR_GAME_ROTATION_VECTOR
@ ANDROID_SENSOR_ROTATION_VECTOR
@ ANDROID_SENSOR_RAW_GYROSCOPE
@ ANDROID_SENSOR_MAGNETIC_FIELD_UNCALIBRATED
@ ANDROID_SENSOR_RAW_ACCELEROMETER
@ ANDROID_SENSOR_STEP_DETECTOR
@ ANDROID_SENSOR_B2S
@ ANDROID_SENSOR_GYROSCOPE_UNCALIBRATED
@ ANDROID_SENSOR_ORIENTATION
@ ANDROID_SENSOR_GEOMAGNETIC_FIELD
@ ANDROID_SENSOR_GEOMAGNETIC_ROTATION_VECTOR
@ ANDROID_SENSOR_WAKEUP_SIGNIFICANT_MOTION
@ ANDROID_SENSOR_ACCELEROMETER
@ ANDROID_SENSOR_STEP_COUNTER
@ ANDROID_SENSOR_FLIP_PICKUP
@ ANDROID_SENSOR_WAKEUP_TILT_DETECTOR
#define icm_20948_DMP_Header_Bytes
#define GYRO_SF
DMP_ODR_Registers
@ DMP_ODR_Reg_ALS
@ DMP_ODR_Reg_Pressure
@ DMP_ODR_Reg_Cpass_Calibr
@ DMP_ODR_Reg_Gyro_Calibr
@ DMP_ODR_Reg_Geomag
@ DMP_ODR_Reg_Quat6
@ DMP_ODR_Reg_PQuat6
@ DMP_ODR_Reg_Gyro
@ DMP_ODR_Reg_Accel
@ DMP_ODR_Reg_Cpass
@ DMP_ODR_Reg_Quat9
#define icm_20948_DMP_Maximum_Bytes
#define ODR_CNTR_QUAT9
#define icm_20948_DMP_ALS_Bytes
#define ODR_QUAT6
#define ODR_GEOMAG
#define INV_NEEDS_COMPASS_MASK1
#define icm_20948_DMP_Compass_Accuracy_Bytes
#define icm_20948_DMP_Geomag_Bytes
inv_icm20948_sensor
Sensor identifier for control function.
@ INV_ICM20948_SENSOR_FLIP_PICKUP
@ INV_ICM20948_SENSOR_ORIENTATION
@ INV_ICM20948_SENSOR_ACTIVITY_CLASSIFICATON
@ INV_ICM20948_SENSOR_ACCELEROMETER
@ INV_ICM20948_SENSOR_STEP_COUNTER
@ INV_ICM20948_SENSOR_GEOMAGNETIC_ROTATION_VECTOR
@ INV_ICM20948_SENSOR_GRAVITY
@ INV_ICM20948_SENSOR_GYROSCOPE
@ INV_ICM20948_SENSOR_GYROSCOPE_UNCALIBRATED
@ INV_ICM20948_SENSOR_WAKEUP_TILT_DETECTOR
@ INV_ICM20948_SENSOR_WAKEUP_SIGNIFICANT_MOTION
@ INV_ICM20948_SENSOR_STEP_DETECTOR
@ INV_ICM20948_SENSOR_ROTATION_VECTOR
@ INV_ICM20948_SENSOR_RAW_ACCELEROMETER
@ INV_ICM20948_SENSOR_GEOMAGNETIC_FIELD
@ INV_ICM20948_SENSOR_RAW_GYROSCOPE
@ INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR
@ INV_ICM20948_SENSOR_MAX
@ INV_ICM20948_SENSOR_B2S
@ INV_ICM20948_SENSOR_MAGNETIC_FIELD_UNCALIBRATED
@ INV_ICM20948_SENSOR_LINEAR_ACCELERATION
#define icm_20948_DMP_Raw_Gyro_Bytes
#define ODR_CNTR_PRESSURE
#define icm_20948_DMP_Activity_Recognition_Bytes
#define ODR_PQUAT6
#define INV_NEEDS_COMPASS_MASK
#define icm_20948_DMP_Step_Detector_Bytes
@ DMP_Data_Output_Control_2_Compass_Accuracy
@ DMP_Data_Output_Control_2_Accel_Accuracy
@ DMP_Data_Output_Control_2_Gyro_Accuracy
ICM_20948_PWR_MGMT_1_CLKSEL_e
ICM_20948_LP_CONFIG_CYCLE_e
@ AGB0_REG_FIFO_COUNT_H
@ AGB0_REG_MEM_BANK_SEL
@ AGB0_REG_INT_ENABLE_3
@ AGB3_REG_I2C_PERIPH2_REG
@ AGB3_REG_I2C_PERIPH3_CTRL
@ REG_BANK_SEL
@ AGB0_REG_FIFO_R_W
@ AGB0_REG_INT_ENABLE_2
@ AGB3_REG_I2C_PERIPH4_REG
@ AGB0_REG_MEM_R_W
@ AGB0_REG_INT_STATUS_1
@ AGB0_REG_PWR_MGMT_1
@ AGB3_REG_I2C_PERIPH2_DO
@ AGB0_REG_INT_ENABLE_1
@ AGB3_REG_I2C_PERIPH1_DO
@ AGB0_REG_INT_PIN_CONFIG
@ AGB3_REG_I2C_PERIPH2_ADDR
@ AGB1_REG_TIMEBASE_CORRECTION_PLL
@ AGB3_REG_I2C_PERIPH4_CTRL
@ AGB2_REG_GYRO_SMPLRT_DIV
@ AGB3_REG_I2C_PERIPH4_DO
@ AGB3_REG_I2C_PERIPH1_CTRL
@ AGB3_REG_I2C_PERIPH0_DO
@ AGB3_REG_I2C_PERIPH0_ADDR
@ AGB2_REG_ACCEL_WOM_THR
@ AGB3_REG_I2C_MST_CTRL
@ AGB3_REG_I2C_PERIPH3_ADDR
@ AGB2_REG_PRGM_START_ADDRH
@ AGB3_REG_I2C_PERIPH2_CTRL
@ AGB3_REG_I2C_PERIPH4_ADDR
@ AGB0_REG_FIFO_MODE
@ AGB3_REG_I2C_PERIPH3_DO
@ AGB2_REG_ACCEL_INTEL_CTRL
@ AGB3_REG_I2C_PERIPH1_REG
@ AGB2_REG_ACCEL_SMPLRT_DIV_1
@ AGB0_REG_MEM_START_ADDR
@ AGB0_REG_WHO_AM_I
@ AGB0_REG_INT_ENABLE
@ AGB2_REG_ACCEL_CONFIG_2
@ AGB0_REG_I2C_MST_STATUS
@ AGB0_REG_LP_CONFIG
@ AGB3_REG_I2C_PERIPH3_REG
@ AGB0_REG_FIFO_RST
@ AGB0_REG_USER_CTRL
@ AGB2_REG_ACCEL_SMPLRT_DIV_2
@ AGB3_REG_I2C_PERIPH0_CTRL
@ AGB3_REG_I2C_PERIPH1_ADDR
@ AGB3_REG_I2C_PERIPH4_DI
@ AGB2_REG_ACCEL_CONFIG
@ AGB0_REG_FIFO_COUNT_L
@ AGB2_REG_GYRO_CONFIG_1
@ AGB0_REG_ACCEL_XOUT_H
@ AGB3_REG_I2C_PERIPH0_REG
ICM_20948_axis3named_t acc
ICM_20948_fss_t fss
ICM_20948_axis3named_t mag
union ICM_20948_AGMT_t::@3 tmp
ICM_20948_axis3named_t gyr
uint16_t _dataRdyStatus
uint32_t _enabled_Android_0
uint32_t _enabled_Android_1
uint16_t _motionEventCtl
uint32_t _enabled_Android_intr_1
const ICM_20948_Serif_t * _serif
uint32_t _enabled_Android_intr_0
ICM_20948_Status_e(* read)(uint8_t regaddr, uint8_t *pdata, uint32_t len, void *user)
ICM_20948_Status_e(* write)(uint8_t regaddr, uint8_t *pdata, uint32_t len, void *user)
union icm_20948_DMP_data_t::@6 Compass
union icm_20948_DMP_data_t::@10 Geomag
union icm_20948_DMP_data_t::@5 Raw_Gyro
union icm_20948_DMP_data_t::@12 Compass_Calibr
union icm_20948_DMP_data_t::@14 Secondary_On_Off
union icm_20948_DMP_data_t::@9 PQuat6
uint8_t ALS[icm_20948_DMP_ALS_Bytes]
uint8_t Bytes[icm_20948_DMP_Raw_Accel_Bytes]
union icm_20948_DMP_data_t::@7 Quat6
union icm_20948_DMP_data_t::@4 Raw_Accel
union icm_20948_DMP_data_t::@13 Activity_Recognition
union icm_20948_DMP_data_t::@8 Quat9
struct ICM_20948_INT_ENABLE_2_t::@26 individual
struct ICM_20948_INT_ENABLE_3_t::@28 individual
struct ICM_20948_axis3named_t::@2 axes