@@ -18,11 +18,6 @@ ICM_20948_AGMT_t ICM_20948::getAGMT(void)
1818{
1919 status = ICM_20948_get_agmt (&_device, &agmt);
2020
21- if (_has_magnetometer)
22- {
23- getMagnetometerData (&agmt);
24- }
25-
2621 return agmt;
2722}
2823
@@ -527,7 +522,6 @@ ICM_20948_Status_e ICM_20948::intEnableRawDataReady(bool enable)
527522 }
528523 if (en.RAW_DATA_0_RDY_EN != enable)
529524 {
530- Serial.println (" mismatch error" );
531525 status = ICM_20948_Stat_Err;
532526 return status;
533527 }
@@ -589,6 +583,12 @@ ICM_20948_Status_e ICM_20948::i2cMasterEnable(bool enable)
589583 return status;
590584}
591585
586+ ICM_20948_Status_e ICM_20948::i2cMasterReset ()
587+ {
588+ status = ICM_20948_i2c_master_reset (&_device);
589+ return status;
590+ }
591+
592592ICM_20948_Status_e ICM_20948::i2cMasterConfigureSlave (uint8_t slave, uint8_t addr, uint8_t reg, uint8_t len, bool Rw, bool enable, bool data_only, bool grp, bool swap)
593593{
594594 status = ICM_20948_i2c_master_configure_slave (&_device, slave, addr, reg, len, Rw, enable, data_only, grp, swap);
@@ -600,6 +600,7 @@ ICM_20948_Status_e ICM_20948::i2cMasterSLV4Transaction(uint8_t addr, uint8_t reg
600600 status = ICM_20948_i2c_master_slv4_txn (&_device, addr, reg, data, len, Rw, send_reg_addr);
601601 return status;
602602}
603+
603604ICM_20948_Status_e ICM_20948::i2cMasterSingleW (uint8_t addr, uint8_t reg, uint8_t data)
604605{
605606 status = ICM_20948_i2c_master_single_w (&_device, addr, reg, &data);
@@ -684,49 +685,39 @@ ICM_20948_Status_e ICM_20948::startupDefault(void)
684685 status = retval;
685686 return status;
686687 }
687-
688- _has_magnetometer = true ;
689688 retval = startupMagnetometer ();
690- if (( retval != ICM_20948_Stat_Ok) && (retval != ICM_20948_Stat_NotImpl) )
689+ if (retval != ICM_20948_Stat_Ok)
691690 {
692691 status = retval;
693692 return status;
694693 }
695- if (retval == ICM_20948_Stat_NotImpl)
696- {
697- // This is a temporary fix.
698- // Ultimately we *should* be able to configure the I2C master to handle the
699- // magnetometer no matter what interface (SPI / I2C) we are using.
700-
701- // Should try testing I2C master functionality on a bare ICM chip w/o TXS0108 level shifter...
702-
703- _has_magnetometer = false ;
704- retval = ICM_20948_Stat_Ok; // reset the retval because we handled it in this cases
705- }
706694
707- status = retval;
708695 return status;
709696}
710697
711- ICM_20948_Status_e ICM_20948::startupMagnetometer (void )
698+ // direct read/write
699+ ICM_20948_Status_e ICM_20948::read (uint8_t reg, uint8_t *pdata, uint32_t len)
712700{
713- return ICM_20948_Stat_NotImpl; // By default we assume that we cannot access the magnetometer
701+ status = ICM_20948_execute_r (&_device, reg, pdata, len);
702+ return (status);
714703}
715704
716- ICM_20948_Status_e ICM_20948::getMagnetometerData (ICM_20948_AGMT_t *pagmt )
705+ ICM_20948_Status_e ICM_20948::write ( uint8_t reg, uint8_t *pdata, uint32_t len )
717706{
718- return ICM_20948_Stat_NotImpl; // By default we assume that we cannot access the magnetometer
707+ status = ICM_20948_execute_w (&_device, reg, pdata, len);
708+ return (status);
719709}
720710
721- // direct read/write
722- ICM_20948_Status_e ICM_20948::read (uint8_t reg, uint8_t *pdata, uint32_t len)
711+ uint8_t ICM_20948::readMag (AK09916_Reg_Addr_e reg)
723712{
724- status = ICM_20948_execute_r (&_device, reg, pdata, len);
713+ uint8_t data = i2cMasterSingleR (MAG_AK09916_I2C_ADDR, reg);
714+ return data;
725715}
726716
727- ICM_20948_Status_e ICM_20948::write ( uint8_t reg, uint8_t *pdata, uint32_t len )
717+ ICM_20948_Status_e ICM_20948::writeMag (AK09916_Reg_Addr_e reg, uint8_t *pdata)
728718{
729- status = ICM_20948_execute_w (&_device, reg, pdata, len);
719+ status = i2cMasterSingleW (MAG_AK09916_I2C_ADDR, reg, pdata);
720+ return status;
730721}
731722
732723// I2C
@@ -778,103 +769,78 @@ ICM_20948_Status_e ICM_20948_I2C::begin(TwoWire &wirePort, bool ad0val, uint8_t
778769 return status;
779770}
780771
781- ICM_20948_Status_e ICM_20948_I2C ::startupMagnetometer (void )
772+ ICM_20948_Status_e ICM_20948 ::startupMagnetometer (void )
782773{
783- // If using the magnetometer through passthrough:
784- i2cMasterPassthrough (true ); // Set passthrough mode to try to access the magnetometer (by default I2C master is disabled but you still have to enable the passthrough)
774+ ICM_20948_Status_e retval = ICM_20948_Stat_Ok;
785775
786- // Try to set up magnetometer
787- AK09916_CNTL2_Reg_t reg;
788- reg.MODE = AK09916_mode_cont_100hz;
776+ i2cMasterPassthrough (false ); // Do not connect the SDA/SCL pins to AUX_DA/AUX_CL
777+ i2cMasterEnable (true );
789778
790- ICM_20948_Status_e retval = writeMag (AK09916_REG_CNTL2, (uint8_t *)®, sizeof (AK09916_CNTL2_Reg_t));
791- status = retval;
792- if (status == ICM_20948_Stat_Ok)
779+ // After a ICM reset the Mag sensor may stop responding over the I2C master
780+ // Reset the Master I2C until it responds
781+ uint8_t tries = 0 ;
782+ uint8_t maxTries = 5 ;
783+ while (tries < maxTries)
793784 {
794- _has_magnetometer = true ;
795- }
796- return status;
797- }
798-
799- ICM_20948_Status_e ICM_20948_I2C::magWhoIAm (void )
800- {
801- ICM_20948_Status_e retval = ICM_20948_Stat_Ok;
785+ // See if we can read the WhoIAm register correctly
786+ retval = magWhoIAm ();
787+ if (retval == ICM_20948_Stat_Ok)
788+ break ; // WIA matched!
802789
803- const uint8_t len = 2 ;
804- uint8_t whoiam[len];
805- retval = readMag (AK09916_REG_WIA1, whoiam, len);
806- status = retval;
807- if (retval != ICM_20948_Stat_Ok)
808- {
809- return retval;
790+ i2cMasterReset (); // Otherwise, reset the master I2C and try again
791+ tries++;
810792 }
811793
812- if ((whoiam[ 0 ] == (MAG_AK09916_WHO_AM_I >> 8 )) && (whoiam[ 1 ] == (MAG_AK09916_WHO_AM_I & 0xFF )) )
794+ if (tries == maxTries )
813795 {
814- retval = ICM_20948_Stat_Ok;
815- status = retval;
796+ status = ICM_20948_Stat_WrongID;
816797 return status;
817798 }
818- retval = ICM_20948_Stat_WrongID;
819- status = retval;
820- return status;
821- }
822799
823- bool ICM_20948_I2C::magIsConnected (void )
824- {
825- if (magWhoIAm () != ICM_20948_Stat_Ok)
800+ // Serial.printf("Mag connected tries: %d\n", tries);
801+
802+ // Set up magnetometer
803+ AK09916_CNTL2_Reg_t reg;
804+ reg.MODE = AK09916_mode_cont_100hz;
805+ retval = writeMag (AK09916_REG_CNTL2, (uint8_t *)®);
806+ if (retval != ICM_20948_Stat_Ok)
826807 {
827- return false ;
808+ status = retval;
809+ return status;
828810 }
829- return true ;
830- }
831-
832- ICM_20948_Status_e ICM_20948_I2C::getMagnetometerData (ICM_20948_AGMT_t *pagmt)
833- {
834-
835- const uint8_t reqd_len = 9 ; // you must read all the way through the status2 register to re-enable the next measurement
836- uint8_t buff[reqd_len];
837811
838- status = readMag ( AK09916_REG_ST1, buff, reqd_len );
839- if (status != ICM_20948_Stat_Ok)
812+ retval = i2cMasterConfigureSlave ( 0 , MAG_AK09916_I2C_ADDR, AK09916_REG_ST1, 9 , true , true , false , false , false );
813+ if (retval != ICM_20948_Stat_Ok)
840814 {
815+ status = retval;
841816 return status;
842817 }
843818
844- pagmt->mag .axes .x = ((buff[2 ] << 8 ) | (buff[1 ] & 0xFF ));
845- pagmt->mag .axes .y = ((buff[4 ] << 8 ) | (buff[3 ] & 0xFF ));
846- pagmt->mag .axes .z = ((buff[6 ] << 8 ) | (buff[5 ] & 0xFF ));
847-
848819 return status;
849820}
850821
851- ICM_20948_Status_e ICM_20948_I2C::readMag ( uint8_t reg, uint8_t *pdata, uint8_t len )
822+ ICM_20948_Status_e ICM_20948::magWhoIAm ( void )
852823{
853- _i2c->beginTransmission (MAG_AK09916_I2C_ADDR);
854- _i2c->write (reg);
855- _i2c->endTransmission (false );
824+ ICM_20948_Status_e retval = ICM_20948_Stat_Ok;
856825
857- uint8_t num_received = _i2c->requestFrom ((uint8_t )MAG_AK09916_I2C_ADDR, (uint8_t )len);
858- if (num_received != len)
826+ uint8_t whoiam1, whoiam2;
827+ whoiam1 = readMag (AK09916_REG_WIA1);
828+ whoiam2 = readMag (AK09916_REG_WIA2);
829+ status = retval;
830+ if (retval != ICM_20948_Stat_Ok)
859831 {
860- return ICM_20948_Stat_NoData ;
832+ return retval ;
861833 }
862834
863- for ( uint8_t indi = 0 ; indi < len; indi++ )
835+ if ((whoiam1 == (MAG_AK09916_WHO_AM_I >> 8 )) && (whoiam2 == (MAG_AK09916_WHO_AM_I & 0xFF )) )
864836 {
865- *(pdata + indi) = _i2c->read ();
837+ retval = ICM_20948_Stat_Ok;
838+ status = retval;
839+ return status;
866840 }
867-
868- return ICM_20948_Stat_Ok;
869- }
870-
871- ICM_20948_Status_e ICM_20948_I2C::writeMag (uint8_t reg, uint8_t *pdata, uint8_t len)
872- {
873- _i2c->beginTransmission (MAG_AK09916_I2C_ADDR);
874- _i2c->write (reg);
875- _i2c->write (pdata, len);
876- _i2c->endTransmission ();
877- return ICM_20948_Stat_Ok; // todo: check return of 'endTransmission' to verify all bytes sent w/ ACK
841+ retval = ICM_20948_Stat_WrongID;
842+ status = retval;
843+ return status;
878844}
879845
880846// SPI
@@ -923,8 +889,6 @@ ICM_20948_Status_e ICM_20948_SPI::begin(uint8_t csPin, SPIClass &spiPort, uint32
923889 return status;
924890 }
925891
926- // todo: disable I2C interface to prevent accidents
927-
928892 return ICM_20948_Stat_Ok;
929893}
930894
0 commit comments