@@ -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,9 +600,10 @@ 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- ICM_20948_Status_e ICM_20948::i2cMasterSingleW (uint8_t addr, uint8_t reg, uint8_t data)
603+
604+ ICM_20948_Status_e ICM_20948::i2cMasterSingleW (uint8_t addr, uint8_t reg, uint8_t *data)
604605{
605- status = ICM_20948_i2c_master_single_w (&_device, addr, reg, & data);
606+ status = ICM_20948_i2c_master_single_w (&_device, addr, reg, data);
606607 return status;
607608}
608609uint8_t ICM_20948::i2cMasterSingleR (uint8_t addr, uint8_t reg)
@@ -684,40 +685,16 @@ 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 )
712- {
713- return ICM_20948_Stat_NotImpl; // By default we assume that we cannot access the magnetometer
714- }
715-
716- ICM_20948_Status_e ICM_20948::getMagnetometerData (ICM_20948_AGMT_t *pagmt)
717- {
718- return ICM_20948_Stat_NotImpl; // By default we assume that we cannot access the magnetometer
719- }
720-
721698// direct read/write
722699ICM_20948_Status_e ICM_20948::read (uint8_t reg, uint8_t *pdata, uint32_t len)
723700{
@@ -731,6 +708,18 @@ ICM_20948_Status_e ICM_20948::write(uint8_t reg, uint8_t *pdata, uint32_t len)
731708 return (status);
732709}
733710
711+ uint8_t ICM_20948::readMag (AK09916_Reg_Addr_e reg)
712+ {
713+ uint8_t data = i2cMasterSingleR (MAG_AK09916_I2C_ADDR, reg);
714+ return data;
715+ }
716+
717+ ICM_20948_Status_e ICM_20948::writeMag (AK09916_Reg_Addr_e reg, uint8_t *pdata)
718+ {
719+ status = i2cMasterSingleW (MAG_AK09916_I2C_ADDR, reg, pdata);
720+ return status;
721+ }
722+
734723// I2C
735724ICM_20948_I2C::ICM_20948_I2C ()
736725{
@@ -780,103 +769,78 @@ ICM_20948_Status_e ICM_20948_I2C::begin(TwoWire &wirePort, bool ad0val, uint8_t
780769 return status;
781770}
782771
783- ICM_20948_Status_e ICM_20948_I2C ::startupMagnetometer (void )
772+ ICM_20948_Status_e ICM_20948 ::startupMagnetometer (void )
784773{
785- // If using the magnetometer through passthrough:
786- 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;
787775
788- // Try to set up magnetometer
789- AK09916_CNTL2_Reg_t reg;
790- reg.MODE = AK09916_mode_cont_100hz;
776+ i2cMasterPassthrough (false ); // Do not connect the SDA/SCL pins to AUX_DA/AUX_CL
777+ i2cMasterEnable (true );
791778
792- ICM_20948_Status_e retval = writeMag (AK09916_REG_CNTL2, (uint8_t *)®, sizeof (AK09916_CNTL2_Reg_t));
793- status = retval;
794- 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)
795784 {
796- _has_magnetometer = true ;
797- }
798- return status;
799- }
785+ // See if we can read the WhoIAm register correctly
786+ retval = magWhoIAm ();
787+ if (retval == ICM_20948_Stat_Ok)
788+ break ; // WIA matched!
800789
801- ICM_20948_Status_e ICM_20948_I2C::magWhoIAm (void )
802- {
803- ICM_20948_Status_e retval = ICM_20948_Stat_Ok;
804-
805- const uint8_t len = 2 ;
806- uint8_t whoiam[len];
807- retval = readMag (AK09916_REG_WIA1, whoiam, len);
808- status = retval;
809- if (retval != ICM_20948_Stat_Ok)
810- {
811- return retval;
790+ i2cMasterReset (); // Otherwise, reset the master I2C and try again
791+ tries++;
812792 }
813793
814- if ((whoiam[ 0 ] == (MAG_AK09916_WHO_AM_I >> 8 )) && (whoiam[ 1 ] == (MAG_AK09916_WHO_AM_I & 0xFF )) )
794+ if (tries == maxTries )
815795 {
816- retval = ICM_20948_Stat_Ok;
817- status = retval;
796+ status = ICM_20948_Stat_WrongID;
818797 return status;
819798 }
820- retval = ICM_20948_Stat_WrongID;
821- status = retval;
822- return status;
823- }
824799
825- bool ICM_20948_I2C::magIsConnected (void )
826- {
827- 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)
828807 {
829- return false ;
808+ status = retval;
809+ return status;
830810 }
831- return true ;
832- }
833811
834- ICM_20948_Status_e ICM_20948_I2C::getMagnetometerData (ICM_20948_AGMT_t *pagmt)
835- {
836-
837- const uint8_t reqd_len = 9 ; // you must read all the way through the status2 register to re-enable the next measurement
838- uint8_t buff[reqd_len];
839-
840- status = readMag (AK09916_REG_ST1, buff, reqd_len);
841- 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)
842814 {
815+ status = retval;
843816 return status;
844817 }
845818
846- pagmt->mag .axes .x = ((buff[2 ] << 8 ) | (buff[1 ] & 0xFF ));
847- pagmt->mag .axes .y = ((buff[4 ] << 8 ) | (buff[3 ] & 0xFF ));
848- pagmt->mag .axes .z = ((buff[6 ] << 8 ) | (buff[5 ] & 0xFF ));
849-
850819 return status;
851820}
852821
853- 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 )
854823{
855- _i2c->beginTransmission (MAG_AK09916_I2C_ADDR);
856- _i2c->write (reg);
857- _i2c->endTransmission (false );
824+ ICM_20948_Status_e retval = ICM_20948_Stat_Ok;
858825
859- uint8_t num_received = _i2c->requestFrom ((uint8_t )MAG_AK09916_I2C_ADDR, (uint8_t )len);
860- 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)
861831 {
862- return ICM_20948_Stat_NoData ;
832+ return retval ;
863833 }
864834
865- for ( uint8_t indi = 0 ; indi < len; indi++ )
835+ if ((whoiam1 == (MAG_AK09916_WHO_AM_I >> 8 )) && (whoiam2 == (MAG_AK09916_WHO_AM_I & 0xFF )) )
866836 {
867- *(pdata + indi) = _i2c->read ();
837+ retval = ICM_20948_Stat_Ok;
838+ status = retval;
839+ return status;
868840 }
869-
870- return ICM_20948_Stat_Ok;
871- }
872-
873- ICM_20948_Status_e ICM_20948_I2C::writeMag (uint8_t reg, uint8_t *pdata, uint8_t len)
874- {
875- _i2c->beginTransmission (MAG_AK09916_I2C_ADDR);
876- _i2c->write (reg);
877- _i2c->write (pdata, len);
878- _i2c->endTransmission ();
879- 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;
880844}
881845
882846// SPI
@@ -925,8 +889,6 @@ ICM_20948_Status_e ICM_20948_SPI::begin(uint8_t csPin, SPIClass &spiPort, uint32
925889 return status;
926890 }
927891
928- // todo: disable I2C interface to prevent accidents
929-
930892 return ICM_20948_Stat_Ok;
931893}
932894
0 commit comments