Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit 86e78de

Browse files
authored
Merge pull request #89 from sparkfun/Serial_checksum_correction
Better packet validity checking
2 parents 180d9c5 + 4cc1afa commit 86e78de

File tree

2 files changed

+78
-52
lines changed

2 files changed

+78
-52
lines changed

src/SparkFun_Ublox_Arduino_Library.cpp

+67-49
Original file line numberDiff line numberDiff line change
@@ -472,13 +472,13 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
472472
if (incoming == UBX_CLASS_ACK)
473473
{
474474
packetAck.counter = 0;
475-
packetAck.valid = false;
475+
packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
476476
ubxFrameClass = CLASS_ACK;
477477
}
478478
else
479479
{
480480
packetCfg.counter = 0;
481-
packetCfg.valid = false;
481+
packetCfg.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
482482
ubxFrameClass = CLASS_NOT_AN_ACK;
483483
}
484484
}
@@ -573,7 +573,7 @@ void SFE_UBLOX_GPS::processRTCM(uint8_t incoming)
573573
}
574574

575575
//Given a character, file it away into the uxb packet structure
576-
//Set valid = true once sentence is completely received and passes CRC
576+
//Set valid to VALID or NOT_VALID once sentence is completely received and passes or fails CRC
577577
//The payload portion of the packet can be 100s of bytes but the max array
578578
//size is roughly 64 bytes. startingSpot can be set so we only record
579579
//a subset of bytes within a larger packet.
@@ -613,7 +613,7 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX)
613613
//Validate this sentence
614614
if (incomingUBX->checksumA == rollingChecksumA && incomingUBX->checksumB == rollingChecksumB)
615615
{
616-
incomingUBX->valid = true;
616+
incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_VALID;
617617

618618
if (_printDebug == true)
619619
{
@@ -622,14 +622,14 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX)
622622
_debugSerial->print(F(" Received: "));
623623
printPacket(incomingUBX);
624624

625-
if (packetCfg.valid == true)
625+
if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID)
626626
{
627627
if (_printDebug == true)
628628
{
629629
_debugSerial->println(F("packetCfg now valid"));
630630
}
631631
}
632-
if (packetAck.valid == true)
632+
if (packetAck.valid == SFE_UBLOX_PACKET_VALIDITY_VALID)
633633
{
634634
if (_printDebug == true)
635635
{
@@ -640,8 +640,10 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX)
640640

641641
processUBXpacket(incomingUBX); //We've got a valid packet, now do something with it
642642
}
643-
else
643+
else // Checksum failure
644644
{
645+
incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_NOT_VALID;
646+
645647
if (_printDebug == true)
646648
{
647649
//Drive an external pin to allow for easier logic analyzation
@@ -1067,18 +1069,30 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet)
10671069
//"not acknowledge"(UBX-ACK-NAK) message back to the sender, depending on whether or not the message was processed correctly.
10681070
//Some messages from other classes also use the same acknowledgement mechanism.
10691071

1070-
//If the packetCfg len is 1, then we are querying the device for data
1071-
//If the packetCfg len is >1, then we are sending a new setting
1072+
//When we poll or get a setting, we will receive _both_ a config packet and an ACK
1073+
//If the poll or get request is not valid, we will receive _only_ a NACK
1074+
1075+
//If we are trying to get or poll a setting, then packetCfg.len will be 0 or 1 when the packetCfg is _sent_.
1076+
//If we poll the setting for a particular port using UBX-CFG-PRT then .len will be 1 initially
1077+
//For all other gets or polls, .len will be 0 initially
1078+
//(It would be possible for .len to be 2 _if_ we were using UBX-CFG-MSG to poll the settings for a particular message - but we don't use that (currently))
1079+
1080+
//If the get or poll _fails_, i.e. is NACK'd, then packetCfg.len could still be 0 or 1 after the NACK is received
1081+
//But if the get or poll is ACK'd, then packetCfg.len will have been updated by the incoming data and will always be at least 2
1082+
1083+
//If we are going to set the value for a setting, then packetCfg.len will be at least 3 when the packetCfg is _sent_.
1084+
//(UBX-CFG-MSG appears to have the shortest set length of 3 bytes)
10721085

1073-
//Returns true if we got the following:
1074-
//* If packetCfg len is 1 and we got and ACK and a valid packetCfg (module is responding with register content)
1075-
//* If packetCfg len is >1 and we got an ACK (no valid packetCfg needed, module absorbs new register data)
1076-
//Returns false if we timed out, got a NACK (command unknown), or had a CLS/ID mismatch
1086+
//Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg (module is responding with register content)
1087+
//Returns SFE_UBLOX_STATUS_DATA_SENT if we got an ACK and no packetCfg (no valid packetCfg needed, module absorbs new register data)
1088+
//Returns SFE_UBLOX_STATUS_FAIL if we got an invalid packetCfg (checksum failure)
1089+
//Returns SFE_UBLOX_STATUS_COMMAND_UNKNOWN if we got a NACK (command unknown)
1090+
//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out
10771091
sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime)
10781092
{
10791093
commandAck = UBX_ACK_NONE; //Reset flag
1080-
packetCfg.valid = false; //This will go true when we receive a response to the packet we sent
1081-
packetAck.valid = false;
1094+
packetCfg.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent
1095+
packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
10821096

10831097
unsigned long startTime = millis();
10841098
while (millis() - startTime < maxTime)
@@ -1095,42 +1109,43 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin
10951109
_debugSerial->println(F(" msec"));
10961110
}
10971111

1098-
//Are we expecting data back or just an ACK?
1099-
if (packetCfg.len == 1)
1112+
//We've got the a valid ACK for this CLS/ID, so is packetCfg valid?
1113+
if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID)
11001114
{
1101-
//We are expecting a data response so now we verify the response packet was valid
1102-
if (packetCfg.valid == true)
1115+
//We've got a valid packetCfg, so does it match the requested Class and ID?
1116+
if (packetCfg.cls == requestedClass && packetCfg.id == requestedID)
11031117
{
1104-
if (packetCfg.cls == requestedClass && packetCfg.id == requestedID)
1105-
{
1106-
if (_printDebug == true)
1107-
{
1108-
_debugSerial->print(F("waitForACKResponse: CLS/ID match after "));
1109-
_debugSerial->print(millis() - startTime);
1110-
_debugSerial->println(F(" msec"));
1111-
}
1112-
return (SFE_UBLOX_STATUS_DATA_RECEIVED); //Received a data and a correct ACK!
1113-
}
1114-
else
1118+
if (_printDebug == true)
11151119
{
1116-
//Reset packet and continue checking incoming data for matching cls/id
1117-
if (_printDebug == true)
1118-
{
1119-
_debugSerial->println(F("waitForACKResponse: CLS/ID mismatch, continue to wait..."));
1120-
}
1121-
packetCfg.valid = false; //This will go true when we receive a response to the packet we sent
1120+
_debugSerial->print(F("waitForACKResponse: CLS/ID match after "));
1121+
_debugSerial->print(millis() - startTime);
1122+
_debugSerial->println(F(" msec"));
11221123
}
1124+
return (SFE_UBLOX_STATUS_DATA_RECEIVED); //Received a data and a correct ACK!
11231125
}
11241126
else
1127+
// The Class and/or ID don't match the requested ones, so keep trying...
11251128
{
1126-
//We were expecting data but didn't get a valid config packet
1129+
//Reset packet and continue checking incoming data for matching cls/id
11271130
if (_printDebug == true)
11281131
{
1129-
_debugSerial->println(F("waitForACKResponse: Invalid config packet"));
1132+
_debugSerial->println(F("waitForACKResponse: CLS/ID mismatch, continue to wait..."));
11301133
}
1131-
return (SFE_UBLOX_STATUS_FAIL); //We got an ACK, we're never going to get valid config data
1134+
packetCfg.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent
1135+
}
1136+
}
1137+
//If we received an invalid packetCfg (checksum failure) then we can't trust it, including its Class and ID
1138+
else if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID)
1139+
{
1140+
//We were expecting data but didn't get a valid config packet
1141+
if (_printDebug == true)
1142+
{
1143+
_debugSerial->println(F("waitForACKResponse: Invalid config packet"));
11321144
}
1145+
return (SFE_UBLOX_STATUS_FAIL); //We got a checksum failure, we're never going to get valid config data
11331146
}
1147+
//We didn't receive a valid or invalid packetCfg, so we must have only received the ACK
1148+
//Let's hope this was a set?
11341149
else
11351150
{
11361151
//We have sent new data. We expect an ACK but no return config packet.
@@ -1141,6 +1156,7 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin
11411156
return (SFE_UBLOX_STATUS_DATA_SENT); //New data successfully sent
11421157
}
11431158
}
1159+
//Did we receive a NACK?
11441160
else if (commandAck == UBX_ACK_NACK)
11451161
{
11461162
if (_printDebug == true)
@@ -1158,7 +1174,7 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin
11581174

11591175
//TODO add check here if config went valid but we never got the following ack
11601176
//Through debug warning, This command might not get an ACK
1161-
if (packetCfg.valid == true)
1177+
if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID)
11621178
{
11631179
if (_printDebug == true)
11641180
{
@@ -1177,12 +1193,13 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin
11771193
}
11781194

11791195
//For non-CFG queries no ACK is sent so we use this function
1180-
//Returns true if we got a config packet full of response data that has CLS/ID match to our query packet
1181-
//Returns false if we timed out
1196+
//Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a config packet full of response data that has CLS/ID match to our query packet
1197+
//Returns SFE_UBLOX_STATUS_CRC_FAIL if we got a corrupt config packet that has CLS/ID match to our query packet
1198+
//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out
11821199
sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime)
11831200
{
1184-
packetCfg.valid = false; //This will go true when we receive a response to the packet we sent
1185-
packetAck.valid = false;
1201+
packetCfg.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent
1202+
packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
11861203
packetCfg.cls = 255;
11871204
packetCfg.id = 255;
11881205

@@ -1192,10 +1209,10 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u
11921209
if (checkUblox() == true) //See if new data is available. Process bytes as they come in.
11931210
{
11941211
//Did we receive a config packet that matches the cls/id we requested?
1195-
if (packetCfg.cls == requestedClass && packetCfg.id == requestedID)
1212+
if ((packetCfg.cls == requestedClass) && (packetCfg.id == requestedID) && (packetCfg.valid != SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED))
11961213
{
11971214
//This packet might be good or it might be CRC corrupt
1198-
if (packetCfg.valid == true)
1215+
if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID)
11991216
{
12001217
if (_printDebug == true)
12011218
{
@@ -1205,7 +1222,7 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u
12051222
}
12061223
return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We have new data to act upon
12071224
}
1208-
else
1225+
else // if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID)
12091226
{
12101227
if (_printDebug == true)
12111228
{
@@ -1214,8 +1231,9 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u
12141231
return (SFE_UBLOX_STATUS_CRC_FAIL); //We got the right packet but it was corrupt
12151232
}
12161233
}
1217-
else if (packetCfg.cls < 255 && packetCfg.id < 255)
1234+
else if ((packetCfg.cls < 255) && (packetCfg.id < 255) && (packetCfg.valid != SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED))
12181235
{
1236+
//We got a valid or invalid packet but it was not the droid we were looking for
12191237
//Reset packet and continue checking incoming data for matching cls/id
12201238
if (_printDebug == true)
12211239
{
@@ -1227,7 +1245,7 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u
12271245
_debugSerial->println();
12281246
}
12291247

1230-
packetCfg.valid = false; //This will go true when we receive a response to the packet we sent
1248+
packetCfg.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent
12311249
packetCfg.cls = 255;
12321250
packetCfg.id = 255;
12331251
}

src/SparkFun_Ublox_Arduino_Library.h

+11-3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ typedef enum
104104
SFE_UBLOX_STATUS_I2C_COMM_FAILURE,
105105
} sfe_ublox_status_e;
106106

107+
// ubxPacket validity
108+
typedef enum
109+
{
110+
SFE_UBLOX_PACKET_VALIDITY_NOT_VALID,
111+
SFE_UBLOX_PACKET_VALIDITY_VALID,
112+
SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED
113+
} sfe_ublox_packet_validity_e;
114+
107115
//Registers
108116
const uint8_t UBX_SYNCH_1 = 0xB5;
109117
const uint8_t UBX_SYNCH_2 = 0x62;
@@ -400,7 +408,7 @@ typedef struct
400408
uint8_t *payload;
401409
uint8_t checksumA; //Given to us from module. Checked against the rolling calculated A/B checksums.
402410
uint8_t checksumB;
403-
boolean valid; //Goes true when both checksums pass
411+
sfe_ublox_packet_validity_e valid; //Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
404412
} ubxPacket;
405413

406414
// Struct to hold the results returned by getGeofenceState (returned by UBX-NAV-GEOFENCE)
@@ -712,8 +720,8 @@ class SFE_UBLOX_GPS
712720
uint8_t payloadCfg[MAX_PAYLOAD_SIZE];
713721

714722
//Init the packet structures and init them with pointers to the payloadAck and payloadCfg arrays
715-
ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, false};
716-
ubxPacket packetCfg = {0, 0, 0, 0, 0, payloadCfg, 0, 0, false};
723+
ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
724+
ubxPacket packetCfg = {0, 0, 0, 0, 0, payloadCfg, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
717725

718726
//Limit checking of new data to every X ms
719727
//If we are expecting an update every X Hz then we should check every half that amount of time

0 commit comments

Comments
 (0)