@@ -1300,7 +1300,7 @@ ICM_20948_Status_e inv_icm20948_write_mems(ICM_20948_Device_t *pdev, unsigned sh
13001300ICM_20948_Status_e inv_icm20948_read_mems (ICM_20948_Device_t * pdev , unsigned short reg , unsigned int length , unsigned char * data )
13011301{
13021302 ICM_20948_Status_e result = ICM_20948_Stat_Ok ;
1303- unsigned int bytesWritten = 0 ;
1303+ unsigned int bytesRead = 0 ;
13041304 unsigned int thisLen ;
13051305 unsigned char lBankSelected ;
13061306 unsigned char lStartAddrSelected ;
@@ -1318,13 +1318,17 @@ ICM_20948_Status_e inv_icm20948_read_mems(ICM_20948_Device_t *pdev, unsigned sho
13181318
13191319 lBankSelected = (reg >> 8 );
13201320
1321- result = ICM_20948_execute_w (pdev , AGB0_REG_MEM_BANK_SEL , & lBankSelected , 1 );
1322- if (result != ICM_20948_Stat_Ok )
1321+ if (lBankSelected != pdev -> _last_mems_bank )
13231322 {
1324- return result ;
1323+ pdev -> _last_mems_bank = lBankSelected ;
1324+ result = ICM_20948_execute_w (pdev , AGB0_REG_MEM_BANK_SEL , & lBankSelected , 1 );
1325+ if (result != ICM_20948_Stat_Ok )
1326+ {
1327+ return result ;
1328+ }
13251329 }
13261330
1327- while (bytesWritten < length )
1331+ while (bytesRead < length )
13281332 {
13291333 lStartAddrSelected = (reg & 0xff );
13301334
@@ -1339,20 +1343,20 @@ ICM_20948_Status_e inv_icm20948_read_mems(ICM_20948_Device_t *pdev, unsigned sho
13391343 return result ;
13401344 }
13411345
1342- if (length - bytesWritten <= INV_MAX_SERIAL_READ )
1343- thisLen = length - bytesWritten ;
1346+ if (length - bytesRead <= INV_MAX_SERIAL_READ )
1347+ thisLen = length - bytesRead ;
13441348 else
13451349 thisLen = INV_MAX_SERIAL_READ ;
13461350
13471351 /* Read data */
13481352
1349- result = ICM_20948_execute_r (pdev , AGB0_REG_MEM_R_W , & data [bytesWritten ], thisLen );
1353+ result = ICM_20948_execute_r (pdev , AGB0_REG_MEM_R_W , & data [bytesRead ], thisLen );
13501354 if (result != ICM_20948_Stat_Ok )
13511355 {
13521356 return result ;
13531357 }
13541358
1355- bytesWritten += thisLen ;
1359+ bytesRead += thisLen ;
13561360 reg += thisLen ;
13571361 }
13581362
@@ -1361,7 +1365,7 @@ ICM_20948_Status_e inv_icm20948_read_mems(ICM_20948_Device_t *pdev, unsigned sho
13611365
13621366ICM_20948_Status_e inv_icm20948_set_dmp_sensor_period (ICM_20948_Device_t * pdev , enum DMP_ODR_Registers odr_reg , uint16_t interval )
13631367{
1364- // Set the ODR registersand clear the ODR counter
1368+ // Set the ODR registers and clear the ODR counter
13651369
13661370 // 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.
13671371 // Setting value can be calculated as follows:
@@ -1529,6 +1533,10 @@ ICM_20948_Status_e inv_icm20948_enable_dmp_sensor(ICM_20948_Device_t *pdev, enum
15291533 }
15301534 // TO DO: Add DMP_Data_Output_Control_2_Pickup etc. if required
15311535
1536+ // Keep a record of DATA_OUT_CTL1 so multiple sensors can be configured
1537+ delta |= pdev -> _DATA_OUT_CTL1 ;
1538+ pdev -> _DATA_OUT_CTL1 = delta ;
1539+
15321540 // Write the sensor control bits into memory address DATA_OUT_CTL1
15331541 unsigned char data_output_control_reg [2 ];
15341542 data_output_control_reg [0 ] = (unsigned char )(delta >> 8 );
@@ -1539,6 +1547,10 @@ ICM_20948_Status_e inv_icm20948_enable_dmp_sensor(ICM_20948_Device_t *pdev, enum
15391547 return result ;
15401548 }
15411549
1550+ // Keep a record of DATA_OUT_CTL2 so multiple sensors can be configured
1551+ delta2 |= pdev -> _DATA_OUT_CTL2 ;
1552+ pdev -> _DATA_OUT_CTL2 = delta2 ;
1553+
15421554 // Write the 'header2' sensor control bits into memory address DATA_OUT_CTL2
15431555 data_output_control_reg [0 ] = (unsigned char )(delta2 >> 8 );
15441556 data_output_control_reg [1 ] = (unsigned char )(delta2 & 0xff );
@@ -1589,6 +1601,11 @@ ICM_20948_Status_e inv_icm20948_enable_dmp_sensor(ICM_20948_Device_t *pdev, enum
15891601 inv_event_control |= DMP_Motion_Event_Control_Compass_Calibr ;
15901602 }
15911603 }
1604+
1605+ // Keep a record of _DATA_RDY_STATUS so multiple sensors can be configured
1606+ data_rdy_status |= pdev -> _DATA_RDY_STATUS ;
1607+ pdev -> _DATA_RDY_STATUS = data_rdy_status ;
1608+
15921609 data_output_control_reg [0 ] = (unsigned char )(data_rdy_status >> 8 );
15931610 data_output_control_reg [1 ] = (unsigned char )(data_rdy_status & 0xff );
15941611 result = inv_icm20948_write_mems (pdev , DATA_RDY_STATUS , 2 , (const unsigned char * )& data_output_control_reg );
@@ -1611,6 +1628,11 @@ ICM_20948_Status_e inv_icm20948_enable_dmp_sensor(ICM_20948_Device_t *pdev, enum
16111628 {
16121629 inv_event_control |= DMP_Motion_Event_Control_Geomag ;
16131630 }
1631+
1632+ // Keep a record of _MOTION_EVENT_CTL so multiple sensors can be configured
1633+ inv_event_control |= pdev -> _MOTION_EVENT_CTL ;
1634+ pdev -> _MOTION_EVENT_CTL = inv_event_control ;
1635+
16141636 data_output_control_reg [0 ] = (unsigned char )(inv_event_control >> 8 );
16151637 data_output_control_reg [1 ] = (unsigned char )(inv_event_control & 0xff );
16161638 result = inv_icm20948_write_mems (pdev , MOTION_EVENT_CTL , 2 , (const unsigned char * )& data_output_control_reg );
@@ -2171,6 +2193,7 @@ static uint8_t sensor_type_2_android_sensor(enum inv_icm20948_sensor sensor)
21712193 case INV_ICM20948_SENSOR_LINEAR_ACCELERATION : return ANDROID_SENSOR_LINEAR_ACCELERATION ; // 10
21722194 case INV_ICM20948_SENSOR_ORIENTATION : return ANDROID_SENSOR_ORIENTATION ; // 3
21732195 case INV_ICM20948_SENSOR_B2S : return ANDROID_SENSOR_B2S ; // 45
2196+ case INV_ICM20948_SENSOR_RAW_MAGNETOMETER : return ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD_UNCALIBRATED ; // 34
21742197 default : return ANDROID_SENSOR_NUM_MAX ;
21752198 }
21762199}
@@ -2198,6 +2221,65 @@ enum inv_icm20948_sensor inv_icm20948_sensor_android_2_sensor_type(int sensor)
21982221 case ANDROID_SENSOR_LINEAR_ACCELERATION : return INV_ICM20948_SENSOR_LINEAR_ACCELERATION ;
21992222 case ANDROID_SENSOR_ORIENTATION : return INV_ICM20948_SENSOR_ORIENTATION ;
22002223 case ANDROID_SENSOR_B2S : return INV_ICM20948_SENSOR_B2S ;
2224+ case ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD_UNCALIBRATED : return INV_ICM20948_SENSOR_RAW_MAGNETOMETER ;
22012225 default : return INV_ICM20948_SENSOR_MAX ;
22022226 }
22032227}
2228+
2229+ ICM_20948_Status_e inv_icm20948_set_gyro_sf (ICM_20948_Device_t * pdev , unsigned char div , int gyro_level )
2230+ {
2231+ ICM_20948_Status_e result = ICM_20948_Stat_Ok ;
2232+
2233+ if (pdev -> _dmp_firmware_available == false)
2234+ return ICM_20948_Stat_DMPNotSupported ;
2235+
2236+ // gyro_level should be set to 4 regardless of fullscale, due to the addition of API dmp_icm20648_set_gyro_fsr()
2237+ gyro_level = 4 ;
2238+
2239+ // First read the TIMEBASE_CORRECTION_PLL register from Bank 1
2240+ int8_t pll ; // Signed. Typical value is 0x18
2241+ result = ICM_20948_set_bank (pdev , 1 );
2242+ result = ICM_20948_execute_r (pdev , AGB1_REG_TIMEBASE_CORRECTION_PLL , (uint8_t * )& pll , 1 );
2243+ if (result != ICM_20948_Stat_Ok )
2244+ {
2245+ return result ;
2246+ }
2247+
2248+ pdev -> _gyroSFpll = pll ; // Record the PLL value so we can debug print it
2249+
2250+ // Now calculate the Gyro SF using code taken from the InvenSense example (inv_icm20948_set_gyro_sf)
2251+
2252+ long gyro_sf ;
2253+
2254+ unsigned long long const MagicConstant = 264446880937391LL ;
2255+ unsigned long long const MagicConstantScale = 100000LL ;
2256+ unsigned long long ResultLL ;
2257+
2258+ if (pll & 0x80 ) {
2259+ ResultLL = (MagicConstant * (long long )(1ULL << gyro_level ) * (1 + div ) / (1270 - (pll & 0x7F )) / MagicConstantScale );
2260+ }
2261+ else {
2262+ ResultLL = (MagicConstant * (long long )(1ULL << gyro_level ) * (1 + div ) / (1270 + pll ) / MagicConstantScale );
2263+ }
2264+ /*
2265+ In above deprecated FP version, worst case arguments can produce a result that overflows a signed long.
2266+ Here, for such cases, we emulate the FP behavior of setting the result to the maximum positive value, as
2267+ the compiler's conversion of a u64 to an s32 is simple truncation of the u64's high half, sadly....
2268+ */
2269+ if (ResultLL > 0x7FFFFFFF )
2270+ gyro_sf = 0x7FFFFFFF ;
2271+ else
2272+ gyro_sf = (long )ResultLL ;
2273+
2274+ pdev -> _gyroSF = gyro_sf ; // Record value so we can debug print it
2275+
2276+ // Finally, write the value to the DMP GYRO_SF register
2277+ unsigned char gyro_sf_reg [4 ];
2278+ gyro_sf_reg [0 ] = (unsigned char )(gyro_sf >> 24 );
2279+ gyro_sf_reg [1 ] = (unsigned char )(gyro_sf >> 16 );
2280+ gyro_sf_reg [2 ] = (unsigned char )(gyro_sf >> 8 );
2281+ gyro_sf_reg [3 ] = (unsigned char )(gyro_sf & 0xff );
2282+ result = inv_icm20948_write_mems (pdev , GYRO_SF , 4 , (const unsigned char * )& gyro_sf_reg );
2283+
2284+ return result ;
2285+ }
0 commit comments