From e16a266203b5c9237fdca537a13e031dd7c9c4a7 Mon Sep 17 00:00:00 2001 From: Paul <5690545+PaulZC@users.noreply.github.com> Date: Sat, 28 Dec 2019 19:09:16 +0000 Subject: [PATCH 1/5] Do Not Merge As-Is! But contains useful things! --- src/SparkFun_Ublox_Arduino_Library.cpp | 139 ++++++++++++++++++++----- 1 file changed, 113 insertions(+), 26 deletions(-) diff --git a/src/SparkFun_Ublox_Arduino_Library.cpp b/src/SparkFun_Ublox_Arduino_Library.cpp index c8c68e2..e45b479 100644 --- a/src/SparkFun_Ublox_Arduino_Library.cpp +++ b/src/SparkFun_Ublox_Arduino_Library.cpp @@ -281,7 +281,11 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C() if (lsb == 0xFF) { //I believe this is a Ublox bug. Device should never present an 0xFF. - debugPrintln((char *)F("checkUbloxI2C: Ublox bug, no bytes available")); + if (_printDebug == true) + { + _debugSerial->println(F("checkUbloxI2C: Ublox bug, no bytes available")); + } + //debugPrintln((char *)F("checkUbloxI2C: Ublox bug, no bytes available")); lastCheck = millis(); //Put off checking to avoid I2C bus traffic return (false); } @@ -290,7 +294,11 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C() if (bytesAvailable == 0) { - debugPrintln((char *)F("checkUbloxI2C: OK, zero bytes available")); + if (_printDebug == true) + { + _debugSerial->println(F("checkUbloxI2C: OK, zero bytes available")); + } + //debugPrintln((char *)F("checkUbloxI2C: OK, zero bytes available")); lastCheck = millis(); //Put off checking to avoid I2C bus traffic return (false); } @@ -347,7 +355,11 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C() { if (incoming == 0x7F) { - debugPrintln((char *)F("Module not ready with data")); + if (_printDebug == true) + { + _debugSerial->println(F("Module not ready with data")); + } + //debugPrintln((char *)F("Module not ready with data")); delay(5); //In logic analyzation, the module starting responding after 1.48ms goto TRY_AGAIN; } @@ -542,7 +554,7 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX) } else if (incomingUBX->counter == 1) { - incomingUBX->id = incoming; + incomingUBX->id = incoming; // PZC: packetCfg.cls and .id will match NOW - not at the end of the message! } else if (incomingUBX->counter == 2) //Len LSB { @@ -575,9 +587,21 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX) printPacket(incomingUBX); if (packetCfg.valid == true) - debugPrintln((char *)F("packetCfg now valid")); + { + if (_printDebug == true) + { + _debugSerial->println(F("packetCfg now valid")); + } + //debugPrintln((char *)F("packetCfg now valid")); + } if (packetAck.valid == true) - debugPrintln((char *)F("packetAck now valid")); + { + if (_printDebug == true) + { + _debugSerial->println(F("packetAck now valid")); + } + //debugPrintln((char *)F("packetAck now valid")); + } } processUBXpacket(incomingUBX); //We've got a valid packet, now do something with it @@ -594,7 +618,8 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX) digitalWrite((uint8_t)checksumFailurePin, HIGH); } - debugPrint((char *)F("Checksum failed:")); + _debugSerial->print(F("Checksum failed:")); + //debugPrint((char *)F("Checksum failed:")); _debugSerial->print(F(" checksumA: ")); _debugSerial->print(incomingUBX->checksumA); _debugSerial->print(F(" checksumB: ")); @@ -642,13 +667,21 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg) if (msg->id == UBX_ACK_ACK && msg->payload[0] == packetCfg.cls && msg->payload[1] == packetCfg.id) { //The ack we just received matched the CLS/ID of last packetCfg sent (or received) - debugPrintln((char *)F("UBX ACK: Command sent/ack'd successfully")); + if (_printDebug == true) + { + _debugSerial->println(F("UBX ACK: Command sent/ack'd successfully")); + } + //debugPrintln((char *)F("UBX ACK: Command sent/ack'd successfully")); commandAck = UBX_ACK_ACK; } else if (msg->id == UBX_ACK_NACK && msg->payload[0] == packetCfg.cls && msg->payload[1] == packetCfg.id) { //The ack we just received matched the CLS/ID of last packetCfg sent - debugPrintln((char *)F("UBX ACK: Not-Acknowledged")); + if (_printDebug == true) + { + _debugSerial->println(F("UBX ACK: Not-Acknowledged")); + } + //debugPrintln((char *)F("UBX ACK: Not-Acknowledged")); commandAck = UBX_ACK_NACK; } break; @@ -773,7 +806,11 @@ sfe_ublox_status_e SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t ma retVal = sendI2cCommand(outgoingUBX, maxWait); if (retVal != SFE_UBLOX_STATUS_SUCCESS) { - debugPrintln((char *)F("Send I2C Command failed")); + if (_printDebug == true) + { + _debugSerial->println(F("Send I2C Command failed")); + } + //debugPrintln((char *)F("Send I2C Command failed")); return retVal; } } @@ -787,12 +824,20 @@ sfe_ublox_status_e SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t ma //Depending on what we just sent, either we need to look for an ACK or not if (outgoingUBX.cls == UBX_CLASS_CFG) { - debugPrintln((char *)F("sendCommand: Waiting for ACK response")); + if (_printDebug == true) + { + _debugSerial->println(F("sendCommand: Waiting for ACK response")); + } + //debugPrintln((char *)F("sendCommand: Waiting for ACK response")); retVal = waitForACKResponse(outgoingUBX.cls, outgoingUBX.id, maxWait); //Wait for Ack response } else { - debugPrintln((char *)F("sendCommand: Waiting for No ACK response")); + if (_printDebug == true) + { + _debugSerial->println(F("sendCommand: Waiting for No ACK response")); + } + //debugPrintln((char *)F("sendCommand: Waiting for No ACK response")); retVal = waitForNoACKResponse(outgoingUBX.cls, outgoingUBX.id, maxWait); //Wait for Ack response } } @@ -1009,7 +1054,7 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin } //Are we expecting data back or just an ACK? - if (packetCfg.len == 1) + if (packetCfg.len == 1) // PZC: Maybe this should be <= 1 ? Most gets are zero length ? { //We are expecting a data response so now we verify the response packet was valid if (packetCfg.valid == true) @@ -1027,21 +1072,33 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin else { //Reset packet and continue checking incoming data for matching cls/id - debugPrintln((char *)F("waitForACKResponse: CLS/ID mismatch, continue to wait...")); + if (_printDebug == true) + { + _debugSerial->println(F("waitForACKResponse: CLS/ID mismatch, continue to wait...")); + } + //debugPrintln((char *)F("waitForACKResponse: CLS/ID mismatch, continue to wait...")); packetCfg.valid = false; //This will go true when we receive a response to the packet we sent } } else { //We were expecting data but didn't get a valid config packet - debugPrintln((char *)F("waitForACKResponse: Invalid config packet")); + if (_printDebug == true) + { + _debugSerial->println(F("waitForACKResponse: Invalid config packet")); + } + //debugPrintln((char *)F("waitForACKResponse: Invalid config packet")); return (SFE_UBLOX_STATUS_FAIL); //We got an ACK, we're never going to get valid config data } } else { //We have sent new data. We expect an ACK but no return config packet. - debugPrintln((char *)F("waitForACKResponse: New data successfully sent")); + if (_printDebug == true) + { + _debugSerial->println(F("waitForACKResponse: New data successfully sent")); + } + //debugPrintln((char *)F("waitForACKResponse: New data successfully sent")); return (SFE_UBLOX_STATUS_DATA_SENT); //New data successfully sent } } @@ -1064,7 +1121,11 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin //Through debug warning, This command might not get an ACK if (packetCfg.valid == true) { - debugPrintln((char *)F("waitForACKResponse: Config was valid but ACK not received")); + if (_printDebug == true) + { + _debugSerial->println(F("waitForACKResponse: Config was valid but ACK not received")); + } + //debugPrintln((char *)F("waitForACKResponse: Config was valid but ACK not received")); } if (_printDebug == true) @@ -1093,7 +1154,7 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u if (checkUblox() == true) //See if new data is available. Process bytes as they come in. { //Did we receive a config packet that matches the cls/id we requested? - if (packetCfg.cls == requestedClass && packetCfg.id == requestedID) + if (packetCfg.cls == requestedClass && packetCfg.id == requestedID && currentSentence == NONE) // PZC: Won't these match much earlier than the .valid ? Added "&& currentSentence == NONE" { //This packet might be good or it might be CRC corrupt if (packetCfg.valid == true) @@ -1108,16 +1169,21 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u } else { - debugPrintln((char *)F("waitForNoACKResponse: CLS/ID match but failed CRC")); + if (_printDebug == true) + { + _debugSerial->println(F("waitForNoACKResponse: CLS/ID match but failed CRC")); + } + //debugPrintln((char *)F("waitForNoACKResponse: CLS/ID match but failed CRC")); return (SFE_UBLOX_STATUS_CRC_FAIL); //We got the right packet but it was corrupt } } - else if (packetCfg.cls < 255 && packetCfg.id < 255) + else if (packetCfg.cls < 255 && packetCfg.id < 255 && currentSentence == NONE) // PZC: added "&& currentSentence == NONE" { //Reset packet and continue checking incoming data for matching cls/id if (_printDebug == true) { - debugPrint((char *)F("waitForNoACKResponse: CLS/ID mismatch: ")); + _debugSerial->print(F("waitForNoACKResponse: CLS/ID mismatch: ")); + //debugPrint((char *)F("waitForNoACKResponse: CLS/ID mismatch: ")); _debugSerial->print(F("CLS: ")); _debugSerial->print(packetCfg.cls, HEX); _debugSerial->print(F(" ID: ")); @@ -1683,7 +1749,11 @@ boolean SFE_UBLOX_GPS::setPortOutput(uint8_t portID, uint8_t outStreamSettings, if (commandAck != UBX_ACK_ACK) { - debugPrintln((char *)F("setPortOutput failed to ACK")); + if (_printDebug == true) + { + _debugSerial->println(F("setPortOutput failed to ACK")); + } + //debugPrintln((char *)F("setPortOutput failed to ACK")); return (false); } @@ -2070,7 +2140,11 @@ boolean SFE_UBLOX_GPS::powerSaveMode(bool power_save, uint16_t maxWait) */ if (protVer >= 27) { - debugPrintln((char *)F("powerSaveMode (UBX-CFG-RXM) is not supported by this protocol version")); + if (_printDebug == true) + { + _debugSerial->println(F("powerSaveMode (UBX-CFG-RXM) is not supported by this protocol version")); + } + //debugPrintln((char *)F("powerSaveMode (UBX-CFG-RXM) is not supported by this protocol version")); return (false); } @@ -2228,25 +2302,38 @@ boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait) if (autoPVT && autoPVTImplicitUpdate) { //The GPS is automatically reporting, we just check whether we got unread data - debugPrintln((char *)F("getPVT: Autoreporting")); + if (_printDebug == true) + { + _debugSerial->println(F("getPVT: Autoreporting")); + } + //debugPrintln((char *)F("getPVT: Autoreporting")); checkUblox(); return moduleQueried.all; } else if (autoPVT && !autoPVTImplicitUpdate) { //Someone else has to call checkUblox for us... - debugPrintln((char *)F("getPVT: Exit immediately")); + if (_printDebug == true) + { + _debugSerial->println(F("getPVT: Exit immediately")); + } + //debugPrintln((char *)F("getPVT: Exit immediately")); return (false); } else { - debugPrintln((char *)F("getPVT: Polling")); + if (_printDebug == true) + { + _debugSerial->println(F("getPVT: Polling")); + } + //debugPrintln((char *)F("getPVT: Polling")); //The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_PVT; packetCfg.len = 0; //packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+MAX_PAYLOAD_SIZE = 84 bytes Note:now hard-coded in processUBX + packetCfg.startingSpot = 0; //The data is parsed as part of processing the response sfe_ublox_status_e retVal = sendCommand(packetCfg, maxWait); From fc73deb1bfc2235066ea232b510ddee445a87527 Mon Sep 17 00:00:00 2001 From: Paul <5690545+PaulZC@users.noreply.github.com> Date: Fri, 3 Jan 2020 21:02:19 +0000 Subject: [PATCH 2/5] Added packet_validity --- src/SparkFun_Ublox_Arduino_Library.cpp | 139 ++++++++++++------------- src/SparkFun_Ublox_Arduino_Library.h | 13 ++- 2 files changed, 77 insertions(+), 75 deletions(-) diff --git a/src/SparkFun_Ublox_Arduino_Library.cpp b/src/SparkFun_Ublox_Arduino_Library.cpp index e45b479..f66930b 100644 --- a/src/SparkFun_Ublox_Arduino_Library.cpp +++ b/src/SparkFun_Ublox_Arduino_Library.cpp @@ -164,9 +164,11 @@ void SFE_UBLOX_GPS::factoryReset() packetCfg.startingSpot = 0; for (uint8_t i = 0; i < 4; i++) { + //u-center suggests we should set clear mask _and_ load mask, to ensure the defaults are restored and made current + //then we can save them using saveConfiguration payloadCfg[0 + i] = 0xff; // clear mask: copy default config to permanent config payloadCfg[4 + i] = 0x00; // save mask: don't save current to permanent - payloadCfg[8 + i] = 0x00; // load mask: don't copy permanent config to current + payloadCfg[8 + i] = 0xff; // load mask: copy permanent config to current } payloadCfg[12] = 0xff; // all forms of permanent memory sendCommand(packetCfg, 0); // don't expect ACK @@ -285,7 +287,6 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C() { _debugSerial->println(F("checkUbloxI2C: Ublox bug, no bytes available")); } - //debugPrintln((char *)F("checkUbloxI2C: Ublox bug, no bytes available")); lastCheck = millis(); //Put off checking to avoid I2C bus traffic return (false); } @@ -298,7 +299,6 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C() { _debugSerial->println(F("checkUbloxI2C: OK, zero bytes available")); } - //debugPrintln((char *)F("checkUbloxI2C: OK, zero bytes available")); lastCheck = millis(); //Put off checking to avoid I2C bus traffic return (false); } @@ -359,7 +359,6 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C() { _debugSerial->println(F("Module not ready with data")); } - //debugPrintln((char *)F("Module not ready with data")); delay(5); //In logic analyzation, the module starting responding after 1.48ms goto TRY_AGAIN; } @@ -436,13 +435,13 @@ void SFE_UBLOX_GPS::process(uint8_t incoming) if (incoming == UBX_CLASS_ACK) { packetAck.counter = 0; - packetAck.valid = false; + packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; ubxFrameClass = CLASS_ACK; } else { packetCfg.counter = 0; - packetCfg.valid = false; + packetCfg.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; ubxFrameClass = CLASS_NOT_AN_ACK; } } @@ -537,7 +536,7 @@ void SFE_UBLOX_GPS::processRTCM(uint8_t incoming) } //Given a character, file it away into the uxb packet structure -//Set valid = true once sentence is completely received and passes CRC +//Set valid to VALID or NOT_VALID once sentence is completely received and passes or fails CRC //The payload portion of the packet can be 100s of bytes but the max array //size is roughly 64 bytes. startingSpot can be set so we only record //a subset of bytes within a larger packet. @@ -554,7 +553,7 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX) } else if (incomingUBX->counter == 1) { - incomingUBX->id = incoming; // PZC: packetCfg.cls and .id will match NOW - not at the end of the message! + incomingUBX->id = incoming; } else if (incomingUBX->counter == 2) //Len LSB { @@ -577,7 +576,7 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX) //Validate this sentence if (incomingUBX->checksumA == rollingChecksumA && incomingUBX->checksumB == rollingChecksumB) { - incomingUBX->valid = true; + incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_VALID; if (_printDebug == true) { @@ -586,28 +585,28 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX) _debugSerial->print(F(" Received: ")); printPacket(incomingUBX); - if (packetCfg.valid == true) + if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID) { if (_printDebug == true) { _debugSerial->println(F("packetCfg now valid")); } - //debugPrintln((char *)F("packetCfg now valid")); } - if (packetAck.valid == true) + if (packetAck.valid == SFE_UBLOX_PACKET_VALIDITY_VALID) { if (_printDebug == true) { _debugSerial->println(F("packetAck now valid")); } - //debugPrintln((char *)F("packetAck now valid")); } } processUBXpacket(incomingUBX); //We've got a valid packet, now do something with it } - else + else // Checksum failure { + incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_NOT_VALID; + if (_printDebug == true) { //Drive an external pin to allow for easier logic analyzation @@ -619,7 +618,6 @@ void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX) } _debugSerial->print(F("Checksum failed:")); - //debugPrint((char *)F("Checksum failed:")); _debugSerial->print(F(" checksumA: ")); _debugSerial->print(incomingUBX->checksumA); _debugSerial->print(F(" checksumB: ")); @@ -671,7 +669,6 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg) { _debugSerial->println(F("UBX ACK: Command sent/ack'd successfully")); } - //debugPrintln((char *)F("UBX ACK: Command sent/ack'd successfully")); commandAck = UBX_ACK_ACK; } else if (msg->id == UBX_ACK_NACK && msg->payload[0] == packetCfg.cls && msg->payload[1] == packetCfg.id) @@ -681,7 +678,6 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg) { _debugSerial->println(F("UBX ACK: Not-Acknowledged")); } - //debugPrintln((char *)F("UBX ACK: Not-Acknowledged")); commandAck = UBX_ACK_NACK; } break; @@ -810,7 +806,6 @@ sfe_ublox_status_e SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t ma { _debugSerial->println(F("Send I2C Command failed")); } - //debugPrintln((char *)F("Send I2C Command failed")); return retVal; } } @@ -828,7 +823,6 @@ sfe_ublox_status_e SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t ma { _debugSerial->println(F("sendCommand: Waiting for ACK response")); } - //debugPrintln((char *)F("sendCommand: Waiting for ACK response")); retVal = waitForACKResponse(outgoingUBX.cls, outgoingUBX.id, maxWait); //Wait for Ack response } else @@ -837,7 +831,6 @@ sfe_ublox_status_e SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t ma { _debugSerial->println(F("sendCommand: Waiting for No ACK response")); } - //debugPrintln((char *)F("sendCommand: Waiting for No ACK response")); retVal = waitForNoACKResponse(outgoingUBX.cls, outgoingUBX.id, maxWait); //Wait for Ack response } } @@ -1025,18 +1018,29 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet) //"not acknowledge"(UBX-ACK-NAK) message back to the sender, depending on whether or not the message was processed correctly. //Some messages from other classes also use the same acknowledgement mechanism. -//If the packetCfg len is 1, then we are querying the device for data -//If the packetCfg len is >1, then we are sending a new setting +//When we poll or get a setting, we will receive _both_ a config packet and an ACK +//If the poll or get request is not valid, we will receive _only_ a NACK + +//If we are trying to get or poll a setting, then packetCfg.len will be 0 or 1 when the packetCfg is _sent_. +//If we poll the setting for a particular port using UBX-CFG-PRT then .len will be 1 initially +//For all other gets or polls, .len will be 0 initially +//(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)) + +//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 +//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 + +//If we are going to set the value for a setting, then packetCfg.len will be at least 3 when the packetCfg is _sent_. +//(UBX-CFG-MSG appears to have the shortest set length of 3 bytes) //Returns true if we got the following: -//* If packetCfg len is 1 and we got and ACK and a valid packetCfg (module is responding with register content) -//* If packetCfg len is >1 and we got an ACK (no valid packetCfg needed, module absorbs new register data) -//Returns false if we timed out, got a NACK (command unknown), or had a CLS/ID mismatch +//* If we got an ACK and a valid packetCfg (module is responding with register content) +//* If we got an ACK and no packetCfg (no valid packetCfg needed, module absorbs new register data) +//Returns false if we timed out, got a NACK (command unknown), an invalid packetCfg (checksum failure) or had a CLS/ID mismatch sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime) { commandAck = UBX_ACK_NONE; //Reset flag - packetCfg.valid = false; //This will go true when we receive a response to the packet we sent - packetAck.valid = false; + 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 + packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; unsigned long startTime = millis(); while (millis() - startTime < maxTime) @@ -1053,44 +1057,43 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin _debugSerial->println(F(" msec")); } - //Are we expecting data back or just an ACK? - if (packetCfg.len == 1) // PZC: Maybe this should be <= 1 ? Most gets are zero length ? + //We've got the a valid ACK for this CLS/ID, so is packetCfg valid? + if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID) { - //We are expecting a data response so now we verify the response packet was valid - if (packetCfg.valid == true) + //We've got a valid packetCfg, so does it match the requested Class and ID? + if (packetCfg.cls == requestedClass && packetCfg.id == requestedID) { - if (packetCfg.cls == requestedClass && packetCfg.id == requestedID) - { - if (_printDebug == true) - { - _debugSerial->print(F("waitForACKResponse: CLS/ID match after ")); - _debugSerial->print(millis() - startTime); - _debugSerial->println(F(" msec")); - } - return (SFE_UBLOX_STATUS_DATA_RECEIVED); //Received a data and a correct ACK! - } - else + if (_printDebug == true) { - //Reset packet and continue checking incoming data for matching cls/id - if (_printDebug == true) - { - _debugSerial->println(F("waitForACKResponse: CLS/ID mismatch, continue to wait...")); - } - //debugPrintln((char *)F("waitForACKResponse: CLS/ID mismatch, continue to wait...")); - packetCfg.valid = false; //This will go true when we receive a response to the packet we sent + _debugSerial->print(F("waitForACKResponse: CLS/ID match after ")); + _debugSerial->print(millis() - startTime); + _debugSerial->println(F(" msec")); } + return (SFE_UBLOX_STATUS_DATA_RECEIVED); //Received a data and a correct ACK! } else + // The Class and/or ID don't match the requested ones, so keep trying... { - //We were expecting data but didn't get a valid config packet + //Reset packet and continue checking incoming data for matching cls/id if (_printDebug == true) { - _debugSerial->println(F("waitForACKResponse: Invalid config packet")); + _debugSerial->println(F("waitForACKResponse: CLS/ID mismatch, continue to wait...")); } - //debugPrintln((char *)F("waitForACKResponse: Invalid config packet")); - return (SFE_UBLOX_STATUS_FAIL); //We got an ACK, we're never going to get valid config data + 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 + } + } + //If we received an invalid packetCfg (checksum failure) then we can't trust it, including its Class and ID + else if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID) + { + //We were expecting data but didn't get a valid config packet + if (_printDebug == true) + { + _debugSerial->println(F("waitForACKResponse: Invalid config packet")); } + return (SFE_UBLOX_STATUS_FAIL); //We got a checksum failure, we're never going to get valid config data } + //We didn't receive a valid or invalid packetCfg, so we must have only received the ACK + //Let's hope this was a set? else { //We have sent new data. We expect an ACK but no return config packet. @@ -1098,10 +1101,10 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin { _debugSerial->println(F("waitForACKResponse: New data successfully sent")); } - //debugPrintln((char *)F("waitForACKResponse: New data successfully sent")); return (SFE_UBLOX_STATUS_DATA_SENT); //New data successfully sent } } + //Did we receive a NACK? else if (commandAck == UBX_ACK_NACK) { if (_printDebug == true) @@ -1119,13 +1122,12 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin //TODO add check here if config went valid but we never got the following ack //Through debug warning, This command might not get an ACK - if (packetCfg.valid == true) + if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID) { if (_printDebug == true) { _debugSerial->println(F("waitForACKResponse: Config was valid but ACK not received")); } - //debugPrintln((char *)F("waitForACKResponse: Config was valid but ACK not received")); } if (_printDebug == true) @@ -1139,12 +1141,12 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin } //For non-CFG queries no ACK is sent so we use this function -//Returns true if we got a config packet full of response data that has CLS/ID match to our query packet -//Returns false if we timed out +//Returns true if we got a valid config packet full of response data that has CLS/ID match to our query packet +//Returns false if we timed out or received an invalid packet (checksum failure) sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime) { - packetCfg.valid = false; //This will go true when we receive a response to the packet we sent - packetAck.valid = false; + 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 + packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; packetCfg.cls = 255; packetCfg.id = 255; @@ -1154,10 +1156,10 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u if (checkUblox() == true) //See if new data is available. Process bytes as they come in. { //Did we receive a config packet that matches the cls/id we requested? - if (packetCfg.cls == requestedClass && packetCfg.id == requestedID && currentSentence == NONE) // PZC: Won't these match much earlier than the .valid ? Added "&& currentSentence == NONE" + if (packetCfg.cls == requestedClass && packetCfg.id == requestedID && packetCfg.valid != SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED) { //This packet might be good or it might be CRC corrupt - if (packetCfg.valid == true) + if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_VALID) { if (_printDebug == true) { @@ -1167,23 +1169,21 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u } return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We have new data to act upon } - else + else //if (packetCfg.valid == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID) { if (_printDebug == true) { _debugSerial->println(F("waitForNoACKResponse: CLS/ID match but failed CRC")); } - //debugPrintln((char *)F("waitForNoACKResponse: CLS/ID match but failed CRC")); return (SFE_UBLOX_STATUS_CRC_FAIL); //We got the right packet but it was corrupt } } - else if (packetCfg.cls < 255 && packetCfg.id < 255 && currentSentence == NONE) // PZC: added "&& currentSentence == NONE" + else if (packetCfg.cls < 255 && packetCfg.id < 255 && packetCfg.valid != SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED) { //Reset packet and continue checking incoming data for matching cls/id if (_printDebug == true) { _debugSerial->print(F("waitForNoACKResponse: CLS/ID mismatch: ")); - //debugPrint((char *)F("waitForNoACKResponse: CLS/ID mismatch: ")); _debugSerial->print(F("CLS: ")); _debugSerial->print(packetCfg.cls, HEX); _debugSerial->print(F(" ID: ")); @@ -1191,7 +1191,7 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, u _debugSerial->println(); } - packetCfg.valid = false; //This will go true when we receive a response to the packet we sent + 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 packetCfg.cls = 255; packetCfg.id = 255; } @@ -1753,7 +1753,6 @@ boolean SFE_UBLOX_GPS::setPortOutput(uint8_t portID, uint8_t outStreamSettings, { _debugSerial->println(F("setPortOutput failed to ACK")); } - //debugPrintln((char *)F("setPortOutput failed to ACK")); return (false); } @@ -2144,7 +2143,6 @@ boolean SFE_UBLOX_GPS::powerSaveMode(bool power_save, uint16_t maxWait) { _debugSerial->println(F("powerSaveMode (UBX-CFG-RXM) is not supported by this protocol version")); } - //debugPrintln((char *)F("powerSaveMode (UBX-CFG-RXM) is not supported by this protocol version")); return (false); } @@ -2306,7 +2304,6 @@ boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait) { _debugSerial->println(F("getPVT: Autoreporting")); } - //debugPrintln((char *)F("getPVT: Autoreporting")); checkUblox(); return moduleQueried.all; } @@ -2317,7 +2314,6 @@ boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait) { _debugSerial->println(F("getPVT: Exit immediately")); } - //debugPrintln((char *)F("getPVT: Exit immediately")); return (false); } else @@ -2326,7 +2322,6 @@ boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait) { _debugSerial->println(F("getPVT: Polling")); } - //debugPrintln((char *)F("getPVT: Polling")); //The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; diff --git a/src/SparkFun_Ublox_Arduino_Library.h b/src/SparkFun_Ublox_Arduino_Library.h index 843a203..6589a14 100644 --- a/src/SparkFun_Ublox_Arduino_Library.h +++ b/src/SparkFun_Ublox_Arduino_Library.h @@ -99,6 +99,13 @@ typedef enum SFE_UBLOX_STATUS_I2C_COMM_FAILURE, } sfe_ublox_status_e; +typedef enum +{ + SFE_UBLOX_PACKET_VALIDITY_NOT_VALID, + SFE_UBLOX_PACKET_VALIDITY_VALID, + SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED +} sfe_ublox_packet_validity_e; + //Registers const uint8_t UBX_SYNCH_1 = 0xB5; const uint8_t UBX_SYNCH_2 = 0x62; @@ -244,7 +251,7 @@ typedef struct uint8_t *payload; uint8_t checksumA; //Given to us from module. Checked against the rolling calculated A/B checksums. uint8_t checksumB; - boolean valid; //Goes true when both checksums pass + sfe_ublox_packet_validity_e valid; //Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked } ubxPacket; // Struct to hold the results returned by getGeofenceState (returned by UBX-NAV-GEOFENCE) @@ -545,8 +552,8 @@ class SFE_UBLOX_GPS uint8_t payloadCfg[MAX_PAYLOAD_SIZE]; //Init the packet structures and init them with pointers to the payloadAck and payloadCfg arrays - ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, false}; - ubxPacket packetCfg = {0, 0, 0, 0, 0, payloadCfg, 0, 0, false}; + ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; + ubxPacket packetCfg = {0, 0, 0, 0, 0, payloadCfg, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; //Limit checking of new data to every X ms //If we are expecting an update every X Hz then we should check every half that amount of time From 7445c9e1dfe19f37bc61dcfc5c859edd8a0f4f41 Mon Sep 17 00:00:00 2001 From: Paul <5690545+PaulZC@users.noreply.github.com> Date: Fri, 3 Jan 2020 22:23:54 +0000 Subject: [PATCH 3/5] Added a missing comment --- src/SparkFun_Ublox_Arduino_Library.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SparkFun_Ublox_Arduino_Library.cpp b/src/SparkFun_Ublox_Arduino_Library.cpp index f66930b..c8b0902 100644 --- a/src/SparkFun_Ublox_Arduino_Library.cpp +++ b/src/SparkFun_Ublox_Arduino_Library.cpp @@ -1031,6 +1031,7 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet) //If we are going to set the value for a setting, then packetCfg.len will be at least 3 when the packetCfg is _sent_. //(UBX-CFG-MSG appears to have the shortest set length of 3 bytes) +//And we are only expecting an ACK (or a NACK) in return. //Returns true if we got the following: //* If we got an ACK and a valid packetCfg (module is responding with register content) From 9eccda5b5b403373a6d9c20e5bf192b1bfec8e5b Mon Sep 17 00:00:00 2001 From: Paul <5690545+PaulZC@users.noreply.github.com> Date: Sat, 4 Jan 2020 18:34:21 +0000 Subject: [PATCH 4/5] Corrected the sendCommand return value checking sendCommand now returns sfe_ublox_status_e but many functions were still assuming it returned a boolean. This commit fixes that... **It hasn't yet been tested on the ZED!** --- src/SparkFun_Ublox_Arduino_Library.cpp | 236 ++++++++++++++++++++----- src/SparkFun_Ublox_Arduino_Library.h | 8 +- 2 files changed, 194 insertions(+), 50 deletions(-) diff --git a/src/SparkFun_Ublox_Arduino_Library.cpp b/src/SparkFun_Ublox_Arduino_Library.cpp index c8b0902..90acbe0 100644 --- a/src/SparkFun_Ublox_Arduino_Library.cpp +++ b/src/SparkFun_Ublox_Arduino_Library.cpp @@ -219,7 +219,12 @@ void SFE_UBLOX_GPS::setSerialRate(uint32_t baudrate, uint8_t uartPort, uint16_t _debugSerial->println(((uint32_t)payloadCfg[10] << 16) | ((uint32_t)payloadCfg[9] << 8) | payloadCfg[8]); } - sendCommand(packetCfg, maxWait); + sfe_ublox_status_e retVal = sendCommand(packetCfg, maxWait); + if (_printDebug == true) + { + _debugSerial->print(F("setSerialRate: sendCommand returned: ")); + _debugSerial->println(statusString(retVal)); + } } //Changes the I2C address that the Ublox module responds to @@ -237,7 +242,9 @@ boolean SFE_UBLOX_GPS::setI2CAddress(uint8_t deviceAddress, uint16_t maxWait) //payloadCfg is now loaded with current bytes. Change only the ones we need to payloadCfg[4] = deviceAddress << 1; //DDC mode LSB - if (sendCommand(packetCfg, maxWait) == true) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT) { //Success! Now change our internal global. _gpsI2Caddress = deviceAddress; //Store the I2C address from user @@ -935,9 +942,13 @@ boolean SFE_UBLOX_GPS::isConnected() packetCfg.len = 0; packetCfg.startingSpot = 0; - return sendCommand(packetCfg); + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + sfe_ublox_status_e retVal = sendCommand(packetCfg); // Use default maxWait + if (retVal == SFE_UBLOX_STATUS_DATA_RECEIVED) + return (true); } - return false; + return (false); } //Given a message, calc and store the two byte "8-Bit Fletcher" checksum over the entirety of the message @@ -1014,6 +1025,8 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet) //=-=-=-=-=-=-=-= Specific commands =-=-=-=-=-=-=-==-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +//waitForACKResponse: + //When messages from the class CFG are sent to the receiver, the receiver will send an "acknowledge"(UBX - ACK - ACK) or a //"not acknowledge"(UBX-ACK-NAK) message back to the sender, depending on whether or not the message was processed correctly. //Some messages from other classes also use the same acknowledgement mechanism. @@ -1033,10 +1046,11 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet) //(UBX-CFG-MSG appears to have the shortest set length of 3 bytes) //And we are only expecting an ACK (or a NACK) in return. -//Returns true if we got the following: -//* If we got an ACK and a valid packetCfg (module is responding with register content) -//* If we got an ACK and no packetCfg (no valid packetCfg needed, module absorbs new register data) -//Returns false if we timed out, got a NACK (command unknown), an invalid packetCfg (checksum failure) or had a CLS/ID mismatch +//Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg (module is responding with register content) +//Returns SFE_UBLOX_STATUS_DATA_SENT if we got an ACK and no packetCfg (no valid packetCfg needed, module absorbs new register data) +//Returns SFE_UBLOX_STATUS_FAIL if we got an invalid packetCfg (checksum failure) +//Returns SFE_UBLOX_STATUS_COMMAND_UNKNOWN if we got a NACK (command unknown) +//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime) { commandAck = UBX_ACK_NONE; //Reset flag @@ -1141,9 +1155,10 @@ sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uin return (SFE_UBLOX_STATUS_TIMEOUT); } -//For non-CFG queries no ACK is sent so we use this function -//Returns true if we got a valid config packet full of response data that has CLS/ID match to our query packet -//Returns false if we timed out or received an invalid packet (checksum failure) +//waitForNoACKResponse: for non-CFG queries no ACK is sent so we use this function +//Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a valid config packet full of response data that has CLS/ID match to our query packet +//Returns SFE_UBLOX_STATUS_CRC_FAIL if we received an invalid packet (checksum failure) +//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out sfe_ublox_status_e SFE_UBLOX_GPS::waitForNoACKResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime) { 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 @@ -1226,7 +1241,9 @@ boolean SFE_UBLOX_GPS::saveConfiguration(uint16_t maxWait) packetCfg.payload[4] = 0xFF; //Set any bit in the saveMask field to save current config to Flash and BBR - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail return (true); @@ -1248,7 +1265,9 @@ boolean SFE_UBLOX_GPS::factoryDefault(uint16_t maxWait) packetCfg.payload[0] = 0xFF; //Set any bit in the clearMask field to clear saved config packetCfg.payload[8] = 0xFF; //Set any bit in the loadMask field to discard current config and rebuild from lower non-volatile memory layers - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail return (true); @@ -1307,7 +1326,10 @@ uint8_t SFE_UBLOX_GPS::getVal8(uint32_t key, uint8_t layer, uint16_t maxWait) } //Send VALGET command with this key - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + // PZC: THIS NEEDS TESTING! Does VALGET return a packet _and_ an ACK? + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); //If command send fails then bail //Verify the response is the correct length as compared to what the user called (did the module respond with 8-bits but the user called getVal32?) @@ -1357,7 +1379,10 @@ uint8_t SFE_UBLOX_GPS::setVal16(uint32_t key, uint16_t value, uint8_t layer, uin payloadCfg[9] = value >> 8 * 1; //Send VALSET command with this key and value - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + // PZC: THIS NEEDS TESTING! Does VALSET only return an ACK? + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail //All done @@ -1392,7 +1417,10 @@ uint8_t SFE_UBLOX_GPS::setVal8(uint32_t key, uint8_t value, uint8_t layer, uint1 payloadCfg[8] = value; //Value //Send VALSET command with this key and value - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + // PZC: THIS NEEDS TESTING! Does VALSET only return an ACK? + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail //All done @@ -1430,7 +1458,10 @@ uint8_t SFE_UBLOX_GPS::setVal32(uint32_t key, uint32_t value, uint8_t layer, uin payloadCfg[11] = value >> 8 * 3; //Send VALSET command with this key and value - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + // PZC: THIS NEEDS TESTING! Does VALSET only return an ACK? + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail //All done @@ -1606,7 +1637,10 @@ uint8_t SFE_UBLOX_GPS::sendCfgValset32(uint32_t key, uint32_t value, uint16_t ma addCfgValset32(key, value); //Send VALSET command with this key and value - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + // PZC: THIS NEEDS TESTING! Does VALSET only return an ACK? + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail //All done @@ -1621,7 +1655,10 @@ uint8_t SFE_UBLOX_GPS::sendCfgValset16(uint32_t key, uint16_t value, uint16_t ma addCfgValset16(key, value); //Send VALSET command with this key and value - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + // PZC: THIS NEEDS TESTING! Does VALSET only return an ACK? + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail //All done @@ -1636,7 +1673,10 @@ uint8_t SFE_UBLOX_GPS::sendCfgValset8(uint32_t key, uint8_t value, uint16_t maxW addCfgValset8(key, value); //Send VALSET command with this key and value - if (sendCommand(packetCfg, maxWait) == false) + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + // PZC: THIS NEEDS TESTING! Does VALSET only return an ACK? + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) return (false); //If command send fails then bail //All done @@ -1651,7 +1691,13 @@ boolean SFE_UBLOX_GPS::getSurveyMode(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - return (sendCommand(packetCfg, maxWait)); + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) + return (false); + + //All done + return (true); } //Control Survey-In for NEO-M8P @@ -1680,7 +1726,13 @@ boolean SFE_UBLOX_GPS::setSurveyMode(uint8_t mode, uint16_t observationTime, flo payloadCfg[29] = svinAccLimit >> 8; payloadCfg[30] = svinAccLimit >> 16; - return (sendCommand(packetCfg, maxWait)); //Wait for ack + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Begin Survey-In for NEO-M8P @@ -1711,7 +1763,9 @@ boolean SFE_UBLOX_GPS::getSurveyStatus(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) + // waitForNoACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a valid packetCfg + // (module is responding with register content) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); //If command send fails then bail //We got a response, now parse the bits into the svin structure @@ -1736,7 +1790,13 @@ boolean SFE_UBLOX_GPS::getPortSettings(uint8_t portID, uint16_t maxWait) payloadCfg[0] = portID; - return (sendCommand(packetCfg, maxWait)); + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) + return (false); //If command send fails then bail + + //All done + return (true); } //Configure a given port to output UBX, NMEA, RTCM3 or a combination thereof @@ -1765,7 +1825,13 @@ boolean SFE_UBLOX_GPS::setPortOutput(uint8_t portID, uint8_t outStreamSettings, //payloadCfg is now loaded with current bytes. Change only the ones we need to payloadCfg[14] = outStreamSettings; //OutProtocolMask LSB - Set outStream bits - return (sendCommand(packetCfg, maxWait)); + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof @@ -1786,7 +1852,13 @@ boolean SFE_UBLOX_GPS::setPortInput(uint8_t portID, uint8_t inStreamSettings, ui //payloadCfg is now loaded with current bytes. Change only the ones we need to payloadCfg[12] = inStreamSettings; //InProtocolMask LSB - Set inStream bits - return (sendCommand(packetCfg, maxWait)); + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Configure a port to output UBX, NMEA, RTCM3 or a combination thereof @@ -1827,8 +1899,11 @@ boolean SFE_UBLOX_GPS::setNavigationFrequency(uint8_t navFreq, uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) //This will load the payloadCfg array with current settings of the given register - return (false); //If command send fails then bail + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + //This will load the payloadCfg array with current settings of the given register + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) + return (false); //If command send fails then bail uint16_t measurementRate = 1000 / navFreq; @@ -1836,7 +1911,13 @@ boolean SFE_UBLOX_GPS::setNavigationFrequency(uint8_t navFreq, uint16_t maxWait) payloadCfg[0] = measurementRate & 0xFF; //measRate LSB payloadCfg[1] = measurementRate >> 8; //measRate MSB - return (sendCommand(packetCfg, maxWait)); + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Get the rate at which the module is outputting nav solutions @@ -1848,8 +1929,11 @@ uint8_t SFE_UBLOX_GPS::getNavigationFrequency(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) //This will load the payloadCfg array with current settings of the given register - return (0); //If command send fails then bail + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + //This will load the payloadCfg array with current settings of the given register + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) + return (0); //If command send fails then bail uint16_t measurementRate = 0; @@ -1892,7 +1976,11 @@ boolean SFE_UBLOX_GPS::setAutoPVT(boolean enable, boolean implicitUpdate, uint16 payloadCfg[1] = UBX_NAV_PVT; payloadCfg[2] = enable ? 1 : 0; // rate relative to navigation freq. - bool ok = sendCommand(packetCfg, maxWait); + bool ok = true; + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + ok = false; if (ok) { autoPVT = enable; @@ -1918,7 +2006,13 @@ boolean SFE_UBLOX_GPS::configureMessage(uint8_t msgClass, uint8_t msgID, uint8_t packetCfg.payload[1] = msgID; packetCfg.payload[2 + portID] = sendRate; //Send rate is relative to the event a message is registered on. For example, if the rate of a navigation message is set to 2, the message is sent every 2nd navigation solution. - return (sendCommand(packetCfg, maxWait)); + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Enable a given message type, default of 1 per update rate (usually 1 per second) @@ -2056,7 +2150,13 @@ boolean SFE_UBLOX_GPS::addGeofence(int32_t latitude, int32_t longitude, uint32_t payloadCfg[54] = currentGeofenceParams.rads[3] >> 16; payloadCfg[55] = currentGeofenceParams.rads[3] >> 24; } - return (sendCommand(packetCfg, maxWait)); //Wait for ack + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Clear all geofences using UBX-CFG-GEOFENCE @@ -2078,7 +2178,13 @@ boolean SFE_UBLOX_GPS::clearGeofences(uint16_t maxWait) currentGeofenceParams.numFences = 0; // Zero the number of geofences currently in use - return (sendCommand(packetCfg, maxWait)); //Wait for ack + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Clear the antenna control settings using UBX-CFG-ANT @@ -2096,7 +2202,13 @@ boolean SFE_UBLOX_GPS::clearAntPIO(uint16_t maxWait) payloadCfg[2] = 0xFF; // Antenna pin configuration: set pinSwitch and pinSCD to 31 payloadCfg[3] = 0xFF; // Antenna pin configuration: set pinOCD to 31, set reconfig bit - return (sendCommand(packetCfg, maxWait)); //Wait for ack + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Returns the combined geofence state using UBX-NAV-GEOFENCE @@ -2107,7 +2219,10 @@ boolean SFE_UBLOX_GPS::getGeofenceState(geofenceState ¤tGeofenceState, uin packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) //Ask module for the geofence status. Loads into payloadCfg. + // waitForNoACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a valid packetCfg + // (module is responding with register content) + //Ask module for the geofence status. Loads into payloadCfg. + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); currentGeofenceState.status = payloadCfg[5]; // Extract the status @@ -2153,7 +2268,10 @@ boolean SFE_UBLOX_GPS::powerSaveMode(bool power_save, uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) //Ask module for the current power management settings. Loads into payloadCfg. + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + //Ask module for the current power management settings. Loads into payloadCfg. + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); if (power_save) @@ -2168,7 +2286,13 @@ boolean SFE_UBLOX_GPS::powerSaveMode(bool power_save, uint16_t maxWait) packetCfg.len = 2; packetCfg.startingSpot = 0; - return (sendCommand(packetCfg, maxWait)); //Wait for ack + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Change the dynamic platform model using UBX-CFG-NAV5 @@ -2184,7 +2308,10 @@ boolean SFE_UBLOX_GPS::setDynamicModel(dynModel newDynamicModel, uint16_t maxWai packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) //Ask module for the current navigation model settings. Loads into payloadCfg. + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg + // (module is responding with register content) + //Ask module for the current navigation model settings. Loads into payloadCfg. + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); payloadCfg[0] = 0x01; // mask: set only the dyn bit (0) @@ -2194,7 +2321,13 @@ boolean SFE_UBLOX_GPS::setDynamicModel(dynModel newDynamicModel, uint16_t maxWai packetCfg.len = 36; packetCfg.startingSpot = 0; - return (sendCommand(packetCfg, maxWait)); //Wait for ack + // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg + // (no valid packetCfg needed, module absorbs new register data) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) + return (false); + + //All done + return (true); } //Given a spot in the payload array, extract four bytes and build a long @@ -2417,8 +2550,13 @@ boolean SFE_UBLOX_GPS::getHPPOSLLH(uint16_t maxWait) packetCfg.id = UBX_NAV_HPPOSLLH; packetCfg.len = 0; - return sendCommand(packetCfg, maxWait); - return (false); //If command send fails then bail + // waitForNoACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a valid packetCfg + // (module is responding with register content) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) + return (false); //If command send fails then bail + + //All done + return (true); } //Get the current 3D high precision positional accuracy - a fun thing to watch @@ -2430,7 +2568,9 @@ uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) + // waitForNoACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a valid packetCfg + // (module is responding with register content) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (0); //If command send fails then bail uint32_t tempAccuracy = extractLong(24); //We got a response, now extract a long beginning at a given position @@ -2590,7 +2730,9 @@ boolean SFE_UBLOX_GPS::getProtocolVersion(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 40; //Start at first "extended software information" string - if (sendCommand(packetCfg, maxWait) == false) + // waitForNoACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a valid packetCfg + // (module is responding with register content) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); //If command send fails then bail //Payload should now contain ~220 characters (depends on module type) @@ -2666,7 +2808,9 @@ boolean SFE_UBLOX_GPS::getRELPOSNED(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - if (sendCommand(packetCfg, maxWait) == false) + // waitForNoACKResponse returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a valid packetCfg + // (module is responding with register content) + if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); //If command send fails then bail //We got a response, now parse the bits diff --git a/src/SparkFun_Ublox_Arduino_Library.h b/src/SparkFun_Ublox_Arduino_Library.h index 6589a14..dbedc93 100644 --- a/src/SparkFun_Ublox_Arduino_Library.h +++ b/src/SparkFun_Ublox_Arduino_Library.h @@ -84,8 +84,8 @@ const int checksumFailurePin = -1; // Global Status Returns typedef enum { - SFE_UBLOX_STATUS_SUCCESS, - SFE_UBLOX_STATUS_FAIL, + SFE_UBLOX_STATUS_FAIL = 0, // FAIL == 0 + SFE_UBLOX_STATUS_SUCCESS, // SUCCESS == 1 SFE_UBLOX_STATUS_CRC_FAIL, SFE_UBLOX_STATUS_TIMEOUT, SFE_UBLOX_STATUS_COMMAND_UNKNOWN, @@ -101,8 +101,8 @@ typedef enum typedef enum { - SFE_UBLOX_PACKET_VALIDITY_NOT_VALID, - SFE_UBLOX_PACKET_VALIDITY_VALID, + SFE_UBLOX_PACKET_VALIDITY_NOT_VALID = 0, // NOT_VALID == 0 + SFE_UBLOX_PACKET_VALIDITY_VALID, // VALID == 1 SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED } sfe_ublox_packet_validity_e; From 3fd1b718dbe8ad946feb88690594d45dd1369378 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2020 10:48:19 -0700 Subject: [PATCH 5/5] Small whitespace changes. Expand debug message. --- src/SparkFun_Ublox_Arduino_Library.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/SparkFun_Ublox_Arduino_Library.cpp b/src/SparkFun_Ublox_Arduino_Library.cpp index 90acbe0..2db25bf 100644 --- a/src/SparkFun_Ublox_Arduino_Library.cpp +++ b/src/SparkFun_Ublox_Arduino_Library.cpp @@ -364,7 +364,7 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C() { if (_printDebug == true) { - _debugSerial->println(F("Module not ready with data")); + _debugSerial->println(F("checkUbloxI2C: Module not ready with data. Retrying.")); } delay(5); //In logic analyzation, the module starting responding after 1.48ms goto TRY_AGAIN; @@ -1005,6 +1005,10 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet) _debugSerial->print(F(" ID:")); if (packet->cls == UBX_CLASS_NAV && packet->id == UBX_NAV_PVT) _debugSerial->print("PVT"); + else if (packet->cls == UBX_CLASS_CFG && packet->id == UBX_CFG_VALSET) + _debugSerial->print("VALSET"); + else if (packet->cls == UBX_CLASS_CFG && packet->id == UBX_CFG_VALGET) + _debugSerial->print("VALGET"); else _debugSerial->print(packet->id, HEX); @@ -1053,8 +1057,8 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet) //Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out sfe_ublox_status_e SFE_UBLOX_GPS::waitForACKResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime) { - commandAck = UBX_ACK_NONE; //Reset flag - 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 + commandAck = UBX_ACK_NONE; //Reset flag + 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 packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; unsigned long startTime = millis(); @@ -2289,7 +2293,7 @@ boolean SFE_UBLOX_GPS::powerSaveMode(bool power_save, uint16_t maxWait) // waitForACKResponse returns SFE_UBLOX_STATUS_DATA_SENT if it got an ACK and no packetCfg // (no valid packetCfg needed, module absorbs new register data) if (sendCommand(packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) - return (false); + return (false); //All done return (true);