Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ICM_20948_C.c
00001 #include "ICM_20948_C.h" 00002 #include "ICM_20948_REGISTERS.h" 00003 #include "AK09916_REGISTERS.h" 00004 00005 /* 00006 * Icm20948 device require a DMP image to be loaded on init 00007 * Provide such images by mean of a byte array 00008 */ 00009 #if defined(ICM_20948_USE_DMP) // Only include the 14301 Bytes of DMP if ICM_20948_USE_DMP is defined 00010 00011 #if defined(ARDUINO_ARCH_MBED) // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM 00012 const uint8_t dmp3_image[] = { 00013 #elif (defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__)) && !defined(__linux__) // Store the DMP firmware in PROGMEM on older AVR (ATmega) platforms 00014 #define ICM_20948_USE_PROGMEM_FOR_DMP 00015 #include <avr/pgmspace.h> 00016 const uint8_t dmp3_image[] PROGMEM = { 00017 #else 00018 const uint8_t dmp3_image[] = { 00019 #endif 00020 00021 #include "icm20948_img.dmp3a.h" 00022 }; 00023 #endif 00024 00025 // ICM-20948 data is big-endian. We need to make it little-endian when writing into icm_20948_DMP_data_t 00026 const int DMP_Quat9_Byte_Ordering[icm_20948_DMP_Quat9_Bytes] = 00027 { 00028 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 13, 12 // Also used for Geomag 00029 }; 00030 const int DMP_Quat6_Byte_Ordering[icm_20948_DMP_Quat6_Bytes] = 00031 { 00032 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8 // Also used for Gyro_Calibr, Compass_Calibr 00033 }; 00034 const int DMP_PQuat6_Byte_Ordering[icm_20948_DMP_PQuat6_Bytes] = 00035 { 00036 1, 0, 3, 2, 5, 4 // Also used for Raw_Accel, Compass 00037 }; 00038 const int DMP_Raw_Gyro_Byte_Ordering[icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes] = 00039 { 00040 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10}; 00041 const int DMP_Activity_Recognition_Byte_Ordering[icm_20948_DMP_Activity_Recognition_Bytes] = 00042 { 00043 0, 1, 5, 4, 3, 2}; 00044 const int DMP_Secondary_On_Off_Byte_Ordering[icm_20948_DMP_Secondary_On_Off_Bytes] = 00045 { 00046 1, 0}; 00047 00048 const uint16_t inv_androidSensor_to_control_bits[ANDROID_SENSOR_NUM_MAX] = 00049 { 00050 // Data output control 1 register bit definition 00051 // 16-bit accel 0x8000 00052 // 16-bit gyro 0x4000 00053 // 16-bit compass 0x2000 00054 // 16-bit ALS 0x1000 00055 // 32-bit 6-axis quaternion 0x0800 00056 // 32-bit 9-axis quaternion + heading accuracy 0x0400 00057 // 16-bit pedometer quaternion 0x0200 00058 // 32-bit Geomag rv + heading accuracy 0x0100 00059 // 16-bit Pressure 0x0080 00060 // 32-bit calibrated gyro 0x0040 00061 // 32-bit calibrated compass 0x0020 00062 // Pedometer Step Detector 0x0010 00063 // Header 2 0x0008 00064 // Pedometer Step Indicator Bit 2 0x0004 00065 // Pedometer Step Indicator Bit 1 0x0002 00066 // Pedometer Step Indicator Bit 0 0x0001 00067 // Unsupported Sensors are 0xFFFF 00068 00069 0xFFFF, // 0 Meta Data 00070 0x8008, // 1 Accelerometer 00071 0x0028, // 2 Magnetic Field 00072 0x0408, // 3 Orientation 00073 0x4048, // 4 Gyroscope 00074 0x1008, // 5 Light 00075 0x0088, // 6 Pressure 00076 0xFFFF, // 7 Temperature 00077 0xFFFF, // 8 Proximity <----------- fixme 00078 0x0808, // 9 Gravity 00079 0x8808, // 10 Linear Acceleration 00080 0x0408, // 11 Rotation Vector 00081 0xFFFF, // 12 Humidity 00082 0xFFFF, // 13 Ambient Temperature 00083 0x2008, // 14 Magnetic Field Uncalibrated 00084 0x0808, // 15 Game Rotation Vector 00085 0x4008, // 16 Gyroscope Uncalibrated 00086 0x0000, // 17 Significant Motion 00087 0x0018, // 18 Step Detector 00088 0x0010, // 19 Step Counter <----------- fixme 00089 0x0108, // 20 Geomagnetic Rotation Vector 00090 0xFFFF, // 21 ANDROID_SENSOR_HEART_RATE, 00091 0xFFFF, // 22 ANDROID_SENSOR_PROXIMITY, 00092 00093 0x8008, // 23 ANDROID_SENSOR_WAKEUP_ACCELEROMETER, 00094 0x0028, // 24 ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD, 00095 0x0408, // 25 ANDROID_SENSOR_WAKEUP_ORIENTATION, 00096 0x4048, // 26 ANDROID_SENSOR_WAKEUP_GYROSCOPE, 00097 0x1008, // 27 ANDROID_SENSOR_WAKEUP_LIGHT, 00098 0x0088, // 28 ANDROID_SENSOR_WAKEUP_PRESSURE, 00099 0x0808, // 29 ANDROID_SENSOR_WAKEUP_GRAVITY, 00100 0x8808, // 30 ANDROID_SENSOR_WAKEUP_LINEAR_ACCELERATION, 00101 0x0408, // 31 ANDROID_SENSOR_WAKEUP_ROTATION_VECTOR, 00102 0xFFFF, // 32 ANDROID_SENSOR_WAKEUP_RELATIVE_HUMIDITY, 00103 0xFFFF, // 33 ANDROID_SENSOR_WAKEUP_AMBIENT_TEMPERATURE, 00104 0x2008, // 34 ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD_UNCALIBRATED, 00105 0x0808, // 35 ANDROID_SENSOR_WAKEUP_GAME_ROTATION_VECTOR, 00106 0x4008, // 36 ANDROID_SENSOR_WAKEUP_GYROSCOPE_UNCALIBRATED, 00107 0x0018, // 37 ANDROID_SENSOR_WAKEUP_STEP_DETECTOR, 00108 0x0010, // 38 ANDROID_SENSOR_WAKEUP_STEP_COUNTER, 00109 0x0108, // 39 ANDROID_SENSOR_WAKEUP_GEOMAGNETIC_ROTATION_VECTOR 00110 0xFFFF, // 40 ANDROID_SENSOR_WAKEUP_HEART_RATE, 00111 0x0000, // 41 ANDROID_SENSOR_WAKEUP_TILT_DETECTOR, 00112 0x8008, // 42 Raw Acc 00113 0x4048, // 43 Raw Gyr 00114 }; 00115 00116 const ICM_20948_Serif_t NullSerif = { 00117 NULL, // write 00118 NULL, // read 00119 NULL, // user 00120 }; 00121 00122 // Private function prototypes 00123 00124 // Function definitions 00125 ICM_20948_Status_e ICM_20948_init_struct(ICM_20948_Device_t *pdev) 00126 { 00127 // Initialize all elements by 0 except for _last_bank 00128 // Initialize _last_bank to 4 (invalid bank number) 00129 // so ICM_20948_set_bank function does not skip issuing bank change operation 00130 static const ICM_20948_Device_t init_device = { ._last_bank = 4 }; 00131 *pdev = init_device; 00132 return ICM_20948_Stat_Ok; 00133 } 00134 00135 ICM_20948_Status_e ICM_20948_link_serif(ICM_20948_Device_t *pdev, const ICM_20948_Serif_t *s) 00136 { 00137 if (s == NULL) 00138 { 00139 return ICM_20948_Stat_ParamErr; 00140 } 00141 if (pdev == NULL) 00142 { 00143 return ICM_20948_Stat_ParamErr; 00144 } 00145 pdev->_serif = s; 00146 return ICM_20948_Stat_Ok; 00147 } 00148 00149 ICM_20948_Status_e ICM_20948_execute_w(ICM_20948_Device_t *pdev, uint8_t regaddr, uint8_t *pdata, uint32_t len) 00150 { 00151 if (pdev->_serif->write == NULL) 00152 { 00153 return ICM_20948_Stat_NotImpl; 00154 } 00155 return (*pdev->_serif->write)(regaddr, pdata, len, pdev->_serif->user); 00156 } 00157 00158 ICM_20948_Status_e ICM_20948_execute_r(ICM_20948_Device_t *pdev, uint8_t regaddr, uint8_t *pdata, uint32_t len) 00159 { 00160 if (pdev->_serif->read == NULL) 00161 { 00162 return ICM_20948_Stat_NotImpl; 00163 } 00164 return (*pdev->_serif->read)(regaddr, pdata, len, pdev->_serif->user); 00165 } 00166 00167 //Transact directly with an I2C device, one byte at a time 00168 //Used to configure a device before it is setup into a normal 0-3 peripheral slot 00169 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) 00170 { 00171 // Thanks MikeFair! // https://github.com/kriswiner/MPU9250/issues/86 00172 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00173 00174 addr = (((Rw) ? 0x80 : 0x00) | addr); 00175 00176 retval = ICM_20948_set_bank(pdev, 3); 00177 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_ADDR, (uint8_t *)&addr, 1); 00178 if (retval != ICM_20948_Stat_Ok) 00179 { 00180 return retval; 00181 } 00182 00183 retval = ICM_20948_set_bank(pdev, 3); 00184 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_REG, (uint8_t *)®, 1); 00185 if (retval != ICM_20948_Stat_Ok) 00186 { 00187 return retval; 00188 } 00189 00190 ICM_20948_I2C_PERIPH4_CTRL_t ctrl; 00191 ctrl.EN = 1; 00192 ctrl.INT_EN = false; 00193 ctrl.DLY = 0; 00194 ctrl.REG_DIS = !send_reg_addr; 00195 00196 ICM_20948_I2C_MST_STATUS_t i2c_mst_status; 00197 bool txn_failed = false; 00198 uint16_t nByte = 0; 00199 00200 while (nByte < len) 00201 { 00202 if (!Rw) 00203 { 00204 retval = ICM_20948_set_bank(pdev, 3); 00205 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_DO, (uint8_t *)&(data[nByte]), 1); 00206 if (retval != ICM_20948_Stat_Ok) 00207 { 00208 return retval; 00209 } 00210 } 00211 00212 // Kick off txn 00213 retval = ICM_20948_set_bank(pdev, 3); 00214 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_PERIPH4_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_PERIPH4_CTRL_t)); 00215 if (retval != ICM_20948_Stat_Ok) 00216 { 00217 return retval; 00218 } 00219 00220 // long tsTimeout = millis() + 3000; // Emergency timeout for txn (hard coded to 3 secs) 00221 uint32_t max_cycles = 1000; 00222 uint32_t count = 0; 00223 bool peripheral4Done = false; 00224 while (!peripheral4Done) 00225 { 00226 retval = ICM_20948_set_bank(pdev, 0); 00227 retval = ICM_20948_execute_r(pdev, AGB0_REG_I2C_MST_STATUS, (uint8_t *)&i2c_mst_status, 1); 00228 00229 peripheral4Done = (i2c_mst_status.I2C_PERIPH4_DONE /*| (millis() > tsTimeout) */); //Avoid forever-loops 00230 peripheral4Done |= (count >= max_cycles); 00231 count++; 00232 } 00233 txn_failed = (i2c_mst_status.I2C_PERIPH4_NACK /*| (millis() > tsTimeout) */); 00234 txn_failed |= (count >= max_cycles); 00235 if (txn_failed) 00236 break; 00237 00238 if (Rw) 00239 { 00240 retval = ICM_20948_set_bank(pdev, 3); 00241 retval = ICM_20948_execute_r(pdev, AGB3_REG_I2C_PERIPH4_DI, &data[nByte], 1); 00242 } 00243 00244 nByte++; 00245 } 00246 00247 if (txn_failed) 00248 { 00249 //We often fail here if mag is stuck 00250 return ICM_20948_Stat_Err; 00251 } 00252 00253 return retval; 00254 } 00255 00256 ICM_20948_Status_e ICM_20948_i2c_master_single_w(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data) 00257 { 00258 return ICM_20948_i2c_controller_periph4_txn(pdev, addr, reg, data, 1, false, true); 00259 } 00260 00261 ICM_20948_Status_e ICM_20948_i2c_master_single_r(ICM_20948_Device_t *pdev, uint8_t addr, uint8_t reg, uint8_t *data) 00262 { 00263 return ICM_20948_i2c_controller_periph4_txn(pdev, addr, reg, data, 1, true, true); 00264 } 00265 00266 ICM_20948_Status_e ICM_20948_set_bank(ICM_20948_Device_t *pdev, uint8_t bank) 00267 { 00268 if (bank > 3) 00269 { 00270 return ICM_20948_Stat_ParamErr; 00271 } // Only 4 possible banks 00272 00273 if (bank == pdev->_last_bank) // Do we need to change bank? 00274 return ICM_20948_Stat_Ok; // Bail if we don't need to change bank to avoid unnecessary bus traffic 00275 00276 pdev->_last_bank = bank; // Store the requested bank (before we bit-shift) 00277 bank = (bank << 4) & 0x30; // bits 5:4 of REG_BANK_SEL 00278 return ICM_20948_execute_w(pdev, REG_BANK_SEL, &bank, 1); 00279 } 00280 00281 ICM_20948_Status_e ICM_20948_sw_reset(ICM_20948_Device_t *pdev) 00282 { 00283 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00284 ICM_20948_PWR_MGMT_1_t reg; 00285 00286 ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00287 00288 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00289 if (retval != ICM_20948_Stat_Ok) 00290 { 00291 return retval; 00292 } 00293 00294 reg.DEVICE_RESET = 1; 00295 00296 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00297 if (retval != ICM_20948_Stat_Ok) 00298 { 00299 return retval; 00300 } 00301 return retval; 00302 } 00303 00304 ICM_20948_Status_e ICM_20948_sleep(ICM_20948_Device_t *pdev, bool on) 00305 { 00306 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00307 ICM_20948_PWR_MGMT_1_t reg; 00308 00309 ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00310 00311 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00312 if (retval != ICM_20948_Stat_Ok) 00313 { 00314 return retval; 00315 } 00316 00317 if (on) 00318 { 00319 reg.SLEEP = 1; 00320 } 00321 else 00322 { 00323 reg.SLEEP = 0; 00324 } 00325 00326 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00327 if (retval != ICM_20948_Stat_Ok) 00328 { 00329 return retval; 00330 } 00331 return retval; 00332 } 00333 00334 ICM_20948_Status_e ICM_20948_low_power(ICM_20948_Device_t *pdev, bool on) 00335 { 00336 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00337 ICM_20948_PWR_MGMT_1_t reg; 00338 00339 ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00340 00341 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00342 if (retval != ICM_20948_Stat_Ok) 00343 { 00344 return retval; 00345 } 00346 00347 if (on) 00348 { 00349 reg.LP_EN = 1; 00350 } 00351 else 00352 { 00353 reg.LP_EN = 0; 00354 } 00355 00356 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00357 if (retval != ICM_20948_Stat_Ok) 00358 { 00359 return retval; 00360 } 00361 return retval; 00362 } 00363 00364 ICM_20948_Status_e ICM_20948_set_clock_source(ICM_20948_Device_t *pdev, ICM_20948_PWR_MGMT_1_CLKSEL_e source) 00365 { 00366 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00367 ICM_20948_PWR_MGMT_1_t reg; 00368 00369 ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00370 00371 retval = ICM_20948_execute_r(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00372 if (retval != ICM_20948_Stat_Ok) 00373 { 00374 return retval; 00375 } 00376 00377 reg.CLKSEL = source; 00378 00379 retval = ICM_20948_execute_w(pdev, AGB0_REG_PWR_MGMT_1, (uint8_t *)®, sizeof(ICM_20948_PWR_MGMT_1_t)); 00380 if (retval != ICM_20948_Stat_Ok) 00381 { 00382 return retval; 00383 } 00384 return retval; 00385 } 00386 00387 ICM_20948_Status_e ICM_20948_get_who_am_i(ICM_20948_Device_t *pdev, uint8_t *whoami) 00388 { 00389 if (whoami == NULL) 00390 { 00391 return ICM_20948_Stat_ParamErr; 00392 } 00393 ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00394 return ICM_20948_execute_r(pdev, AGB0_REG_WHO_AM_I, whoami, 1); 00395 } 00396 00397 ICM_20948_Status_e ICM_20948_check_id(ICM_20948_Device_t *pdev) 00398 { 00399 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00400 uint8_t whoami = 0x00; 00401 retval = ICM_20948_get_who_am_i(pdev, &whoami); 00402 if (retval != ICM_20948_Stat_Ok) 00403 { 00404 return retval; 00405 } 00406 if (whoami != ICM_20948_WHOAMI) 00407 { 00408 return ICM_20948_Stat_WrongID; 00409 } 00410 return retval; 00411 } 00412 00413 ICM_20948_Status_e ICM_20948_data_ready(ICM_20948_Device_t *pdev) 00414 { 00415 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00416 ICM_20948_INT_STATUS_1_t reg; 00417 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00418 if (retval != ICM_20948_Stat_Ok) 00419 { 00420 return retval; 00421 } 00422 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_STATUS_1, (uint8_t *)®, sizeof(ICM_20948_INT_STATUS_1_t)); 00423 if (retval != ICM_20948_Stat_Ok) 00424 { 00425 return retval; 00426 } 00427 if (!reg.RAW_DATA_0_RDY_INT) 00428 { 00429 retval = ICM_20948_Stat_NoData; 00430 } 00431 return retval; 00432 } 00433 00434 // Interrupt Configuration 00435 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) 00436 { 00437 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00438 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00439 if (write != NULL) 00440 { // write first, if available 00441 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)write, sizeof(ICM_20948_INT_PIN_CFG_t)); 00442 if (retval != ICM_20948_Stat_Ok) 00443 { 00444 return retval; 00445 } 00446 } 00447 if (read != NULL) 00448 { // then read, to allow for verification 00449 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)read, sizeof(ICM_20948_INT_PIN_CFG_t)); 00450 if (retval != ICM_20948_Stat_Ok) 00451 { 00452 return retval; 00453 } 00454 } 00455 return retval; 00456 } 00457 00458 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) 00459 { 00460 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00461 00462 ICM_20948_INT_ENABLE_t en_0; 00463 ICM_20948_INT_ENABLE_1_t en_1; 00464 ICM_20948_INT_ENABLE_2_t en_2; 00465 ICM_20948_INT_ENABLE_3_t en_3; 00466 00467 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00468 00469 if (write != NULL) 00470 { // If the write pointer is not NULL then write to the registers BEFORE reading 00471 en_0.I2C_MST_INT_EN = write->I2C_MST_INT_EN; 00472 en_0.DMP_INT1_EN = write->DMP_INT1_EN; 00473 en_0.PLL_READY_EN = write->PLL_RDY_EN; 00474 en_0.WOM_INT_EN = write->WOM_INT_EN; 00475 en_0.reserved_0 = 0; // Clear RAM garbage 00476 en_0.REG_WOF_EN = write->REG_WOF_EN; 00477 en_1.RAW_DATA_0_RDY_EN = write->RAW_DATA_0_RDY_EN; 00478 en_1.reserved_0 = 0; // Clear RAM garbage 00479 en_2.individual.FIFO_OVERFLOW_EN_4 = write->FIFO_OVERFLOW_EN_4; 00480 en_2.individual.FIFO_OVERFLOW_EN_3 = write->FIFO_OVERFLOW_EN_3; 00481 en_2.individual.FIFO_OVERFLOW_EN_2 = write->FIFO_OVERFLOW_EN_2; 00482 en_2.individual.FIFO_OVERFLOW_EN_1 = write->FIFO_OVERFLOW_EN_1; 00483 en_2.individual.FIFO_OVERFLOW_EN_0 = write->FIFO_OVERFLOW_EN_0; 00484 en_2.individual.reserved_0 = 0; // Clear RAM garbage 00485 en_3.individual.FIFO_WM_EN_4 = write->FIFO_WM_EN_4; 00486 en_3.individual.FIFO_WM_EN_3 = write->FIFO_WM_EN_3; 00487 en_3.individual.FIFO_WM_EN_2 = write->FIFO_WM_EN_2; 00488 en_3.individual.FIFO_WM_EN_1 = write->FIFO_WM_EN_1; 00489 en_3.individual.FIFO_WM_EN_0 = write->FIFO_WM_EN_0; 00490 en_3.individual.reserved_0 = 0; // Clear RAM garbage 00491 00492 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE, (uint8_t *)&en_0, sizeof(ICM_20948_INT_ENABLE_t)); 00493 if (retval != ICM_20948_Stat_Ok) 00494 { 00495 return retval; 00496 } 00497 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE_1, (uint8_t *)&en_1, sizeof(ICM_20948_INT_ENABLE_1_t)); 00498 if (retval != ICM_20948_Stat_Ok) 00499 { 00500 return retval; 00501 } 00502 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE_2, (uint8_t *)&en_2, sizeof(ICM_20948_INT_ENABLE_2_t)); 00503 if (retval != ICM_20948_Stat_Ok) 00504 { 00505 return retval; 00506 } 00507 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_ENABLE_3, (uint8_t *)&en_3, sizeof(ICM_20948_INT_ENABLE_3_t)); 00508 if (retval != ICM_20948_Stat_Ok) 00509 { 00510 return retval; 00511 } 00512 } 00513 00514 if (read != NULL) 00515 { // 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) 00516 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE, (uint8_t *)&en_0, sizeof(ICM_20948_INT_ENABLE_t)); 00517 if (retval != ICM_20948_Stat_Ok) 00518 { 00519 return retval; 00520 } 00521 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE_1, (uint8_t *)&en_1, sizeof(ICM_20948_INT_ENABLE_1_t)); 00522 if (retval != ICM_20948_Stat_Ok) 00523 { 00524 return retval; 00525 } 00526 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE_2, (uint8_t *)&en_2, sizeof(ICM_20948_INT_ENABLE_2_t)); 00527 if (retval != ICM_20948_Stat_Ok) 00528 { 00529 return retval; 00530 } 00531 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_ENABLE_3, (uint8_t *)&en_3, sizeof(ICM_20948_INT_ENABLE_3_t)); 00532 if (retval != ICM_20948_Stat_Ok) 00533 { 00534 return retval; 00535 } 00536 00537 read->I2C_MST_INT_EN = en_0.I2C_MST_INT_EN; 00538 read->DMP_INT1_EN = en_0.DMP_INT1_EN; 00539 read->PLL_RDY_EN = en_0.PLL_READY_EN; 00540 read->WOM_INT_EN = en_0.WOM_INT_EN; 00541 read->REG_WOF_EN = en_0.REG_WOF_EN; 00542 read->RAW_DATA_0_RDY_EN = en_1.RAW_DATA_0_RDY_EN; 00543 read->FIFO_OVERFLOW_EN_4 = en_2.individual.FIFO_OVERFLOW_EN_4; 00544 read->FIFO_OVERFLOW_EN_3 = en_2.individual.FIFO_OVERFLOW_EN_3; 00545 read->FIFO_OVERFLOW_EN_2 = en_2.individual.FIFO_OVERFLOW_EN_2; 00546 read->FIFO_OVERFLOW_EN_1 = en_2.individual.FIFO_OVERFLOW_EN_1; 00547 read->FIFO_OVERFLOW_EN_0 = en_2.individual.FIFO_OVERFLOW_EN_0; 00548 read->FIFO_WM_EN_4 = en_3.individual.FIFO_WM_EN_4; 00549 read->FIFO_WM_EN_3 = en_3.individual.FIFO_WM_EN_3; 00550 read->FIFO_WM_EN_2 = en_3.individual.FIFO_WM_EN_2; 00551 read->FIFO_WM_EN_1 = en_3.individual.FIFO_WM_EN_1; 00552 read->FIFO_WM_EN_0 = en_3.individual.FIFO_WM_EN_0; 00553 } 00554 00555 return retval; 00556 } 00557 00558 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) 00559 { 00560 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00561 00562 ICM_20948_ACCEL_WOM_THR_t thr; 00563 00564 retval = ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00565 00566 if (write != NULL) 00567 { // If the write pointer is not NULL then write to the registers BEFORE reading 00568 thr.WOM_THRESHOLD = write->WOM_THRESHOLD; 00569 00570 retval = ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_WOM_THR, (uint8_t *)&thr, sizeof(ICM_20948_ACCEL_WOM_THR_t)); 00571 if (retval != ICM_20948_Stat_Ok) 00572 { 00573 return retval; 00574 } 00575 } 00576 00577 if (read != NULL) 00578 { // 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) 00579 retval = ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_WOM_THR, (uint8_t *)&thr, sizeof(ICM_20948_ACCEL_WOM_THR_t)); 00580 if (retval != ICM_20948_Stat_Ok) 00581 { 00582 return retval; 00583 } 00584 00585 read->WOM_THRESHOLD = thr.WOM_THRESHOLD; 00586 } 00587 00588 return retval; 00589 } 00590 00591 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) 00592 { 00593 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00594 ICM_20948_LP_CONFIG_t reg; 00595 00596 if (!(sensors & (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr | ICM_20948_Internal_Mst))) 00597 { 00598 return ICM_20948_Stat_SensorNotSupported; 00599 } 00600 00601 retval = ICM_20948_set_bank(pdev, 0); // Must be in the right bank 00602 if (retval != ICM_20948_Stat_Ok) 00603 { 00604 return retval; 00605 } 00606 retval = ICM_20948_execute_r(pdev, AGB0_REG_LP_CONFIG, (uint8_t *)®, sizeof(ICM_20948_LP_CONFIG_t)); 00607 if (retval != ICM_20948_Stat_Ok) 00608 { 00609 return retval; 00610 } 00611 00612 if (sensors & ICM_20948_Internal_Acc) 00613 { 00614 reg.ACCEL_CYCLE = mode; 00615 } // Set all desired sensors to this setting 00616 if (sensors & ICM_20948_Internal_Gyr) 00617 { 00618 reg.GYRO_CYCLE = mode; 00619 } 00620 if (sensors & ICM_20948_Internal_Mst) 00621 { 00622 reg.I2C_MST_CYCLE = mode; 00623 } 00624 00625 retval = ICM_20948_execute_w(pdev, AGB0_REG_LP_CONFIG, (uint8_t *)®, sizeof(ICM_20948_LP_CONFIG_t)); 00626 if (retval != ICM_20948_Stat_Ok) 00627 { 00628 return retval; 00629 } 00630 00631 // Check the data was written correctly 00632 retval = ICM_20948_execute_r(pdev, AGB0_REG_LP_CONFIG, (uint8_t *)®, sizeof(ICM_20948_LP_CONFIG_t)); 00633 if (retval != ICM_20948_Stat_Ok) 00634 { 00635 return retval; 00636 } 00637 if (sensors & ICM_20948_Internal_Acc) 00638 { 00639 if (reg.ACCEL_CYCLE != mode) retval = ICM_20948_Stat_Err; 00640 } 00641 if (sensors & ICM_20948_Internal_Gyr) 00642 { 00643 if (reg.GYRO_CYCLE != mode) retval = ICM_20948_Stat_Err; 00644 } 00645 if (sensors & ICM_20948_Internal_Mst) 00646 { 00647 if (reg.I2C_MST_CYCLE != mode) retval = ICM_20948_Stat_Err; 00648 } 00649 00650 return retval; 00651 } 00652 00653 ICM_20948_Status_e ICM_20948_set_full_scale(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, ICM_20948_fss_t fss) 00654 { 00655 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00656 00657 if (!(sensors & (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr))) 00658 { 00659 return ICM_20948_Stat_SensorNotSupported; 00660 } 00661 00662 if (sensors & ICM_20948_Internal_Acc) 00663 { 00664 ICM_20948_ACCEL_CONFIG_t reg; 00665 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00666 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00667 reg.ACCEL_FS_SEL = fss.a; 00668 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00669 // Check the data was written correctly 00670 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00671 if (reg.ACCEL_FS_SEL != fss.a) retval |= ICM_20948_Stat_Err; 00672 } 00673 if (sensors & ICM_20948_Internal_Gyr) 00674 { 00675 ICM_20948_GYRO_CONFIG_1_t reg; 00676 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00677 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00678 reg.GYRO_FS_SEL = fss.g; 00679 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00680 // Check the data was written correctly 00681 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00682 if (reg.GYRO_FS_SEL != fss.g) retval |= ICM_20948_Stat_Err; 00683 } 00684 return retval; 00685 } 00686 00687 ICM_20948_Status_e ICM_20948_set_dlpf_cfg(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, ICM_20948_dlpcfg_t cfg) 00688 { 00689 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00690 00691 if (!(sensors & (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr))) 00692 { 00693 return ICM_20948_Stat_SensorNotSupported; 00694 } 00695 00696 if (sensors & ICM_20948_Internal_Acc) 00697 { 00698 ICM_20948_ACCEL_CONFIG_t reg; 00699 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00700 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00701 reg.ACCEL_DLPFCFG = cfg.a; 00702 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00703 // Check the data was written correctly 00704 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00705 if (reg.ACCEL_DLPFCFG != cfg.a) retval |= ICM_20948_Stat_Err; 00706 } 00707 if (sensors & ICM_20948_Internal_Gyr) 00708 { 00709 ICM_20948_GYRO_CONFIG_1_t reg; 00710 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00711 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00712 reg.GYRO_DLPFCFG = cfg.g; 00713 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00714 // Check the data was written correctly 00715 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00716 if (reg.GYRO_DLPFCFG != cfg.g) retval |= ICM_20948_Stat_Err; 00717 } 00718 return retval; 00719 } 00720 00721 ICM_20948_Status_e ICM_20948_enable_dlpf(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, bool enable) 00722 { 00723 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00724 00725 if (!(sensors & (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr))) 00726 { 00727 return ICM_20948_Stat_SensorNotSupported; 00728 } 00729 00730 if (sensors & ICM_20948_Internal_Acc) 00731 { 00732 ICM_20948_ACCEL_CONFIG_t reg; 00733 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00734 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00735 if (enable) 00736 { 00737 reg.ACCEL_FCHOICE = 1; 00738 } 00739 else 00740 { 00741 reg.ACCEL_FCHOICE = 0; 00742 } 00743 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00744 // Check the data was written correctly 00745 retval |= ICM_20948_execute_r(pdev, AGB2_REG_ACCEL_CONFIG, (uint8_t *)®, sizeof(ICM_20948_ACCEL_CONFIG_t)); 00746 if (enable) 00747 { 00748 if (reg.ACCEL_FCHOICE != 1) retval |= ICM_20948_Stat_Err; 00749 } 00750 else 00751 { 00752 if (reg.ACCEL_FCHOICE != 0) retval |= ICM_20948_Stat_Err; 00753 } 00754 } 00755 if (sensors & ICM_20948_Internal_Gyr) 00756 { 00757 ICM_20948_GYRO_CONFIG_1_t reg; 00758 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00759 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00760 if (enable) 00761 { 00762 reg.GYRO_FCHOICE = 1; 00763 } 00764 else 00765 { 00766 reg.GYRO_FCHOICE = 0; 00767 } 00768 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00769 // Check the data was written correctly 00770 retval |= ICM_20948_execute_r(pdev, AGB2_REG_GYRO_CONFIG_1, (uint8_t *)®, sizeof(ICM_20948_GYRO_CONFIG_1_t)); 00771 if (enable) 00772 { 00773 if (reg.GYRO_FCHOICE != 1) retval |= ICM_20948_Stat_Err; 00774 } 00775 else 00776 { 00777 if (reg.GYRO_FCHOICE != 0) retval |= ICM_20948_Stat_Err; 00778 } 00779 } 00780 return retval; 00781 } 00782 00783 ICM_20948_Status_e ICM_20948_set_sample_rate(ICM_20948_Device_t *pdev, ICM_20948_InternalSensorID_bm sensors, ICM_20948_smplrt_t smplrt) 00784 { 00785 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00786 00787 if (!(sensors & (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr))) 00788 { 00789 return ICM_20948_Stat_SensorNotSupported; 00790 } 00791 00792 if (sensors & ICM_20948_Internal_Acc) 00793 { 00794 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00795 uint8_t div1 = (smplrt.a << 8); 00796 uint8_t div2 = (smplrt.a & 0xFF); 00797 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_SMPLRT_DIV_1, &div1, 1); 00798 retval |= ICM_20948_execute_w(pdev, AGB2_REG_ACCEL_SMPLRT_DIV_2, &div2, 1); 00799 } 00800 if (sensors & ICM_20948_Internal_Gyr) 00801 { 00802 retval |= ICM_20948_set_bank(pdev, 2); // Must be in the right bank 00803 uint8_t div = (smplrt.g); 00804 retval |= ICM_20948_execute_w(pdev, AGB2_REG_GYRO_SMPLRT_DIV, &div, 1); 00805 } 00806 return retval; 00807 } 00808 00809 // Interface Things 00810 ICM_20948_Status_e ICM_20948_i2c_master_passthrough(ICM_20948_Device_t *pdev, bool passthrough) 00811 { 00812 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00813 00814 ICM_20948_INT_PIN_CFG_t reg; 00815 retval = ICM_20948_set_bank(pdev, 0); 00816 if (retval != ICM_20948_Stat_Ok) 00817 { 00818 return retval; 00819 } 00820 retval = ICM_20948_execute_r(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)®, sizeof(ICM_20948_INT_PIN_CFG_t)); 00821 if (retval != ICM_20948_Stat_Ok) 00822 { 00823 return retval; 00824 } 00825 reg.BYPASS_EN = passthrough; 00826 retval = ICM_20948_execute_w(pdev, AGB0_REG_INT_PIN_CONFIG, (uint8_t *)®, sizeof(ICM_20948_INT_PIN_CFG_t)); 00827 if (retval != ICM_20948_Stat_Ok) 00828 { 00829 return retval; 00830 } 00831 00832 return retval; 00833 } 00834 00835 ICM_20948_Status_e ICM_20948_i2c_master_enable(ICM_20948_Device_t *pdev, bool enable) 00836 { 00837 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00838 00839 // Disable BYPASS_EN 00840 retval = ICM_20948_i2c_master_passthrough(pdev, false); 00841 if (retval != ICM_20948_Stat_Ok) 00842 { 00843 return retval; 00844 } 00845 00846 ICM_20948_I2C_MST_CTRL_t ctrl; 00847 retval = ICM_20948_set_bank(pdev, 3); 00848 if (retval != ICM_20948_Stat_Ok) 00849 { 00850 return retval; 00851 } 00852 retval = ICM_20948_execute_r(pdev, AGB3_REG_I2C_MST_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_MST_CTRL_t)); 00853 if (retval != ICM_20948_Stat_Ok) 00854 { 00855 return retval; 00856 } 00857 ctrl.I2C_MST_CLK = 0x07; // corresponds to 345.6 kHz, good for up to 400 kHz 00858 ctrl.I2C_MST_P_NSR = 1; 00859 retval = ICM_20948_execute_w(pdev, AGB3_REG_I2C_MST_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_MST_CTRL_t)); 00860 if (retval != ICM_20948_Stat_Ok) 00861 { 00862 return retval; 00863 } 00864 00865 ICM_20948_USER_CTRL_t reg; 00866 retval = ICM_20948_set_bank(pdev, 0); 00867 if (retval != ICM_20948_Stat_Ok) 00868 { 00869 return retval; 00870 } 00871 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)®, sizeof(ICM_20948_USER_CTRL_t)); 00872 if (retval != ICM_20948_Stat_Ok) 00873 { 00874 return retval; 00875 } 00876 if (enable) 00877 { 00878 reg.I2C_MST_EN = 1; 00879 } 00880 else 00881 { 00882 reg.I2C_MST_EN = 0; 00883 } 00884 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)®, sizeof(ICM_20948_USER_CTRL_t)); 00885 if (retval != ICM_20948_Stat_Ok) 00886 { 00887 return retval; 00888 } 00889 00890 return retval; 00891 } 00892 00893 ICM_20948_Status_e ICM_20948_i2c_master_reset(ICM_20948_Device_t *pdev) 00894 { 00895 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00896 00897 ICM_20948_USER_CTRL_t ctrl; 00898 retval = ICM_20948_set_bank(pdev, 0); 00899 if (retval != ICM_20948_Stat_Ok) 00900 { 00901 return retval; 00902 } 00903 00904 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 00905 if (retval != ICM_20948_Stat_Ok) 00906 { 00907 return retval; 00908 } 00909 00910 ctrl.I2C_MST_RST = 1; //Reset! 00911 00912 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 00913 if (retval != ICM_20948_Stat_Ok) 00914 { 00915 return retval; 00916 } 00917 return retval; 00918 } 00919 00920 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) 00921 { 00922 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 00923 00924 uint8_t periph_addr_reg; 00925 uint8_t periph_reg_reg; 00926 uint8_t periph_ctrl_reg; 00927 uint8_t periph_do_reg; 00928 00929 switch (peripheral) 00930 { 00931 case 0: 00932 periph_addr_reg = AGB3_REG_I2C_PERIPH0_ADDR; 00933 periph_reg_reg = AGB3_REG_I2C_PERIPH0_REG; 00934 periph_ctrl_reg = AGB3_REG_I2C_PERIPH0_CTRL; 00935 periph_do_reg = AGB3_REG_I2C_PERIPH0_DO; 00936 break; 00937 case 1: 00938 periph_addr_reg = AGB3_REG_I2C_PERIPH1_ADDR; 00939 periph_reg_reg = AGB3_REG_I2C_PERIPH1_REG; 00940 periph_ctrl_reg = AGB3_REG_I2C_PERIPH1_CTRL; 00941 periph_do_reg = AGB3_REG_I2C_PERIPH1_DO; 00942 break; 00943 case 2: 00944 periph_addr_reg = AGB3_REG_I2C_PERIPH2_ADDR; 00945 periph_reg_reg = AGB3_REG_I2C_PERIPH2_REG; 00946 periph_ctrl_reg = AGB3_REG_I2C_PERIPH2_CTRL; 00947 periph_do_reg = AGB3_REG_I2C_PERIPH2_DO; 00948 break; 00949 case 3: 00950 periph_addr_reg = AGB3_REG_I2C_PERIPH3_ADDR; 00951 periph_reg_reg = AGB3_REG_I2C_PERIPH3_REG; 00952 periph_ctrl_reg = AGB3_REG_I2C_PERIPH3_CTRL; 00953 periph_do_reg = AGB3_REG_I2C_PERIPH3_DO; 00954 break; 00955 default: 00956 return ICM_20948_Stat_ParamErr; 00957 } 00958 00959 retval = ICM_20948_set_bank(pdev, 3); 00960 if (retval != ICM_20948_Stat_Ok) 00961 { 00962 return retval; 00963 } 00964 00965 // Set the peripheral address and the Rw flag 00966 ICM_20948_I2C_PERIPHX_ADDR_t address; 00967 address.ID = addr; 00968 if (Rw) 00969 { 00970 address.RNW = 1; 00971 } 00972 else 00973 { 00974 address.RNW = 0; // Make sure bit is clear (just in case there is any garbage in that RAM location) 00975 } 00976 retval = ICM_20948_execute_w(pdev, periph_addr_reg, (uint8_t *)&address, sizeof(ICM_20948_I2C_PERIPHX_ADDR_t)); 00977 if (retval != ICM_20948_Stat_Ok) 00978 { 00979 return retval; 00980 } 00981 00982 // If we are setting up a write, configure the Data Out register too 00983 if (!Rw) 00984 { 00985 ICM_20948_I2C_PERIPHX_DO_t dataOutByte; 00986 dataOutByte.DO = dataOut; 00987 retval = ICM_20948_execute_w(pdev, periph_do_reg, (uint8_t *)&dataOutByte, sizeof(ICM_20948_I2C_PERIPHX_DO_t)); 00988 if (retval != ICM_20948_Stat_Ok) 00989 { 00990 return retval; 00991 } 00992 } 00993 00994 // Set the peripheral sub-address (register address) 00995 ICM_20948_I2C_PERIPHX_REG_t subaddress; 00996 subaddress.REG = reg; 00997 retval = ICM_20948_execute_w(pdev, periph_reg_reg, (uint8_t *)&subaddress, sizeof(ICM_20948_I2C_PERIPHX_REG_t)); 00998 if (retval != ICM_20948_Stat_Ok) 00999 { 01000 return retval; 01001 } 01002 01003 // Set up the control info 01004 ICM_20948_I2C_PERIPHX_CTRL_t ctrl; 01005 ctrl.LENG = len; 01006 ctrl.EN = enable; 01007 ctrl.REG_DIS = data_only; 01008 ctrl.GRP = grp; 01009 ctrl.BYTE_SW = swap; 01010 retval = ICM_20948_execute_w(pdev, periph_ctrl_reg, (uint8_t *)&ctrl, sizeof(ICM_20948_I2C_PERIPHX_CTRL_t)); 01011 if (retval != ICM_20948_Stat_Ok) 01012 { 01013 return retval; 01014 } 01015 01016 return retval; 01017 } 01018 01019 // Higher Level 01020 ICM_20948_Status_e ICM_20948_get_agmt(ICM_20948_Device_t *pdev, ICM_20948_AGMT_t *pagmt) 01021 { 01022 if (pagmt == NULL) 01023 { 01024 return ICM_20948_Stat_ParamErr; 01025 } 01026 01027 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01028 const uint8_t numbytes = 14 + 9; //Read Accel, gyro, temp, and 9 bytes of mag 01029 uint8_t buff[numbytes]; 01030 01031 // Get readings 01032 retval |= ICM_20948_set_bank(pdev, 0); 01033 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB0_REG_ACCEL_XOUT_H, buff, numbytes); 01034 01035 pagmt->acc.axes.x = ((buff[0] << 8) | (buff[1] & 0xFF)); 01036 pagmt->acc.axes.y = ((buff[2] << 8) | (buff[3] & 0xFF)); 01037 pagmt->acc.axes.z = ((buff[4] << 8) | (buff[5] & 0xFF)); 01038 01039 pagmt->gyr.axes.x = ((buff[6] << 8) | (buff[7] & 0xFF)); 01040 pagmt->gyr.axes.y = ((buff[8] << 8) | (buff[9] & 0xFF)); 01041 pagmt->gyr.axes.z = ((buff[10] << 8) | (buff[11] & 0xFF)); 01042 01043 pagmt->tmp.val = ((buff[12] << 8) | (buff[13] & 0xFF)); 01044 01045 pagmt->magStat1 = buff[14]; 01046 pagmt->mag.axes.x = ((buff[16] << 8) | (buff[15] & 0xFF)); //Mag data is read little endian 01047 pagmt->mag.axes.y = ((buff[18] << 8) | (buff[17] & 0xFF)); 01048 pagmt->mag.axes.z = ((buff[20] << 8) | (buff[19] & 0xFF)); 01049 pagmt->magStat2 = buff[22]; 01050 01051 // Get settings to be able to compute scaled values 01052 retval |= ICM_20948_set_bank(pdev, 2); 01053 ICM_20948_ACCEL_CONFIG_t acfg; 01054 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB2_REG_ACCEL_CONFIG, (uint8_t *)&acfg, 1 * sizeof(acfg)); 01055 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 01056 // 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... 01057 retval |= ICM_20948_set_bank(pdev, 2); 01058 ICM_20948_GYRO_CONFIG_1_t gcfg1; 01059 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB2_REG_GYRO_CONFIG_1, (uint8_t *)&gcfg1, 1 * sizeof(gcfg1)); 01060 pagmt->fss.g = gcfg1.GYRO_FS_SEL; 01061 ICM_20948_ACCEL_CONFIG_2_t acfg2; 01062 retval |= ICM_20948_execute_r(pdev, (uint8_t)AGB2_REG_ACCEL_CONFIG_2, (uint8_t *)&acfg2, 1 * sizeof(acfg2)); 01063 01064 return retval; 01065 } 01066 01067 // FIFO 01068 01069 ICM_20948_Status_e ICM_20948_enable_FIFO(ICM_20948_Device_t *pdev, bool enable) 01070 { 01071 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01072 01073 ICM_20948_USER_CTRL_t ctrl; 01074 retval = ICM_20948_set_bank(pdev, 0); 01075 if (retval != ICM_20948_Stat_Ok) 01076 { 01077 return retval; 01078 } 01079 01080 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 01081 if (retval != ICM_20948_Stat_Ok) 01082 { 01083 return retval; 01084 } 01085 01086 if (enable) 01087 ctrl.FIFO_EN = 1; 01088 else 01089 ctrl.FIFO_EN = 0; 01090 01091 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 01092 if (retval != ICM_20948_Stat_Ok) 01093 { 01094 return retval; 01095 } 01096 return retval; 01097 } 01098 01099 ICM_20948_Status_e ICM_20948_reset_FIFO(ICM_20948_Device_t *pdev) 01100 { 01101 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01102 01103 ICM_20948_FIFO_RST_t ctrl; 01104 retval = ICM_20948_set_bank(pdev, 0); 01105 if (retval != ICM_20948_Stat_Ok) 01106 { 01107 return retval; 01108 } 01109 01110 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_RST, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_RST_t)); 01111 if (retval != ICM_20948_Stat_Ok) 01112 { 01113 return retval; 01114 } 01115 01116 ctrl.FIFO_RESET = 0x1F; // Datasheet says "FIFO_RESET[4:0]" 01117 01118 retval = ICM_20948_execute_w(pdev, AGB0_REG_FIFO_RST, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_RST_t)); 01119 if (retval != ICM_20948_Stat_Ok) 01120 { 01121 return retval; 01122 } 01123 01124 //delay ??? 01125 01126 ctrl.FIFO_RESET = 0x1E; // The InvenSense Nucleo examples write 0x1F followed by 0x1E 01127 01128 retval = ICM_20948_execute_w(pdev, AGB0_REG_FIFO_RST, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_RST_t)); 01129 if (retval != ICM_20948_Stat_Ok) 01130 { 01131 return retval; 01132 } 01133 01134 return retval; 01135 } 01136 01137 ICM_20948_Status_e ICM_20948_set_FIFO_mode(ICM_20948_Device_t *pdev, bool snapshot) 01138 { 01139 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01140 01141 ICM_20948_FIFO_MODE_t ctrl; 01142 retval = ICM_20948_set_bank(pdev, 0); 01143 if (retval != ICM_20948_Stat_Ok) 01144 { 01145 return retval; 01146 } 01147 01148 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_MODE, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_MODE_t)); 01149 if (retval != ICM_20948_Stat_Ok) 01150 { 01151 return retval; 01152 } 01153 01154 if (snapshot) 01155 ctrl.FIFO_MODE = 0x1F; // Datasheet says "FIFO_MODE[4:0]" 01156 else 01157 ctrl.FIFO_MODE = 0; 01158 01159 retval = ICM_20948_execute_w(pdev, AGB0_REG_FIFO_MODE, (uint8_t *)&ctrl, sizeof(ICM_20948_FIFO_MODE_t)); 01160 if (retval != ICM_20948_Stat_Ok) 01161 { 01162 return retval; 01163 } 01164 return retval; 01165 } 01166 01167 ICM_20948_Status_e ICM_20948_get_FIFO_count(ICM_20948_Device_t *pdev, uint16_t *count) 01168 { 01169 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01170 01171 ICM_20948_FIFO_COUNTH_t ctrlh; 01172 ICM_20948_FIFO_COUNTL_t ctrll; 01173 retval = ICM_20948_set_bank(pdev, 0); 01174 if (retval != ICM_20948_Stat_Ok) 01175 { 01176 return retval; 01177 } 01178 01179 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_COUNT_H, (uint8_t *)&ctrlh, sizeof(ICM_20948_FIFO_COUNTH_t)); 01180 if (retval != ICM_20948_Stat_Ok) 01181 { 01182 return retval; 01183 } 01184 01185 ctrlh.FIFO_COUNTH &= 0x1F; // Datasheet says "FIFO_CNT[12:8]" 01186 01187 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_COUNT_L, (uint8_t *)&ctrll, sizeof(ICM_20948_FIFO_COUNTL_t)); 01188 if (retval != ICM_20948_Stat_Ok) 01189 { 01190 return retval; 01191 } 01192 01193 *count = (((uint16_t)ctrlh.FIFO_COUNTH) << 8) | (uint16_t)ctrll.FIFO_COUNTL; 01194 01195 return retval; 01196 } 01197 01198 ICM_20948_Status_e ICM_20948_read_FIFO(ICM_20948_Device_t *pdev, uint8_t *data, uint8_t len) 01199 { 01200 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01201 01202 retval = ICM_20948_set_bank(pdev, 0); 01203 if (retval != ICM_20948_Stat_Ok) 01204 { 01205 return retval; 01206 } 01207 01208 retval = ICM_20948_execute_r(pdev, AGB0_REG_FIFO_R_W, data, len); 01209 if (retval != ICM_20948_Stat_Ok) 01210 { 01211 return retval; 01212 } 01213 01214 return retval; 01215 } 01216 01217 // DMP 01218 01219 ICM_20948_Status_e ICM_20948_enable_DMP(ICM_20948_Device_t *pdev, bool enable) 01220 { 01221 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01222 01223 ICM_20948_USER_CTRL_t ctrl; 01224 retval = ICM_20948_set_bank(pdev, 0); 01225 if (retval != ICM_20948_Stat_Ok) 01226 { 01227 return retval; 01228 } 01229 01230 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 01231 if (retval != ICM_20948_Stat_Ok) 01232 { 01233 return retval; 01234 } 01235 01236 if (enable) 01237 ctrl.DMP_EN = 1; 01238 else 01239 ctrl.DMP_EN = 0; 01240 01241 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 01242 if (retval != ICM_20948_Stat_Ok) 01243 { 01244 return retval; 01245 } 01246 return retval; 01247 } 01248 01249 ICM_20948_Status_e ICM_20948_reset_DMP(ICM_20948_Device_t *pdev) 01250 { 01251 ICM_20948_Status_e retval = ICM_20948_Stat_Ok; 01252 01253 ICM_20948_USER_CTRL_t ctrl; 01254 retval = ICM_20948_set_bank(pdev, 0); 01255 if (retval != ICM_20948_Stat_Ok) 01256 { 01257 return retval; 01258 } 01259 01260 retval = ICM_20948_execute_r(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 01261 if (retval != ICM_20948_Stat_Ok) 01262 { 01263 return retval; 01264 } 01265 01266 ctrl.DMP_RST = 1; 01267 01268 retval = ICM_20948_execute_w(pdev, AGB0_REG_USER_CTRL, (uint8_t *)&ctrl, sizeof(ICM_20948_USER_CTRL_t)); 01269 if (retval != ICM_20948_Stat_Ok) 01270 { 01271 return retval; 01272 } 01273 return retval; 01274 } 01275 01276 ICM_20948_Status_e ICM_20948_firmware_load(ICM_20948_Device_t *pdev) 01277 { 01278 #if defined(ICM_20948_USE_DMP) 01279 return (inv_icm20948_firmware_load(pdev, dmp3_image, sizeof(dmp3_image), DMP_LOAD_START)); 01280 #else 01281 return ICM_20948_Stat_DMPNotSupported; 01282 #endif 01283 } 01284 01285 /** @brief Loads the DMP firmware from SRAM 01286 * @param[in] data pointer where the image 01287 * @param[in] size size if the image 01288 * @param[in] load_addr address to loading the image 01289 * @return 0 in case of success, -1 for any error 01290 */ 01291 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) 01292 { 01293 int write_size; 01294 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01295 unsigned short memaddr; 01296 const unsigned char *data; 01297 unsigned short size; 01298 unsigned char data_cmp[INV_MAX_SERIAL_READ]; 01299 int flag = 0; 01300 01301 if (pdev->_dmp_firmware_available == false) 01302 return ICM_20948_Stat_DMPNotSupported; 01303 01304 if (pdev->_firmware_loaded) 01305 return ICM_20948_Stat_Ok; // Bail with no error if firmware is already loaded 01306 01307 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake 01308 if (result != ICM_20948_Stat_Ok) 01309 { 01310 return result; 01311 } 01312 01313 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state 01314 if (result != ICM_20948_Stat_Ok) 01315 { 01316 return result; 01317 } 01318 01319 // Write DMP memory 01320 01321 data = data_start; 01322 size = size_start; 01323 memaddr = load_addr; 01324 #ifdef ICM_20948_USE_PROGMEM_FOR_DMP 01325 unsigned char data_not_pg[INV_MAX_SERIAL_READ]; // Suggested by @HyperKokichi in Issue #63 01326 #endif 01327 while (size > 0) 01328 { 01329 //write_size = min(size, INV_MAX_SERIAL_WRITE); // Write in chunks of INV_MAX_SERIAL_WRITE 01330 if (size <= INV_MAX_SERIAL_WRITE) // Write in chunks of INV_MAX_SERIAL_WRITE 01331 write_size = size; 01332 else 01333 write_size = INV_MAX_SERIAL_WRITE; 01334 if ((memaddr & 0xff) + write_size > 0x100) 01335 { 01336 // Moved across a bank 01337 write_size = (memaddr & 0xff) + write_size - 0x100; 01338 } 01339 #ifdef ICM_20948_USE_PROGMEM_FOR_DMP 01340 memcpy_P(data_not_pg, data, write_size); // Suggested by @HyperKokichi in Issue #63 01341 result = inv_icm20948_write_mems(pdev, memaddr, write_size, (unsigned char *)data_not_pg); 01342 #else 01343 result = inv_icm20948_write_mems(pdev, memaddr, write_size, (unsigned char *)data); 01344 #endif 01345 if (result != ICM_20948_Stat_Ok) 01346 return result; 01347 data += write_size; 01348 size -= write_size; 01349 memaddr += write_size; 01350 } 01351 01352 // Verify DMP memory 01353 01354 data = data_start; 01355 size = size_start; 01356 memaddr = load_addr; 01357 while (size > 0) 01358 { 01359 //write_size = min(size, INV_MAX_SERIAL_READ); // Read in chunks of INV_MAX_SERIAL_READ 01360 if (size <= INV_MAX_SERIAL_READ) // Read in chunks of INV_MAX_SERIAL_READ 01361 write_size = size; 01362 else 01363 write_size = INV_MAX_SERIAL_READ; 01364 if ((memaddr & 0xff) + write_size > 0x100) 01365 { 01366 // Moved across a bank 01367 write_size = (memaddr & 0xff) + write_size - 0x100; 01368 } 01369 result = inv_icm20948_read_mems(pdev, memaddr, write_size, data_cmp); 01370 if (result != ICM_20948_Stat_Ok) 01371 flag++; // Error, DMP not written correctly 01372 #ifdef ICM_20948_USE_PROGMEM_FOR_DMP 01373 memcpy_P(data_not_pg, data, write_size); // Suggested by @HyperKokichi in Issue #63 01374 if (memcmp(data_cmp, data_not_pg, write_size)) 01375 #else 01376 if (memcmp(data_cmp, data, write_size)) // Compare the data 01377 #endif 01378 return ICM_20948_Stat_DMPVerifyFail; 01379 data += write_size; 01380 size -= write_size; 01381 memaddr += write_size; 01382 } 01383 01384 //Enable LP_EN since we disabled it at begining of this function. 01385 result = ICM_20948_low_power(pdev, true); // Put chip into low power state 01386 if (result != ICM_20948_Stat_Ok) 01387 return result; 01388 01389 if (!flag) 01390 { 01391 //Serial.println("DMP Firmware was updated successfully.."); 01392 pdev->_firmware_loaded = true; 01393 } 01394 01395 return result; 01396 } 01397 01398 ICM_20948_Status_e ICM_20948_set_dmp_start_address(ICM_20948_Device_t *pdev, unsigned short address) 01399 { 01400 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01401 01402 if (pdev->_dmp_firmware_available == false) 01403 return ICM_20948_Stat_DMPNotSupported; 01404 01405 unsigned char start_address[2]; 01406 01407 start_address[0] = (unsigned char)(address >> 8); 01408 start_address[1] = (unsigned char)(address & 0xff); 01409 01410 // result = ICM_20948_sleep(pdev, false); // Make sure chip is awake 01411 // if (result != ICM_20948_Stat_Ok) 01412 // { 01413 // return result; 01414 // } 01415 // 01416 // result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state 01417 // if (result != ICM_20948_Stat_Ok) 01418 // { 01419 // return result; 01420 // } 01421 01422 result = ICM_20948_set_bank(pdev, 2); // Set bank 2 01423 if (result != ICM_20948_Stat_Ok) 01424 { 01425 return result; 01426 } 01427 01428 // Write the sensor control bits into memory address AGB2_REG_PRGM_START_ADDRH 01429 result = ICM_20948_execute_w(pdev, AGB2_REG_PRGM_START_ADDRH, (uint8_t *)start_address, 2); 01430 01431 return result; 01432 } 01433 01434 /** 01435 * @brief Write data to a register in DMP memory 01436 * @param[in] DMP memory address 01437 * @param[in] number of byte to be written 01438 * @param[out] output data from the register 01439 * @return 0 if successful. 01440 */ 01441 ICM_20948_Status_e inv_icm20948_write_mems(ICM_20948_Device_t *pdev, unsigned short reg, unsigned int length, const unsigned char *data) 01442 { 01443 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01444 unsigned int bytesWritten = 0; 01445 unsigned int thisLen; 01446 unsigned char lBankSelected; 01447 unsigned char lStartAddrSelected; 01448 01449 if (!data) 01450 { 01451 return ICM_20948_Stat_NoData; 01452 } 01453 01454 result = ICM_20948_set_bank(pdev, 0); // Set bank 0 01455 if (result != ICM_20948_Stat_Ok) 01456 { 01457 return result; 01458 } 01459 01460 lBankSelected = (reg >> 8); 01461 01462 if (lBankSelected != pdev->_last_mems_bank) 01463 { 01464 pdev->_last_mems_bank = lBankSelected; 01465 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_BANK_SEL, &lBankSelected, 1); 01466 if (result != ICM_20948_Stat_Ok) 01467 { 01468 return result; 01469 } 01470 } 01471 01472 while (bytesWritten < length) 01473 { 01474 lStartAddrSelected = (reg & 0xff); 01475 01476 /* Sets the starting read or write address for the selected memory, inside of the selected page (see MEM_SEL Register). 01477 Contents are changed after read or write of the selected memory. 01478 This register must be written prior to each access to initialize the register to the proper starting address. 01479 The address will auto increment during burst transactions. Two consecutive bursts without re-initializing the start address would skip one address. */ 01480 01481 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_START_ADDR, &lStartAddrSelected, 1); 01482 if (result != ICM_20948_Stat_Ok) 01483 { 01484 return result; 01485 } 01486 01487 if (length - bytesWritten <= INV_MAX_SERIAL_WRITE) 01488 thisLen = length - bytesWritten; 01489 else 01490 thisLen = INV_MAX_SERIAL_WRITE; 01491 01492 /* Write data */ 01493 01494 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_R_W, (uint8_t *)&data[bytesWritten], thisLen); 01495 if (result != ICM_20948_Stat_Ok) 01496 { 01497 return result; 01498 } 01499 01500 bytesWritten += thisLen; 01501 reg += thisLen; 01502 } 01503 01504 return result; 01505 } 01506 01507 /** 01508 * @brief Read data from a register in DMP memory 01509 * @param[in] DMP memory address 01510 * @param[in] number of byte to be read 01511 * @param[in] input data from the register 01512 * @return 0 if successful. 01513 */ 01514 ICM_20948_Status_e inv_icm20948_read_mems(ICM_20948_Device_t *pdev, unsigned short reg, unsigned int length, unsigned char *data) 01515 { 01516 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01517 unsigned int bytesRead = 0; 01518 unsigned int thisLen; 01519 unsigned char lBankSelected; 01520 unsigned char lStartAddrSelected; 01521 01522 if (!data) 01523 { 01524 return ICM_20948_Stat_NoData; 01525 } 01526 01527 result = ICM_20948_set_bank(pdev, 0); // Set bank 0 01528 if (result != ICM_20948_Stat_Ok) 01529 { 01530 return result; 01531 } 01532 01533 lBankSelected = (reg >> 8); 01534 01535 if (lBankSelected != pdev->_last_mems_bank) 01536 { 01537 pdev->_last_mems_bank = lBankSelected; 01538 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_BANK_SEL, &lBankSelected, 1); 01539 if (result != ICM_20948_Stat_Ok) 01540 { 01541 return result; 01542 } 01543 } 01544 01545 while (bytesRead < length) 01546 { 01547 lStartAddrSelected = (reg & 0xff); 01548 01549 /* Sets the starting read or write address for the selected memory, inside of the selected page (see MEM_SEL Register). 01550 Contents are changed after read or write of the selected memory. 01551 This register must be written prior to each access to initialize the register to the proper starting address. 01552 The address will auto increment during burst transactions. Two consecutive bursts without re-initializing the start address would skip one address. */ 01553 01554 result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_START_ADDR, &lStartAddrSelected, 1); 01555 if (result != ICM_20948_Stat_Ok) 01556 { 01557 return result; 01558 } 01559 01560 if (length - bytesRead <= INV_MAX_SERIAL_READ) 01561 thisLen = length - bytesRead; 01562 else 01563 thisLen = INV_MAX_SERIAL_READ; 01564 01565 /* Read data */ 01566 01567 result = ICM_20948_execute_r(pdev, AGB0_REG_MEM_R_W, &data[bytesRead], thisLen); 01568 if (result != ICM_20948_Stat_Ok) 01569 { 01570 return result; 01571 } 01572 01573 bytesRead += thisLen; 01574 reg += thisLen; 01575 } 01576 01577 return result; 01578 } 01579 01580 ICM_20948_Status_e inv_icm20948_set_dmp_sensor_period(ICM_20948_Device_t *pdev, enum DMP_ODR_Registers odr_reg, uint16_t interval) 01581 { 01582 // Set the ODR registers and clear the ODR counter 01583 01584 // 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. 01585 // Setting value can be calculated as follows: 01586 // Value = (DMP running rate (225Hz) / ODR ) - 1 01587 // E.g. For a 25Hz ODR rate, value= (225/25) -1 = 8. 01588 01589 // During run-time, if an ODR is changed, the corresponding rate counter must be reset. 01590 // To reset, write 2-byte {0,0} to DMP using keys below for a particular sensor: 01591 01592 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01593 ICM_20948_Status_e result2 = ICM_20948_Stat_Ok; 01594 01595 if (pdev->_dmp_firmware_available == false) 01596 return ICM_20948_Stat_DMPNotSupported; 01597 01598 unsigned char odr_reg_val[2]; 01599 odr_reg_val[0] = (unsigned char)(interval >> 8); 01600 odr_reg_val[1] = (unsigned char)(interval & 0xff); 01601 01602 unsigned char odr_count_zero[2] = {0x00, 0x00}; 01603 01604 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake 01605 if (result != ICM_20948_Stat_Ok) 01606 { 01607 return result; 01608 } 01609 01610 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state 01611 if (result != ICM_20948_Stat_Ok) 01612 { 01613 return result; 01614 } 01615 01616 switch (odr_reg) 01617 { 01618 case DMP_ODR_Reg_Cpass_Calibr: 01619 { 01620 result = inv_icm20948_write_mems(pdev, ODR_CPASS_CALIBR, 2, (const unsigned char *)&odr_reg_val); 01621 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_CPASS_CALIBR, 2, (const unsigned char *)&odr_count_zero); 01622 } 01623 break; 01624 case DMP_ODR_Reg_Gyro_Calibr: 01625 { 01626 result = inv_icm20948_write_mems(pdev, ODR_GYRO_CALIBR, 2, (const unsigned char *)&odr_reg_val); 01627 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_GYRO_CALIBR, 2, (const unsigned char *)&odr_count_zero); 01628 } 01629 break; 01630 case DMP_ODR_Reg_Pressure: 01631 { 01632 result = inv_icm20948_write_mems(pdev, ODR_PRESSURE, 2, (const unsigned char *)&odr_reg_val); 01633 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_PRESSURE, 2, (const unsigned char *)&odr_count_zero); 01634 } 01635 break; 01636 case DMP_ODR_Reg_Geomag: 01637 { 01638 result = inv_icm20948_write_mems(pdev, ODR_GEOMAG, 2, (const unsigned char *)&odr_reg_val); 01639 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_GEOMAG, 2, (const unsigned char *)&odr_count_zero); 01640 } 01641 break; 01642 case DMP_ODR_Reg_PQuat6: 01643 { 01644 result = inv_icm20948_write_mems(pdev, ODR_PQUAT6, 2, (const unsigned char *)&odr_reg_val); 01645 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_PQUAT6, 2, (const unsigned char *)&odr_count_zero); 01646 } 01647 break; 01648 case DMP_ODR_Reg_Quat9: 01649 { 01650 result = inv_icm20948_write_mems(pdev, ODR_QUAT9, 2, (const unsigned char *)&odr_reg_val); 01651 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_QUAT9, 2, (const unsigned char *)&odr_count_zero); 01652 } 01653 break; 01654 case DMP_ODR_Reg_Quat6: 01655 { 01656 result = inv_icm20948_write_mems(pdev, ODR_QUAT6, 2, (const unsigned char *)&odr_reg_val); 01657 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_QUAT6, 2, (const unsigned char *)&odr_count_zero); 01658 } 01659 break; 01660 case DMP_ODR_Reg_ALS: 01661 { 01662 result = inv_icm20948_write_mems(pdev, ODR_ALS, 2, (const unsigned char *)&odr_reg_val); 01663 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_ALS, 2, (const unsigned char *)&odr_count_zero); 01664 } 01665 break; 01666 case DMP_ODR_Reg_Cpass: 01667 { 01668 result = inv_icm20948_write_mems(pdev, ODR_CPASS, 2, (const unsigned char *)&odr_reg_val); 01669 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_CPASS, 2, (const unsigned char *)&odr_count_zero); 01670 } 01671 break; 01672 case DMP_ODR_Reg_Gyro: 01673 { 01674 result = inv_icm20948_write_mems(pdev, ODR_GYRO, 2, (const unsigned char *)&odr_reg_val); 01675 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_GYRO, 2, (const unsigned char *)&odr_count_zero); 01676 } 01677 break; 01678 case DMP_ODR_Reg_Accel: 01679 { 01680 result = inv_icm20948_write_mems(pdev, ODR_ACCEL, 2, (const unsigned char *)&odr_reg_val); 01681 result2 = inv_icm20948_write_mems(pdev, ODR_CNTR_ACCEL, 2, (const unsigned char *)&odr_count_zero); 01682 } 01683 break; 01684 default: 01685 result = ICM_20948_Stat_InvalDMPRegister; 01686 break; 01687 } 01688 01689 result = ICM_20948_low_power(pdev, true); // Put chip into low power state 01690 if (result != ICM_20948_Stat_Ok) 01691 return result; 01692 01693 if (result2 > result) 01694 result = result2; // Return the highest error 01695 01696 return result; 01697 } 01698 01699 ICM_20948_Status_e inv_icm20948_enable_dmp_sensor(ICM_20948_Device_t *pdev, enum inv_icm20948_sensor sensor, int state) 01700 { 01701 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01702 01703 uint16_t inv_event_control = 0; // Use this to store the value for MOTION_EVENT_CTL 01704 uint16_t data_rdy_status = 0; // Use this to store the value for DATA_RDY_STATUS 01705 01706 if (pdev->_dmp_firmware_available == false) 01707 return ICM_20948_Stat_DMPNotSupported; // Bail if DMP is not supported 01708 01709 uint8_t androidSensor = sensor_type_2_android_sensor(sensor); // Convert sensor from enum inv_icm20948_sensor to Android numbering 01710 01711 if (androidSensor >= ANDROID_SENSOR_NUM_MAX) 01712 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported (TO DO: Support B2S etc) 01713 01714 // Convert the Android sensor into a bit mask for DATA_OUT_CTL1 01715 uint16_t delta = inv_androidSensor_to_control_bits[androidSensor]; 01716 if (delta == 0xFFFF) 01717 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported 01718 01719 // Convert the Android sensor number into a bitmask and set or clear that bit in _enabled_Android_0 / _enabled_Android_1 01720 unsigned long androidSensorAsBitMask; 01721 if (androidSensor < 32) // Sensors 0-31 01722 { 01723 androidSensorAsBitMask = 1L << androidSensor; 01724 if (state == 0) // Should we disable the sensor? 01725 { 01726 pdev->_enabled_Android_0 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor 01727 } 01728 else 01729 { 01730 pdev->_enabled_Android_0 |= androidSensorAsBitMask; // Set the bit to enable the sensor 01731 } 01732 } 01733 else // Sensors 32- 01734 { 01735 androidSensorAsBitMask = 1L << (androidSensor - 32); 01736 if (state == 0) // Should we disable the sensor? 01737 { 01738 pdev->_enabled_Android_1 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor 01739 } 01740 else 01741 { 01742 pdev->_enabled_Android_1 |= androidSensorAsBitMask; // Set the bit to enable the sensor 01743 } 01744 } 01745 01746 // Now we know androidSensor is valid, reconstruct the value for DATA_OUT_CTL1 from _enabled_Android_0 and _enabled_Android_0 01747 delta = 0; // Clear delta 01748 for (int i = 0; i < 32; i++) 01749 { 01750 androidSensorAsBitMask = 1L << i; 01751 if ((pdev->_enabled_Android_0 & androidSensorAsBitMask) > 0) // Check if the Android sensor (0-31) is enabled 01752 { 01753 delta |= inv_androidSensor_to_control_bits[i]; // If it is, or the required bits into delta 01754 } 01755 if ((pdev->_enabled_Android_1 & androidSensorAsBitMask) > 0) // Check if the Android sensor (32-) is enabled 01756 { 01757 delta |= inv_androidSensor_to_control_bits[i + 32]; // If it is, or the required bits into delta 01758 } 01759 // Also check which bits need to be set in the Data Ready Status and Motion Event Control registers 01760 // Compare to INV_NEEDS_ACCEL_MASK, INV_NEEDS_GYRO_MASK and INV_NEEDS_COMPASS_MASK 01761 if (((androidSensorAsBitMask & INV_NEEDS_ACCEL_MASK) > 0) || ((androidSensorAsBitMask & INV_NEEDS_ACCEL_MASK1) > 0)) 01762 { 01763 data_rdy_status |= DMP_Data_ready_Accel; 01764 inv_event_control |= DMP_Motion_Event_Control_Accel_Calibr; 01765 } 01766 if (((androidSensorAsBitMask & INV_NEEDS_GYRO_MASK) > 0) || ((androidSensorAsBitMask & INV_NEEDS_GYRO_MASK1) > 0)) 01767 { 01768 data_rdy_status |= DMP_Data_ready_Gyro; 01769 inv_event_control |= DMP_Motion_Event_Control_Gyro_Calibr; 01770 } 01771 if (((androidSensorAsBitMask & INV_NEEDS_COMPASS_MASK) > 0) || ((androidSensorAsBitMask & INV_NEEDS_COMPASS_MASK1) > 0)) 01772 { 01773 data_rdy_status |= DMP_Data_ready_Secondary_Compass; 01774 inv_event_control |= DMP_Motion_Event_Control_Compass_Calibr; 01775 } 01776 } 01777 01778 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake 01779 if (result != ICM_20948_Stat_Ok) 01780 { 01781 return result; 01782 } 01783 01784 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state 01785 if (result != ICM_20948_Stat_Ok) 01786 { 01787 return result; 01788 } 01789 01790 // 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. 01791 uint16_t delta2 = 0; 01792 if ((delta & DMP_Data_Output_Control_1_Accel) > 0) 01793 { 01794 delta2 |= DMP_Data_Output_Control_2_Accel_Accuracy; 01795 } 01796 if (((delta & DMP_Data_Output_Control_1_Gyro_Calibr) > 0) || ((delta & DMP_Data_Output_Control_1_Gyro) > 0)) 01797 { 01798 delta2 |= DMP_Data_Output_Control_2_Gyro_Accuracy; 01799 } 01800 if (((delta & DMP_Data_Output_Control_1_Compass_Calibr) > 0) || ((delta & DMP_Data_Output_Control_1_Compass) > 0) || ((delta & DMP_Data_Output_Control_1_Quat9) > 0) || ((delta & DMP_Data_Output_Control_1_Geomag) > 0)) 01801 { 01802 delta2 |= DMP_Data_Output_Control_2_Compass_Accuracy; 01803 } 01804 // TO DO: Add DMP_Data_Output_Control_2_Pickup etc. if required 01805 01806 // Write the sensor control bits into memory address DATA_OUT_CTL1 01807 unsigned char data_output_control_reg[2]; 01808 data_output_control_reg[0] = (unsigned char)(delta >> 8); 01809 data_output_control_reg[1] = (unsigned char)(delta & 0xff); 01810 pdev->_dataOutCtl1 = delta; // Diagnostics 01811 result = inv_icm20948_write_mems(pdev, DATA_OUT_CTL1, 2, (const unsigned char *)&data_output_control_reg); 01812 if (result != ICM_20948_Stat_Ok) 01813 { 01814 return result; 01815 } 01816 01817 // Write the 'header2' sensor control bits into memory address DATA_OUT_CTL2 01818 data_output_control_reg[0] = (unsigned char)(delta2 >> 8); 01819 data_output_control_reg[1] = (unsigned char)(delta2 & 0xff); 01820 pdev->_dataOutCtl2 = delta2; // Diagnostics 01821 result = inv_icm20948_write_mems(pdev, DATA_OUT_CTL2, 2, (const unsigned char *)&data_output_control_reg); 01822 if (result != ICM_20948_Stat_Ok) 01823 { 01824 return result; 01825 } 01826 01827 // Set the DATA_RDY_STATUS register 01828 data_output_control_reg[0] = (unsigned char)(data_rdy_status >> 8); 01829 data_output_control_reg[1] = (unsigned char)(data_rdy_status & 0xff); 01830 pdev->_dataRdyStatus = data_rdy_status; // Diagnostics 01831 result = inv_icm20948_write_mems(pdev, DATA_RDY_STATUS, 2, (const unsigned char *)&data_output_control_reg); 01832 if (result != ICM_20948_Stat_Ok) 01833 { 01834 return result; 01835 } 01836 01837 // Check which extra bits need to be set in the Motion Event Control register 01838 if ((delta & DMP_Data_Output_Control_1_Quat9) > 0) 01839 { 01840 inv_event_control |= DMP_Motion_Event_Control_9axis; 01841 } 01842 if (((delta & DMP_Data_Output_Control_1_Step_Detector) > 0) || ((delta & DMP_Data_Output_Control_1_Step_Ind_0) > 0) || ((delta & DMP_Data_Output_Control_1_Step_Ind_1) > 0) || ((delta & DMP_Data_Output_Control_1_Step_Ind_2) > 0)) 01843 { 01844 inv_event_control |= DMP_Motion_Event_Control_Pedometer_Interrupt; 01845 } 01846 if ((delta & DMP_Data_Output_Control_1_Geomag) > 0) 01847 { 01848 inv_event_control |= DMP_Motion_Event_Control_Geomag; 01849 } 01850 01851 // Set the MOTION_EVENT_CTL register 01852 data_output_control_reg[0] = (unsigned char)(inv_event_control >> 8); 01853 data_output_control_reg[1] = (unsigned char)(inv_event_control & 0xff); 01854 pdev->_motionEventCtl = inv_event_control; // Diagnostics 01855 result = inv_icm20948_write_mems(pdev, MOTION_EVENT_CTL, 2, (const unsigned char *)&data_output_control_reg); 01856 if (result != ICM_20948_Stat_Ok) 01857 { 01858 return result; 01859 } 01860 01861 result = ICM_20948_low_power(pdev, true); // Put chip into low power state 01862 if (result != ICM_20948_Stat_Ok) 01863 return result; 01864 01865 return result; 01866 } 01867 01868 ICM_20948_Status_e inv_icm20948_enable_dmp_sensor_int(ICM_20948_Device_t *pdev, enum inv_icm20948_sensor sensor, int state) 01869 { 01870 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01871 01872 if (pdev->_dmp_firmware_available == false) 01873 return ICM_20948_Stat_DMPNotSupported; // Bail if DMP is not supported 01874 01875 uint8_t androidSensor = sensor_type_2_android_sensor(sensor); // Convert sensor from enum inv_icm20948_sensor to Android numbering 01876 01877 if (androidSensor > ANDROID_SENSOR_NUM_MAX) 01878 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported 01879 01880 // Convert the Android sensor into a bit mask for DATA_OUT_CTL1 01881 uint16_t delta = inv_androidSensor_to_control_bits[androidSensor]; 01882 if (delta == 0xFFFF) 01883 return ICM_20948_Stat_SensorNotSupported; // Bail if the sensor is not supported 01884 01885 // Convert the Android sensor number into a bitmask and set or clear that bit in _enabled_Android_intr_0 / _enabled_Android_intr_1 01886 unsigned long androidSensorAsBitMask; 01887 if (androidSensor < 32) // Sensors 0-31 01888 { 01889 androidSensorAsBitMask = 1L << androidSensor; 01890 if (state == 0) // Should we disable the sensor interrupt? 01891 { 01892 pdev->_enabled_Android_intr_0 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor interrupt 01893 } 01894 else 01895 { 01896 pdev->_enabled_Android_intr_0 |= androidSensorAsBitMask; // Set the bit to enable the sensor interrupt 01897 } 01898 } 01899 else // Sensors 32- 01900 { 01901 androidSensorAsBitMask = 1L << (androidSensor - 32); 01902 if (state == 0) // Should we disable the sensor? 01903 { 01904 pdev->_enabled_Android_intr_1 &= ~androidSensorAsBitMask; // Clear the bit to disable the sensor interrupt 01905 } 01906 else 01907 { 01908 pdev->_enabled_Android_intr_1 |= androidSensorAsBitMask; // Set the bit to enable the sensor interrupt 01909 } 01910 } 01911 01912 // Now we know androidSensor is valid, reconstruct the value for DATA_INTR_CTL from _enabled_Android_intr_0 and _enabled_Android_intr_0 01913 delta = 0; // Clear delta 01914 for (int i = 0; i < 32; i++) 01915 { 01916 androidSensorAsBitMask = 1L << i; 01917 if ((pdev->_enabled_Android_intr_0 & androidSensorAsBitMask) > 0) // Check if the Android sensor (0-31) interrupt is enabled 01918 { 01919 delta |= inv_androidSensor_to_control_bits[i]; // If it is, or the required bits into delta 01920 } 01921 if ((pdev->_enabled_Android_intr_1 & androidSensorAsBitMask) > 0) // Check if the Android sensor (32-) interrupt is enabled 01922 { 01923 delta |= inv_androidSensor_to_control_bits[i + 32]; // If it is, or the required bits into delta 01924 } 01925 } 01926 01927 result = ICM_20948_sleep(pdev, false); // Make sure chip is awake 01928 if (result != ICM_20948_Stat_Ok) 01929 { 01930 return result; 01931 } 01932 01933 result = ICM_20948_low_power(pdev, false); // Make sure chip is not in low power state 01934 if (result != ICM_20948_Stat_Ok) 01935 { 01936 return result; 01937 } 01938 01939 unsigned char data_intr_ctl[2]; 01940 01941 data_intr_ctl[0] = (unsigned char)(delta >> 8); 01942 data_intr_ctl[1] = (unsigned char)(delta & 0xff); 01943 pdev->_dataIntrCtl = delta; // Diagnostics 01944 01945 // Write the interrupt control bits into memory address DATA_INTR_CTL 01946 result = inv_icm20948_write_mems(pdev, DATA_INTR_CTL, 2, (const unsigned char *)&data_intr_ctl); 01947 01948 result = ICM_20948_low_power(pdev, true); // Put chip into low power state 01949 if (result != ICM_20948_Stat_Ok) 01950 return result; 01951 01952 return result; 01953 } 01954 01955 ICM_20948_Status_e inv_icm20948_read_dmp_data(ICM_20948_Device_t *pdev, icm_20948_DMP_data_t *data) 01956 { 01957 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 01958 uint8_t fifoBytes[icm_20948_DMP_Maximum_Bytes]; // Interim storage for the FIFO data 01959 01960 if (pdev->_dmp_firmware_available == false) 01961 return ICM_20948_Stat_DMPNotSupported; 01962 01963 // Check how much data is in the FIFO 01964 uint16_t fifo_count; 01965 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 01966 if (result != ICM_20948_Stat_Ok) 01967 return result; 01968 01969 if (fifo_count < icm_20948_DMP_Header_Bytes) // Has a 2-byte header arrived? 01970 return ICM_20948_Stat_FIFONoDataAvail; // Bail if no header is available 01971 01972 // Read the header (2 bytes) 01973 data->header = 0; // Clear the existing header 01974 uint16_t aShort = 0; 01975 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Header_Bytes); 01976 if (result != ICM_20948_Stat_Ok) 01977 return result; 01978 for (int i = 0; i < icm_20948_DMP_Header_Bytes; i++) 01979 { 01980 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 01981 } 01982 data->header = aShort; // Store the header in data->header 01983 fifo_count -= icm_20948_DMP_Header_Bytes; // Decrement the count 01984 01985 // If the header indicates a header2 is present then read that now 01986 data->header2 = 0; // Clear the existing header2 01987 if ((data->header & DMP_header_bitmap_Header2) > 0) // If the header2 bit is set 01988 { 01989 if (fifo_count < icm_20948_DMP_Header2_Bytes) // Check if we need to read the FIFO count again 01990 { 01991 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 01992 if (result != ICM_20948_Stat_Ok) 01993 return result; 01994 } 01995 if (fifo_count < icm_20948_DMP_Header2_Bytes) 01996 return ICM_20948_Stat_FIFOIncompleteData; // Bail if no header2 is available 01997 // Read the header (2 bytes) 01998 aShort = 0; 01999 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Header2_Bytes); 02000 if (result != ICM_20948_Stat_Ok) 02001 return result; 02002 for (int i = 0; i < icm_20948_DMP_Header2_Bytes; i++) 02003 { 02004 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 02005 } 02006 data->header2 = aShort; // Store the header2 in data->header2 02007 fifo_count -= icm_20948_DMP_Header2_Bytes; // Decrement the count 02008 } 02009 02010 if ((data->header & DMP_header_bitmap_Accel) > 0) // case DMP_header_bitmap_Accel: 02011 { 02012 if (fifo_count < icm_20948_DMP_Raw_Accel_Bytes) // Check if we need to read the FIFO count again 02013 { 02014 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02015 if (result != ICM_20948_Stat_Ok) 02016 return result; 02017 } 02018 if (fifo_count < icm_20948_DMP_Raw_Accel_Bytes) 02019 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02020 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Raw_Accel_Bytes); 02021 if (result != ICM_20948_Stat_Ok) 02022 return result; 02023 for (int i = 0; i < icm_20948_DMP_Raw_Accel_Bytes; i++) 02024 { 02025 data->Raw_Accel.Bytes[DMP_PQuat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02026 } 02027 fifo_count -= icm_20948_DMP_Raw_Accel_Bytes; // Decrement the count 02028 } 02029 02030 if ((data->header & DMP_header_bitmap_Gyro) > 0) // case DMP_header_bitmap_Gyro: 02031 { 02032 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 02033 { 02034 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02035 if (result != ICM_20948_Stat_Ok) 02036 return result; 02037 } 02038 if (fifo_count < (icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes)) 02039 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02040 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], (icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes)); 02041 if (result != ICM_20948_Stat_Ok) 02042 return result; 02043 for (int i = 0; i < (icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes); i++) 02044 { 02045 data->Raw_Gyro.Bytes[DMP_Raw_Gyro_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02046 } 02047 fifo_count -= (icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes); // Decrement the count 02048 } 02049 02050 if ((data->header & DMP_header_bitmap_Compass) > 0) // case DMP_header_bitmap_Compass: 02051 { 02052 if (fifo_count < icm_20948_DMP_Compass_Bytes) // Check if we need to read the FIFO count again 02053 { 02054 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02055 if (result != ICM_20948_Stat_Ok) 02056 return result; 02057 } 02058 if (fifo_count < icm_20948_DMP_Compass_Bytes) 02059 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02060 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Compass_Bytes); 02061 if (result != ICM_20948_Stat_Ok) 02062 return result; 02063 for (int i = 0; i < icm_20948_DMP_Compass_Bytes; i++) 02064 { 02065 data->Compass.Bytes[DMP_PQuat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02066 } 02067 fifo_count -= icm_20948_DMP_Compass_Bytes; // Decrement the count 02068 } 02069 02070 if ((data->header & DMP_header_bitmap_ALS) > 0) // case DMP_header_bitmap_ALS: 02071 { 02072 if (fifo_count < icm_20948_DMP_ALS_Bytes) // Check if we need to read the FIFO count again 02073 { 02074 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02075 if (result != ICM_20948_Stat_Ok) 02076 return result; 02077 } 02078 if (fifo_count < icm_20948_DMP_ALS_Bytes) 02079 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02080 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_ALS_Bytes); 02081 if (result != ICM_20948_Stat_Ok) 02082 return result; 02083 for (int i = 0; i < icm_20948_DMP_ALS_Bytes; i++) 02084 { 02085 data->ALS[i] = fifoBytes[i]; 02086 } 02087 fifo_count -= icm_20948_DMP_ALS_Bytes; // Decrement the count 02088 } 02089 02090 if ((data->header & DMP_header_bitmap_Quat6) > 0) // case DMP_header_bitmap_Quat6: 02091 { 02092 if (fifo_count < icm_20948_DMP_Quat6_Bytes) // Check if we need to read the FIFO count again 02093 { 02094 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02095 if (result != ICM_20948_Stat_Ok) 02096 return result; 02097 } 02098 if (fifo_count < icm_20948_DMP_Quat6_Bytes) 02099 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02100 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Quat6_Bytes); 02101 if (result != ICM_20948_Stat_Ok) 02102 return result; 02103 for (int i = 0; i < icm_20948_DMP_Quat6_Bytes; i++) 02104 { 02105 data->Quat6.Bytes[DMP_Quat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02106 } 02107 fifo_count -= icm_20948_DMP_Quat6_Bytes; // Decrement the count 02108 } 02109 02110 if ((data->header & DMP_header_bitmap_Quat9) > 0) // case DMP_header_bitmap_Quat9: 02111 { 02112 if (fifo_count < icm_20948_DMP_Quat9_Bytes) // Check if we need to read the FIFO count again 02113 { 02114 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02115 if (result != ICM_20948_Stat_Ok) 02116 return result; 02117 } 02118 if (fifo_count < icm_20948_DMP_Quat9_Bytes) 02119 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02120 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Quat9_Bytes); 02121 if (result != ICM_20948_Stat_Ok) 02122 return result; 02123 for (int i = 0; i < icm_20948_DMP_Quat9_Bytes; i++) 02124 { 02125 data->Quat9.Bytes[DMP_Quat9_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02126 } 02127 fifo_count -= icm_20948_DMP_Quat9_Bytes; // Decrement the count 02128 } 02129 02130 if ((data->header & DMP_header_bitmap_PQuat6) > 0) // case DMP_header_bitmap_PQuat6: 02131 { 02132 if (fifo_count < icm_20948_DMP_PQuat6_Bytes) // Check if we need to read the FIFO count again 02133 { 02134 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02135 if (result != ICM_20948_Stat_Ok) 02136 return result; 02137 } 02138 if (fifo_count < icm_20948_DMP_PQuat6_Bytes) 02139 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02140 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_PQuat6_Bytes); 02141 if (result != ICM_20948_Stat_Ok) 02142 return result; 02143 for (int i = 0; i < icm_20948_DMP_PQuat6_Bytes; i++) 02144 { 02145 data->PQuat6.Bytes[DMP_PQuat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02146 } 02147 fifo_count -= icm_20948_DMP_PQuat6_Bytes; // Decrement the count 02148 } 02149 02150 if ((data->header & DMP_header_bitmap_Geomag) > 0) // case DMP_header_bitmap_Geomag: 02151 { 02152 if (fifo_count < icm_20948_DMP_Geomag_Bytes) // Check if we need to read the FIFO count again 02153 { 02154 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02155 if (result != ICM_20948_Stat_Ok) 02156 return result; 02157 } 02158 if (fifo_count < icm_20948_DMP_Geomag_Bytes) 02159 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02160 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Geomag_Bytes); 02161 if (result != ICM_20948_Stat_Ok) 02162 return result; 02163 for (int i = 0; i < icm_20948_DMP_Geomag_Bytes; i++) 02164 { 02165 data->Geomag.Bytes[DMP_Quat9_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02166 } 02167 fifo_count -= icm_20948_DMP_Geomag_Bytes; // Decrement the count 02168 } 02169 02170 if ((data->header & DMP_header_bitmap_Pressure) > 0) // case DMP_header_bitmap_Pressure: 02171 { 02172 if (fifo_count < icm_20948_DMP_Pressure_Bytes) // Check if we need to read the FIFO count again 02173 { 02174 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02175 if (result != ICM_20948_Stat_Ok) 02176 return result; 02177 } 02178 if (fifo_count < icm_20948_DMP_Pressure_Bytes) 02179 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02180 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Pressure_Bytes); 02181 if (result != ICM_20948_Stat_Ok) 02182 return result; 02183 for (int i = 0; i < icm_20948_DMP_Pressure_Bytes; i++) 02184 { 02185 data->Pressure[i] = fifoBytes[i]; 02186 } 02187 fifo_count -= icm_20948_DMP_Pressure_Bytes; // Decrement the count 02188 } 02189 02190 if ((data->header & DMP_header_bitmap_Gyro_Calibr) > 0) // case DMP_header_bitmap_Gyro_Calibr: 02191 { 02192 // lcm20948MPUFifoControl.c suggests icm_20948_DMP_Gyro_Calibr_Bytes is not supported 02193 // and looking at DMP frames which have the Gyro_Calibr bit set, that certainly seems to be true. 02194 // So, we'll skip this...: 02195 /* 02196 if (fifo_count < icm_20948_DMP_Gyro_Calibr_Bytes) // Check if we need to read the FIFO count again 02197 { 02198 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02199 if (result != ICM_20948_Stat_Ok) 02200 return result; 02201 } 02202 if (fifo_count < icm_20948_DMP_Gyro_Calibr_Bytes) 02203 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02204 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Gyro_Calibr_Bytes); 02205 if (result != ICM_20948_Stat_Ok) 02206 return result; 02207 for (int i = 0; i < icm_20948_DMP_Gyro_Calibr_Bytes; i++) 02208 { 02209 data->Gyro_Calibr.Bytes[DMP_Quat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02210 } 02211 fifo_count -= icm_20948_DMP_Gyro_Calibr_Bytes; // Decrement the count 02212 */ 02213 } 02214 02215 if ((data->header & DMP_header_bitmap_Compass_Calibr) > 0) // case DMP_header_bitmap_Compass_Calibr: 02216 { 02217 if (fifo_count < icm_20948_DMP_Compass_Calibr_Bytes) // Check if we need to read the FIFO count again 02218 { 02219 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02220 if (result != ICM_20948_Stat_Ok) 02221 return result; 02222 } 02223 if (fifo_count < icm_20948_DMP_Compass_Calibr_Bytes) 02224 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02225 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Compass_Calibr_Bytes); 02226 if (result != ICM_20948_Stat_Ok) 02227 return result; 02228 for (int i = 0; i < icm_20948_DMP_Compass_Calibr_Bytes; i++) 02229 { 02230 data->Compass_Calibr.Bytes[DMP_Quat6_Byte_Ordering[i]] = fifoBytes[i]; // Correct the byte order (map big endian to little endian) 02231 } 02232 fifo_count -= icm_20948_DMP_Compass_Calibr_Bytes; // Decrement the count 02233 } 02234 02235 if ((data->header & DMP_header_bitmap_Step_Detector) > 0) // case DMP_header_bitmap_Step_Detector: 02236 { 02237 if (fifo_count < icm_20948_DMP_Step_Detector_Bytes) // Check if we need to read the FIFO count again 02238 { 02239 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02240 if (result != ICM_20948_Stat_Ok) 02241 return result; 02242 } 02243 if (fifo_count < icm_20948_DMP_Step_Detector_Bytes) 02244 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02245 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Step_Detector_Bytes); 02246 if (result != ICM_20948_Stat_Ok) 02247 return result; 02248 uint32_t aWord = 0; 02249 for (int i = 0; i < icm_20948_DMP_Step_Detector_Bytes; i++) 02250 { 02251 aWord |= ((uint32_t)fifoBytes[i]) << (24 - (i * 8)); 02252 } 02253 data->Pedometer_Timestamp = aWord; 02254 fifo_count -= icm_20948_DMP_Step_Detector_Bytes; // Decrement the count 02255 } 02256 02257 // Now check for header2 features 02258 02259 if ((data->header2 & DMP_header2_bitmap_Accel_Accuracy) > 0) // case DMP_header2_bitmap_Accel_Accuracy: 02260 { 02261 if (fifo_count < icm_20948_DMP_Accel_Accuracy_Bytes) // Check if we need to read the FIFO count again 02262 { 02263 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02264 if (result != ICM_20948_Stat_Ok) 02265 return result; 02266 } 02267 if (fifo_count < icm_20948_DMP_Accel_Accuracy_Bytes) 02268 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02269 aShort = 0; 02270 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Accel_Accuracy_Bytes); 02271 if (result != ICM_20948_Stat_Ok) 02272 return result; 02273 for (int i = 0; i < icm_20948_DMP_Accel_Accuracy_Bytes; i++) 02274 { 02275 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 02276 } 02277 data->Accel_Accuracy = aShort; 02278 fifo_count -= icm_20948_DMP_Accel_Accuracy_Bytes; // Decrement the count 02279 } 02280 02281 if ((data->header2 & DMP_header2_bitmap_Gyro_Accuracy) > 0) // case DMP_header2_bitmap_Gyro_Accuracy: 02282 { 02283 if (fifo_count < icm_20948_DMP_Gyro_Accuracy_Bytes) // Check if we need to read the FIFO count again 02284 { 02285 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02286 if (result != ICM_20948_Stat_Ok) 02287 return result; 02288 } 02289 if (fifo_count < icm_20948_DMP_Gyro_Accuracy_Bytes) 02290 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02291 aShort = 0; 02292 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Gyro_Accuracy_Bytes); 02293 if (result != ICM_20948_Stat_Ok) 02294 return result; 02295 for (int i = 0; i < icm_20948_DMP_Gyro_Accuracy_Bytes; i++) 02296 { 02297 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 02298 } 02299 data->Gyro_Accuracy = aShort; 02300 fifo_count -= icm_20948_DMP_Gyro_Accuracy_Bytes; // Decrement the count 02301 } 02302 02303 if ((data->header2 & DMP_header2_bitmap_Compass_Accuracy) > 0) // case DMP_header2_bitmap_Compass_Accuracy: 02304 { 02305 if (fifo_count < icm_20948_DMP_Compass_Accuracy_Bytes) // Check if we need to read the FIFO count again 02306 { 02307 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02308 if (result != ICM_20948_Stat_Ok) 02309 return result; 02310 } 02311 if (fifo_count < icm_20948_DMP_Compass_Accuracy_Bytes) 02312 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02313 aShort = 0; 02314 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Compass_Accuracy_Bytes); 02315 if (result != ICM_20948_Stat_Ok) 02316 return result; 02317 for (int i = 0; i < icm_20948_DMP_Compass_Accuracy_Bytes; i++) 02318 { 02319 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 02320 } 02321 data->Compass_Accuracy = aShort; 02322 fifo_count -= icm_20948_DMP_Compass_Accuracy_Bytes; // Decrement the count 02323 } 02324 02325 if ((data->header2 & DMP_header2_bitmap_Fsync) > 0) // case DMP_header2_bitmap_Fsync: 02326 { 02327 // lcm20948MPUFifoControl.c suggests icm_20948_DMP_Fsync_Detection_Bytes is not supported. 02328 // So, we'll skip this just in case...: 02329 /* 02330 if (fifo_count < icm_20948_DMP_Fsync_Detection_Bytes) // Check if we need to read the FIFO count again 02331 { 02332 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02333 if (result != ICM_20948_Stat_Ok) 02334 return result; 02335 } 02336 if (fifo_count < icm_20948_DMP_Fsync_Detection_Bytes) 02337 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02338 aShort = 0; 02339 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Fsync_Detection_Bytes); 02340 if (result != ICM_20948_Stat_Ok) 02341 return result; 02342 for (int i = 0; i < icm_20948_DMP_Fsync_Detection_Bytes; i++) 02343 { 02344 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 02345 } 02346 data->Fsync_Delay_Time = aShort; 02347 fifo_count -= icm_20948_DMP_Fsync_Detection_Bytes; // Decrement the count 02348 */ 02349 } 02350 02351 if ((data->header2 & DMP_header2_bitmap_Pickup) > 0) // case DMP_header2_bitmap_Pickup: 02352 { 02353 if (fifo_count < icm_20948_DMP_Pickup_Bytes) // Check if we need to read the FIFO count again 02354 { 02355 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02356 if (result != ICM_20948_Stat_Ok) 02357 return result; 02358 } 02359 if (fifo_count < icm_20948_DMP_Pickup_Bytes) 02360 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02361 aShort = 0; 02362 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Pickup_Bytes); 02363 if (result != ICM_20948_Stat_Ok) 02364 return result; 02365 for (int i = 0; i < icm_20948_DMP_Pickup_Bytes; i++) 02366 { 02367 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 02368 } 02369 data->Pickup = aShort; 02370 fifo_count -= icm_20948_DMP_Pickup_Bytes; // Decrement the count 02371 } 02372 02373 if ((data->header2 & DMP_header2_bitmap_Activity_Recog) > 0) // case DMP_header2_bitmap_Activity_Recog: 02374 { 02375 if (fifo_count < icm_20948_DMP_Activity_Recognition_Bytes) // Check if we need to read the FIFO count again 02376 { 02377 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02378 if (result != ICM_20948_Stat_Ok) 02379 return result; 02380 } 02381 if (fifo_count < icm_20948_DMP_Activity_Recognition_Bytes) 02382 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02383 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Activity_Recognition_Bytes); 02384 if (result != ICM_20948_Stat_Ok) 02385 return result; 02386 for (int i = 0; i < icm_20948_DMP_Activity_Recognition_Bytes; i++) 02387 { 02388 data->Activity_Recognition.Bytes[DMP_Activity_Recognition_Byte_Ordering[i]] = fifoBytes[i]; 02389 } 02390 fifo_count -= icm_20948_DMP_Activity_Recognition_Bytes; // Decrement the count 02391 } 02392 02393 if ((data->header2 & DMP_header2_bitmap_Secondary_On_Off) > 0) // case DMP_header2_bitmap_Secondary_On_Off: 02394 { 02395 if (fifo_count < icm_20948_DMP_Secondary_On_Off_Bytes) // Check if we need to read the FIFO count again 02396 { 02397 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02398 if (result != ICM_20948_Stat_Ok) 02399 return result; 02400 } 02401 if (fifo_count < icm_20948_DMP_Secondary_On_Off_Bytes) 02402 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02403 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Secondary_On_Off_Bytes); 02404 if (result != ICM_20948_Stat_Ok) 02405 return result; 02406 for (int i = 0; i < icm_20948_DMP_Secondary_On_Off_Bytes; i++) 02407 { 02408 data->Secondary_On_Off.Bytes[DMP_Secondary_On_Off_Byte_Ordering[i]] = fifoBytes[i]; 02409 } 02410 fifo_count -= icm_20948_DMP_Secondary_On_Off_Bytes; // Decrement the count 02411 } 02412 02413 // Finally, extract the footer (gyro count) 02414 if (fifo_count < icm_20948_DMP_Footer_Bytes) // Check if we need to read the FIFO count again 02415 { 02416 result = ICM_20948_get_FIFO_count(pdev, &fifo_count); 02417 if (result != ICM_20948_Stat_Ok) 02418 return result; 02419 } 02420 if (fifo_count < icm_20948_DMP_Footer_Bytes) 02421 return ICM_20948_Stat_FIFOIncompleteData; // Bail if not enough data is available 02422 aShort = 0; 02423 result = ICM_20948_read_FIFO(pdev, &fifoBytes[0], icm_20948_DMP_Footer_Bytes); 02424 if (result != ICM_20948_Stat_Ok) 02425 return result; 02426 for (int i = 0; i < icm_20948_DMP_Footer_Bytes; i++) 02427 { 02428 aShort |= ((uint16_t)fifoBytes[i]) << (8 - (i * 8)); 02429 } 02430 data->Footer = aShort; 02431 fifo_count -= icm_20948_DMP_Footer_Bytes; // Decrement the count 02432 02433 if (fifo_count > 0) // Check if there is still data waiting to be read 02434 return ICM_20948_Stat_FIFOMoreDataAvail; 02435 02436 return result; 02437 } 02438 02439 uint8_t sensor_type_2_android_sensor(enum inv_icm20948_sensor sensor) 02440 { 02441 switch (sensor) 02442 { 02443 case INV_ICM20948_SENSOR_ACCELEROMETER: 02444 return ANDROID_SENSOR_ACCELEROMETER; // 1 02445 case INV_ICM20948_SENSOR_GYROSCOPE: 02446 return ANDROID_SENSOR_GYROSCOPE; // 4 02447 case INV_ICM20948_SENSOR_RAW_ACCELEROMETER: 02448 return ANDROID_SENSOR_RAW_ACCELEROMETER; // 42 02449 case INV_ICM20948_SENSOR_RAW_GYROSCOPE: 02450 return ANDROID_SENSOR_RAW_GYROSCOPE; // 43 02451 case INV_ICM20948_SENSOR_MAGNETIC_FIELD_UNCALIBRATED: 02452 return ANDROID_SENSOR_MAGNETIC_FIELD_UNCALIBRATED; // 14 02453 case INV_ICM20948_SENSOR_GYROSCOPE_UNCALIBRATED: 02454 return ANDROID_SENSOR_GYROSCOPE_UNCALIBRATED; // 16 02455 case INV_ICM20948_SENSOR_ACTIVITY_CLASSIFICATON: 02456 return ANDROID_SENSOR_ACTIVITY_CLASSIFICATON; // 47 02457 case INV_ICM20948_SENSOR_STEP_DETECTOR: 02458 return ANDROID_SENSOR_STEP_DETECTOR; // 18 02459 case INV_ICM20948_SENSOR_STEP_COUNTER: 02460 return ANDROID_SENSOR_STEP_COUNTER; // 19 02461 case INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR: 02462 return ANDROID_SENSOR_GAME_ROTATION_VECTOR; // 15 02463 case INV_ICM20948_SENSOR_ROTATION_VECTOR: 02464 return ANDROID_SENSOR_ROTATION_VECTOR; // 11 02465 case INV_ICM20948_SENSOR_GEOMAGNETIC_ROTATION_VECTOR: 02466 return ANDROID_SENSOR_GEOMAGNETIC_ROTATION_VECTOR; // 20 02467 case INV_ICM20948_SENSOR_GEOMAGNETIC_FIELD: 02468 return ANDROID_SENSOR_GEOMAGNETIC_FIELD; // 2 02469 case INV_ICM20948_SENSOR_WAKEUP_SIGNIFICANT_MOTION: 02470 return ANDROID_SENSOR_WAKEUP_SIGNIFICANT_MOTION; // 17 02471 case INV_ICM20948_SENSOR_FLIP_PICKUP: 02472 return ANDROID_SENSOR_FLIP_PICKUP; // 46 02473 case INV_ICM20948_SENSOR_WAKEUP_TILT_DETECTOR: 02474 return ANDROID_SENSOR_WAKEUP_TILT_DETECTOR; // 41 02475 case INV_ICM20948_SENSOR_GRAVITY: 02476 return ANDROID_SENSOR_GRAVITY; // 9 02477 case INV_ICM20948_SENSOR_LINEAR_ACCELERATION: 02478 return ANDROID_SENSOR_LINEAR_ACCELERATION; // 10 02479 case INV_ICM20948_SENSOR_ORIENTATION: 02480 return ANDROID_SENSOR_ORIENTATION; // 3 02481 case INV_ICM20948_SENSOR_B2S: 02482 return ANDROID_SENSOR_B2S; // 45 02483 default: 02484 return ANDROID_SENSOR_NUM_MAX; 02485 } 02486 } 02487 02488 enum inv_icm20948_sensor inv_icm20948_sensor_android_2_sensor_type(int sensor) 02489 { 02490 switch (sensor) 02491 { 02492 case ANDROID_SENSOR_ACCELEROMETER: 02493 return INV_ICM20948_SENSOR_ACCELEROMETER; 02494 case ANDROID_SENSOR_GYROSCOPE: 02495 return INV_ICM20948_SENSOR_GYROSCOPE; 02496 case ANDROID_SENSOR_RAW_ACCELEROMETER: 02497 return INV_ICM20948_SENSOR_RAW_ACCELEROMETER; 02498 case ANDROID_SENSOR_RAW_GYROSCOPE: 02499 return INV_ICM20948_SENSOR_RAW_GYROSCOPE; 02500 case ANDROID_SENSOR_MAGNETIC_FIELD_UNCALIBRATED: 02501 return INV_ICM20948_SENSOR_MAGNETIC_FIELD_UNCALIBRATED; 02502 case ANDROID_SENSOR_GYROSCOPE_UNCALIBRATED: 02503 return INV_ICM20948_SENSOR_GYROSCOPE_UNCALIBRATED; 02504 case ANDROID_SENSOR_ACTIVITY_CLASSIFICATON: 02505 return INV_ICM20948_SENSOR_ACTIVITY_CLASSIFICATON; 02506 case ANDROID_SENSOR_STEP_DETECTOR: 02507 return INV_ICM20948_SENSOR_STEP_DETECTOR; 02508 case ANDROID_SENSOR_STEP_COUNTER: 02509 return INV_ICM20948_SENSOR_STEP_COUNTER; 02510 case ANDROID_SENSOR_GAME_ROTATION_VECTOR: 02511 return INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR; 02512 case ANDROID_SENSOR_ROTATION_VECTOR: 02513 return INV_ICM20948_SENSOR_ROTATION_VECTOR; 02514 case ANDROID_SENSOR_GEOMAGNETIC_ROTATION_VECTOR: 02515 return INV_ICM20948_SENSOR_GEOMAGNETIC_ROTATION_VECTOR; 02516 case ANDROID_SENSOR_GEOMAGNETIC_FIELD: 02517 return INV_ICM20948_SENSOR_GEOMAGNETIC_FIELD; 02518 case ANDROID_SENSOR_WAKEUP_SIGNIFICANT_MOTION: 02519 return INV_ICM20948_SENSOR_WAKEUP_SIGNIFICANT_MOTION; 02520 case ANDROID_SENSOR_FLIP_PICKUP: 02521 return INV_ICM20948_SENSOR_FLIP_PICKUP; 02522 case ANDROID_SENSOR_WAKEUP_TILT_DETECTOR: 02523 return INV_ICM20948_SENSOR_WAKEUP_TILT_DETECTOR; 02524 case ANDROID_SENSOR_GRAVITY: 02525 return INV_ICM20948_SENSOR_GRAVITY; 02526 case ANDROID_SENSOR_LINEAR_ACCELERATION: 02527 return INV_ICM20948_SENSOR_LINEAR_ACCELERATION; 02528 case ANDROID_SENSOR_ORIENTATION: 02529 return INV_ICM20948_SENSOR_ORIENTATION; 02530 case ANDROID_SENSOR_B2S: 02531 return INV_ICM20948_SENSOR_B2S; 02532 default: 02533 return INV_ICM20948_SENSOR_MAX; 02534 } 02535 } 02536 02537 ICM_20948_Status_e inv_icm20948_set_gyro_sf(ICM_20948_Device_t *pdev, unsigned char div, int gyro_level) 02538 { 02539 ICM_20948_Status_e result = ICM_20948_Stat_Ok; 02540 02541 if (pdev->_dmp_firmware_available == false) 02542 return ICM_20948_Stat_DMPNotSupported; 02543 02544 // gyro_level should be set to 4 regardless of fullscale, due to the addition of API dmp_icm20648_set_gyro_fsr() 02545 gyro_level = 4; 02546 02547 // First read the TIMEBASE_CORRECTION_PLL register from Bank 1 02548 int8_t pll; // Signed. Typical value is 0x18 02549 result = ICM_20948_set_bank(pdev, 1); 02550 result = ICM_20948_execute_r(pdev, AGB1_REG_TIMEBASE_CORRECTION_PLL, (uint8_t *)&pll, 1); 02551 if (result != ICM_20948_Stat_Ok) 02552 { 02553 return result; 02554 } 02555 02556 pdev->_gyroSFpll = pll; // Record the PLL value so we can debug print it 02557 02558 // Now calculate the Gyro SF using code taken from the InvenSense example (inv_icm20948_set_gyro_sf) 02559 02560 long gyro_sf; 02561 02562 unsigned long long const MagicConstant = 264446880937391LL; 02563 unsigned long long const MagicConstantScale = 100000LL; 02564 unsigned long long ResultLL; 02565 02566 if (pll & 0x80) 02567 { 02568 ResultLL = (MagicConstant * (long long)(1ULL << gyro_level) * (1 + div) / (1270 - (pll & 0x7F)) / MagicConstantScale); 02569 } 02570 else 02571 { 02572 ResultLL = (MagicConstant * (long long)(1ULL << gyro_level) * (1 + div) / (1270 + pll) / MagicConstantScale); 02573 } 02574 /* 02575 In above deprecated FP version, worst case arguments can produce a result that overflows a signed long. 02576 Here, for such cases, we emulate the FP behavior of setting the result to the maximum positive value, as 02577 the compiler's conversion of a u64 to an s32 is simple truncation of the u64's high half, sadly.... 02578 */ 02579 if (ResultLL > 0x7FFFFFFF) 02580 gyro_sf = 0x7FFFFFFF; 02581 else 02582 gyro_sf = (long)ResultLL; 02583 02584 pdev->_gyroSF = gyro_sf; // Record value so we can debug print it 02585 02586 // Finally, write the value to the DMP GYRO_SF register 02587 unsigned char gyro_sf_reg[4]; 02588 gyro_sf_reg[0] = (unsigned char)(gyro_sf >> 24); 02589 gyro_sf_reg[1] = (unsigned char)(gyro_sf >> 16); 02590 gyro_sf_reg[2] = (unsigned char)(gyro_sf >> 8); 02591 gyro_sf_reg[3] = (unsigned char)(gyro_sf & 0xff); 02592 result = inv_icm20948_write_mems(pdev, GYRO_SF, 4, (const unsigned char *)&gyro_sf_reg); 02593 02594 return result; 02595 }
Generated on Thu Aug 18 2022 09:06:28 by
1.7.2