@@ -53,6 +53,13 @@ SFE_UBLOX_GNSS::SFE_UBLOX_GNSS(void)
53
53
54
54
_logNMEA.all = 0 ; // Default to passing no NMEA messages to the file buffer
55
55
_processNMEA.all = SFE_UBLOX_FILTER_NMEA_ALL; // Default to passing all NMEA messages to processNMEA
56
+
57
+ // Support for platforms like ESP32 which do not support multiple I2C restarts
58
+ #if defined(ARDUINO_ARCH_ESP32)
59
+ _i2cStopRestart = true ; // Always use a stop
60
+ #else
61
+ _i2cStopRestart = false ; // Use a restart where needed
62
+ #endif
56
63
}
57
64
58
65
// Stop all automatic message processing. Free all used RAM
@@ -533,6 +540,9 @@ void SFE_UBLOX_GNSS::setSPIpollingWait(uint8_t newPollingWait_ms)
533
540
// Note: If the transaction size is set larger than the platforms buffer size, bad things will happen.
534
541
void SFE_UBLOX_GNSS::setI2CTransactionSize (uint8_t transactionSize)
535
542
{
543
+ if (transactionSize < 8 )
544
+ transactionSize = 8 ; // Ensure transactionSize is at least 8 bytes otherwise sendI2cCommand will have problems!
545
+
536
546
i2cTransactionSize = transactionSize;
537
547
}
538
548
uint8_t SFE_UBLOX_GNSS::getI2CTransactionSize (void )
@@ -715,7 +725,7 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC
715
725
uint16_t bytesAvailable = 0 ;
716
726
_i2cPort->beginTransmission (_gpsI2Caddress);
717
727
_i2cPort->write (0xFD ); // 0xFD (MSB) and 0xFE (LSB) are the registers that contain number of bytes available
718
- uint8_t i2cError = _i2cPort->endTransmission (false ); // Send a restart command. Do not release bus.
728
+ uint8_t i2cError = _i2cPort->endTransmission (false ); // Always send a restart command. Do not release bus. ESP32 supports this .
719
729
if (i2cError != 0 )
720
730
{
721
731
if ((_printDebug == true ) || (_printLimitedDebug == true )) // This is important. Print this if doing limited debugging
@@ -726,7 +736,7 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC
726
736
return (false ); // Sensor did not ACK
727
737
}
728
738
729
- uint8_t bytesReturned = _i2cPort->requestFrom ((uint8_t )_gpsI2Caddress, (uint8_t )2 );
739
+ uint8_t bytesReturned = _i2cPort->requestFrom ((uint8_t )_gpsI2Caddress, (uint8_t )2 ); // TO DO: add _i2cStopRestart here
730
740
if (bytesReturned != 2 )
731
741
{
732
742
if ((_printDebug == true ) || (_printLimitedDebug == true )) // This is important. Print this if doing limited debugging
@@ -740,23 +750,23 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC
740
750
{
741
751
uint8_t msb = _i2cPort->read ();
742
752
uint8_t lsb = _i2cPort->read ();
743
- if (lsb == 0xFF )
744
- {
745
- // I believe this is a u-blox bug. Device should never present an 0xFF.
746
- if ((_printDebug == true ) || (_printLimitedDebug == true )) // This is important. Print this if doing limited debugging
747
- {
748
- _debugSerial->print (F (" checkUbloxI2C: u-blox bug? Length lsb is 0xFF. i2cPollingWait is " ));
749
- _debugSerial->println (i2cPollingWait);
750
- }
751
- if (debugPin >= 0 )
752
- {
753
- digitalWrite ((uint8_t )debugPin, LOW);
754
- delay (10 );
755
- digitalWrite ((uint8_t )debugPin, HIGH);
756
- }
757
- lastCheck = millis (); // Put off checking to avoid I2C bus traffic
758
- return (false );
759
- }
753
+ // if (lsb == 0xFF)
754
+ // {
755
+ // //I believe this is a u-blox bug. Device should never present an 0xFF.
756
+ // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
757
+ // {
758
+ // _debugSerial->print(F("checkUbloxI2C: u-blox bug? Length lsb is 0xFF. i2cPollingWait is "));
759
+ // _debugSerial->println(i2cPollingWait);
760
+ // }
761
+ // if (debugPin >= 0)
762
+ // {
763
+ // digitalWrite((uint8_t)debugPin, LOW);
764
+ // delay(10);
765
+ // digitalWrite((uint8_t)debugPin, HIGH);
766
+ // }
767
+ // lastCheck = millis(); //Put off checking to avoid I2C bus traffic
768
+ // return (false);
769
+ // }
760
770
// if (msb == 0xFF)
761
771
// {
762
772
// //I believe this is a u-blox bug. Device should never present an 0xFF.
@@ -833,10 +843,20 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC
833
843
834
844
while (bytesAvailable)
835
845
{
836
- _i2cPort->beginTransmission (_gpsI2Caddress);
837
- _i2cPort->write (0xFF ); // 0xFF is the register to read data from
838
- if (_i2cPort->endTransmission (false ) != 0 ) // Send a restart command. Do not release bus.
839
- return (false ); // Sensor did not ACK
846
+ // PaulZC : November 15th 2021
847
+ // From the u-blox integration manual:
848
+ // "There are two forms of DDC read transfer. The "random access" form includes a peripheral register
849
+ // address and thus allows any register to be read. The second "current address" form omits the
850
+ // register address. If this second form is used, then an address pointer in the receiver is used to
851
+ // determine which register to read. This address pointer will increment after each read unless it
852
+ // is already pointing at register 0xFF, the highest addressable register, in which case it remains
853
+ // unaltered."
854
+ // This means that after reading bytesAvailable from 0xFD and 0xFE, the address pointer will already be
855
+ // pointing at 0xFF, so we do not need to write it here. The next four lines can be commented.
856
+ // _i2cPort->beginTransmission(_gpsI2Caddress);
857
+ // _i2cPort->write(0xFF); //0xFF is the register to read data from
858
+ // if (_i2cPort->endTransmission(false) != 0) //Send a restart command. Do not release bus.
859
+ // return (false); //Sensor did not ACK
840
860
841
861
// Limit to 32 bytes or whatever the buffer limit is for given platform
842
862
uint16_t bytesToRead = bytesAvailable;
@@ -845,7 +865,7 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC
845
865
846
866
TRY_AGAIN:
847
867
848
- _i2cPort->requestFrom ((uint8_t )_gpsI2Caddress, (uint8_t )bytesToRead);
868
+ _i2cPort->requestFrom ((uint8_t )_gpsI2Caddress, (uint8_t )bytesToRead); // TO DO: add _i2cStopRestart here
849
869
if (_i2cPort->available ())
850
870
{
851
871
for (uint16_t x = 0 ; x < bytesToRead; x++)
@@ -854,24 +874,24 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC
854
874
855
875
// Check to see if the first read is 0x7F. If it is, the module is not ready
856
876
// to respond. Stop, wait, and try again
857
- if (x == 0 )
858
- {
859
- if ((incoming == 0x7F ) && (ubx7FcheckDisabled == false ))
860
- {
861
- if ((_printDebug == true ) || (_printLimitedDebug == true )) // This is important. Print this if doing limited debugging
862
- {
863
- _debugSerial->println (F (" checkUbloxU2C: u-blox error, module not ready with data (7F error)" ));
864
- }
865
- delay (5 ); // In logic analyzation, the module starting responding after 1.48ms
866
- if (debugPin >= 0 )
867
- {
868
- digitalWrite ((uint8_t )debugPin, LOW);
869
- delay (10 );
870
- digitalWrite ((uint8_t )debugPin, HIGH);
871
- }
872
- goto TRY_AGAIN;
873
- }
874
- }
877
+ // if (x == 0)
878
+ // {
879
+ // if ((incoming == 0x7F) && (ubx7FcheckDisabled == false))
880
+ // {
881
+ // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
882
+ // {
883
+ // _debugSerial->println(F("checkUbloxU2C: u-blox error, module not ready with data (7F error)"));
884
+ // }
885
+ // delay(5); //In logic analyzation, the module starting responding after 1.48ms
886
+ // if (debugPin >= 0)
887
+ // {
888
+ // digitalWrite((uint8_t)debugPin, LOW);
889
+ // delay(10);
890
+ // digitalWrite((uint8_t)debugPin, HIGH);
891
+ // }
892
+ // goto TRY_AGAIN;
893
+ // }
894
+ // }
875
895
876
896
process (incoming, incomingUBX, requestedClass, requestedID); // Process this valid character
877
897
}
@@ -2902,56 +2922,121 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t
2902
2922
// Returns false if sensor fails to respond to I2C traffic
2903
2923
sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand (ubxPacket *outgoingUBX, uint16_t maxWait)
2904
2924
{
2905
- // Point at 0xFF data register
2906
- _i2cPort->beginTransmission ((uint8_t )_gpsI2Caddress); // There is no register to write to, we just begin writing data bytes
2907
- _i2cPort->write (0xFF );
2908
- if (_i2cPort->endTransmission (false ) != 0 ) // Don't release bus
2909
- return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); // Sensor did not ACK
2910
-
2911
- // Write header bytes
2912
- _i2cPort->beginTransmission ((uint8_t )_gpsI2Caddress); // There is no register to write to, we just begin writing data bytes
2913
- _i2cPort->write (UBX_SYNCH_1); // μ - oh ublox, you're funny. I will call you micro-blox from now on.
2914
- _i2cPort->write (UBX_SYNCH_2); // b
2915
- _i2cPort->write (outgoingUBX->cls );
2916
- _i2cPort->write (outgoingUBX->id );
2917
- _i2cPort->write (outgoingUBX->len & 0xFF ); // LSB
2918
- _i2cPort->write (outgoingUBX->len >> 8 ); // MSB
2919
- if (_i2cPort->endTransmission (false ) != 0 ) // Do not release bus
2920
- return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); // Sensor did not ACK
2925
+ // PaulZC : November 15th 2021
2926
+ // From the integration guide:
2927
+ // "The receiver does not provide any write access except for writing UBX and NMEA messages to the
2928
+ // receiver, such as configuration or aiding data. Therefore, the register set mentioned in section Read
2929
+ // Access is not writeable. Following the start condition from the master, the 7-bit device address and
2930
+ // the RW bit (which is a logic low for write access) are clocked onto the bus by the master transmitter.
2931
+ // The receiver answers with an acknowledge (logic low) to indicate that it is responsible for the given
2932
+ // address. Now, the master can write 2 to N bytes to the receiver, generating a stop condition after the
2933
+ // last byte being written. The number of data bytes must be at least 2 to properly distinguish from
2934
+ // the write access to set the address counter in random read accesses."
2935
+ // I take two things from this:
2936
+ // 1) We do not need to write 0xFF to point at register 0xFF. We're already pointing at it.
2937
+ // 2) We must always write at least 2 bytes, otherwise it looks like we are starting to do a read.
2938
+ // Point 2 is important. It means:
2939
+ // * In this function:
2940
+ // if we do multiple writes (because we're trying to write more than i2cTransactionSize),
2941
+ // we may need to write one byte less in the previous write to ensure we always have two bytes left for the final write.
2942
+ // * In pushRawData:
2943
+ // if there is one byte to write, or one byte left to write, we need to do the same thing and may need to store a single
2944
+ // byte until pushRawData is called again.
2945
+ // The next four lines can be commented. We do not need to point at the 0xFF data register
2946
+ // _i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); //There is no register to write to, we just begin writing data bytes
2947
+ // _i2cPort->write(0xFF);
2948
+ // if (_i2cPort->endTransmission(false) != 0) //Don't release bus
2949
+ // return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); //Sensor did not ACK
2950
+
2951
+ // The total number of bytes to be written is: payload len + 8
2952
+ // UBX_SYNCH_1
2953
+ // UBX_SYNCH_2
2954
+ // cls
2955
+ // id
2956
+ // len (MSB)
2957
+ // len (LSB)
2958
+ // < payload >
2959
+ // checksumA
2960
+ // checksumB
2961
+
2962
+ // i2cTransactionSize will be at least 8. We don't need to check for smaller values than that.
2963
+
2964
+ uint16_t bytesToSend = outgoingUBX->len + 8 ; // How many bytes need to be sent?
2965
+ uint16_t bytesSent = 0 ; // How many bytes have been sent
2966
+ uint16_t bytesLeftToSend = bytesToSend; // How many bytes remain to be sent?
2921
2967
2922
- // Write payload. Limit the sends into 32 byte chunks
2923
- // This code based on ublox: https://forum.u-blox.com/index.php/20528/how-to-use-i2c-to-get-the-nmea-frames
2924
- uint16_t bytesToSend = outgoingUBX->len ;
2925
-
2926
- // "The number of data bytes must be at least 2 to properly distinguish
2927
- // from the write access to set the address counter in random read accesses."
2928
2968
uint16_t startSpot = 0 ;
2929
- while (bytesToSend > 1 )
2969
+ while (bytesLeftToSend > 0 )
2930
2970
{
2931
- uint8_t len = bytesToSend;
2932
- if (len > i2cTransactionSize)
2971
+ uint8_t len = bytesLeftToSend; // How many bytes should we actually write?
2972
+ if (len > i2cTransactionSize) // Limit len to i2cTransactionSize
2933
2973
len = i2cTransactionSize;
2934
2974
2935
- _i2cPort-> beginTransmission (( uint8_t )_gpsI2Caddress);
2975
+ bytesLeftToSend -= len; // Calculate how many bytes will be left after we do this write
2936
2976
2937
- for (uint16_t x = 0 ; x < len; x++)
2938
- _i2cPort->write (outgoingUBX->payload [startSpot + x]); // Write a portion of the payload to the bus
2977
+ // If bytesLeftToSend is zero, that's OK.
2978
+ // If bytesLeftToSend is >= 2, that's OK.
2979
+ // But if bytesLeftToSend is 1, we need to adjust len to make sure we write at least 2 bytes in the final write
2980
+ if (bytesLeftToSend == 1 )
2981
+ {
2982
+ len -= 1 ; // Decrement len by 1
2983
+ bytesLeftToSend += 1 ; // Increment bytesLeftToSend by 1
2984
+ }
2939
2985
2940
- if (_i2cPort->endTransmission (false ) != 0 ) // Don't release bus
2941
- return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); // Sensor did not ACK
2986
+ _i2cPort->beginTransmission ((uint8_t )_gpsI2Caddress); // Start the transmission
2942
2987
2943
- startSpot += len; // Move the pointer forward
2944
- bytesToSend -= len;
2945
- }
2988
+ if (bytesSent == 0 ) // Is this the first write? If it is, write the header bytes
2989
+ {
2990
+ _i2cPort->write (UBX_SYNCH_1); // μ - oh ublox, you're funny. I will call you micro-blox from now on.
2991
+ _i2cPort->write (UBX_SYNCH_2); // b
2992
+ _i2cPort->write (outgoingUBX->cls );
2993
+ _i2cPort->write (outgoingUBX->id );
2994
+ _i2cPort->write (outgoingUBX->len & 0xFF ); // LSB
2995
+ _i2cPort->write (outgoingUBX->len >> 8 ); // MSB
2946
2996
2947
- _i2cPort-> beginTransmission (( uint8_t )_gpsI2Caddress) ;
2997
+ bytesSent += 6 ;
2948
2998
2949
- if (bytesToSend == 1 ) // Send the single remaining byte if there is one
2950
- _i2cPort->write (outgoingUBX->payload [startSpot]); // Thank you @Valrakk #61
2999
+ uint16_t x;
3000
+ for (x = 0 ; (x < outgoingUBX->len ) && (bytesSent < len); x++) // Write a portion of the payload to the bus
3001
+ {
3002
+ _i2cPort->write (outgoingUBX->payload [startSpot + x]);
3003
+ bytesSent++;
3004
+ }
3005
+ startSpot += x;
2951
3006
2952
- // Write checksum
2953
- _i2cPort->write (outgoingUBX->checksumA );
2954
- _i2cPort->write (outgoingUBX->checksumB );
3007
+ if (bytesSent < len) // Do we need to write both checksum bytes? (Remember that bytesLeftToSend will be zero or >=2 here)
3008
+ {
3009
+ // Write checksum
3010
+ _i2cPort->write (outgoingUBX->checksumA );
3011
+ _i2cPort->write (outgoingUBX->checksumB );
3012
+ bytesSent += 2 ;
3013
+ }
3014
+ }
3015
+ else if (bytesSent < bytesToSend) // Keep writing payload bytes - plus the checksum if required
3016
+ {
3017
+ uint16_t x;
3018
+ for (x = 0 ; (x < len) && ((startSpot + x) < (outgoingUBX->len )); x++) // Write a portion of the payload to the bus
3019
+ {
3020
+ _i2cPort->write (outgoingUBX->payload [startSpot + x]);
3021
+ bytesSent++;
3022
+ }
3023
+ startSpot += x;
3024
+
3025
+ if (bytesSent == (bytesToSend - 2 )) // Do we need to write both checksum bytes? (Remember that bytesLeftToSend will be zero or >=2 here)
3026
+ {
3027
+ // Write checksum
3028
+ _i2cPort->write (outgoingUBX->checksumA );
3029
+ _i2cPort->write (outgoingUBX->checksumB );
3030
+ bytesSent += 2 ;
3031
+ }
3032
+ }
3033
+
3034
+ if (bytesSent < bytesToSend) // Are we all done?
3035
+ {
3036
+ if (_i2cPort->endTransmission (_i2cStopRestart) != 0 ) // Don't release bus unless we have to
3037
+ return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); // Sensor did not ACK
3038
+ }
3039
+ }
2955
3040
2956
3041
// All done transmitting bytes. Release bus.
2957
3042
if (_i2cPort->endTransmission () != 0 )
@@ -3722,6 +3807,16 @@ boolean SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, boo
3722
3807
}
3723
3808
else if (commType == COMM_TYPE_I2C)
3724
3809
{
3810
+ // If stop is true then always use a stop
3811
+ // Else if _i2cStopRestart is true then always use a stop
3812
+ // Else use a restart where needed
3813
+ if (stop == true )
3814
+ stop = true ; // Redundant - but makes it clear what is happening
3815
+ else if (_i2cStopRestart == true )
3816
+ stop = true ;
3817
+ else
3818
+ stop = false ; // Use a restart
3819
+
3725
3820
// I2C: split the data up into packets of i2cTransactionSize
3726
3821
size_t bytesLeftToWrite = numDataBytes;
3727
3822
size_t bytesWrittenTotal = 0 ;
0 commit comments