diff --git a/README.md b/README.md index 6934a52..db53b78 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ v2.1 of the library adds support for u-blox AssistNowTM Assisted GNSS This library is the new and improved version of the very popular SparkFun u-blox GNSS Arduino Library. v2.0 contains some big changes and improvements: * Seamless support for "automatic" message delivery: - * In v1.8, you could ask for the NAV PVT (Navigation Position Velocity Time) message to be delivered _automatically_, without polling. v2.0 adds automatic support for [**26 messages**](./Theory.md#auto-messages), covering the full range of: standard and High Precision position, velocity, attitude and time information; relative positioning; event capture with nanosecond time resolution; raw GNSS signal data including carrier phase; Sensor Fusion; and High Navigation Rate data. + * In v1.8, you could ask for the NAV PVT (Navigation Position Velocity Time) message to be delivered _automatically_, without polling. v2.0 adds automatic support for [**27 messages**](./Theory.md#auto-messages), covering the full range of: standard and High Precision position, velocity, attitude and time information; relative positioning; event capture with nanosecond time resolution; raw GNSS signal data including carrier phase; Sensor Fusion; and High Navigation Rate data. * Don't see the message you really need? [Adding_New_Messages](./Adding_New_Messages.md) provides details on how to add "auto" support for your favourite message. * Dynamic memory allocation with clearly-defined data storage structs for each message: * There are no static 'global' variables to eat up your RAM. v2.0 automatically allocates memory for the automatic messages when they are enabled. You may find your total RAM use is lower with v2.0 than with v1.8. diff --git a/examples/Callbacks/CallbackExample8_NAV_SVIN/CallbackExample8_NAV_SVIN.ino b/examples/Callbacks/CallbackExample8_NAV_SVIN/CallbackExample8_NAV_SVIN.ino new file mode 100644 index 0000000..c8f0a25 --- /dev/null +++ b/examples/Callbacks/CallbackExample8_NAV_SVIN/CallbackExample8_NAV_SVIN.ino @@ -0,0 +1,127 @@ +/* + Configuring the GNSS to automatically send NAV SVIN reports over I2C and display them using a callback + By: Paul Clark + SparkFun Electronics + Date: April 4th, 2022 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to configure the u-blox GNSS to send NAV SVIN reports automatically + and access the data via a callback. No more polling! + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/15136 + + Hardware Connections: + Plug a Qwiic cable into the GPS and a BlackBoard + If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425) + Open the serial monitor at 115200 baud to see the output +*/ + +#include //Needed for I2C to GNSS + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +// Callback: newNAVSVIN will be called when new NAV SVIN data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_SVIN_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSVINcallbackPtr +// / _____ This _must_ be UBX_NAV_SVIN_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void newNAVSVIN(UBX_NAV_SVIN_data_t *ubxDataStruct) +{ + Serial.println(); + + Serial.print(F("Survey-in is ")); + if (ubxDataStruct->active == 0) + Serial.print(F("not ")); + Serial.println(F("in progress")); + + Serial.print(F("Survey-in position is ")); + if (ubxDataStruct->valid == 0) + Serial.print(F("not ")); + Serial.println(F("valid")); + + Serial.print(F("Survey-in observation time (s): ")); + Serial.println(ubxDataStruct->dur); + + Serial.print(F("ECEF position (cm): ")); + Serial.print(ubxDataStruct->meanX); + Serial.print(F(" (")); + if (ubxDataStruct->meanXHP >= 0) + Serial.print(F("+")); + Serial.print((float)ubxDataStruct->meanXHP * 0.01); // Convert 0.1mm to cm + Serial.print(F("), ")); + Serial.print(ubxDataStruct->meanY); + Serial.print(F(" (")); + if (ubxDataStruct->meanYHP >= 0) + Serial.print(F("+")); + Serial.print((float)ubxDataStruct->meanYHP * 0.01); // Convert 0.1mm to cm + Serial.print(F("), ")); + Serial.print(ubxDataStruct->meanZ); + Serial.print(F(" (")); + if (ubxDataStruct->meanZHP >= 0) + Serial.print(F("+")); + Serial.print((float)ubxDataStruct->meanZHP * 0.01); // Convert 0.1mm to cm + Serial.println(F(")")); + + Serial.print(F("Mean position accuracy (cm): ")); + Serial.println((float)ubxDataStruct->meanAcc * 0.01); // Convert 0.1mm to cm +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); //Wait for user to open terminal + Serial.println(F("u-blox Base Station example")); + + Wire.begin(); + + //myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial + + if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port + { + Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + + // Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate + //myGNSS.factoryDefault(); delay(5000); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) + myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save the communications port settings to flash and BBR + + // Set up the callback for NAV SVIN. This will enable SVIN messages at the navigation rate + myGNSS.setAutoNAVSVINcallbackPtr(&newNAVSVIN); + + while (Serial.available()) Serial.read(); //Clear the serial buffer + Serial.println(F("Press any key to begin Survey-In")); +} + +void loop() +{ + myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in. + myGNSS.checkCallbacks(); //Process any waiting callbacks + + if (Serial.available()) // Check if user has pressed a key + { + bool success = myGNSS.enableSurveyMode(60, 5.000); //Enable Survey in, 60 seconds, 5.0m + //bool success = myGNSS.enableSurveyModeFull(86400, 2.000); //Enable Survey in, 24 hours, 2.0m + + Serial.println(); + + if (success) + { + Serial.println(F("Survey-In started!")); + } + else + { + Serial.println(F("Survey start failed!")); + } + + while (Serial.available()) Serial.read(); //Clear the serial buffer + } +} diff --git a/keywords.txt b/keywords.txt index 5e187b2..293d0ae 100644 --- a/keywords.txt +++ b/keywords.txt @@ -238,7 +238,6 @@ setAutoNAVPOSECEFrate KEYWORD2 setAutoNAVPOSECEFcallback KEYWORD2 setAutoNAVPOSECEFcallbackPtr KEYWORD2 assumeAutoNAVPOSECEF KEYWORD2 -initPacketUBXNAVPOSECEF KEYWORD2 flushNAVPOSECEF KEYWORD2 logNAVPOSECEF KEYWORD2 @@ -248,7 +247,6 @@ setAutoNAVSTATUSrate KEYWORD2 setAutoNAVSTATUScallback KEYWORD2 setAutoNAVSTATUScallbackPtr KEYWORD2 assumeAutoNAVSTATUS KEYWORD2 -initPacketUBXNAVSTATUS KEYWORD2 flushNAVSTATUS KEYWORD2 logNAVSTATUS KEYWORD2 @@ -258,7 +256,6 @@ setAutoDOPrate KEYWORD2 setAutoDOPcallback KEYWORD2 setAutoDOPcallbackPtr KEYWORD2 assumeAutoDOP KEYWORD2 -initPacketUBXNAVDOP KEYWORD2 flushDOP KEYWORD2 logNAVDOP KEYWORD2 @@ -269,7 +266,6 @@ setAutoNAVATTrate KEYWORD2 setAutoNAVATTcallback KEYWORD2 setAutoNAVATTcallbackPtr KEYWORD2 assumeAutoNAVATT KEYWORD2 -initPacketUBXNAVATT KEYWORD2 flushNAVATT KEYWORD2 logNAVATT KEYWORD2 @@ -279,7 +275,6 @@ setAutoPVTrate KEYWORD2 setAutoPVTcallback KEYWORD2 setAutoPVTcallbackPtr KEYWORD2 assumeAutoPVT KEYWORD2 -initPacketUBXNAVPVT KEYWORD2 flushPVT KEYWORD2 logNAVPVT KEYWORD2 @@ -289,7 +284,6 @@ setAutoNAVODOrate KEYWORD2 setAutoNAVODOcallback KEYWORD2 setAutoNAVODOcallbackPtr KEYWORD2 assumeAutoNAVODO KEYWORD2 -initPacketUBXNAVODO KEYWORD2 flushNAVODO KEYWORD2 logNAVODO KEYWORD2 @@ -299,7 +293,6 @@ setAutoNAVVELECEFrate KEYWORD2 setAutoNAVVELECEFcallback KEYWORD2 setAutoNAVVELECEFcallbackPtr KEYWORD2 assumeAutoNAVVELECEF KEYWORD2 -initPacketUBXNAVVELECEF KEYWORD2 flushNAVVELECEF KEYWORD2 logNAVVELECEF KEYWORD2 @@ -309,7 +302,6 @@ setAutoNAVVELNEDrate KEYWORD2 setAutoNAVVELNEDcallback KEYWORD2 setAutoNAVVELNEDcallbackPtr KEYWORD2 assumeAutoNAVVELNED KEYWORD2 -initPacketUBXNAVVELNED KEYWORD2 flushNAVVELNED KEYWORD2 logNAVVELNED KEYWORD2 @@ -319,7 +311,6 @@ setAutoNAVHPPOSECEFrate KEYWORD2 setAutoNAVHPPOSECEFcallback KEYWORD2 setAutoNAVHPPOSECEFcallbackPtr KEYWORD2 assumeAutoNAVHPPOSECEF KEYWORD2 -initPacketUBXNAVHPPOSECEF KEYWORD2 flushNAVHPPOSECEF KEYWORD2 logNAVHPPOSECEF KEYWORD2 @@ -329,7 +320,6 @@ setAutoHPPOSLLHrate KEYWORD2 setAutoHPPOSLLHcallback KEYWORD2 setAutoHPPOSLLHcallbackPtr KEYWORD2 assumeAutoHPPOSLLH KEYWORD2 -initPacketUBXNAVHPPOSLLH KEYWORD2 flushHPPOSLLH KEYWORD2 logNAVHPPOSLLH KEYWORD2 @@ -349,17 +339,20 @@ setAutoNAVCLOCKrate KEYWORD2 setAutoNAVCLOCKcallback KEYWORD2 setAutoNAVCLOCKcallbackPtr KEYWORD2 assumeAutoNAVCLOCK KEYWORD2 -initPacketUBXNAVCLOCK KEYWORD2 flushNAVCLOCK KEYWORD2 logNAVCLOCK KEYWORD2 getLeapSecondEvent KEYWORD2 getLeapIndicator KEYWORD2 getCurrentLeapSeconds KEYWORD2 -initPacketUBXNAVTIMELS KEYWORD2 getSurveyStatus KEYWORD2 -initPacketUBXNAVSVIN KEYWORD2 +setAutoNAVSVIN KEYWORD2 +setAutoNAVSVINrate KEYWORD2 +setAutoNAVSVINcallbackPtr KEYWORD2 +assumeAutoNAVSVIN KEYWORD2 +flushNAVSVIN KEYWORD2 +logNAVSVIN KEYWORD2 getNAVSAT KEYWORD2 setAutoNAVSAT KEYWORD2 @@ -367,7 +360,6 @@ setAutoNAVSATrate KEYWORD2 setAutoNAVSATcallback KEYWORD2 setAutoNAVSATcallbackPtr KEYWORD2 assumeAutoNAVSAT KEYWORD2 -initPacketUBXNAVSAT KEYWORD2 flushNAVSAT KEYWORD2 logNAVSAT KEYWORD2 @@ -377,7 +369,6 @@ setAutoRELPOSNEDrate KEYWORD2 setAutoRELPOSNEDcallback KEYWORD2 setAutoRELPOSNEDcallbackPtr KEYWORD2 assumeAutoRELPOSNED KEYWORD2 -initPacketUBXNAVRELPOSNED KEYWORD2 flushNAVRELPOSNED KEYWORD2 logNAVRELPOSNED KEYWORD2 @@ -387,7 +378,6 @@ setAutoAOPSTATUSrate KEYWORD2 setAutoAOPSTATUScallback KEYWORD2 setAutoAOPSTATUScallbackPtr KEYWORD2 assumeAutoAOPSTATUS KEYWORD2 -initPacketUBXAOPSTATUS KEYWORD2 flushAOPSTATUS KEYWORD2 logAOPSTATUS KEYWORD2 @@ -402,7 +392,6 @@ setAutoRXMSFRBXrate KEYWORD2 setAutoRXMSFRBXcallback KEYWORD2 setAutoRXMSFRBXcallbackPtr KEYWORD2 assumeAutoRXMSFRBX KEYWORD2 -initPacketUBXRXMSFRBX KEYWORD2 flushRXMSFRBX KEYWORD2 logRXMSFRBX KEYWORD2 @@ -412,7 +401,6 @@ setAutoRXMRAWXrate KEYWORD2 setAutoRXMRAWXcallback KEYWORD2 setAutoRXMRAWXcallbackPtr KEYWORD2 assumeAutoRXMRAWX KEYWORD2 -initPacketUBXRXMRAWX KEYWORD2 flushRXMRAWX KEYWORD2 logRXMRAWX KEYWORD2 @@ -422,7 +410,6 @@ setAutoTIMTM2rate KEYWORD2 setAutoTIMTM2callback KEYWORD2 setAutoTIMTM2callbackPtr KEYWORD2 assumeAutoTIMTM2 KEYWORD2 -initPacketUBXTIMTM2 KEYWORD2 flushTIMTM2 KEYWORD2 logTIMTM2 KEYWORD2 @@ -433,7 +420,6 @@ setAutoESFALGrate KEYWORD2 setAutoESFALGcallback KEYWORD2 setAutoESFALGcallbackPtr KEYWORD2 assumeAutoESFALG KEYWORD2 -initPacketUBXESFALG KEYWORD2 flushESFALG KEYWORD2 logESFALG KEYWORD2 @@ -444,7 +430,6 @@ setAutoESFSTATUSrate KEYWORD2 setAutoESFSTATUScallback KEYWORD2 setAutoESFSTATUScallbackPtr KEYWORD2 assumeAutoESFSTATUS KEYWORD2 -initPacketUBXESFSTATUS KEYWORD2 flushESFSTATUS KEYWORD2 logESFSTATUS KEYWORD2 @@ -455,7 +440,6 @@ setAutoESFINSrate KEYWORD2 setAutoESFINScallback KEYWORD2 setAutoESFINScallbackPtr KEYWORD2 assumeAutoESFINS KEYWORD2 -initPacketUBXESFINS KEYWORD2 flushESFINS KEYWORD2 logESFINS KEYWORD2 @@ -466,7 +450,6 @@ setAutoESFMEASrate KEYWORD2 setAutoESFMEAScallback KEYWORD2 setAutoESFMEAScallbackPtr KEYWORD2 assumeAutoESFMEAS KEYWORD2 -initPacketUBXESFMEAS KEYWORD2 flushESFMEAS KEYWORD2 logESFMEAS KEYWORD2 @@ -477,7 +460,6 @@ setAutoESFRAWrate KEYWORD2 setAutoESFRAWcallback KEYWORD2 setAutoESFRAWcallbackPtr KEYWORD2 assumeAutoESFRAW KEYWORD2 -initPacketUBXESFRAW KEYWORD2 flushESFRAW KEYWORD2 logESFRAW KEYWORD2 @@ -488,7 +470,6 @@ setAutoHNRATTrate KEYWORD2 setAutoHNRATTcallback KEYWORD2 setAutoHNRATTcallbackPtr KEYWORD2 assumeAutoHNRATT KEYWORD2 -initPacketUBXHNRATT KEYWORD2 flushHNRATT KEYWORD2 logHNRATT KEYWORD2 @@ -499,7 +480,6 @@ setAutoHNRINSrate KEYWORD2 setAutoHNRINScallback KEYWORD2 setAutoHNRINScallbackPtr KEYWORD2 assumeAutoHNRINS KEYWORD2 -initPacketUBXHNRINS KEYWORD2 flushHNRINS KEYWORD2 logHNRINS KEYWORD2 @@ -509,7 +489,6 @@ setAutoHNRPVTrate KEYWORD2 setAutoHNRPVTcallback KEYWORD2 setAutoHNRPVTcallbackPtr KEYWORD2 assumeAutoHNRPVT KEYWORD2 -initPacketUBXHNRPVT KEYWORD2 flushHNRPVT KEYWORD2 logHNRPVT KEYWORD2 diff --git a/library.properties b/library.properties index 19524b0..e6b176c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.2.7 +version=2.2.8 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules

diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 1c42dad..2938b12 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3588,6 +3588,20 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // Mark all datums as fresh (not read before) packetUBXNAVSVIN->moduleQueried.moduleQueried.all = 0xFFFFFFFF; + + // Check if we need to copy the data for the callback + if ((packetUBXNAVSVIN->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVSVIN->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + { + memcpy(&packetUBXNAVSVIN->callbackData->version, &packetUBXNAVSVIN->data.version, sizeof(UBX_NAV_SVIN_data_t)); + packetUBXNAVSVIN->automaticFlags.flags.bits.callbackCopyValid = true; + } + + // Check if we need to copy the data into the file buffer + if (packetUBXNAVSVIN->automaticFlags.flags.bits.addToFileBuffer) + { + storePacket(msg); + } } } else if (msg->id == UBX_NAV_SAT) // Note: length is variable @@ -3735,7 +3749,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // To prevent this, uncomment the line two lines below if ((packetUBXRXMPMP != NULL) && (packetUBXRXMPMP->callbackData != NULL) //&& (packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid == false) // <=== Uncomment this line to prevent new data from overwriting 'old' - ) + ) { packetUBXRXMPMP->callbackData->version = extractByte(msg, 0); packetUBXRXMPMP->callbackData->numBytesUserData = extractInt(msg, 2); @@ -3772,7 +3786,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // To prevent this, uncomment the line two lines below if ((packetUBXRXMPMPmessage != NULL) && (packetUBXRXMPMPmessage->callbackData != NULL) //&& (packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid == false) // <=== Uncomment this line to prevent new data from overwriting 'old' - ) + ) { packetUBXRXMPMPmessage->callbackData->sync1 = UBX_SYNCH_1; packetUBXRXMPMPmessage->callbackData->sync2 = UBX_SYNCH_2; @@ -3794,7 +3808,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // Parse various byte fields into storage - but only if we have memory allocated for it if ((packetUBXRXMCOR != NULL) && (packetUBXRXMCOR->callbackData != NULL) //&& (packetUBXRXMCOR->automaticFlags.flags.bits.callbackCopyValid == false) // <=== Uncomment this line to prevent new data from overwriting 'old' - ) + ) { packetUBXRXMCOR->callbackData->version = extractByte(msg, 0); packetUBXRXMCOR->callbackData->ebno = extractByte(msg, 1); @@ -5313,6 +5327,19 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVCLOCK->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } + if ((packetUBXNAVSVIN != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVSVIN->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVSVIN->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + { + if (packetUBXNAVSVIN->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV SVIN")); + packetUBXNAVSVIN->callbackPointerPtr(packetUBXNAVSVIN->callbackData); // Call the callback + } + packetUBXNAVSVIN->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + } + if ((packetUBXNAVSAT != NULL) // If RAM has been allocated for message storage && (packetUBXNAVSAT->callbackData != NULL) // If RAM has been allocated for the copy of the data && (packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid @@ -5372,34 +5399,34 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) if ((packetUBXRXMPMP != NULL) // If RAM has been allocated for message storage && (packetUBXRXMPMP->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + && (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined && (packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM PMP")); - packetUBXRXMPMP->callbackPointerPtr(packetUBXRXMPMP->callbackData); // Call the callback + packetUBXRXMPMP->callbackPointerPtr(packetUBXRXMPMP->callbackData); // Call the callback packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXRXMPMPmessage != NULL) // If RAM has been allocated for message storage && (packetUBXRXMPMPmessage->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMPMPmessage->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + && (packetUBXRXMPMPmessage->callbackPointerPtr != NULL) // If the pointer to the callback has been defined && (packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM PMP message")); packetUBXRXMPMPmessage->callbackPointerPtr(packetUBXRXMPMPmessage->callbackData); // Call the callback - packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXRXMCOR != NULL) // If RAM has been allocated for message storage && (packetUBXRXMCOR->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMCOR->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + && (packetUBXRXMCOR->callbackPointerPtr != NULL) // If the pointer to the callback has been defined && (packetUBXRXMCOR->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM COR")); - packetUBXRXMCOR->callbackPointerPtr(packetUBXRXMCOR->callbackData); // Call the callback + packetUBXRXMCOR->callbackPointerPtr(packetUBXRXMCOR->callbackData); // Call the callback packetUBXRXMCOR->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } @@ -8441,7 +8468,7 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validF } if (ok) - ok = setDynamicSPARTNKey(keyLengthBytes, validFromWno, validFromTow, (const uint8_t *)binaryKey); + ok = setDynamicSPARTNKey(keyLengthBytes, validFromWno, validFromTow, (const uint8_t *)binaryKey); delete[] binaryKey; // Free the memory allocated for binaryKey @@ -8590,7 +8617,7 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t vali if (ok) ok = setDynamicSPARTNKeys(keyLengthBytes1, validFromWno1, validFromTow1, (const uint8_t *)binaryKey1, - keyLengthBytes2, validFromWno2, validFromTow2, (const uint8_t *)binaryKey2); + keyLengthBytes2, validFromWno2, validFromTow2, (const uint8_t *)binaryKey2); delete[] binaryKey1; // Free the memory allocated for binaryKey1 delete[] binaryKey2; // Free the memory allocated for binaryKey2 @@ -11431,7 +11458,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVCLOCK(bool enable, bool implicitUpdate, uint16_t return setAutoNAVCLOCKrate(enable ? 1 : 0, implicitUpdate, maxWait); } -// Enable or disable automatic CLOCK attitude message generation by the GNSS. This changes the way getNAVCLOCK +// Enable or disable automatic CLOCK message generation by the GNSS. This changes the way getNAVCLOCK // works. bool SFE_UBLOX_GNSS::setAutoNAVCLOCKrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { @@ -11512,7 +11539,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVCLOCKcallbackPtr(void (*callbackPointerPtr)(UBX_N return (true); } -// In case no config access to the GNSS is possible and HNR attitude is send cyclically already +// In case no config access to the GNSS is possible and NAV CLOCK is send cyclically already // set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate) { @@ -11629,23 +11656,126 @@ bool SFE_UBLOX_GNSS::getSurveyStatus(uint16_t maxWait) if (packetUBXNAVSVIN == NULL) // Abort if the RAM allocation failed return (false); - packetCfg.cls = UBX_CLASS_NAV; - packetCfg.id = UBX_NAV_SVIN; - packetCfg.len = 0; + if (packetUBXNAVSVIN->automaticFlags.flags.bits.automatic && packetUBXNAVSVIN->automaticFlags.flags.bits.implicitUpdate) + { + // The GPS is automatically reporting, we just check whether we got unread data + checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_SVIN); + return packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.all; + } + else if (packetUBXNAVSVIN->automaticFlags.flags.bits.automatic && !packetUBXNAVSVIN->automaticFlags.flags.bits.implicitUpdate) + { + // Someone else has to call checkUblox for us... + return (false); + } + else + { + // The GPS is not automatically reporting SVIN so we have to poll explicitly + packetCfg.cls = UBX_CLASS_NAV; + packetCfg.id = UBX_NAV_SVIN; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + // The data is parsed as part of processing the response + sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait); + + if (retVal == SFE_UBLOX_STATUS_DATA_RECEIVED) + return (true); + + if (retVal == SFE_UBLOX_STATUS_DATA_OVERWRITTEN) + { + return (true); + } + + return (false); + } +} + +// Enable or disable automatic SVIN message generation by the GNSS. This changes the way getSurveyStatus +// works. +bool SFE_UBLOX_GNSS::setAutoNAVSVIN(bool enable, uint16_t maxWait) +{ + return setAutoNAVSVINrate(enable ? 1 : 0, true, maxWait); +} + +// Enable or disable automatic SVIN message generation by the GNSS. This changes the way getSurveyStatus +// works. +bool SFE_UBLOX_GNSS::setAutoNAVSVIN(bool enable, bool implicitUpdate, uint16_t maxWait) +{ + return setAutoNAVSVINrate(enable ? 1 : 0, implicitUpdate, maxWait); +} + +// Enable or disable automatic SVIN message generation by the GNSS. This changes the way getSurveyStatus +// works. +bool SFE_UBLOX_GNSS::setAutoNAVSVINrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) +{ + if (packetUBXNAVSVIN == NULL) + initPacketUBXNAVSVIN(); // Check that RAM has been allocated for the data + if (packetUBXNAVSVIN == NULL) // Only attempt this if RAM allocation was successful + return false; + + if (rate > 127) + rate = 127; + + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_MSG; + packetCfg.len = 3; packetCfg.startingSpot = 0; + payloadCfg[0] = UBX_CLASS_NAV; + payloadCfg[1] = UBX_NAV_SVIN; + payloadCfg[2] = rate; // rate relative to navigation freq. - // The data is parsed as part of processing the response - sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait); + bool ok = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK + if (ok) + { + packetUBXNAVSVIN->automaticFlags.flags.bits.automatic = (rate > 0); + packetUBXNAVSVIN->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.all = false; // Mark data as stale + return ok; +} - if (retVal == SFE_UBLOX_STATUS_DATA_RECEIVED) - return (true); +// Enable automatic navigation message generation by the GNSS. +bool SFE_UBLOX_GNSS::setAutoNAVSVINcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SVIN_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVSVIN(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed - if (retVal == SFE_UBLOX_STATUS_DATA_OVERWRITTEN) + if (packetUBXNAVSVIN->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - return (true); + packetUBXNAVSVIN->callbackData = new UBX_NAV_SVIN_data_t; // Allocate RAM for the main struct } - return (false); + if (packetUBXNAVSVIN->callbackData == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setAutoNAVSVINcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVSVIN->callbackPointerPtr = callbackPointerPtr; + return (true); +} + +// In case no config access to the GNSS is possible and SVIN is send cyclically already +// set config to suitable parameters +bool SFE_UBLOX_GNSS::assumeAutoNAVSVIN(bool enabled, bool implicitUpdate) +{ + if (packetUBXNAVSVIN == NULL) + initPacketUBXNAVSVIN(); // Check that RAM has been allocated for the SVIN data + if (packetUBXNAVSVIN == NULL) // Bail if the RAM allocation failed + return (false); + + bool changes = packetUBXNAVSVIN->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVSVIN->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; + if (changes) + { + packetUBXNAVSVIN->automaticFlags.flags.bits.automatic = enabled; + packetUBXNAVSVIN->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + return changes; } // PRIVATE: Allocate RAM for packetUBXNAVSVIN and initialize it @@ -11661,13 +11791,28 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSVIN() return (false); } packetUBXNAVSVIN->automaticFlags.flags.all = 0; - packetUBXNAVSVIN->callbackPointer = NULL; packetUBXNAVSVIN->callbackPointerPtr = NULL; packetUBXNAVSVIN->callbackData = NULL; packetUBXNAVSVIN->moduleQueried.moduleQueried.all = 0; return (true); } +// Mark all the data as read/stale +void SFE_UBLOX_GNSS::flushNAVSVIN() +{ + if (packetUBXNAVSVIN == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSVIN->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) +} + +// Log this data in file buffer +void SFE_UBLOX_GNSS::logNAVSVIN(bool enabled) +{ + if (packetUBXNAVSVIN == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSVIN->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; +} + // ***** NAV SAT automatic support // Signal information @@ -11727,7 +11872,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVSAT(bool enable, bool implicitUpdate, uint16_t ma return setAutoNAVSATrate(enable ? 1 : 0, implicitUpdate, maxWait); } -// Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getNAVSAT +// Enable or disable automatic NAV SAT message generation by the GNSS. This changes the way getNAVSAT // works. bool SFE_UBLOX_GNSS::setAutoNAVSATrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { @@ -11808,7 +11953,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVSATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV return (true); } -// In case no config access to the GNSS is possible and HNR attitude is send cyclically already +// In case no config access to the GNSS is possible and NAV SAT is send cyclically already // set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVSAT(bool enabled, bool implicitUpdate) { @@ -11924,7 +12069,7 @@ bool SFE_UBLOX_GNSS::setAutoRELPOSNED(bool enable, bool implicitUpdate, uint16_t return setAutoRELPOSNEDrate(enable ? 1 : 0, implicitUpdate, maxWait); } -// Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getRELPOSNED +// Enable or disable automatic RELPOSNED message generation by the GNSS. This changes the way getRELPOSNED // works. bool SFE_UBLOX_GNSS::setAutoRELPOSNEDrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { @@ -12005,7 +12150,7 @@ bool SFE_UBLOX_GNSS::setAutoRELPOSNEDcallbackPtr(void (*callbackPointerPtr)(UBX_ return (true); } -// In case no config access to the GNSS is possible and HNR attitude is send cyclically already +// In case no config access to the GNSS is possible and RELPOSNED is send cyclically already // set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoRELPOSNED(bool enabled, bool implicitUpdate) { @@ -15833,6 +15978,15 @@ uint8_t SFE_UBLOX_GNSS::getNavigationFrequency(uint16_t maxWait) uint16_t measurementRate = packetUBXCFGRATE->data.measRate; + if (measurementRate == 0) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("getNavigationFrequency: zero measRate!")); +#endif + return (0); // Avoid divide-by-zero error + } + measurementRate = 1000 / measurementRate; // This may return an int when it's a float, but I'd rather not return 4 bytes return (measurementRate); } @@ -16232,16 +16386,16 @@ uint32_t SFE_UBLOX_GNSS::getUnixEpoch(uint16_t maxWait) packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.min = false; packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.sec = false; packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; - uint32_t t = SFE_UBLOX_DAYS_FROM_1970_TO_2020; // Jan 1st 2020 as days from Jan 1st 1970 - t += (uint32_t)SFE_UBLOX_DAYS_SINCE_2020[packetUBXNAVPVT->data.year - 2020]; // Add on the number of days since 2020 + uint32_t t = SFE_UBLOX_DAYS_FROM_1970_TO_2020; // Jan 1st 2020 as days from Jan 1st 1970 + t += (uint32_t)SFE_UBLOX_DAYS_SINCE_2020[packetUBXNAVPVT->data.year - 2020]; // Add on the number of days since 2020 t += (uint32_t)SFE_UBLOX_DAYS_SINCE_MONTH[packetUBXNAVPVT->data.year % 4 == 0 ? 0 : 1][packetUBXNAVPVT->data.month - 1]; // Add on the number of days since Jan 1st - t += (uint32_t)packetUBXNAVPVT->data.day - 1; // Add on the number of days since the 1st of the month - t *= 24; // Convert to hours - t += (uint32_t)packetUBXNAVPVT->data.hour; // Add on the hour - t *= 60; // Convert to minutes - t += (uint32_t)packetUBXNAVPVT->data.min; // Add on the minute - t *= 60; // Convert to seconds - t += (uint32_t)packetUBXNAVPVT->data.sec; // Add on the second + t += (uint32_t)packetUBXNAVPVT->data.day - 1; // Add on the number of days since the 1st of the month + t *= 24; // Convert to hours + t += (uint32_t)packetUBXNAVPVT->data.hour; // Add on the hour + t *= 60; // Convert to minutes + t += (uint32_t)packetUBXNAVPVT->data.min; // Add on the minute + t *= 60; // Convert to seconds + t += (uint32_t)packetUBXNAVPVT->data.sec; // Add on the second return t; } @@ -16263,23 +16417,23 @@ uint32_t SFE_UBLOX_GNSS::getUnixEpoch(uint32_t µsecond, uint16_t maxWait) packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.sec = false; packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.nano = false; packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; - uint32_t t = SFE_UBLOX_DAYS_FROM_1970_TO_2020; // Jan 1st 2020 as days from Jan 1st 1970 - t += (uint32_t)SFE_UBLOX_DAYS_SINCE_2020[packetUBXNAVPVT->data.year - 2020]; // Add on the number of days since 2020 + uint32_t t = SFE_UBLOX_DAYS_FROM_1970_TO_2020; // Jan 1st 2020 as days from Jan 1st 1970 + t += (uint32_t)SFE_UBLOX_DAYS_SINCE_2020[packetUBXNAVPVT->data.year - 2020]; // Add on the number of days since 2020 t += (uint32_t)SFE_UBLOX_DAYS_SINCE_MONTH[packetUBXNAVPVT->data.year % 4 == 0 ? 0 : 1][packetUBXNAVPVT->data.month - 1]; // Add on the number of days since Jan 1st - t += (uint32_t)packetUBXNAVPVT->data.day - 1; // Add on the number of days since the 1st of the month - t *= 24; // Convert to hours - t += (uint32_t)packetUBXNAVPVT->data.hour; // Add on the hour - t *= 60; // Convert to minutes - t += (uint32_t)packetUBXNAVPVT->data.min; // Add on the minute - t *= 60; // Convert to seconds - t += (uint32_t)packetUBXNAVPVT->data.sec; // Add on the second - int32_t us = packetUBXNAVPVT->data.nano / 1000; // Convert nanos to micros - microsecond = (uint32_t)us; // Could be -ve! + t += (uint32_t)packetUBXNAVPVT->data.day - 1; // Add on the number of days since the 1st of the month + t *= 24; // Convert to hours + t += (uint32_t)packetUBXNAVPVT->data.hour; // Add on the hour + t *= 60; // Convert to minutes + t += (uint32_t)packetUBXNAVPVT->data.min; // Add on the minute + t *= 60; // Convert to seconds + t += (uint32_t)packetUBXNAVPVT->data.sec; // Add on the second + int32_t us = packetUBXNAVPVT->data.nano / 1000; // Convert nanos to micros + microsecond = (uint32_t)us; // Could be -ve! // Adjust t if nano is negative if (us < 0) { microsecond = (uint32_t)(us + 1000000); // Make nano +ve - t--; // Decrement t by 1 second + t--; // Decrement t by 1 second } return t; } diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index dde932c..297d88c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1110,11 +1110,17 @@ class SFE_UBLOX_GNSS void flushNAVCLOCK(); // Mark all the data as read/stale void logNAVCLOCK(bool enabled = true); // Log data to file buffer - // Add "auto" support for NAV SVIN - to avoid needing 'global' storage - bool getSurveyStatus(uint16_t maxWait); // Reads survey in status + bool getSurveyStatus(uint16_t maxWait = 2100); // NAV SVIN - Reads survey in status + bool setAutoNAVSVIN(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic survey in reports at the navigation frequency + bool setAutoNAVSVIN(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic survey in reports at the navigation frequency, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update + bool setAutoNAVSVINrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic SVIN reports + bool setAutoNAVSVINcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SVIN_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic SVIN reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVSVIN(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and survey in is send cyclically already + void flushNAVSVIN(); // Mark all the data as read/stale + void logNAVSVIN(bool enabled = true); // Log data to file buffer // Add "auto" support for NAV TIMELS - to avoid needing 'global' storage - bool getLeapSecondEvent(uint16_t maxWait); // Reads leap second event info + bool getLeapSecondEvent(uint16_t maxWait = defaultMaxWait); // Reads leap second event info bool getNAVSAT(uint16_t maxWait = defaultMaxWait); // Query module for latest AssistNow Autonomous status and load global vars:. If autoNAVSAT is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new NAVSAT is available. bool setAutoNAVSAT(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic NAVSAT reports at the navigation frequency diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 321bf53..105477f 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1233,7 +1233,6 @@ typedef struct ubxAutomaticFlags automaticFlags; UBX_NAV_SVIN_data_t data; UBX_NAV_SVIN_moduleQueried_t moduleQueried; - void (*callbackPointer)(UBX_NAV_SVIN_data_t); void (*callbackPointerPtr)(UBX_NAV_SVIN_data_t *); UBX_NAV_SVIN_data_t *callbackData; } UBX_NAV_SVIN_t;