From d6109694ebdfc1665e4aef8851a5d8625874eb0c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 24 Nov 2021 17:01:41 +0000 Subject: [PATCH 001/122] Add READMEs. Add AssistNow_Online Example1 --- README.md | 4 + .../Example1_AssistNowClient.ino | 163 ++++++++++++++++++ .../Example1_AssistNowClient/secrets.h | 6 + examples/AssistNow/README.md | 55 ++++++ 4 files changed, 228 insertions(+) create mode 100644 examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino create mode 100644 examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/secrets.h create mode 100644 examples/AssistNow/README.md diff --git a/README.md b/README.md index 9a2be98..98a4206 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,10 @@ Migrating to v2.0 is easy. There are two small changes all users will need to ma If you are using the Dead Reckoning Sensor Fusion or High Dynamic Rate messages, you will need to make more small changes to your code. Please see the [dead reckoning examples](./examples/Dead_Reckoning) for more details. There is more detail available in [Theory.md](./Theory.md#migrating-your-code-to-v20) if you need it. +## AssistNowTM + +v2.1.0 of the library adds support for u-blox AssistNowTM Assisted GNSS (A-GNSS) which can dramatically reduce the time-to-first-fix. You can find further details in the [AssistNow Examples folder](./examples/AssistNow). + ## Memory Usage The u-blox GNSS library has grown considerably over the years and v2.0.8 came very close to completely filling the program memory on platforms like the ATmega328 (Arduino Uno). diff --git a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino new file mode 100644 index 0000000..4650355 --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino @@ -0,0 +1,163 @@ +/* + Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream + By: SparkFun Electronics / Paul Clark + Date: November 24th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi + and push it over I2C to a ZED-F9x. + + You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. + + Update secrets.h with your: + - WiFi credentials + - AssistNow token string + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +#include +#include "secrets.h" + +const char assistNowServer[] = "https://online-live1.services.u-blox.com"; +//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server + +const char getQuery[] = "GetOnlineData.ashx?"; +const char tokenPrefix[] = "token="; +const char tokenSuffix[] = ";"; +const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal +const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos + +const unsigned long maxTimeBeforeHangup_ms = 10000; //If we fail to get data after 10s, then disconnect + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println("AssistNow Example"); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + +// Wire.begin(); //Start I2C +// +// if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port +// { +// Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); +// while (1); +// } +// Serial.println(F("u-blox module connected")); +// +// myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise +// +// myGNSS.setNavigationFrequency(1); //Set output in Hz. + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to WiFi. + + Serial.print("Connecting to local WiFi"); + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + Serial.println("WiFi connected!"); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Make the HTTP request + + const int URL_BUFFER_SIZE = 512; + char theURL[URL_BUFFER_SIZE]; + int payloadSize; + String payload; + + // Assemble the URL + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getDataType); + + Serial.print("URL is: "); + Serial.println(theURL); + + HTTPClient http; + + http.begin(theURL); + + int httpCode = http.GET(); + + // httpCode will be negative on error + if(httpCode > 0) + { + // HTTP header has been sent and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\n", httpCode); + + // file found at server + if(httpCode == HTTP_CODE_OK) // Code 200 + { + payloadSize = http.getSize(); + Serial.printf("Server returned %d bytes\r\n", payloadSize); + + payload = http.getString(); // Get the payload + + // Pretty-print the payload as HEX + int i; + for(i = 0; i < payloadSize; i++) + { + if (payload[i] < 0x10) // Print leading zero + Serial.print("0"); + Serial.print(payload[i], HEX); + Serial.print(" "); + if ((i % 16) == 15) + Serial.println(); + } + if ((i % 16) != 15) + Serial.println(); + } + } + else + { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the AssistNow data to the module + + + +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + // Nothing to do here +} diff --git a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/secrets.h b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/secrets.h new file mode 100644 index 0000000..4eb7a9c --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/secrets.h @@ -0,0 +1,6 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "hasBigTeeth"; + +//Your AssistNow token +const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md new file mode 100644 index 0000000..6056018 --- /dev/null +++ b/examples/AssistNow/README.md @@ -0,0 +1,55 @@ +# SparkFun u-blox Arduino GNSS Library - AssistNowTM + +v2.1.0 of the library adds support for u-blox [AssistNowTM Assisted GNSS (A-GNSS)](https://www.u-blox.com/en/product/assistnow) which can dramatically reduce the time-to-first-fix. + +To use AssistNow Online or AssistNow Offline, you will need a token to access the u-blox Thingstream server. See [below](#AssistNow-Service-Token) for details. + +## AssistNowTM Online + +With AssistNow Online, an Internet connected host downloads assistance data from the u-blox AssistNow Online service to the receiver at system start-up. AssistNow Online data is valid for 2 - 4 hours; beyond that fresh data must be downloaded. + +Please see the [AssistNow_Online](./AssistNow_Online) examples for more details. These examples were written for the ESP32, but will run on other platforms too. + +## AssistNowTM Offline + +With the AssistNow Offline service, users can download long-term orbit data over the Internet at their convenience. The orbit data can be stored in the memory of the application processor. The function requires no connectivity at system start-up, enabling a position fix within seconds, even when no network is available. AssistNow Offline offers augmentation for up to 35 days. + +Please see the [AssistNow_Offline](./AssistNow_Offline) examples for more details. These examples were written for the ESP32, but will run on other platforms too. + +## AssistNowTM Autonomous + +AssistNow Autonomous provides aiding information without the need for a host or external network connection. Based on previous broadcast satellite ephemeris data downloaded to and stored by the GNSS receiver, AssistNow Autonomous automatically generates accurate predictions of satellite orbital data (“AssistNow Autonomous data”) that is usable for future GNSS position fixes. + +The benefits of AssistNow Autonomous are: + +* Faster fix in situations where GNSS satellite signals are weak +* No connectivity required +* Compatible with AssistNow Online (can work stand-alone, or in tandem with AssistNow Online service) +* No integration effort; calculations are done in the background, transparent to the user + +AssistNow Autonomous offers augmentation for up to 6 days. + +Please see the [AssistNow_Autonomous](./AssistNow_Autonomous) examples for more details. + +## AssistNow Service Token + +To be able to use AssistNow Online or AssistNow Offline, you will need a token to access the u-blox Thingstream server. + +The following u-blox resources contain useful information: + +* [AssistNow - u-blox A-GNSS services](https://www.u-blox.com/en/product/assistnow) +* [AssistNow Product Summary](https://www.u-blox.com/sites/default/files/products/documents/AssistNow_ProductSummary_UBX-13003352.pdf) +* [AssistNow User Guide](https://www.u-blox.com/sites/default/files/products/documents/MultiGNSS-Assistance_UserGuide_%28UBX-13004360%29.pdf) +* [Thingstream Pricing](https://portal.thingstream.io/pricing) + +You can apply for a _free_ AssistNow Service Evaluation Token by completing the request form: + +* [AssistNow Service evaluation token request form](https://www.u-blox.com/en/assistnow-service-evaluation-token-request-form) + +The _free_ AssistNow Developer token entitles you to: + +* AssistNow Online Developer: 100K free location requests per month. Capped. +* AssistNow Offline Developer: 20K free location requests per month. Capped. +* CellLocate Developer: 5K free location requests per month. Capped. + +The free token will expire after 90 days, but you can continue to use it beyond that by registering it on [Thingstream](https://portal.thingstream.io/). From 28e7c12b32b1de7322f9e57aa2e484dadc3dbc7a Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 25 Nov 2021 12:29:29 +0000 Subject: [PATCH 002/122] Add ring buffer for incoming MGA ACKs --- .../Example1_AssistNowClient.ino | 83 ++++-- keywords.txt | 29 ++- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 239 ++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 37 ++- src/u-blox_structs.h | 25 ++ 5 files changed, 383 insertions(+), 30 deletions(-) diff --git a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino index 4650355..eb468b2 100644 --- a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino +++ b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino @@ -39,8 +39,6 @@ const char tokenSuffix[] = ";"; const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos -const unsigned long maxTimeBeforeHangup_ms = 10000; //If we fail to get data after 10s, then disconnect - //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include //http://librarymanager/All#SparkFun_u-blox_GNSS @@ -58,18 +56,18 @@ void setup() //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Start I2C. Connect to the GNSS. -// Wire.begin(); //Start I2C -// -// if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port -// { -// Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); -// while (1); -// } -// Serial.println(F("u-blox module connected")); -// -// myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise -// -// myGNSS.setNavigationFrequency(1); //Set output in Hz. + Wire.begin(); //Start I2C + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + + myGNSS.setNavigationFrequency(1); //Set output in Hz. //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Connect to WiFi. @@ -86,14 +84,14 @@ void setup() Serial.println("WiFi connected!"); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // Make the HTTP request + // Use HTTP GET to receive the AssistNow_Online data - const int URL_BUFFER_SIZE = 512; - char theURL[URL_BUFFER_SIZE]; - int payloadSize; - String payload; + const int URL_BUFFER_SIZE = 256; + char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL + int payloadSize = 0; // This will be updated with the length of the data we get from the server + String payload; // This will store the data we get from the server - // Assemble the URL + // Assemble the URL. Note the slash after assistNowServer snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", assistNowServer, getQuery, @@ -103,14 +101,14 @@ void setup() getGNSS, getDataType); - Serial.print("URL is: "); + Serial.print("HTTP URL is: "); Serial.println(theURL); HTTPClient http; http.begin(theURL); - int httpCode = http.GET(); + int httpCode = http.GET(); // HTTP GET // httpCode will be negative on error if(httpCode > 0) @@ -118,7 +116,7 @@ void setup() // HTTP header has been sent and Server response header has been handled Serial.printf("[HTTP] GET... code: %d\n", httpCode); - // file found at server + // If the GET was successful, read the data if(httpCode == HTTP_CODE_OK) // Code 200 { payloadSize = http.getSize(); @@ -127,6 +125,7 @@ void setup() payload = http.getString(); // Get the payload // Pretty-print the payload as HEX + /* int i; for(i = 0; i < payloadSize; i++) { @@ -139,6 +138,7 @@ void setup() } if ((i % 16) != 15) Serial.println(); + */ } } else @@ -151,13 +151,46 @@ void setup() //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Push the AssistNow data to the module + if (payloadSize > 0) + { + // Enable the 'major' debug messages on Serial so we can see what AssistNow data is being sent + myGNSS.enableDebugging(Serial, true); - + // Push all the AssistNow data - without checking for UBX-MGA-ACK messages + myGNSS.pushAssistNowData((uint8_t *)&payload, (size_t)payloadSize); + } } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= void loop() { - // Nothing to do here + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte SIV = myGNSS.getSIV(); + Serial.print(F(" SIV: ")); + Serial.print(SIV); + + byte fixType = myGNSS.getFixType(); + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); } diff --git a/keywords.txt b/keywords.txt index d1268a2..6d1123a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -90,6 +90,8 @@ checkCallbacks KEYWORD2 pushRawData KEYWORD2 +pushAssistNowData KEYWORD2 + setFileBufferSize KEYWORD2 getFileBufferSize KEYWORD2 extractFileBufferData KEYWORD2 @@ -153,6 +155,18 @@ getDynamicModel KEYWORD2 resetOdometer KEYWORD2 enableGNSS KEYWORD2 +isGNSSenabled KEYWORD2 + +resetIMUalignment KEYWORD2 + +getESFAutoAlignment KEYWORD2 +setESFAutoAlignment KEYWORD2 + +getTimePulseParameters KEYWORD2 +setTimePulseParameters KEYWORD2 + +getAckAiding KEYWORD2 +setAckAiding KEYWORD2 createKey KEYWORD2 getVal KEYWORD2 @@ -367,9 +381,6 @@ initPacketUBXESFRAW KEYWORD2 flushESFRAW KEYWORD2 logESFRAW KEYWORD2 -getESFAutoAlignment KEYWORD2 -setESFAutoAlignment KEYWORD2 - getHNRAtt KEYWORD2 getHNRATT KEYWORD2 setAutoHNRATT KEYWORD2 @@ -675,4 +686,14 @@ SFE_UBLOX_GNSS_ID_IMES LITERAL1 SFE_UBLOX_GNSS_ID_QZSS LITERAL1 SFE_UBLOX_GNSS_ID_GLONASS LITERAL1 -DAYS_SINCE_MONTH LITERAL1 +SFE_UBLOX_MGA_ASSIST_ACK_NO LITERAL1 +SFE_UBLOX_MGA_ASSIST_ACK_YES LITERAL1 +SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE LITERAL1 + +SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED LITERAL1 +SFE_UBLOX_MGA_ACK_INFOCODE_NO_TIME LITERAL1 +SFE_UBLOX_MGA_ACK_INFOCODE_NOT_SUPPORTED LITERAL1 +SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH LITERAL1 +SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED LITERAL1 +SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY LITERAL1 +SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN LITERAL1 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 68130fa..3217208 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2715,6 +2715,44 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } } break; + case UBX_CLASS_MGA: + if (msg->id == UBX_MGA_ACK_DATA0 && msg->len == UBX_MGA_ACK_DATA0_LEN) + { + //Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXMGAACK != NULL) + { + // Calculate how many ACKs are already stored in the ring buffer + uint8_t ackBufferContains; + if (packetUBXMGAACK->head >= packetUBXMGAACK->tail) // Check if wrap-around has occurred + { + // Wrap-around has not occurred so do a simple subtraction + ackBufferContains = packetUBXMGAACK->head - packetUBXMGAACK->tail; + } + else + { + // Wrap-around has occurred so do a simple subtraction but add in the buffer length (UBX_MGA_ACK_RINGBUFFER_LEN) + ackBufferContains = ((uint8_t)(((uint16_t)packetUBXMGAACK->head + (uint16_t)UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) - (uint16_t)packetUBXMGAACK->tail)); + } + // Have we got space to store this ACK? + if (ackBufferContains < (UBX_MGA_ACK_DATA0_RINGBUFFER_LEN - 1)) + { + // Yes, we have, so store it + packetUBXMGAACK->data[packetUBXMGAACK->head].type = extractByte(msg, 0); + packetUBXMGAACK->data[packetUBXMGAACK->head].version = extractByte(msg, 1); + packetUBXMGAACK->data[packetUBXMGAACK->head].infoCode = extractByte(msg, 2); + packetUBXMGAACK->data[packetUBXMGAACK->head].msgId = extractByte(msg, 3); + packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[0] = extractByte(msg, 4); + packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[1] = extractByte(msg, 5); + packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[2] = extractByte(msg, 6); + packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[3] = extractByte(msg, 7); + // Increment the head + packetUBXMGAACK->head++; + if (packetUBXMGAACK->head == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) + packetUBXMGAACK->head = 0; + } + } + } + break; case UBX_CLASS_HNR: if (msg->id == UBX_HNR_PVT && msg->len == UBX_HNR_PVT_LEN) { @@ -3931,6 +3969,169 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s } } +// Push MGA AssistNow data to the module +// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) +// Wait for maxWait millis after sending each packet (if mgaAck is NO) +// Return how many MGA packets were pushed successfully +uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + size_t dataPtr = 0; // Pointer into dataBytes + uint16_t packetsProcessed = 0; // Keep count of how many packets have been processed + + bool checkForAcks = (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_YES); // If mgaAck is YES, always check for Acks + + // If mgaAck is ENQUIRE, we need to check UBX-CFG-NAVX5 ackAiding to determine if UBX-MGA-ACK's are expected + if (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE) + { + uint8_t ackAiding = getAckAiding(maxWait); // Enquire if we should expect Acks + if (ackAiding == 1) + checkForAcks = true; + } + + // If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages and use the callback + if (checkForAcks) + { + if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data + if (packetUBXMGAACK == NULL) //Bail if the RAM allocation failed + return (0); + } + + while (dataPtr < numDataBytes) // Keep going until we have processed all the bytes + { + // Start by checking the validity of the packet being pointed to + bool dataIsOK = true; + + dataIsOK &= dataBytes[dataPtr + 0] == UBX_SYNCH_1; // Check for 0xB5 + dataIsOK &= dataBytes[dataPtr + 1] == UBX_SYNCH_2; // Check for 0x62 + dataIsOK &= dataBytes[dataPtr + 2] == UBX_CLASS_MGA; // Check for class UBX-MGA + + size_t packetLength = (size_t)dataBytes[dataPtr + 4] + ((size_t)dataBytes[dataPtr + 5] << 8); // Extract the length + uint8_t checksumA = 0; + uint8_t checksumB = 0; + // Calculate the checksum bytes + // Keep going until the end of the packet is reached (payloadPtr == (dataPtr + packetLength)) + // or we reach the end of the AssistNow data (payloadPtr == numDataBytes) + for (size_t payloadPtr = dataPtr + ((size_t)6); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++) + { + checksumA += dataBytes[payloadPtr]; + checksumB += checksumA; + } + // Check the checksum bytes + dataIsOK &= checksumA == dataBytes[dataPtr + packetLength + ((size_t)6)]; + dataIsOK &= checksumB == dataBytes[dataPtr + packetLength + ((size_t)7)]; + dataIsOK &= (dataPtr + packetLength + ((size_t)8)) <= numDataBytes; // Check we haven't overrun + + // If the data is valid, push it + if (dataIsOK) + { + pushRawData((uint8_t *)&dataBytes[dataPtr], packetLength + ((size_t)8)); // Push the data + + if (checkForAcks) + { + unsigned long startTime = millis(); + bool keepGoing = true; + while (keepGoing && (millis() < (startTime + maxWait))) // Keep checking for the ACK until we time out + { + checkUblox(); + if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's? + { + bool dataAckd = true; // Check if we've received the correct ACK + dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == dataBytes[dataPtr + 3]; + dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == dataBytes[dataPtr + 6]; + dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == dataBytes[dataPtr + 7]; + dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == dataBytes[dataPtr + 8]; + dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == dataBytes[dataPtr + 9]; + + if (dataAckd) // Is this the ACK we are looking for? + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: packet ID 0x")); + if (dataBytes[dataPtr + 3] < 0x10) + _debugSerial->print(F("0")); + _debugSerial->print(dataBytes[dataPtr + 3], HEX); + } + if ((packetUBXMGAACK->data[packetUBXMGAACK->tail].type == (uint8_t)1) && (packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode == (uint8_t)SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED)) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F(" was accepted")); + } + packetsProcessed++; + } + else + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F(" was _not_ accepted. infoCode is ")); + _debugSerial->println(packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode); + } + } + keepGoing = false; + } + // Increment the tail + packetUBXMGAACK->tail++; + if (packetUBXMGAACK->tail == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) + packetUBXMGAACK->tail = 0; + } + } + if (keepGoing) // If keepGoing is still true, we must have timed out + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: packet ID 0x")); + if (dataBytes[dataPtr + 3] < 0x10) + _debugSerial->print(F("0")); + _debugSerial->print(dataBytes[dataPtr + 3], HEX); + _debugSerial->println(F(" timed out!")); + } + } + } + else + { + // We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data + if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes) + { + delay(maxWait); + } + } + + dataPtr += packetLength + ((size_t)8); // Point to the next message + } + else + { + // The data was invalid. Send a debug message and then try to find the next 0xB5 + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: bad data - ignored! dataPtr is")); + _debugSerial->println(dataPtr); + } + + while ((dataPtr < numDataBytes) && (dataBytes[++dataPtr] != UBX_SYNCH_1)) + { + ; // Increment dataPtr until we are pointing at the next 0xB5 - or we reach the end of the data + } + } + } + + return (packetsProcessed); +} + +// PRIVATE: Allocate RAM for packetUBXMGAACK and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXMGAACK() +{ + packetUBXMGAACK = new UBX_MGA_ACK_DATA0_t; //Allocate RAM for the main struct + if (packetUBXMGAACK == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXMGAACK: RAM alloc failed!")); + return (false); + } + packetUBXMGAACK->head = 0; // Initialize the ring buffer pointers + packetUBXMGAACK->tail = 0; + return (true); +} + // Support for data logging //Set the file buffer size. This must be called _before_ .begin @@ -5383,6 +5584,44 @@ bool SFE_UBLOX_GNSS::setTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t m return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } +//UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data +uint8_t SFE_UBLOX_GNSS::getAckAiding(uint16_t maxWait) // Get the ackAiding byte - returns 255 if the sendCommand fails +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NAVX5; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (255); + + // Extract the ackAiding byte + // There are three versions of UBX-CFG-NAVX5 but ackAiding is always in byte 17 + return (extractByte(&packetCfg, 17)); +} +bool SFE_UBLOX_GNSS::setAckAiding(uint8_t ackAiding, uint16_t maxWait) // Set the ackAiding byte +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NAVX5; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + // Set the ackAiding byte + // There are three versions of UBX-CFG-NAVX5 but ackAiding is always in byte 17 + payloadCfg[17] = ackAiding; + + // There are three versions of UBX-CFG-NAVX5 but the ackAid flag is always in bit 10 of mask1 + payloadCfg[2] = 0x00; // Clear the LS byte of mask1 + payloadCfg[3] = 0x40; // Set _only_ the ackAid flag = bit 10 of mask1 = bit 2 of the MS byte + payloadCfg[4] = 0x00; // Clear the LS byte of mask2, just in case + payloadCfg[5] = 0x00; // Clear the LS byte of mask2, just in case + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + // CONFIGURATION INTERFACE (protocol v27 and above) //Form 32-bit key from group/id/size diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 1bc37b9..90eea67 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -200,7 +200,7 @@ const uint8_t UBX_CFG_BATCH = 0x93; //Get/set data batching configuration. const uint8_t UBX_CFG_CFG = 0x09; //Clear, Save, and Load Configurations. Used to save current configuration const uint8_t UBX_CFG_DAT = 0x06; //Set User-defined Datum or The currently defined Datum const uint8_t UBX_CFG_DGNSS = 0x70; //DGNSS configuration -const uint8_t UBX_CFG_ESFALG = 0x56; //ESF alignment +const uint8_t UBX_CFG_ESFALG = 0x56; //ESF alignment const uint8_t UBX_CFG_ESFA = 0x4C; //ESF accelerometer const uint8_t UBX_CFG_ESFG = 0x4D; //ESF gyro const uint8_t UBX_CFG_GEOFENCE = 0x69; //Geofencing configuration. Used to configure a geofence @@ -496,6 +496,27 @@ enum sfe_ublox_ls_src_e SFE_UBLOX_LS_SRC_UNKNOWN = 255 }; +typedef enum +{ + SFE_UBLOX_MGA_ASSIST_ACK_NO, // Do not expect UBX-MGA-ACK's. If the module outputs them, they will be ignored + SFE_UBLOX_MGA_ASSIST_ACK_YES, // Expect and check for UBX-MGA-ACK's + SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE // Check UBX-CFG-NAVX5 ackAiding to determine if UBX-MGA-ACK's are expected +} sfe_ublox_mga_assist_ack_e; + +// The infoCode byte included in UBX-MGA-ACK-DATA0 +enum sfe_ublox_mga_ack_infocode_e +{ + SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED, + SFE_UBLOX_MGA_ACK_INFOCODE_NO_TIME, + SFE_UBLOX_MGA_ACK_INFOCODE_NOT_SUPPORTED, + SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH, + SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED, + SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY, + SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN +}; + +//-=-=-=-=- + #ifndef MAX_PAYLOAD_SIZE // v2.0: keep this for backwards-compatibility, but this is largely superseded by setPacketCfgPayloadSize #define MAX_PAYLOAD_SIZE 256 //We need ~220 bytes for getProtocolVersion on most ublox modules @@ -683,6 +704,13 @@ class SFE_UBLOX_GNSS // Default to using a restart between transmissions. But processors like ESP32 seem to need a stop (#30). Set stop to true to use a stop instead. bool pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool stop = false); + // Push MGA AssistNow data to the module + // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) + // Wait for maxWait millis after sending each packet (if mgaAck is NO) + // Return how many MGA packets were pushed successfully + #define defaultMGAdelay 10 // Default to waiting for 10ms between each MGA message + uint16_t pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // Support for data logging void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. uint16_t getFileBufferSize(void); // Return the size of the file buffer @@ -785,6 +813,10 @@ class SFE_UBLOX_GNSS bool getTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Get the time pulse parameters using UBX_CFG_TP5 bool setTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Set the time pulse parameters using UBX_CFG_TP5 + //UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data + uint8_t getAckAiding(uint16_t maxWait = defaultMaxWait); // Get the ackAiding byte - returns 255 if the sendCommand fails + bool setAckAiding(uint8_t ackAiding, uint16_t maxWait = defaultMaxWait); // Set the ackAiding byte + //General configuration (used only on protocol v27 and higher - ie, ZED-F9P) //It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic. @@ -1242,6 +1274,8 @@ class SFE_UBLOX_GNSS UBX_HNR_ATT_t *packetUBXHNRATT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_HNR_INS_t *packetUBXHNRINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_MGA_ACK_DATA0_t *packetUBXMGAACK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame private: @@ -1313,6 +1347,7 @@ class SFE_UBLOX_GNSS bool initPacketUBXHNRATT(); // Allocate RAM for packetUBXHNRATT and initialize it bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it + bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it //Variables TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 763bdb6..ac38510 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1656,6 +1656,31 @@ typedef struct UBX_ESF_STATUS_data_t *callbackData; } UBX_ESF_STATUS_t; +// MGA-specific structs + +// UBX-MGA-ACK-DATA0 (0x13 0x60): Multiple GNSS acknowledge message +const uint16_t UBX_MGA_ACK_DATA0_LEN = 8; + +typedef struct +{ + uint8_t type; // Type of acknowledgment: + // 0: The message was not used by the receiver (see infoCode field for an indication of why) + // 1: The message was accepted for use by the receiver (the infoCode field will be 0) + uint8_t version; // Message version + uint8_t infoCode; // Provides greater information on what the receiver chose to do with the message contents + // See sfe_ublox_mga_ack_infocode_e + uint8_t msgId; // UBX message ID of the acknowledged message + uint8_t msgPayloadStart[4]; // The first 4 bytes of the acknowledged message's payload +} UBX_MGA_ACK_DATA0_data_t; + +#define UBX_MGA_ACK_DATA0_RINGBUFFER_LEN 16 // Provide storage for 16 MGA ACK packets +typedef struct +{ + uint8_t head; + uint8_t tail; + UBX_MGA_ACK_DATA0_data_t data[UBX_MGA_ACK_DATA0_RINGBUFFER_LEN]; // Create a storage array for the MGA ACK packets +} UBX_MGA_ACK_DATA0_t; + // HNR-specific structs // UBX-HNR-PVT (0x28 0x00): High rate output of PVT solution From 19ff31b8b768cd00eea8d5cc84def3212b3851e1 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 25 Nov 2021 20:31:44 +0000 Subject: [PATCH 003/122] AssistNow_Online Example1 is working nicely! TO DO: Overload (?) pushAssistNowData so it can accept uint8_t * as the data source, instead of a String. --- .../Example1_AssistNowClient.ino | 68 ++++++++++---- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 89 ++++++++++++------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 4 +- 3 files changed, 111 insertions(+), 50 deletions(-) diff --git a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino index eb468b2..96f4d9d 100644 --- a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino +++ b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino @@ -6,7 +6,7 @@ basically do whatever you want with this code. This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi - and push it over I2C to a ZED-F9x. + and push it over I2C to a u-blox module. You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. @@ -14,11 +14,14 @@ - WiFi credentials - AssistNow token string + Uncomment the "#define USE_MGA_ACKs" below to test the more robust method of using the + UBX_MGA_ACK_DATA0 acknowledgements to confirm that each MGA message has been accepted. + Feel like supporting open source hardware? Buy a board from SparkFun! - SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 - ZED-F9P RTK2: https://www.sparkfun.com/products/16481 - SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 Hardware Connections: Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus @@ -26,6 +29,8 @@ Open the serial monitor at 115200 baud to see the output */ +//#define USE_MGA_ACKs // Uncomment this line to use the UBX_MGA_ACK_DATA0 acknowledgements + #include #include #include "secrets.h" @@ -67,8 +72,6 @@ void setup() myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise - myGNSS.setNavigationFrequency(1); //Set output in Hz. - //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Connect to WiFi. @@ -91,7 +94,8 @@ void setup() int payloadSize = 0; // This will be updated with the length of the data we get from the server String payload; // This will store the data we get from the server - // Assemble the URL. Note the slash after assistNowServer + // Assemble the URL + // Note the slash after the first %s (assistNowServer) snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", assistNowServer, getQuery, @@ -114,18 +118,18 @@ void setup() if(httpCode > 0) { // HTTP header has been sent and Server response header has been handled - Serial.printf("[HTTP] GET... code: %d\n", httpCode); + Serial.printf("[HTTP] GET... code: %d\r\n", httpCode); // If the GET was successful, read the data - if(httpCode == HTTP_CODE_OK) // Code 200 + if(httpCode == HTTP_CODE_OK) // Check for code 200 { payloadSize = http.getSize(); Serial.printf("Server returned %d bytes\r\n", payloadSize); payload = http.getString(); // Get the payload - // Pretty-print the payload as HEX - /* + // Pretty-print the payload as HEX + /* int i; for(i = 0; i < payloadSize; i++) { @@ -143,7 +147,7 @@ void setup() } else { - Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str()); } http.end(); @@ -152,12 +156,40 @@ void setup() // Push the AssistNow data to the module if (payloadSize > 0) - { + { // Enable the 'major' debug messages on Serial so we can see what AssistNow data is being sent myGNSS.enableDebugging(Serial, true); - - // Push all the AssistNow data - without checking for UBX-MGA-ACK messages - myGNSS.pushAssistNowData((uint8_t *)&payload, (size_t)payloadSize); + +#ifndef USE_MGA_ACKs + + // ***** Don't use the UBX_MGA_ACK_DATA0 messages ***** + + // Push all the AssistNow data. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages. + myGNSS.pushAssistNowData(payload, (size_t)payloadSize); + +#else + + // ***** Use the UBX_MGA_ACK_DATA0 messages ***** + + // Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data + myGNSS.setAckAiding(1); + + // Speed things up by setting setI2CpollingWait to 1ms + myGNSS.setI2CpollingWait(1); + + // Push all the AssistNow data. + // We have called setAckAiding(1) to instruct the module to return MGA-ACK messages. + // So, we could set the pushAssistNowData mgaAck parameter to SFE_UBLOX_MGA_ASSIST_ACK_YES. + // But, just for giggles, let's use SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE just to confirm that the + // MGA-ACK messages are actually enabled. + // Wait for up to 1000ms for each ACK to arrive! 1000ms is a bit excessive... 7ms is nearer the mark. + myGNSS.pushAssistNowData(payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE, 1000); + + // Set setI2CpollingWait to 125ms to avoid pounding the I2C bus + myGNSS.setI2CpollingWait(125); + +#endif + } } @@ -165,6 +197,8 @@ void setup() void loop() { + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + long latitude = myGNSS.getLatitude(); Serial.print(F("Lat: ")); Serial.print(latitude); @@ -193,4 +227,4 @@ void loop() else if(fixType == 5) Serial.print(F("Time only")); Serial.println(); -} +} \ No newline at end of file diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 3217208..e9cdda2 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1075,6 +1075,11 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) } } break; + case UBX_CLASS_MGA: + { + if (packetUBXMGAACK != NULL) result = true; + } + break; case UBX_CLASS_HNR: { switch (ID) @@ -1205,6 +1210,11 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) } } break; + case UBX_CLASS_MGA: + { + maxSize = UBX_MGA_ACK_DATA0_LEN; + } + break; case UBX_CLASS_HNR: { switch (ID) @@ -3973,7 +3983,7 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) // Wait for maxWait millis after sending each packet (if mgaAck is NO) // Return how many MGA packets were pushed successfully -uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +uint16_t SFE_UBLOX_GNSS::pushAssistNowData(String dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { size_t dataPtr = 0; // Pointer into dataBytes uint16_t packetsProcessed = 0; // Keep count of how many packets have been processed @@ -3986,9 +3996,15 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt uint8_t ackAiding = getAckAiding(maxWait); // Enquire if we should expect Acks if (ackAiding == 1) checkForAcks = true; + + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: mgaAck is ENQUIRE. getAckAiding returned ")); + _debugSerial->println(ackAiding); + } } - // If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages and use the callback + // If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages if (checkForAcks) { if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data @@ -4001,31 +4017,43 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt // Start by checking the validity of the packet being pointed to bool dataIsOK = true; - dataIsOK &= dataBytes[dataPtr + 0] == UBX_SYNCH_1; // Check for 0xB5 - dataIsOK &= dataBytes[dataPtr + 1] == UBX_SYNCH_2; // Check for 0x62 - dataIsOK &= dataBytes[dataPtr + 2] == UBX_CLASS_MGA; // Check for class UBX-MGA + dataIsOK &= (dataBytes[dataPtr + 0] == UBX_SYNCH_1); // Check for 0xB5 + dataIsOK &= (dataBytes[dataPtr + 1] == UBX_SYNCH_2); // Check for 0x62 + dataIsOK &= (dataBytes[dataPtr + 2] == UBX_CLASS_MGA); // Check for class UBX-MGA - size_t packetLength = (size_t)dataBytes[dataPtr + 4] + ((size_t)dataBytes[dataPtr + 5] << 8); // Extract the length + size_t packetLength = ((size_t)dataBytes[dataPtr + 4]) | (((size_t)dataBytes[dataPtr + 5]) << 8); // Extract the length + uint8_t checksumA = 0; uint8_t checksumB = 0; // Calculate the checksum bytes // Keep going until the end of the packet is reached (payloadPtr == (dataPtr + packetLength)) // or we reach the end of the AssistNow data (payloadPtr == numDataBytes) - for (size_t payloadPtr = dataPtr + ((size_t)6); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++) + for (size_t payloadPtr = dataPtr + ((size_t)2); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++) { checksumA += dataBytes[payloadPtr]; checksumB += checksumA; } // Check the checksum bytes - dataIsOK &= checksumA == dataBytes[dataPtr + packetLength + ((size_t)6)]; - dataIsOK &= checksumB == dataBytes[dataPtr + packetLength + ((size_t)7)]; - dataIsOK &= (dataPtr + packetLength + ((size_t)8)) <= numDataBytes; // Check we haven't overrun + dataIsOK &= (checksumA == dataBytes[dataPtr + packetLength + ((size_t)6)]); + dataIsOK &= (checksumB == dataBytes[dataPtr + packetLength + ((size_t)7)]); + + dataIsOK &= ((dataPtr + packetLength + ((size_t)8)) <= numDataBytes); // Check we haven't overrun // If the data is valid, push it if (dataIsOK) { pushRawData((uint8_t *)&dataBytes[dataPtr], packetLength + ((size_t)8)); // Push the data + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: packet ID 0x")); + if (dataBytes[dataPtr + 3] < 0x10) + _debugSerial->print(F("0")); + _debugSerial->print(dataBytes[dataPtr + 3], HEX); + _debugSerial->print(F(" length ")); + _debugSerial->println(packetLength); + } + if (checkForAcks) { unsigned long startTime = millis(); @@ -4036,26 +4064,21 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's? { bool dataAckd = true; // Check if we've received the correct ACK - dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == dataBytes[dataPtr + 3]; - dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == dataBytes[dataPtr + 6]; - dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == dataBytes[dataPtr + 7]; - dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == dataBytes[dataPtr + 8]; - dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == dataBytes[dataPtr + 9]; + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == dataBytes[dataPtr + 3]); // Check if the message ID matches + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == dataBytes[dataPtr + 6]); // Check if the first four data bytes match + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == dataBytes[dataPtr + 7]); + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == dataBytes[dataPtr + 8]); + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == dataBytes[dataPtr + 9]); if (dataAckd) // Is this the ACK we are looking for? { - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->print(F("pushAssistNowData: packet ID 0x")); - if (dataBytes[dataPtr + 3] < 0x10) - _debugSerial->print(F("0")); - _debugSerial->print(dataBytes[dataPtr + 3], HEX); - } if ((packetUBXMGAACK->data[packetUBXMGAACK->tail].type == (uint8_t)1) && (packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode == (uint8_t)SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED)) { if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->println(F(" was accepted")); + _debugSerial->print(F("pushAssistNowData: packet was accepted after ")); + _debugSerial->print(millis() - startTime); + _debugSerial->println(F(" ms")); } packetsProcessed++; } @@ -4063,7 +4086,7 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt { if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->print(F(" was _not_ accepted. infoCode is ")); + _debugSerial->print(F("pushAssistNowData: packet was _not_ accepted. infoCode is ")); _debugSerial->println(packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode); } } @@ -4079,16 +4102,14 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt { if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->print(F("pushAssistNowData: packet ID 0x")); - if (dataBytes[dataPtr + 3] < 0x10) - _debugSerial->print(F("0")); - _debugSerial->print(dataBytes[dataPtr + 3], HEX); - _debugSerial->println(F(" timed out!")); + _debugSerial->println(F("pushAssistNowData: packet ack timed out!")); } } } else { + // We are not checking for Acks, so let's assume the send was successful? + packetsProcessed++; // We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes) { @@ -4103,7 +4124,7 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt // The data was invalid. Send a debug message and then try to find the next 0xB5 if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->print(F("pushAssistNowData: bad data - ignored! dataPtr is")); + _debugSerial->print(F("pushAssistNowData: bad data - ignored! dataPtr is ")); _debugSerial->println(dataPtr); } @@ -4114,6 +4135,12 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt } } + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: packetsProcessed: ")); + _debugSerial->println(packetsProcessed); + } + return (packetsProcessed); } @@ -5615,7 +5642,7 @@ bool SFE_UBLOX_GNSS::setAckAiding(uint8_t ackAiding, uint16_t maxWait) // Set th // There are three versions of UBX-CFG-NAVX5 but the ackAid flag is always in bit 10 of mask1 payloadCfg[2] = 0x00; // Clear the LS byte of mask1 - payloadCfg[3] = 0x40; // Set _only_ the ackAid flag = bit 10 of mask1 = bit 2 of the MS byte + payloadCfg[3] = 0x04; // Set _only_ the ackAid flag = bit 10 of mask1 = bit 2 of the MS byte payloadCfg[4] = 0x00; // Clear the LS byte of mask2, just in case payloadCfg[5] = 0x00; // Clear the LS byte of mask2, just in case diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 90eea67..b905c0c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -708,8 +708,8 @@ class SFE_UBLOX_GNSS // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) // Wait for maxWait millis after sending each packet (if mgaAck is NO) // Return how many MGA packets were pushed successfully - #define defaultMGAdelay 10 // Default to waiting for 10ms between each MGA message - uint16_t pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + #define defaultMGAdelay 7 // Default to waiting for 7ms between each MGA message + uint16_t pushAssistNowData(String dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); // Support for data logging void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. From 9e8670851f259c408280153efa36debe897ae6b8 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 26 Nov 2021 11:41:33 +0000 Subject: [PATCH 004/122] Add setUTCTimeAssistance. Change pushAssistNowData to const uint8_t * with String helpers. --- keywords.txt | 1 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 242 +++++++++++++------ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 22 +- 3 files changed, 192 insertions(+), 73 deletions(-) diff --git a/keywords.txt b/keywords.txt index 6d1123a..d824c03 100644 --- a/keywords.txt +++ b/keywords.txt @@ -91,6 +91,7 @@ checkCallbacks KEYWORD2 pushRawData KEYWORD2 pushAssistNowData KEYWORD2 +setUTCTimeAssistance KEYWORD2 setFileBufferSize KEYWORD2 getFileBufferSize KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index e9cdda2..ac1a636 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3979,14 +3979,43 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s } } -// Push MGA AssistNow data to the module -// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) -// Wait for maxWait millis after sending each packet (if mgaAck is NO) -// Return how many MGA packets were pushed successfully -uint16_t SFE_UBLOX_GNSS::pushAssistNowData(String dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +// Push MGA AssistNow data to the module. +// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE). +// Wait for maxWait millis after sending each packet (if mgaAck is NO). +// Return how many MGA packets were pushed successfully. +// If skipTime is true, any UBX-MGA-INI-TIME_UTC or UBX-MGA-INI-TIME_GNSS packets found in the data will be skipped, +// allowing the user to override with their own time data with setUTCTimeAssistance. +size_t SFE_UBLOX_GNSS::pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("pushAssistNowData: OK so far... (1)")); + _debugSerial->flush(); + } + return (pushAssistNowDataInternal(false, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); +} +size_t SFE_UBLOX_GNSS::pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + return (pushAssistNowDataInternal(false, dataBytes, numDataBytes, mgaAck, maxWait)); +} +size_t SFE_UBLOX_GNSS::pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + return (pushAssistNowDataInternal(skipTime, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); +} +size_t SFE_UBLOX_GNSS::pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + return (pushAssistNowDataInternal(skipTime, dataBytes, numDataBytes, mgaAck, maxWait)); +} +size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { size_t dataPtr = 0; // Pointer into dataBytes - uint16_t packetsProcessed = 0; // Keep count of how many packets have been processed + size_t packetsProcessed = 0; // Keep count of how many packets have been processed + + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("pushAssistNowData: OK so far... (2)")); + _debugSerial->flush(); + } bool checkForAcks = (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_YES); // If mgaAck is YES, always check for Acks @@ -3997,11 +4026,13 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(String dataBytes, size_t numDataBytes if (ackAiding == 1) checkForAcks = true; +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("pushAssistNowData: mgaAck is ENQUIRE. getAckAiding returned ")); _debugSerial->println(ackAiding); } +#endif } // If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages @@ -4017,11 +4048,17 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(String dataBytes, size_t numDataBytes // Start by checking the validity of the packet being pointed to bool dataIsOK = true; - dataIsOK &= (dataBytes[dataPtr + 0] == UBX_SYNCH_1); // Check for 0xB5 - dataIsOK &= (dataBytes[dataPtr + 1] == UBX_SYNCH_2); // Check for 0x62 - dataIsOK &= (dataBytes[dataPtr + 2] == UBX_CLASS_MGA); // Check for class UBX-MGA + dataIsOK &= (*(dataBytes + dataPtr + 0) == UBX_SYNCH_1); // Check for 0xB5 + dataIsOK &= (*(dataBytes + dataPtr + 1) == UBX_SYNCH_2); // Check for 0x62 + dataIsOK &= (*(dataBytes + dataPtr + 2) == UBX_CLASS_MGA); // Check for class UBX-MGA - size_t packetLength = ((size_t)dataBytes[dataPtr + 4]) | (((size_t)dataBytes[dataPtr + 5]) << 8); // Extract the length + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("pushAssistNowData: OK so far... (3)")); + _debugSerial->flush(); + } + + size_t packetLength = ((size_t)*(dataBytes + dataPtr + 4)) | (((size_t)*(dataBytes + dataPtr + 5)) << 8); // Extract the length uint8_t checksumA = 0; uint8_t checksumB = 0; @@ -4030,90 +4067,110 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(String dataBytes, size_t numDataBytes // or we reach the end of the AssistNow data (payloadPtr == numDataBytes) for (size_t payloadPtr = dataPtr + ((size_t)2); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++) { - checksumA += dataBytes[payloadPtr]; + checksumA += *(dataBytes + payloadPtr); checksumB += checksumA; } // Check the checksum bytes - dataIsOK &= (checksumA == dataBytes[dataPtr + packetLength + ((size_t)6)]); - dataIsOK &= (checksumB == dataBytes[dataPtr + packetLength + ((size_t)7)]); + dataIsOK &= (checksumA == *(dataBytes + dataPtr + packetLength + ((size_t)6))); + dataIsOK &= (checksumB == *(dataBytes + dataPtr + packetLength + ((size_t)7))); dataIsOK &= ((dataPtr + packetLength + ((size_t)8)) <= numDataBytes); // Check we haven't overrun // If the data is valid, push it if (dataIsOK) { - pushRawData((uint8_t *)&dataBytes[dataPtr], packetLength + ((size_t)8)); // Push the data - - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + // Check if this is time assistance data which should be skipped + if ((skipTime) && ((*(dataBytes + dataPtr + 3) == UBX_MGA_INI_TIME_UTC) || (*(dataBytes + dataPtr + 3) == UBX_MGA_INI_TIME_GNSS))) { - _debugSerial->print(F("pushAssistNowData: packet ID 0x")); - if (dataBytes[dataPtr + 3] < 0x10) - _debugSerial->print(F("0")); - _debugSerial->print(dataBytes[dataPtr + 3], HEX); - _debugSerial->print(F(" length ")); - _debugSerial->println(packetLength); +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: skipped INI_TIME ID 0x")); + if (*(dataBytes + dataPtr + 3) < 0x10) + _debugSerial->print(F("0")); + _debugSerial->println(*(dataBytes + dataPtr + 3), HEX); + } +#endif } - - if (checkForAcks) + else { - unsigned long startTime = millis(); - bool keepGoing = true; - while (keepGoing && (millis() < (startTime + maxWait))) // Keep checking for the ACK until we time out + pushRawData((uint8_t *)(dataBytes + dataPtr), packetLength + ((size_t)8)); // Push the data + + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: packet ID 0x")); + if (*(dataBytes + dataPtr + 3) < 0x10) + _debugSerial->print(F("0")); + _debugSerial->print(*(dataBytes + dataPtr + 3), HEX); + _debugSerial->print(F(" length ")); + _debugSerial->println(packetLength); + } + + if (checkForAcks) { - checkUblox(); - if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's? + unsigned long startTime = millis(); + bool keepGoing = true; + while (keepGoing && (millis() < (startTime + maxWait))) // Keep checking for the ACK until we time out { - bool dataAckd = true; // Check if we've received the correct ACK - dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == dataBytes[dataPtr + 3]); // Check if the message ID matches - dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == dataBytes[dataPtr + 6]); // Check if the first four data bytes match - dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == dataBytes[dataPtr + 7]); - dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == dataBytes[dataPtr + 8]); - dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == dataBytes[dataPtr + 9]); - - if (dataAckd) // Is this the ACK we are looking for? + checkUblox(); + if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's? { - if ((packetUBXMGAACK->data[packetUBXMGAACK->tail].type == (uint8_t)1) && (packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode == (uint8_t)SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED)) + bool dataAckd = true; // Check if we've received the correct ACK + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == *(dataBytes + dataPtr + 3)); // Check if the message ID matches + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == *(dataBytes + dataPtr + 6)); // Check if the first four data bytes match + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == *(dataBytes + dataPtr + 7)); + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == *(dataBytes + dataPtr + 8)); + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == *(dataBytes + dataPtr + 9)); + + if (dataAckd) // Is this the ACK we are looking for? { - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + if ((packetUBXMGAACK->data[packetUBXMGAACK->tail].type == (uint8_t)1) && (packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode == (uint8_t)SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED)) { - _debugSerial->print(F("pushAssistNowData: packet was accepted after ")); - _debugSerial->print(millis() - startTime); - _debugSerial->println(F(" ms")); +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: packet was accepted after ")); + _debugSerial->print(millis() - startTime); + _debugSerial->println(F(" ms")); + } +#endif + packetsProcessed++; } - packetsProcessed++; - } - else - { - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + else { - _debugSerial->print(F("pushAssistNowData: packet was _not_ accepted. infoCode is ")); - _debugSerial->println(packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode); +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: packet was _not_ accepted. infoCode is ")); + _debugSerial->println(packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode); + } +#endif } + keepGoing = false; } - keepGoing = false; + // Increment the tail + packetUBXMGAACK->tail++; + if (packetUBXMGAACK->tail == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) + packetUBXMGAACK->tail = 0; } - // Increment the tail - packetUBXMGAACK->tail++; - if (packetUBXMGAACK->tail == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) - packetUBXMGAACK->tail = 0; } - } - if (keepGoing) // If keepGoing is still true, we must have timed out - { - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + if (keepGoing) // If keepGoing is still true, we must have timed out { - _debugSerial->println(F("pushAssistNowData: packet ack timed out!")); + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("pushAssistNowData: packet ack timed out!")); + } } } - } - else - { - // We are not checking for Acks, so let's assume the send was successful? - packetsProcessed++; - // We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data - if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes) + else { - delay(maxWait); + // We are not checking for Acks, so let's assume the send was successful? + packetsProcessed++; + // We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data + if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes) + { + delay(maxWait); + } } } @@ -4121,25 +4178,30 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(String dataBytes, size_t numDataBytes } else { + +#ifndef SFE_UBLOX_REDUCED_PROG_MEM // The data was invalid. Send a debug message and then try to find the next 0xB5 if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("pushAssistNowData: bad data - ignored! dataPtr is ")); _debugSerial->println(dataPtr); } +#endif - while ((dataPtr < numDataBytes) && (dataBytes[++dataPtr] != UBX_SYNCH_1)) + while ((dataPtr < numDataBytes) && (*(dataBytes + ++dataPtr) != UBX_SYNCH_1)) { ; // Increment dataPtr until we are pointing at the next 0xB5 - or we reach the end of the data } } } +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("pushAssistNowData: packetsProcessed: ")); _debugSerial->println(packetsProcessed); } +#endif return (packetsProcessed); } @@ -4159,6 +4221,50 @@ bool SFE_UBLOX_GNSS::initPacketUBXMGAACK() return (true); } +// Provide initial time assistance +bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + uint8_t iniTimeUTC[32]; // Create the UBX-MGA-INI-TIME_UTC message by hand + memset(iniTimeUTC, 0x00, 32); // Set all unused / reserved bytes and the checksum to zero + + iniTimeUTC[0] = UBX_SYNCH_1; // Sync char 1 + iniTimeUTC[1] = UBX_SYNCH_2; // Sync char 2 + iniTimeUTC[2] = UBX_CLASS_MGA; // Class + iniTimeUTC[3] = UBX_MGA_INI_TIME_UTC; // ID + iniTimeUTC[4] = 24; // Length LSB + iniTimeUTC[5] = 0x00; // Length MSB + iniTimeUTC[6] = 0x10; // type + iniTimeUTC[7] = 0x00; // version + iniTimeUTC[8] = source; // ref (source) + iniTimeUTC[9] = 0x80; // leapSecs. Set to 0x80 = unknown + iniTimeUTC[10] = (uint8_t)(year & 0xFF); // year LSB + iniTimeUTC[11] = (uint8_t)(year >> 8); // year MSB + iniTimeUTC[12] = month; // month starting at 1 + iniTimeUTC[13] = day; // day starting at 1 + iniTimeUTC[14] = hour; // hour 0:23 + iniTimeUTC[15] = minute; // minute 0:59 + iniTimeUTC[16] = second; // seconds 0:59 + iniTimeUTC[18] = (uint8_t)(nanos & 0xFF); // nanoseconds LSB + iniTimeUTC[19] = (uint8_t)((nanos >> 8) & 0xFF); + iniTimeUTC[20] = (uint8_t)((nanos >> 16) & 0xFF); + iniTimeUTC[21] = (uint8_t)(nanos >> 24); // nanoseconds MSB + iniTimeUTC[22] = (uint8_t)(tAccS & 0xFF); // seconds part of the accuracy LSB + iniTimeUTC[23] = (uint8_t)(tAccS >> 8); // seconds part of the accuracy MSB + iniTimeUTC[26] = (uint8_t)(tAccNs & 0xFF); // nanoseconds part of the accuracy LSB + iniTimeUTC[27] = (uint8_t)((tAccNs >> 8) & 0xFF); + iniTimeUTC[28] = (uint8_t)((tAccNs >> 16) & 0xFF); + iniTimeUTC[29] = (uint8_t)(tAccNs >> 24); // nanoseconds part of the accuracy MSB + + for (uint8_t i = 2; i < 30; i++) // Calculate the checksum + { + iniTimeUTC[30] += iniTimeUTC[i]; + iniTimeUTC[31] += iniTimeUTC[30]; + } + + // Return true if the one packet was pushed successfully + return (pushAssistNowData(true, iniTimeUTC, 32, mgaAck, maxWait) == 1); +} + // Support for data logging //Set the file buffer size. This must be called _before_ .begin diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index b905c0c..b2a51fe 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -704,12 +704,23 @@ class SFE_UBLOX_GNSS // Default to using a restart between transmissions. But processors like ESP32 seem to need a stop (#30). Set stop to true to use a stop instead. bool pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool stop = false); - // Push MGA AssistNow data to the module - // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) - // Wait for maxWait millis after sending each packet (if mgaAck is NO) - // Return how many MGA packets were pushed successfully + // Push MGA AssistNow data to the module. + // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE). + // Wait for maxWait millis after sending each packet (if mgaAck is NO). + // Return how many MGA packets were pushed successfully. + // If skipTime is true, any UBX-MGA-INI-TIME_UTC or UBX-MGA-INI-TIME_GNSS packets found in the data will be skipped, + // allowing the user to override with their own time data with setUTCTimeAssistance. #define defaultMGAdelay 7 // Default to waiting for 7ms between each MGA message - uint16_t pushAssistNowData(String dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + + // Provide initial time assistance + #define defaultMGAINITIMEtAccS 2 // Default to setting the seconds time accuracy to 2 seconds + #define defaultMGAINITIMEtAccNs 0 // Default to setting the nanoseconds time accuracy to zero + #define defaultMGAINITIMEsource 0 // Set default source to none, i.e. on receipt of message (will be inaccurate!) + bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); // Support for data logging void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. @@ -1306,6 +1317,7 @@ class SFE_UBLOX_GNSS //Functions bool checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass = 255, uint8_t requestedID = 255); //Checks module with user selected commType void addToChecksum(uint8_t incoming); //Given an incoming byte, adjust rollingChecksumA/B + size_t pushAssistNowDataInternal(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); //Return true if this "automatic" message has storage allocated for it bool checkAutomatic(uint8_t Class, uint8_t ID); From 142ca9853e3f2fd3d33953fddcd776bd8f19bdfc Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 26 Nov 2021 11:54:15 +0000 Subject: [PATCH 005/122] Remove debug messages. Update Example1 --- .../Example1_AssistNowClient.ino | 20 ++++++++++++------- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 19 +----------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino index 96f4d9d..f2e644d 100644 --- a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino +++ b/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino @@ -56,7 +56,11 @@ void setup() delay(1000); Serial.begin(115200); - Serial.println("AssistNow Example"); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Start I2C. Connect to the GNSS. @@ -75,16 +79,16 @@ void setup() //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Connect to WiFi. - Serial.print("Connecting to local WiFi"); + Serial.print(F("Connecting to local WiFi")); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); - Serial.print("."); + Serial.print(F(".")); } Serial.println(); - Serial.println("WiFi connected!"); + Serial.println(F("WiFi connected!")); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Use HTTP GET to receive the AssistNow_Online data @@ -105,7 +109,7 @@ void setup() getGNSS, getDataType); - Serial.print("HTTP URL is: "); + Serial.print(F("HTTP URL is: ")); Serial.println(theURL); HTTPClient http; @@ -157,8 +161,8 @@ void setup() if (payloadSize > 0) { - // Enable the 'major' debug messages on Serial so we can see what AssistNow data is being sent - myGNSS.enableDebugging(Serial, true); + // Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent + //myGNSS.enableDebugging(Serial, true); #ifndef USE_MGA_ACKs @@ -191,6 +195,8 @@ void setup() #endif } + + Serial.println(F("Here we go!")); } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index ac1a636..0c3ffe6 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3987,11 +3987,6 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s // allowing the user to override with their own time data with setUTCTimeAssistance. size_t SFE_UBLOX_GNSS::pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->println(F("pushAssistNowData: OK so far... (1)")); - _debugSerial->flush(); - } return (pushAssistNowDataInternal(false, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); } size_t SFE_UBLOX_GNSS::pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) @@ -4011,12 +4006,6 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(bool skipTime, const uint8_t *d size_t dataPtr = 0; // Pointer into dataBytes size_t packetsProcessed = 0; // Keep count of how many packets have been processed - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->println(F("pushAssistNowData: OK so far... (2)")); - _debugSerial->flush(); - } - bool checkForAcks = (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_YES); // If mgaAck is YES, always check for Acks // If mgaAck is ENQUIRE, we need to check UBX-CFG-NAVX5 ackAiding to determine if UBX-MGA-ACK's are expected @@ -4052,12 +4041,6 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(bool skipTime, const uint8_t *d dataIsOK &= (*(dataBytes + dataPtr + 1) == UBX_SYNCH_2); // Check for 0x62 dataIsOK &= (*(dataBytes + dataPtr + 2) == UBX_CLASS_MGA); // Check for class UBX-MGA - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->println(F("pushAssistNowData: OK so far... (3)")); - _debugSerial->flush(); - } - size_t packetLength = ((size_t)*(dataBytes + dataPtr + 4)) | (((size_t)*(dataBytes + dataPtr + 5)) << 8); // Extract the length uint8_t checksumA = 0; @@ -4262,7 +4245,7 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t } // Return true if the one packet was pushed successfully - return (pushAssistNowData(true, iniTimeUTC, 32, mgaAck, maxWait) == 1); + return (pushAssistNowDataInternal(true, iniTimeUTC, 32, mgaAck, maxWait) == 1); } // Support for data logging From ae65547d01164ae86945af3d3975c34991a152de Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 26 Nov 2021 12:59:34 +0000 Subject: [PATCH 006/122] Add Example2 AssistNow Online with time delay allowing 'stale' data to be re-used --- .../Example2_AssistNowOnline_TimeDelay.ino | 252 ++++++++++++++++++ .../secrets.h | 6 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 2 +- 3 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino create mode 100644 examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/secrets.h diff --git a/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino b/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino new file mode 100644 index 0000000..1b8f3fb --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino @@ -0,0 +1,252 @@ +/* + Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream + By: SparkFun Electronics / Paul Clark + Date: November 24th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi + and push it over I2C to a u-blox module. + + The AssistNow Online data is valid for 2-4 hours, so it can be re-used. + BUT you need to provide the time assistance separately. + This example shows how to do that. + The ESP32's RTC is set from network time. + The RTC time is pushed to the module using setUTCTimeAssistance, + followed by the AssistNow data (without time). + + You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. + + Update secrets.h with your: + - WiFi credentials + - AssistNow token string + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +#include +#include "secrets.h" + +const char assistNowServer[] = "https://online-live1.services.u-blox.com"; +//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server + +const char getQuery[] = "GetOnlineData.ashx?"; +const char tokenPrefix[] = "token="; +const char tokenSuffix[] = ";"; +const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal +const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "time.h" + +const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + + Wire.begin(); //Start I2C + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to WiFi. + + Serial.print(F("Connecting to local WiFi")); + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.println(F("WiFi connected!")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Set the RTC using network time. (Code taken from the SimpleTime example.) + + // Request the time from the NTP server and use it to set the ESP32's RTC. + configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time. + + struct tm timeinfo; + if(!getLocalTime(&timeinfo)) + { + Serial.println("Failed to obtain time"); + return; + } + Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Use HTTP GET to receive the AssistNow_Online data + + const int URL_BUFFER_SIZE = 256; + char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL + int payloadSize = 0; // This will be updated with the length of the data we get from the server + String payload; // This will store the data we get from the server + + // Assemble the URL + // Note the slash after the first %s (assistNowServer) + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getDataType); + + Serial.print(F("HTTP URL is: ")); + Serial.println(theURL); + + HTTPClient http; + + http.begin(theURL); + + int httpCode = http.GET(); // HTTP GET + + // httpCode will be negative on error + if(httpCode > 0) + { + // HTTP header has been sent and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\r\n", httpCode); + + // If the GET was successful, read the data + if(httpCode == HTTP_CODE_OK) // Check for code 200 + { + payloadSize = http.getSize(); + Serial.printf("Server returned %d bytes\r\n", payloadSize); + + payload = http.getString(); // Get the payload + + // Pretty-print the payload as HEX + /* + int i; + for(i = 0; i < payloadSize; i++) + { + if (payload[i] < 0x10) // Print leading zero + Serial.print("0"); + Serial.print(payload[i], HEX); + Serial.print(" "); + if ((i % 16) == 15) + Serial.println(); + } + if ((i % 16) != 15) + Serial.println(); + */ + } + } + else + { + Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the RTC time to the module + + // Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent + //myGNSS.enableDebugging(Serial, true); + + if(getLocalTime(&timeinfo)) + { + // setUTCTimeAssistance uses a default time accuracy of 2 seconds which should be OK here. + // Have a look at the library source code for more details. + myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + } + else + { + Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly."); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the AssistNow data to the module - WITHOUT THE TIME + + if (payloadSize > 0) + { + // Push the AssistNow data. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages. + // The 'true' parameter tells pushAssistNowData not to push any time data from the payload. + myGNSS.pushAssistNowData(true, payload, (size_t)payloadSize); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Disconnect the WiFi as it's no longer needed + + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + Serial.println(F("WiFi disconnected")); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte SIV = myGNSS.getSIV(); + Serial.print(F(" SIV: ")); + Serial.print(SIV); + + byte fixType = myGNSS.getFixType(); + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); +} diff --git a/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/secrets.h b/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/secrets.h new file mode 100644 index 0000000..4eb7a9c --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/secrets.h @@ -0,0 +1,6 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "hasBigTeeth"; + +//Your AssistNow token +const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 0c3ffe6..3b422b1 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4245,7 +4245,7 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t } // Return true if the one packet was pushed successfully - return (pushAssistNowDataInternal(true, iniTimeUTC, 32, mgaAck, maxWait) == 1); + return (pushAssistNowDataInternal(false, iniTimeUTC, 32, mgaAck, maxWait) == 1); } // Support for data logging From 859a5d085825df734a2fbb83bf16ecb47f369eae Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 26 Nov 2021 19:11:38 +0000 Subject: [PATCH 007/122] Add support for AssistNow Offline. Add Example. Add findMGAANOForDate. --- .../Example1_AssistNowOffline.ino | 323 ++++++++++++++++++ .../Example1_AssistNowOffline/secrets.h | 6 + examples/AssistNow/README.md | 2 + keywords.txt | 1 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 192 ++++++++++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 16 +- 6 files changed, 531 insertions(+), 9 deletions(-) create mode 100644 examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino create mode 100644 examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/secrets.h diff --git a/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino b/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino new file mode 100644 index 0000000..f230126 --- /dev/null +++ b/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino @@ -0,0 +1,323 @@ +/* + Use ESP32 WiFi to get AssistNow Offline data from u-blox Thingstream + By: SparkFun Electronics / Paul Clark + Date: November 26th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to obtain AssistNow Offline data from u-blox Thingstream over WiFi + and push it over I2C to a u-blox module. + + The module still needs to be given time assistance to achieve a fast fix. This example + uses network time to do that. If you don't have a WiFi connection, you may have to use + a separate RTC to provide the time. + + Note: AssistNow Offline is not supported by the ZED-F9P! "The ZED-F9P supports AssistNow Online only." + + You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. + + Update secrets.h with your: + - WiFi credentials + - AssistNow token string + + Uncomment the "#define USE_MGA_ACKs" below to test the more robust method of using the + UBX_MGA_ACK_DATA0 acknowledgements to confirm that each MGA message has been accepted. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +*/ + +//#define USE_MGA_ACKs // Uncomment this line to use the UBX_MGA_ACK_DATA0 acknowledgements + +#include +#include +#include "secrets.h" + +const char assistNowServer[] = "https://offline-live1.services.u-blox.com"; +//const char assistNowServer[] = "https://offline-live2.services.u-blox.com"; // Alternate server + +const char getQuery[] = "GetOfflineData.ashx?"; +const char tokenPrefix[] = "token="; +const char tokenSuffix[] = ";"; +const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal +const char getFormat[] = "format=mga;"; // Data format. Leave set to mga for M8 onwards. Can be aid. +const char getPeriod[] = "period=1;"; // Optional. The number of weeks into the future that the data will be valid. Can be 1-5. Default = 4. +const char getMgaResolution[] = "resolution=1;"; // Optional. Data resolution: 1 = every day; 2 = every other day; 3 = every 3rd day. +//Note: always use resolution=1. findMGAANOForDate does not yet support finding the 'closest' date. It needs an exact match. + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "time.h" + +const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + + Wire.begin(); //Start I2C + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to WiFi. + + Serial.print(F("Connecting to local WiFi")); + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.println(F("WiFi connected!")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Set the RTC using network time. (Code taken from the SimpleTime example.) + + // Request the time from the NTP server and use it to set the ESP32's RTC. + configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time. + + struct tm timeinfo; + if(!getLocalTime(&timeinfo)) + { + Serial.println("Failed to obtain time"); + return; + } + Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Use HTTP GET to receive the AssistNow_Online data + + const int URL_BUFFER_SIZE = 256; + char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL + int payloadSize = 0; // This will be updated with the length of the data we get from the server + String payload; // This will store the data we get from the server + + // Assemble the URL + // Note the slash after the first %s (assistNowServer) + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getFormat, + getPeriod, + getMgaResolution + ); + + Serial.print(F("HTTP URL is: ")); + Serial.println(theURL); + + HTTPClient http; + + http.begin(theURL); + + int httpCode = http.GET(); // HTTP GET + + // httpCode will be negative on error + if(httpCode > 0) + { + // HTTP header has been sent and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\r\n", httpCode); + + // If the GET was successful, read the data + if(httpCode == HTTP_CODE_OK) // Check for code 200 + { + payloadSize = http.getSize(); + Serial.printf("Server returned %d bytes\r\n", payloadSize); + + payload = http.getString(); // Get the payload + + // Pretty-print the payload as HEX + /* + int i; + for(i = 0; i < payloadSize; i++) + { + if (payload[i] < 0x10) // Print leading zero + Serial.print("0"); + Serial.print(payload[i], HEX); + Serial.print(" "); + if ((i % 16) == 15) + Serial.println(); + } + if ((i % 16) != 15) + Serial.println(); + */ + } + } + else + { + Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Find where the AssistNow data for today starts and ends + + size_t todayStart = 0; // Default to sending all the data + size_t tomorrowStart = (size_t)payloadSize; + + // Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent + //myGNSS.enableDebugging(Serial, true); + + if (payloadSize > 0) + { + if(getLocalTime(&timeinfo)) + { + // Find the start of today's data + todayStart = myGNSS.findMGAANOForDate(payload, (size_t)payloadSize, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday); + if (todayStart < (size_t)payloadSize) + { + Serial.print(F("Found the data for today starting at location ")); + Serial.println(todayStart); + } + else + { + Serial.println("Could not find the data for today. This will not work well. The GNSS needs help to start up quickly."); + } + + // Find the start of tomorrow's data + tomorrowStart = myGNSS.findMGAANOForDate(payload, (size_t)payloadSize, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, 1); + if (tomorrowStart < (size_t)payloadSize) + { + Serial.print(F("Found the data for tomorrow starting at location ")); + Serial.println(tomorrowStart); + } + else + { + Serial.println("Could not find the data for tomorrow. (Today's data may be the last?)"); + } + } + else + { + Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly."); + } + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the RTC time to the module + + if(getLocalTime(&timeinfo)) // Get the local time again, just to make sure we are using the most accurate time + { + // setUTCTimeAssistance uses a default time accuracy of 2 seconds which should be OK here. + // Have a look at the library source code for more details. + myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + } + else + { + Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly."); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the AssistNow data for today to the module - without the time + + if (payloadSize > 0) + { + +#ifndef USE_MGA_ACKs + + // ***** Don't use the UBX_MGA_ACK_DATA0 messages ***** + + // Push the AssistNow data for today. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages. + myGNSS.pushAssistNowData(todayStart, true, payload, tomorrowStart - todayStart); + +#else + + // ***** Use the UBX_MGA_ACK_DATA0 messages ***** + + // Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data + myGNSS.setAckAiding(1); + + // Speed things up by setting setI2CpollingWait to 1ms + myGNSS.setI2CpollingWait(1); + + // Push the AssistNow data for today. + myGNSS.pushAssistNowData(todayStart, true, payload, tomorrowStart - todayStart, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); + + // Set setI2CpollingWait to 125ms to avoid pounding the I2C bus + myGNSS.setI2CpollingWait(125); + +#endif + + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Disconnect the WiFi as it's no longer needed + + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + Serial.println(F("WiFi disconnected")); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte SIV = myGNSS.getSIV(); + Serial.print(F(" SIV: ")); + Serial.print(SIV); + + byte fixType = myGNSS.getFixType(); + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); +} diff --git a/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/secrets.h b/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/secrets.h new file mode 100644 index 0000000..4eb7a9c --- /dev/null +++ b/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/secrets.h @@ -0,0 +1,6 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "hasBigTeeth"; + +//Your AssistNow token +const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 6056018..23b4541 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -16,6 +16,8 @@ With the AssistNow Offline service, users can download long-term orbit data over Please see the [AssistNow_Offline](./AssistNow_Offline) examples for more details. These examples were written for the ESP32, but will run on other platforms too. +**Note: AssistNow Offline is not supported by the ZED-F9P. "The ZED-F9P supports AssistNow Online only."** + ## AssistNowTM Autonomous AssistNow Autonomous provides aiding information without the need for a host or external network connection. Based on previous broadcast satellite ephemeris data downloaded to and stored by the GNSS receiver, AssistNow Autonomous automatically generates accurate predictions of satellite orbital data (“AssistNow Autonomous data”) that is usable for future GNSS position fixes. diff --git a/keywords.txt b/keywords.txt index d824c03..34f4716 100644 --- a/keywords.txt +++ b/keywords.txt @@ -92,6 +92,7 @@ pushRawData KEYWORD2 pushAssistNowData KEYWORD2 setUTCTimeAssistance KEYWORD2 +findMGAANOForDate KEYWORD2 setFileBufferSize KEYWORD2 getFileBufferSize KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 3b422b1..e1643c5 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3987,23 +3987,56 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s // allowing the user to override with their own time data with setUTCTimeAssistance. size_t SFE_UBLOX_GNSS::pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - return (pushAssistNowDataInternal(false, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); + return (pushAssistNowDataInternal(0, false, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); } size_t SFE_UBLOX_GNSS::pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - return (pushAssistNowDataInternal(false, dataBytes, numDataBytes, mgaAck, maxWait)); + return (pushAssistNowDataInternal(0, false, dataBytes, numDataBytes, mgaAck, maxWait)); } size_t SFE_UBLOX_GNSS::pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - return (pushAssistNowDataInternal(skipTime, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); + return (pushAssistNowDataInternal(0, skipTime, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); } size_t SFE_UBLOX_GNSS::pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - return (pushAssistNowDataInternal(skipTime, dataBytes, numDataBytes, mgaAck, maxWait)); + return (pushAssistNowDataInternal(0, skipTime, dataBytes, numDataBytes, mgaAck, maxWait)); } -size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +size_t SFE_UBLOX_GNSS::pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - size_t dataPtr = 0; // Pointer into dataBytes + return (pushAssistNowDataInternal(offset, skipTime, (const uint8_t *)dataBytes.c_str(), numDataBytes, mgaAck, maxWait)); +} +size_t SFE_UBLOX_GNSS::pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + return (pushAssistNowDataInternal(offset, skipTime, dataBytes, numDataBytes, mgaAck, maxWait)); +} +size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + size_t dataPtr = offset; // Pointer into dataBytes + + if ((offset >= numDataBytes) || (offset < 0)) // Sanity check. Return now if offset is invalid. + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("pushAssistNowData: offset (")); + _debugSerial->print(offset); + _debugSerial->println(F(") is invalid! Aborting...")); + } +#endif + return ((size_t)0); + } + + if (numDataBytes < 0) // Sanity check. Return now if numDataBytes is negative. + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("pushAssistNowData: numDataBytes is negative! Aborting...")); + } +#endif + return ((size_t)0); + } + size_t packetsProcessed = 0; // Keep count of how many packets have been processed bool checkForAcks = (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_YES); // If mgaAck is YES, always check for Acks @@ -4245,7 +4278,152 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t } // Return true if the one packet was pushed successfully - return (pushAssistNowDataInternal(false, iniTimeUTC, 32, mgaAck, maxWait) == 1); + return (pushAssistNowDataInternal(0, false, iniTimeUTC, 32, mgaAck, maxWait) == 1); +} + +// Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day +// The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date +// Returns numDataBytes if unsuccessful +// TO DO: enhance this so it will find the nearest data for the chosen day - instead of an exact match +size_t SFE_UBLOX_GNSS::findMGAANOForDate(const String &dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture) +{ + return (findMGAANOForDateInternal((const uint8_t *)dataBytes.c_str(), numDataBytes, year, month, day, daysIntoFuture)); +} +size_t SFE_UBLOX_GNSS::findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture) +{ + return (findMGAANOForDateInternal(dataBytes, numDataBytes, year, month, day, daysIntoFuture)); +} +size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture) +{ + size_t dataPtr = 0; // Pointer into dataBytes + bool dateFound = false; // Flag to indicate when the date has been found + + // Calculate matchDay, matchMonth and matchYear + uint8_t matchDay = day; + uint8_t matchMonth = month; + uint8_t matchYear = (uint8_t)(year - 2000); + + // Add on daysIntoFuture + uint8_t daysIntoFutureCopy = daysIntoFuture; + while (daysIntoFutureCopy > 0) + { + matchDay++; + daysIntoFutureCopy--; + switch (matchMonth) + { + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: + if (matchDay == 32) + { + matchDay = 1; + matchMonth++; + if (matchMonth == 13) + { + matchMonth = 1; + matchYear++; + } + } + break; + case 4: + case 6: + case 9: + case 11: + if (matchDay == 31) + { + matchDay = 1; + matchMonth++; + } + break; + default: // February + if (((matchYear % 4) == 0) && (matchDay == 30)) + { + matchDay = 1; + matchMonth++; + } + else if (((matchYear % 4) > 0) && (matchDay == 29)) + { + matchDay = 1; + matchMonth++; + } + break; + } + } + + while ((!dateFound) && (dataPtr < numDataBytes)) // Keep going until we have found the date or processed all the bytes + { + // Start by checking the validity of the packet being pointed to + bool dataIsOK = true; + + dataIsOK &= (*(dataBytes + dataPtr + 0) == UBX_SYNCH_1); // Check for 0xB5 + dataIsOK &= (*(dataBytes + dataPtr + 1) == UBX_SYNCH_2); // Check for 0x62 + dataIsOK &= (*(dataBytes + dataPtr + 2) == UBX_CLASS_MGA); // Check for class UBX-MGA + + size_t packetLength = ((size_t)*(dataBytes + dataPtr + 4)) | (((size_t)*(dataBytes + dataPtr + 5)) << 8); // Extract the length + + uint8_t checksumA = 0; + uint8_t checksumB = 0; + // Calculate the checksum bytes + // Keep going until the end of the packet is reached (payloadPtr == (dataPtr + packetLength)) + // or we reach the end of the AssistNow data (payloadPtr == numDataBytes) + for (size_t payloadPtr = dataPtr + ((size_t)2); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++) + { + checksumA += *(dataBytes + payloadPtr); + checksumB += checksumA; + } + // Check the checksum bytes + dataIsOK &= (checksumA == *(dataBytes + dataPtr + packetLength + ((size_t)6))); + dataIsOK &= (checksumB == *(dataBytes + dataPtr + packetLength + ((size_t)7))); + + dataIsOK &= ((dataPtr + packetLength + ((size_t)8)) <= numDataBytes); // Check we haven't overrun + + // If the data is valid, check for a date match + if (dataIsOK) + { + if ((*(dataBytes + dataPtr + 3) == UBX_MGA_ANO) + && (*(dataBytes + dataPtr + 10) == matchYear) + && (*(dataBytes + dataPtr + 11) == matchMonth) + && (*(dataBytes + dataPtr + 12) == matchDay)) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("findMGAANOForDate: found date match at location ")); + _debugSerial->println(dataPtr); + } +#endif + dateFound = true; + } + else + { + // The data is valid, but these are not the droids we are looking for... + dataPtr += packetLength + ((size_t)8); // Point to the next message + } + } + else + { + +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + // The data was invalid. Send a debug message and then try to find the next 0xB5 + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("findMGAANOForDate: bad data - ignored! dataPtr is ")); + _debugSerial->println(dataPtr); + } +#endif + + while ((dataPtr < numDataBytes) && (*(dataBytes + ++dataPtr) != UBX_SYNCH_1)) + { + ; // Increment dataPtr until we are pointing at the next 0xB5 - or we reach the end of the data + } + } + } + + return (dataPtr); } // Support for data logging diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index b2a51fe..3bd4fc3 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -295,6 +295,7 @@ const uint8_t UBX_LOG_STRING = 0x04; //Store arbitrary string on on-board fl //Class: MGA //The following are used to configure MGA UBX messages (Multiple GNSS Assistance Messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34) const uint8_t UBX_MGA_ACK_DATA0 = 0x60; //Multiple GNSS Acknowledge message +const uint8_t UBX_MGA_ANO = 0x20; //Multiple GNSS AssistNow Offline assistance - NOT SUPPORTED BY THE ZED-F9P! "The ZED-F9P supports AssistNow Online only." const uint8_t UBX_MGA_BDS_EPH = 0x03; //BDS Ephemeris Assistance const uint8_t UBX_MGA_BDS_ALM = 0x03; //BDS Almanac Assistance const uint8_t UBX_MGA_BDS_HEALTH = 0x03; //BDS Health Assistance @@ -710,11 +711,14 @@ class SFE_UBLOX_GNSS // Return how many MGA packets were pushed successfully. // If skipTime is true, any UBX-MGA-INI-TIME_UTC or UBX-MGA-INI-TIME_GNSS packets found in the data will be skipped, // allowing the user to override with their own time data with setUTCTimeAssistance. + // offset allows a sub-set of the data to be sent - starting from offset. #define defaultMGAdelay 7 // Default to waiting for 7ms between each MGA message size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); // Provide initial time assistance #define defaultMGAINITIMEtAccS 2 // Default to setting the seconds time accuracy to 2 seconds @@ -722,6 +726,13 @@ class SFE_UBLOX_GNSS #define defaultMGAINITIMEsource 0 // Set default source to none, i.e. on receipt of message (will be inaccurate!) bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day + // The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date + // Returns numDataBytes if unsuccessful + // TO DO: enhance this so it will find the nearest data for the chosen day - instead of an exact match + size_t findMGAANOForDate(const String &dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); + size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); + // Support for data logging void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. uint16_t getFileBufferSize(void); // Return the size of the file buffer @@ -1316,8 +1327,9 @@ class SFE_UBLOX_GNSS //Functions bool checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass = 255, uint8_t requestedID = 255); //Checks module with user selected commType - void addToChecksum(uint8_t incoming); //Given an incoming byte, adjust rollingChecksumA/B - size_t pushAssistNowDataInternal(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + void addToChecksum(uint8_t incoming); //Given an incoming byte, adjust rollingChecksumA/B + size_t pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t findMGAANOForDateInternal(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); //Return true if this "automatic" message has storage allocated for it bool checkAutomatic(uint8_t Class, uint8_t ID); From 0339462b92adc4743f3f6e9c8e5ba61e20d7f2c4 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 29 Nov 2021 11:30:53 +0000 Subject: [PATCH 008/122] Example updates. Remove default parameters from Internal functions. --- .../Example1_AssistNowOffline.ino | 6 +- .../Example1_AssistNowOnline.ino} | 6 +- .../secrets.h | 0 .../Example2_AssistNowOnline_TimeDelay.ino | 6 +- examples/AssistNow/README.md | 84 +++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 4 +- 6 files changed, 97 insertions(+), 9 deletions(-) rename examples/AssistNow/AssistNow_Online/{Example1_AssistNowClient/Example1_AssistNowClient.ino => Example1_AssistNowOnline/Example1_AssistNowOnline.ino} (98%) rename examples/AssistNow/AssistNow_Online/{Example1_AssistNowClient => Example1_AssistNowOnline}/secrets.h (100%) diff --git a/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino b/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino index f230126..a0836e4 100644 --- a/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino +++ b/examples/AssistNow/AssistNow_Offline/Example1_AssistNowOffline/Example1_AssistNowOffline.ino @@ -114,9 +114,11 @@ void setup() if(!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); - return; } - Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + else + { + Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Use HTTP GET to receive the AssistNow_Online data diff --git a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino b/examples/AssistNow/AssistNow_Online/Example1_AssistNowOnline/Example1_AssistNowOnline.ino similarity index 98% rename from examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino rename to examples/AssistNow/AssistNow_Online/Example1_AssistNowOnline/Example1_AssistNowOnline.ino index f2e644d..24a3c5d 100644 --- a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/Example1_AssistNowClient.ino +++ b/examples/AssistNow/AssistNow_Online/Example1_AssistNowOnline/Example1_AssistNowOnline.ino @@ -186,8 +186,8 @@ void setup() // So, we could set the pushAssistNowData mgaAck parameter to SFE_UBLOX_MGA_ASSIST_ACK_YES. // But, just for giggles, let's use SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE just to confirm that the // MGA-ACK messages are actually enabled. - // Wait for up to 1000ms for each ACK to arrive! 1000ms is a bit excessive... 7ms is nearer the mark. - myGNSS.pushAssistNowData(payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE, 1000); + // Wait for up to 100ms for each ACK to arrive! 100ms is a bit excessive... 7ms is nearer the mark. + myGNSS.pushAssistNowData(payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE, 100); // Set setI2CpollingWait to 125ms to avoid pounding the I2C bus myGNSS.setI2CpollingWait(125); @@ -233,4 +233,4 @@ void loop() else if(fixType == 5) Serial.print(F("Time only")); Serial.println(); -} \ No newline at end of file +} diff --git a/examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/secrets.h b/examples/AssistNow/AssistNow_Online/Example1_AssistNowOnline/secrets.h similarity index 100% rename from examples/AssistNow/AssistNow_Online/Example1_AssistNowClient/secrets.h rename to examples/AssistNow/AssistNow_Online/Example1_AssistNowOnline/secrets.h diff --git a/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino b/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino index 1b8f3fb..5ed4f3a 100644 --- a/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino +++ b/examples/AssistNow/AssistNow_Online/Example2_AssistNowOnline_TimeDelay/Example2_AssistNowOnline_TimeDelay.ino @@ -109,9 +109,11 @@ void setup() if(!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); - return; } - Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + else + { + Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Use HTTP GET to receive the AssistNow_Online data diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 23b4541..8b5e540 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -10,6 +10,8 @@ With AssistNow Online, an Internet connected host downloads assistance data from Please see the [AssistNow_Online](./AssistNow_Online) examples for more details. These examples were written for the ESP32, but will run on other platforms too. +The new functions we've added to the library to support AssistNow Online are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) + ## AssistNowTM Offline With the AssistNow Offline service, users can download long-term orbit data over the Internet at their convenience. The orbit data can be stored in the memory of the application processor. The function requires no connectivity at system start-up, enabling a position fix within seconds, even when no network is available. AssistNow Offline offers augmentation for up to 35 days. @@ -18,6 +20,8 @@ Please see the [AssistNow_Offline](./AssistNow_Offline) examples for more detail **Note: AssistNow Offline is not supported by the ZED-F9P. "The ZED-F9P supports AssistNow Online only."** +The new functions we've added to the library to support AssistNow Offline are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) + ## AssistNowTM Autonomous AssistNow Autonomous provides aiding information without the need for a host or external network connection. Based on previous broadcast satellite ephemeris data downloaded to and stored by the GNSS receiver, AssistNow Autonomous automatically generates accurate predictions of satellite orbital data (“AssistNow Autonomous data”) that is usable for future GNSS position fixes. @@ -33,6 +37,8 @@ AssistNow Autonomous offers augmentation for up to 6 days. Please see the [AssistNow_Autonomous](./AssistNow_Autonomous) examples for more details. +The new functions we've added to the library to support AssistNow Autonomous are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) + ## AssistNow Service Token To be able to use AssistNow Online or AssistNow Offline, you will need a token to access the u-blox Thingstream server. @@ -55,3 +61,81 @@ The _free_ AssistNow Developer token entitles you to: * CellLocate Developer: 5K free location requests per month. Capped. The free token will expire after 90 days, but you can continue to use it beyond that by registering it on [Thingstream](https://portal.thingstream.io/). + +## Code Support for AssistNow + +```pushAssistNowData``` allows the AssistNow Online data or Offline data from the u-blox server to be pushed to the module. As the ESP32 HTTP GET function returns a ```String```, we've included overloaded functions which allow you to pass the data as a ```String``` or as ```const uint8_t *```. + +The String-based function declarations are: + +* size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + +The const uint8_t * function declarations are: + +* size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + +```dataBytes``` is a pointer to the AssistNow Online data. +
+```numDataBytes``` is the length of the AssistNow Online data. +
+ +```pushAssistNowData``` pushes individual packets of data to the u-blox module. Sending all of the data contiguously would overload the module, so ```pushAssistNowData``` can either: + +* insert a small delay between each packet (the default is 7ms) +* or use the ```UBX-MGA-ACK-DATA0``` acknowledgement message to acknowledge each packet + +```mgaAck``` controls which method is used. + +* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_NO``` (**default**), a delay of ```maxWait``` milliseconds is inserted between eack packet. ```maxWait``` defaults to 7ms. +* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_YES```, acknowledgement messages will be expected with a _timeout_ of ```maxWait``` milliseconds. The default timeout is again 7ms, but you can increase this if required by passing a larger value. +* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE```, the code will poll the module to enquire if the achnowledgement messages are enabled. If they are, they will be used. If not, a delay is used. + +```setAckAiding``` enables or disables the acknowledgement messages. By default they are disabled. ```setAckAiding(1)``` will enable them. ```setAckAiding(0)``` will disable them again. +
+```getAckAiding``` returns 1 if the acknowledgement messages are enabled, 0 if they are disabled. 255 indicates an error or timeout. +
+ +AssistNow Online data is valid for 2-4 hours. 'Stale' data can be re-used but: + +* ```pushAssistNowData``` needs to be told to skip the time information contained in the AssistNow data +* the user needs to provide the module with UTC time separately + +The ```skipTime``` parameter tells ```pushAssistNowData``` to skip any time information in the data. ```skipTime``` is bool. Set it to ```true``` to skip the time information. +
+UTC time can be pushed to the module first by calling ```setUTCTimeAssistance```: + +* bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + +Only the ```year```, ```month```, ```day```, ```hour```, ```minute``` and ```second``` parameters are mandatory. The others default to sensible values. Again ```mgaAck``` and ```maxWait``` control if a delay is used when configuring the time, or if an acknowledgement message will be expected. +
+```nanos``` (nanoseconds), ```tAccS``` (time accuracy estimate (seconds)), ```tAccNs``` (time accuracy estimate (nanoseconds)) and ```source``` (if a clock signal will be provided on EXT_INT) are optional, but are available for advanced users. +
+```year``` numbering starts at 0; 2021 is 2021, not 121 (years since 1900). ```month``` and ```day``` numbering starts at 1, not 0. +
+ +Call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. + +## Additional Code Support for AssistNow Offline + +AssistNow Offline data downloaded from the u-blox server can contain 1-5 weeks of data. However, only the data for _today_ should be pushed the module. Sending data for past or future days will confuse the module. +```findMGAANOForDate``` can be used to find the location of the start of the UBX-MGA-ANO data for the specified date within the offline data. That location can then be passed to ```pushAssistNowData``` using the ```offset``` parameter. + +* size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture); + +The sequence of events is: + +* call ```findMGAANOForDate``` passing the ```year```, ```month``` and ```day``` for today. ```findMGAANOForDate``` will return the location / offset of the data for today within the offline data. +* call ```findMGAANOForDate``` again passing the ```year```, ```month``` and ```day``` for _today_ but also set ```daysIntoFuture``` to 1. ```findMGAANOForDate``` will then return the location / offset of the data for _tomorrow_ (one day into the future). +* call ```pushAssistNowData``` setting: + * ```offset``` to the location (offset) of today's data within the offline data + * ```skipTime``` to ```true``` + * ```numDataBytes``` to ((tomorrow's location) - (today's location)). Only the offline data for today will be pushed. + +```findMGAANOForDate``` will return a value of numDataBytes if the data for the chosen day cannot be found. +
+Again, call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. + diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 3bd4fc3..06eaf7a 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1328,8 +1328,8 @@ class SFE_UBLOX_GNSS //Functions bool checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass = 255, uint8_t requestedID = 255); //Checks module with user selected commType void addToChecksum(uint8_t incoming); //Given an incoming byte, adjust rollingChecksumA/B - size_t pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - size_t findMGAANOForDateInternal(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); + size_t pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + size_t findMGAANOForDateInternal(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture); //Return true if this "automatic" message has storage allocated for it bool checkAutomatic(uint8_t Class, uint8_t ID); From 0edeaf04c41176d9362e634903527d86c5283025 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 29 Nov 2021 11:44:52 +0000 Subject: [PATCH 009/122] Update README.md --- examples/AssistNow/README.md | 38 +++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 8b5e540..505b86b 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -64,23 +64,23 @@ The free token will expire after 90 days, but you can continue to use it beyond ## Code Support for AssistNow -```pushAssistNowData``` allows the AssistNow Online data or Offline data from the u-blox server to be pushed to the module. As the ESP32 HTTP GET function returns a ```String```, we've included overloaded functions which allow you to pass the data as a ```String``` or as ```const uint8_t *```. +```pushAssistNowData``` allows the AssistNow Online data or AssistNow Offline data from the u-blox server to be pushed to the module. As the ESP32 HTTP GET function returns a ```String```, we've included overloaded functions which allow you to pass the data as a ```String``` or as ```const uint8_t *```. The String-based function declarations are: -* size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); -* size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); -* size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* **size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** +* **size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** +* **size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** The const uint8_t * function declarations are: -* size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); -* size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); -* size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* **size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** +* **size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** +* **size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** -```dataBytes``` is a pointer to the AssistNow Online data. +```dataBytes``` is a pointer to the AssistNow data.
-```numDataBytes``` is the length of the AssistNow Online data. +```numDataBytes``` is the length of the AssistNow data.
```pushAssistNowData``` pushes individual packets of data to the u-blox module. Sending all of the data contiguously would overload the module, so ```pushAssistNowData``` can either: @@ -90,14 +90,17 @@ The const uint8_t * function declarations are: ```mgaAck``` controls which method is used. -* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_NO``` (**default**), a delay of ```maxWait``` milliseconds is inserted between eack packet. ```maxWait``` defaults to 7ms. -* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_YES```, acknowledgement messages will be expected with a _timeout_ of ```maxWait``` milliseconds. The default timeout is again 7ms, but you can increase this if required by passing a larger value. -* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE```, the code will poll the module to enquire if the achnowledgement messages are enabled. If they are, they will be used. If not, a delay is used. +* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_NO``` (**default**), a delay of ```maxWait``` milliseconds is inserted between each packet. ```maxWait``` defaults to 7ms. +* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_YES```, acknowledgement messages will be expected with a _timeout_ of ```maxWait``` milliseconds. The default timeout is again 7ms, but you can change this if required by passing a different value. +* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE```, the code will poll the module to enquire if the acknowledgement messages are enabled. If they are, they will be used. If not, a delay is used. ```setAckAiding``` enables or disables the acknowledgement messages. By default they are disabled. ```setAckAiding(1)``` will enable them. ```setAckAiding(0)``` will disable them again. -
+ +* **bool setAckAiding(uint8_t ackAiding, uint16_t maxWait);** + ```getAckAiding``` returns 1 if the acknowledgement messages are enabled, 0 if they are disabled. 255 indicates an error or timeout. -
+ +* **uint8_t getAckAiding(uint16_t maxWait);** AssistNow Online data is valid for 2-4 hours. 'Stale' data can be re-used but: @@ -108,12 +111,14 @@ The ```skipTime``` parameter tells ```pushAssistNowData``` to skip any time info
UTC time can be pushed to the module first by calling ```setUTCTimeAssistance```: -* bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* **bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** Only the ```year```, ```month```, ```day```, ```hour```, ```minute``` and ```second``` parameters are mandatory. The others default to sensible values. Again ```mgaAck``` and ```maxWait``` control if a delay is used when configuring the time, or if an acknowledgement message will be expected.
+ ```nanos``` (nanoseconds), ```tAccS``` (time accuracy estimate (seconds)), ```tAccNs``` (time accuracy estimate (nanoseconds)) and ```source``` (if a clock signal will be provided on EXT_INT) are optional, but are available for advanced users.
+ ```year``` numbering starts at 0; 2021 is 2021, not 121 (years since 1900). ```month``` and ```day``` numbering starts at 1, not 0.
@@ -124,7 +129,7 @@ Call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. AssistNow Offline data downloaded from the u-blox server can contain 1-5 weeks of data. However, only the data for _today_ should be pushed the module. Sending data for past or future days will confuse the module. ```findMGAANOForDate``` can be used to find the location of the start of the UBX-MGA-ANO data for the specified date within the offline data. That location can then be passed to ```pushAssistNowData``` using the ```offset``` parameter. -* size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture); +* **size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture);** The sequence of events is: @@ -137,5 +142,6 @@ The sequence of events is: ```findMGAANOForDate``` will return a value of numDataBytes if the data for the chosen day cannot be found.
+ Again, call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. From 7e37bf6192fc05b1821a1b3d517ee0d0eca0009f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 29 Nov 2021 11:48:55 +0000 Subject: [PATCH 010/122] Update README.md --- examples/AssistNow/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 505b86b..6dc2471 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -68,15 +68,15 @@ The free token will expire after 90 days, but you can continue to use it beyond The String-based function declarations are: -* **size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** -* **size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** -* **size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** +* size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); The const uint8_t * function declarations are: -* **size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** -* **size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** -* **size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** +* size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); +* size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); ```dataBytes``` is a pointer to the AssistNow data.
@@ -96,11 +96,11 @@ The const uint8_t * function declarations are: ```setAckAiding``` enables or disables the acknowledgement messages. By default they are disabled. ```setAckAiding(1)``` will enable them. ```setAckAiding(0)``` will disable them again. -* **bool setAckAiding(uint8_t ackAiding, uint16_t maxWait);** +* bool setAckAiding(uint8_t ackAiding, uint16_t maxWait); ```getAckAiding``` returns 1 if the acknowledgement messages are enabled, 0 if they are disabled. 255 indicates an error or timeout. -* **uint8_t getAckAiding(uint16_t maxWait);** +* uint8_t getAckAiding(uint16_t maxWait); AssistNow Online data is valid for 2-4 hours. 'Stale' data can be re-used but: @@ -111,7 +111,7 @@ The ```skipTime``` parameter tells ```pushAssistNowData``` to skip any time info
UTC time can be pushed to the module first by calling ```setUTCTimeAssistance```: -* **bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);** +* bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); Only the ```year```, ```month```, ```day```, ```hour```, ```minute``` and ```second``` parameters are mandatory. The others default to sensible values. Again ```mgaAck``` and ```maxWait``` control if a delay is used when configuring the time, or if an acknowledgement message will be expected.
@@ -129,7 +129,7 @@ Call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. AssistNow Offline data downloaded from the u-blox server can contain 1-5 weeks of data. However, only the data for _today_ should be pushed the module. Sending data for past or future days will confuse the module. ```findMGAANOForDate``` can be used to find the location of the start of the UBX-MGA-ANO data for the specified date within the offline data. That location can then be passed to ```pushAssistNowData``` using the ```offset``` parameter. -* **size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture);** +* size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture); The sequence of events is: From cc27ec27461ad54dc636af58180d6440c5ad8d9c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 29 Nov 2021 13:48:15 +0000 Subject: [PATCH 011/122] Add setPositionAssistanceXYZ, setPositionAssistanceLLH and a new example. --- ...xample3_AssistNowOnline_PositionAssist.ino | 299 ++++++++++++++++++ .../secrets.h | 6 + examples/AssistNow/README.md | 22 +- keywords.txt | 2 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 110 +++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 7 + 6 files changed, 443 insertions(+), 3 deletions(-) create mode 100644 examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/Example3_AssistNowOnline_PositionAssist.ino create mode 100644 examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/secrets.h diff --git a/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/Example3_AssistNowOnline_PositionAssist.ino b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/Example3_AssistNowOnline_PositionAssist.ino new file mode 100644 index 0000000..75ba417 --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/Example3_AssistNowOnline_PositionAssist.ino @@ -0,0 +1,299 @@ +/* + Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream + By: SparkFun Electronics / Paul Clark + Date: November 24th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi + and push it over I2C to a u-blox module. + + This example shows how to provide initial position assistance. Uncomment #define USE_SERVER_ASSISTANCE + below to include the position in the AssistNow data request, instead of using setPositionAssistanceLLH. + + You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. + + Update secrets.h with your: + - WiFi credentials + - AssistNow token string + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +*/ + +//#define USE_SERVER_ASSISTANCE // Uncomment this line to include the position in the AssistNow data request + +#include +#include +#include "secrets.h" + +const char assistNowServer[] = "https://online-live1.services.u-blox.com"; +//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server + +const char getQuery[] = "GetOnlineData.ashx?"; +const char tokenPrefix[] = "token="; +const char tokenSuffix[] = ";"; +const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal +const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos + +#ifdef USE_SERVER_ASSISTANCE +const char useLatitude[] = "lat=55.0;"; // Use an approximate latitude of 55 degrees north. Replace this with your latitude. +const char useLongitude[] = "lon=-1.0;"; // Use an approximate longitude of 1 degree west. Replace this with your longitude. +const char useAlt[] = "alt=100;"; // Use an approximate latitude of 100m above WGS84. Replace this with your altitude. +const char usePosAcc[] = "pacc=100000;"; // Use a position accuracy of 100000m (100km) +#endif + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "time.h" + +const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + + Wire.begin(); //Start I2C + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to WiFi. + + Serial.print(F("Connecting to local WiFi")); + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.println(F("WiFi connected!")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Set the RTC using network time. (Code taken from the SimpleTime example.) + + // Request the time from the NTP server and use it to set the ESP32's RTC. + configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time. + + struct tm timeinfo; + if(!getLocalTime(&timeinfo)) + { + Serial.println("Failed to obtain time"); + } + else + { + Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Use HTTP GET to receive the AssistNow_Online data + + const int URL_BUFFER_SIZE = 256; + char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL + int payloadSize = 0; // This will be updated with the length of the data we get from the server + String payload; // This will store the data we get from the server + + // Assemble the URL + // Note the slash after the first %s (assistNowServer) +#ifdef USE_SERVER_ASSISTANCE + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getDataType, + useLatitude, + useLongitude, + useAlt, + usePosAcc); +#else + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getDataType); +#endif + + Serial.print(F("HTTP URL is: ")); + Serial.println(theURL); + + HTTPClient http; + + http.begin(theURL); + + int httpCode = http.GET(); // HTTP GET + + // httpCode will be negative on error + if(httpCode > 0) + { + // HTTP header has been sent and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\r\n", httpCode); + + // If the GET was successful, read the data + if(httpCode == HTTP_CODE_OK) // Check for code 200 + { + payloadSize = http.getSize(); + Serial.printf("Server returned %d bytes\r\n", payloadSize); + + payload = http.getString(); // Get the payload + + // Pretty-print the payload as HEX + /* + int i; + for(i = 0; i < payloadSize; i++) + { + if (payload[i] < 0x10) // Print leading zero + Serial.print("0"); + Serial.print(payload[i], HEX); + Serial.print(" "); + if ((i % 16) == 15) + Serial.println(); + } + if ((i % 16) != 15) + Serial.println(); + */ + } + } + else + { + Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Speed things up by setting setI2CpollingWait to 1ms + myGNSS.setI2CpollingWait(1); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data + myGNSS.setAckAiding(1); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the RTC time to the module + + // Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent + //myGNSS.enableDebugging(Serial, true); + + if(getLocalTime(&timeinfo)) + { + // Provide time assistance. Use the UBX_MGA_ACK_DATA0 acknowledgements. Set tAccS to 2 seconds. + myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, 0, 2, 0, 0, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); + } + else + { + Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly."); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // If desired - push initial position assistance to the module + +#ifndef USE_SERVER_ASSISTANCE + + // Use 55 degrees (*10^7) north, 1 degree (*10^7) west, 100m (10000cm) altitude, 100km (10000000cm) accuracy. Replace these with your position. + // The units for lat and lon are degrees * 1e-7 (WGS84) + // The units for alt (WGS84) and posAcc (stddev) are cm. + myGNSS.setPositionAssistanceLLH(550000000, -10000000, 10000, 10000000, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); + + // We could use setPositionAssistanceXYZ instead if needed. + +#endif + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the AssistNow data to the module - WITHOUT THE TIME + + if (payloadSize > 0) + { + // Push the AssistNow data. Use the UBX_MGA_ACK_DATA0 acknowledgements. + // The 'true' parameter tells pushAssistNowData not to push any time data from the payload. + myGNSS.pushAssistNowData(true, payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Disconnect the WiFi as it's no longer needed + + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + Serial.println(F("WiFi disconnected")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Avoid pounding the I2C bus by setting setI2CpollingWait to 125ms + myGNSS.setI2CpollingWait(125); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte SIV = myGNSS.getSIV(); + Serial.print(F(" SIV: ")); + Serial.print(SIV); + + byte fixType = myGNSS.getFixType(); + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); +} diff --git a/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/secrets.h b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/secrets.h new file mode 100644 index 0000000..4eb7a9c --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/secrets.h @@ -0,0 +1,6 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "hasBigTeeth"; + +//Your AssistNow token +const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 6dc2471..cee89a9 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -10,7 +10,7 @@ With AssistNow Online, an Internet connected host downloads assistance data from Please see the [AssistNow_Online](./AssistNow_Online) examples for more details. These examples were written for the ESP32, but will run on other platforms too. -The new functions we've added to the library to support AssistNow Online are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) +The new functions we've added to the library to support AssistNow Online are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). ## AssistNowTM Offline @@ -20,7 +20,7 @@ Please see the [AssistNow_Offline](./AssistNow_Offline) examples for more detail **Note: AssistNow Offline is not supported by the ZED-F9P. "The ZED-F9P supports AssistNow Online only."** -The new functions we've added to the library to support AssistNow Offline are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) +The new functions we've added to the library to support AssistNow Offline are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). ## AssistNowTM Autonomous @@ -37,7 +37,7 @@ AssistNow Autonomous offers augmentation for up to 6 days. Please see the [AssistNow_Autonomous](./AssistNow_Autonomous) examples for more details. -The new functions we've added to the library to support AssistNow Autonomous are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) +The new functions we've added to the library to support AssistNow Autonomous are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). ## AssistNow Service Token @@ -124,6 +124,22 @@ Only the ```year```, ```month```, ```day```, ```hour```, ```minute``` and ```sec Call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. +## Initial Position Assistance + +You can further decrease the time-to-first-fix by also providing the receiver's position - if known. There are two ways to do this: + +* The position can be specified when requesting AssistNow Online data from the server: + * include the key name ```lat``` with the approximate user latitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -90 to 90. Example: ```lat=47.2;``` + * include the key name ```lon``` with the approximate user longitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -180 to 180. Example: ```lon=8.55;``` + * include the key name ```alt``` with the approximate user altitude above WGS 84 Ellipsoid in meters. If this value is not provided, the server assumes an altitude of 0 meters. Must be in range -1000 to 50000 + * if possible, include the key name ```pacc``` with the approximate accuracy of submitted position in meters. If this value is not provided, the server assumes an accuracy of 300 km. Must be in range 0 to 6000000 + * the position assistance data will then be automatically included in the AssistNow Online data +* Provide initial position assistance data by calling one of: + * bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + * The units for ```ecefX/Y/Z``` and ```posAcc``` (stddev) are cm + * bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + * The units for ```lat``` and ```lon``` are degrees * 1e-7 (WGS84). The units for ```alt``` (WGS84) and ```posAcc``` (stddev) are cm (not m) + ## Additional Code Support for AssistNow Offline AssistNow Offline data downloaded from the u-blox server can contain 1-5 weeks of data. However, only the data for _today_ should be pushed the module. Sending data for past or future days will confuse the module. diff --git a/keywords.txt b/keywords.txt index 34f4716..e4d1b03 100644 --- a/keywords.txt +++ b/keywords.txt @@ -92,6 +92,8 @@ pushRawData KEYWORD2 pushAssistNowData KEYWORD2 setUTCTimeAssistance KEYWORD2 +setPositionAssistanceXYZ KEYWORD2 +setPositionAssistanceLLH KEYWORD2 findMGAANOForDate KEYWORD2 setFileBufferSize KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index e1643c5..984fbb7 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4281,6 +4281,116 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t return (pushAssistNowDataInternal(0, false, iniTimeUTC, 32, mgaAck, maxWait) == 1); } +// Provide initial position assistance +// The units for ecefX/Y/Z and posAcc (stddev) are cm. +bool SFE_UBLOX_GNSS::setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + uint8_t iniPosXYZ[28]; // Create the UBX-MGA-INI-POS_XYZ message by hand + memset(iniPosXYZ, 0x00, 28); // Set all unused / reserved bytes and the checksum to zero + + iniPosXYZ[0] = UBX_SYNCH_1; // Sync char 1 + iniPosXYZ[1] = UBX_SYNCH_2; // Sync char 2 + iniPosXYZ[2] = UBX_CLASS_MGA; // Class + iniPosXYZ[3] = UBX_MGA_INI_POS_XYZ; // ID + iniPosXYZ[4] = 20; // Length LSB + iniPosXYZ[5] = 0x00; // Length MSB + iniPosXYZ[6] = 0x00; // type + iniPosXYZ[7] = 0x00; // version + + union // Use a union to convert from int32_t to uint32_t + { + int32_t signedLong; + uint32_t unsignedLong; + } signedUnsigned; + + signedUnsigned.signedLong = ecefX; + iniPosXYZ[10] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosXYZ[11] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosXYZ[12] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosXYZ[13] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = ecefY; + iniPosXYZ[14] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosXYZ[15] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosXYZ[16] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosXYZ[17] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = ecefZ; + iniPosXYZ[18] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosXYZ[19] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosXYZ[20] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosXYZ[21] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + iniPosXYZ[22] = (uint8_t)(posAcc & 0xFF); // LSB + iniPosXYZ[23] = (uint8_t)((posAcc >> 8) & 0xFF); + iniPosXYZ[24] = (uint8_t)((posAcc >> 16) & 0xFF); + iniPosXYZ[25] = (uint8_t)(posAcc >> 24); // MSB + + for (uint8_t i = 2; i < 26; i++) // Calculate the checksum + { + iniPosXYZ[26] += iniPosXYZ[i]; + iniPosXYZ[27] += iniPosXYZ[26]; + } + + // Return true if the one packet was pushed successfully + return (pushAssistNowDataInternal(0, false, iniPosXYZ, 28, mgaAck, maxWait) == 1); +} + +// The units for lat and lon are degrees * 1e-7 (WGS84) +// The units for alt (WGS84) and posAcc (stddev) are cm. +bool SFE_UBLOX_GNSS::setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + uint8_t iniPosLLH[28]; // Create the UBX-MGA-INI-POS_LLH message by hand + memset(iniPosLLH, 0x00, 28); // Set all unused / reserved bytes and the checksum to zero + + iniPosLLH[0] = UBX_SYNCH_1; // Sync char 1 + iniPosLLH[1] = UBX_SYNCH_2; // Sync char 2 + iniPosLLH[2] = UBX_CLASS_MGA; // Class + iniPosLLH[3] = UBX_MGA_INI_POS_LLH; // ID + iniPosLLH[4] = 20; // Length LSB + iniPosLLH[5] = 0x00; // Length MSB + iniPosLLH[6] = 0x01; // type + iniPosLLH[7] = 0x00; // version + + union // Use a union to convert from int32_t to uint32_t + { + int32_t signedLong; + uint32_t unsignedLong; + } signedUnsigned; + + signedUnsigned.signedLong = lat; + iniPosLLH[10] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosLLH[11] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosLLH[12] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosLLH[13] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = lon; + iniPosLLH[14] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosLLH[15] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosLLH[16] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosLLH[17] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = alt; + iniPosLLH[18] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosLLH[19] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosLLH[20] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosLLH[21] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + iniPosLLH[22] = (uint8_t)(posAcc & 0xFF); // LSB + iniPosLLH[23] = (uint8_t)((posAcc >> 8) & 0xFF); + iniPosLLH[24] = (uint8_t)((posAcc >> 16) & 0xFF); + iniPosLLH[25] = (uint8_t)(posAcc >> 24); // MSB + + for (uint8_t i = 2; i < 26; i++) // Calculate the checksum + { + iniPosLLH[26] += iniPosLLH[i]; + iniPosLLH[27] += iniPosLLH[26]; + } + + // Return true if the one packet was pushed successfully + return (pushAssistNowDataInternal(0, false, iniPosLLH, 28, mgaAck, maxWait) == 1); +} + // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day // The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date // Returns numDataBytes if unsuccessful diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 06eaf7a..806cc64 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -726,6 +726,13 @@ class SFE_UBLOX_GNSS #define defaultMGAINITIMEsource 0 // Set default source to none, i.e. on receipt of message (will be inaccurate!) bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // Provide initial position assistance + // The units for ecefX/Y/Z and posAcc (stddev) are cm. + bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // The units for lat and lon are degrees * 1e-7 (WGS84) + // The units for alt (WGS84) and posAcc (stddev) are cm. + bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day // The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date // Returns numDataBytes if unsuccessful From 611e0868645a703b75361d079a979b4cbcda029c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 29 Nov 2021 17:11:15 +0000 Subject: [PATCH 012/122] Add getAopCfg and setAopCfg - for AssistNow Autonomous --- examples/AssistNow/README.md | 55 ++++++++++++-------- keywords.txt | 3 ++ src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 48 +++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 5 ++ 4 files changed, 90 insertions(+), 21 deletions(-) diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index cee89a9..413e5de 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -10,7 +10,7 @@ With AssistNow Online, an Internet connected host downloads assistance data from Please see the [AssistNow_Online](./AssistNow_Online) examples for more details. These examples were written for the ESP32, but will run on other platforms too. -The new functions we've added to the library to support AssistNow Online are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). +The new functions we've added to the library to support AssistNow Online are described [Support for AssistNow below](#Support-for-AssistNow). ## AssistNowTM Offline @@ -20,7 +20,7 @@ Please see the [AssistNow_Offline](./AssistNow_Offline) examples for more detail **Note: AssistNow Offline is not supported by the ZED-F9P. "The ZED-F9P supports AssistNow Online only."** -The new functions we've added to the library to support AssistNow Offline are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). +The new functions we've added to the library to support AssistNow Offline are described [Support for AssistNow](#Support-for-AssistNow) and [Additional Support for AssistNow Offline](#Additional-Support-for-AssistNow-Offline). ## AssistNowTM Autonomous @@ -37,7 +37,7 @@ AssistNow Autonomous offers augmentation for up to 6 days. Please see the [AssistNow_Autonomous](./AssistNow_Autonomous) examples for more details. -The new functions we've added to the library to support AssistNow Autonomous are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). +The new functions we've added to the library to support AssistNow Autonomous are described [Support for AssistNow Autonomous below](#Support-for-AssistNow-Autonomous). ## AssistNow Service Token @@ -62,7 +62,23 @@ The _free_ AssistNow Developer token entitles you to: The free token will expire after 90 days, but you can continue to use it beyond that by registering it on [Thingstream](https://portal.thingstream.io/). -## Code Support for AssistNow +## Initial Position Assistance + +You can further decrease the time-to-first-fix by providing the receiver's approximate position - if known. There are two ways to do this: + +* The position can be specified when requesting AssistNow Online data from the server: + * include the key name ```lat``` with the approximate user latitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -90 to 90. Example: ```lat=47.2;``` + * include the key name ```lon``` with the approximate user longitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -180 to 180. Example: ```lon=8.55;``` + * include the key name ```alt``` with the approximate user altitude above WGS 84 Ellipsoid in meters. If this value is not provided, the server assumes an altitude of 0 meters. Must be in range -1000 to 50000 + * include the key name ```pacc``` with the approximate accuracy of submitted position in meters. If this value is not provided, the server assumes an accuracy of 300 km. Must be in range 0 to 6000000 + * the position assistance data will then be automatically included in the AssistNow Online data +* Provide initial position assistance data by calling one of: + * bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + * The units for ```ecefX/Y/Z``` and ```posAcc``` (stddev) are cm + * bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + * The units for ```lat``` and ```lon``` are degrees * 1e-7 (WGS84). The units for ```alt``` (WGS84) and ```posAcc``` (stddev) are cm (not m) + +## Support for AssistNow ```pushAssistNowData``` allows the AssistNow Online data or AssistNow Offline data from the u-blox server to be pushed to the module. As the ESP32 HTTP GET function returns a ```String```, we've included overloaded functions which allow you to pass the data as a ```String``` or as ```const uint8_t *```. @@ -124,23 +140,7 @@ Only the ```year```, ```month```, ```day```, ```hour```, ```minute``` and ```sec Call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. -## Initial Position Assistance - -You can further decrease the time-to-first-fix by also providing the receiver's position - if known. There are two ways to do this: - -* The position can be specified when requesting AssistNow Online data from the server: - * include the key name ```lat``` with the approximate user latitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -90 to 90. Example: ```lat=47.2;``` - * include the key name ```lon``` with the approximate user longitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -180 to 180. Example: ```lon=8.55;``` - * include the key name ```alt``` with the approximate user altitude above WGS 84 Ellipsoid in meters. If this value is not provided, the server assumes an altitude of 0 meters. Must be in range -1000 to 50000 - * if possible, include the key name ```pacc``` with the approximate accuracy of submitted position in meters. If this value is not provided, the server assumes an accuracy of 300 km. Must be in range 0 to 6000000 - * the position assistance data will then be automatically included in the AssistNow Online data -* Provide initial position assistance data by calling one of: - * bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); - * The units for ```ecefX/Y/Z``` and ```posAcc``` (stddev) are cm - * bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); - * The units for ```lat``` and ```lon``` are degrees * 1e-7 (WGS84). The units for ```alt``` (WGS84) and ```posAcc``` (stddev) are cm (not m) - -## Additional Code Support for AssistNow Offline +## Additional Support for AssistNow Offline AssistNow Offline data downloaded from the u-blox server can contain 1-5 weeks of data. However, only the data for _today_ should be pushed the module. Sending data for past or future days will confuse the module. ```findMGAANOForDate``` can be used to find the location of the start of the UBX-MGA-ANO data for the specified date within the offline data. That location can then be passed to ```pushAssistNowData``` using the ```offset``` parameter. @@ -161,3 +161,16 @@ The sequence of events is: Again, call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. +## Support for AssistNow Autonomous + +AssistNow Autonomous is disabled by default. You can enable it by calling ```setAopCfg``` and check if it is enabled by calling ```getAopCfg```: + +* uint8_t getAopCfg(uint16_t maxWait); +* bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t maxWait) + +```getAopCfg``` will return 1 if AssistNow Autonomous is enabled, 0 if disabled. 255 indicates an error or timeout. + +```setAopCfg``` has two parameters: + +* set ```aopCfg``` to 1 to enable AssistNow Autonomous, or 0 to disable it +* ```aopOrbMaxErr``` is used to set the 'lifetime' of the AssistNow data. It is recommended to set aopOrbMaxErr to 0 (the default value). This instructs the module to use the firmware default value that corresponds to a default orbit data validity of approximately three days (for GPS satellites observed once) and up to six days (for GPS and GLONASS satellites observed multiple times over a period of at least half a day). diff --git a/keywords.txt b/keywords.txt index e4d1b03..686ff55 100644 --- a/keywords.txt +++ b/keywords.txt @@ -172,6 +172,9 @@ setTimePulseParameters KEYWORD2 getAckAiding KEYWORD2 setAckAiding KEYWORD2 +getAopCfg KEYWORD2 +setAopCfg KEYWORD2 + createKey KEYWORD2 getVal KEYWORD2 getVal8 KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 984fbb7..2f0f26d 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -334,6 +334,12 @@ void SFE_UBLOX_GNSS::end(void) packetUBXESFRAW = NULL; // Redundant? } + if (packetUBXMGAACK != NULL) + { + delete packetUBXMGAACK; + packetUBXMGAACK = NULL; // Redundant? + } + if (packetUBXHNRATT != NULL) { if (packetUBXHNRATT->callbackData != NULL) @@ -6026,6 +6032,48 @@ bool SFE_UBLOX_GNSS::setAckAiding(uint8_t ackAiding, uint16_t maxWait) // Set th return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } +//AssistNow Autonomous support +//UBX-CFG-NAVX5 - get the AssistNow Autonomous configuration (aopCfg) - returns 255 if the sendCommand fails +uint8_t SFE_UBLOX_GNSS::getAopCfg(uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NAVX5; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (255); + + // Extract the aopCfg byte + // There are three versions of UBX-CFG-NAVX5 but aopCfg is always in byte 27 + return (extractByte(&packetCfg, 27)); +} +// Set the aopCfg byte and the aopOrdMaxErr word +bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NAVX5; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + // Set the aopCfg byte + // There are three versions of UBX-CFG-NAVX5 but aopCfg is always in byte 27 and aopOrbMaxErr is always in bytes 30 & 31 + payloadCfg[27] = aopCfg; + payloadCfg[30] = (uint8_t)(aopOrbMaxErr & 0xFF); // aopOrbMaxErr LSB + payloadCfg[31] = (uint8_t)(aopOrbMaxErr >> 8); // aopOrbMaxErr MSB + + // There are three versions of UBX-CFG-NAVX5 but the aop flag is always in bit 14 of mask1 + payloadCfg[2] = 0x00; // Clear the LS byte of mask1 + payloadCfg[3] = 0x40; // Set _only_ the aop flag = bit 14 of mask1 = bit 6 of the MS byte + payloadCfg[4] = 0x00; // Clear the LS byte of mask2, just in case + payloadCfg[5] = 0x00; // Clear the LS byte of mask2, just in case + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + // CONFIGURATION INTERFACE (protocol v27 and above) //Form 32-bit key from group/id/size diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 806cc64..e8ed574 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -846,6 +846,11 @@ class SFE_UBLOX_GNSS uint8_t getAckAiding(uint16_t maxWait = defaultMaxWait); // Get the ackAiding byte - returns 255 if the sendCommand fails bool setAckAiding(uint8_t ackAiding, uint16_t maxWait = defaultMaxWait); // Set the ackAiding byte + //AssistNow Autonomous support + //UBX-CFG-NAVX5 - get/set the aopCfg byte and set the aopOrdMaxErr word. If aopOrbMaxErr is 0 (default), the max orbit error is reset to the firmware default. + uint8_t getAopCfg(uint16_t maxWait = defaultMaxWait); // Get the AssistNow Autonomous configuration (aopCfg) - returns 255 if the sendCommand fails + bool setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr = 0, uint16_t maxWait = defaultMaxWait); // Set the aopCfg byte and the aopOrdMaxErr word + //General configuration (used only on protocol v27 and higher - ie, ZED-F9P) //It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic. From 64f830f418ae65330d3cd685fcd73e13c00dd4f5 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 29 Nov 2021 18:40:12 +0000 Subject: [PATCH 013/122] Add auto support UBX-NAV-AOPSTATUS (AssistNow Autonomous) --- keywords.txt | 12 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 262 ++++++++++++++++++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 17 ++ src/u-blox_structs.h | 47 ++++ 4 files changed, 336 insertions(+), 2 deletions(-) diff --git a/keywords.txt b/keywords.txt index 686ff55..cdfccd2 100644 --- a/keywords.txt +++ b/keywords.txt @@ -311,6 +311,15 @@ initPacketUBXNAVRELPOSNED KEYWORD2 flushNAVRELPOSNED KEYWORD2 logNAVRELPOSNED KEYWORD2 +getNAVAOPSTATUS KEYWORD2 +setAutoNAVAOPSTATUS KEYWORD2 +setAutoNAVAOPSTATUSrate KEYWORD2 +setAutoNAVAOPSTATUScallback KEYWORD2 +assumeAutoNAVAOPSTATUS KEYWORD2 +initPacketUBXNAVAOPSTATUS KEYWORD2 +flushNAVAOPSTATUS KEYWORD2 +logNAVAOPSTATUS KEYWORD2 + getRXMSFRBX KEYWORD2 setAutoRXMSFRBX KEYWORD2 setAutoRXMSFRBXrate KEYWORD2 @@ -509,6 +518,9 @@ getRelPosAccN KEYWORD2 getRelPosAccE KEYWORD2 getRelPosAccD KEYWORD2 +getAOPSTATUSuseAOP KEYWORD2 +getAOPSTATUSstatus KEYWORD2 + getESFroll KEYWORD2 getESFpitch KEYWORD2 getESFyaw KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 2f0f26d..6ceb543 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -244,6 +244,16 @@ void SFE_UBLOX_GNSS::end(void) packetUBXNAVRELPOSNED = NULL; // Redundant? } + if (packetUBXNAVAOPSTATUS != NULL) + { + if (packetUBXNAVAOPSTATUS->callbackData != NULL) + { + delete packetUBXNAVAOPSTATUS->callbackData; + } + delete packetUBXNAVAOPSTATUS; + packetUBXNAVAOPSTATUS = NULL; // Redundant? + } + if (packetUBXRXMSFRBX != NULL) { if (packetUBXRXMSFRBX->callbackData != NULL) @@ -1023,6 +1033,9 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) case UBX_NAV_RELPOSNED: if (packetUBXNAVRELPOSNED != NULL) result = true; break; + case UBX_NAV_AOPSTATUS: + if (packetUBXNAVAOPSTATUS != NULL) result = true; + break; } } break; @@ -1158,6 +1171,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) case UBX_NAV_RELPOSNED: maxSize = UBX_NAV_RELPOSNED_LEN_F9; break; + case UBX_NAV_AOPSTATUS: + maxSize = UBX_NAV_AOPSTATUS_LEN; + break; } } break; @@ -2417,6 +2433,33 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } } } + else if (msg->id == UBX_NAV_AOPSTATUS && msg->len == UBX_NAV_AOPSTATUS_LEN) + { + //Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXNAVAOPSTATUS != NULL) + { + packetUBXNAVAOPSTATUS->data.iTOW = extractLong(msg, 0); + packetUBXNAVAOPSTATUS->data.aopCfg.all = extractByte(msg, 4); + packetUBXNAVAOPSTATUS->data.status = extractByte(msg, 5); + + //Mark all datums as fresh (not read before) + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; + + //Check if we need to copy the data for the callback + if ((packetUBXNAVAOPSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + { + memcpy(&packetUBXNAVAOPSTATUS->callbackData->iTOW, &packetUBXNAVAOPSTATUS->data.iTOW, sizeof(UBX_NAV_AOPSTATUS_data_t)); + packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid = true; + } + + //Check if we need to copy the data into the file buffer + if (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.addToFileBuffer) + { + storePacket(msg); + } + } + } break; case UBX_CLASS_RXM: if (msg->id == UBX_RXM_SFRBX) @@ -3756,6 +3799,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } + if ((packetUBXNAVAOPSTATUS != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVAOPSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVAOPSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined + && (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV AOPSTATUS")); + packetUBXNAVAOPSTATUS->callbackPointer(*packetUBXNAVAOPSTATUS->callbackData); // Call the callback + packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + } + if ((packetUBXRXMSFRBX != NULL) // If RAM has been allocated for message storage && (packetUBXRXMSFRBX->callbackData != NULL) // If RAM has been allocated for the copy of the data && (packetUBXRXMSFRBX->callbackPointer != NULL) // If the pointer to the callback has been defined @@ -7130,11 +7184,11 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVATT() return (true); } -//Mark all the DOP data as read/stale. This is handy to get data alignment after CRC failure +//Mark all the ATT data as read/stale. This is handy to get data alignment after CRC failure void SFE_UBLOX_GNSS::flushNAVATT() { if (packetUBXNAVATT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVATT->moduleQueried.moduleQueried.all = 0; //Mark all DOPs as stale (read before) + packetUBXNAVATT->moduleQueried.moduleQueried.all = 0; //Mark all ATT data as stale (read before) } //Log this data in file buffer @@ -8538,6 +8592,182 @@ void SFE_UBLOX_GNSS::logNAVRELPOSNED(bool enabled) packetUBXNAVRELPOSNED->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } +// ***** AOPSTATUS automatic support + +bool SFE_UBLOX_GNSS::getAOPSTATUS(uint16_t maxWait) +{ + if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the AOPSTATUS data + if (packetUBXNAVAOPSTATUS == NULL) //Bail if the RAM allocation failed + return (false); + + if (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic && packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate) + { + //The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getAOPSTATUS: Autoreporting")); + // } + checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_AOPSTATUS); + return packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.all; + } + else if (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic && !packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate) + { + //Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getAOPSTATUS: Exit immediately")); + // } + return (false); + } + else + { + // if (_printDebug == true) + // { + // _debugSerial->println(F("getAOPSTATUS: Polling")); + // } + + //The GPS is not automatically reporting navigation position so we have to poll explicitly + packetCfg.cls = UBX_CLASS_NAV; + packetCfg.id = UBX_NAV_AOPSTATUS; + 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) + { + // if (_printDebug == true) + // { + // _debugSerial->println(F("getAOPSTATUS: data in packetCfg was OVERWRITTEN by another message (but that's OK)")); + // } + return (true); + } + + // if (_printDebug == true) + // { + // _debugSerial->print(F("getAOPSTATUS retVal: ")); + // _debugSerial->println(statusString(retVal)); + // } + return (false); + } +} + +//Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS +//works. +bool SFE_UBLOX_GNSS::setAutoAOPSTATUS(bool enable, uint16_t maxWait) +{ + return setAutoAOPSTATUSrate(enable ? 1 : 0, true, maxWait); +} + +//Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS +//works. +bool SFE_UBLOX_GNSS::setAutoAOPSTATUS(bool enable, bool implicitUpdate, uint16_t maxWait) +{ + return setAutoAOPSTATUSrate(enable ? 1 : 0, implicitUpdate, maxWait); +} + +//Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS +//works. +bool SFE_UBLOX_GNSS::setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) +{ + if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the data + if (packetUBXNAVAOPSTATUS == NULL) //Only attempt this if RAM allocation was successful + return false; + + 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_AOPSTATUS; + payloadCfg[2] = rate; // rate relative to navigation freq. + + bool ok = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK + if (ok) + { + packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic = (rate > 0); + packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.all = false; + return ok; +} + +//Enable automatic navigation message generation by the GNSS. +bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoAOPSTATUS(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVAOPSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVAOPSTATUS->callbackData = new UBX_NAV_AOPSTATUS_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVAOPSTATUS->callbackData == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setAutoAOPSTATUScallback: RAM alloc failed!")); + return (false); + } + + packetUBXNAVAOPSTATUS->callbackPointer = callbackPointer; + return (true); +} + +//In case no config access to the GNSS is possible and AOPSTATUS is send cyclically already +//set config to suitable parameters +bool SFE_UBLOX_GNSS::assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate) +{ + if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the data + if (packetUBXNAVAOPSTATUS == NULL) //Only attempt this if RAM allocation was successful + return false; + + bool changes = packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; + if (changes) + { + packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic = enabled; + packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + return changes; +} + +// PRIVATE: Allocate RAM for packetUBXNAVAOPSTATUS and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXNAVAOPSTATUS() +{ + packetUBXNAVAOPSTATUS = new UBX_NAV_AOPSTATUS_t; //Allocate RAM for the main struct + if (packetUBXNAVAOPSTATUS == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXNAVAOPSTATUS: RAM alloc failed!")); + return (false); + } + packetUBXNAVAOPSTATUS->automaticFlags.flags.all = 0; + packetUBXNAVAOPSTATUS->callbackPointer = NULL; + packetUBXNAVAOPSTATUS->callbackData = NULL; + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.all = 0; + return (true); +} + +//Mark all the AOPSTATUS data as read/stale. This is handy to get data alignment after CRC failure +void SFE_UBLOX_GNSS::flushAOPSTATUS() +{ + if (packetUBXNAVAOPSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.all = 0; //Mark all AOPSTATUSs as stale (read before) +} + +//Log this data in file buffer +void SFE_UBLOX_GNSS::logNAVAOPSTATUS(bool enabled) +{ + if (packetUBXNAVAOPSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; +} + // ***** RXM SFRBX automatic support bool SFE_UBLOX_GNSS::getRXMSFRBX(uint16_t maxWait) @@ -11804,6 +12034,34 @@ float SFE_UBLOX_GNSS::getRelPosAccD(uint16_t maxWait) // Returned as m return (((float)packetUBXNAVRELPOSNED->data.accD) / 10000.0); // Convert to m } +// ***** AOPSTATUS Helper Functions + +uint8_t SFE_UBLOX_GNSS::getAOPSTATUSuseAOP(uint16_t maxWait) +{ + if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the AOPSTATUS data + if (packetUBXNAVAOPSTATUS == NULL) //Bail if the RAM allocation failed + return 0; + + if (packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.useAOP == false) + getAOPSTATUS(maxWait); + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.useAOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.all = false; + return (packetUBXNAVAOPSTATUS->data.aopCfg.bits.useAOP); +} + +uint8_t SFE_UBLOX_GNSS::getAOPSTATUSstatus(uint16_t maxWait) +{ + if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the AOPSTATUS data + if (packetUBXNAVAOPSTATUS == NULL) //Bail if the RAM allocation failed + return 0; + + if (packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.status == false) + getAOPSTATUS(maxWait); + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.status = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.all = false; + return (packetUBXNAVAOPSTATUS->data.status); +} + // ***** ESF Helper Functions float SFE_UBLOX_GNSS::getESFroll(uint16_t maxWait) // Returned as degrees diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index e8ed574..3ffca28 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -369,6 +369,7 @@ const uint8_t UBX_NAV_TIMELS = 0x26; //Leap second event information const uint8_t UBX_NAV_TIMEUTC = 0x21; //UTC Time Solution const uint8_t UBX_NAV_VELECEF = 0x11; //Velocity Solution in ECEF const uint8_t UBX_NAV_VELNED = 0x12; //Velocity Solution in NED +const uint8_t UBX_NAV_AOPSTATUS = 0x60; //AssistNow Autonomous status //Class: RXM //The following are used to configure the RXM UBX messages (receiver manager messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) @@ -1001,6 +1002,15 @@ class SFE_UBLOX_GNSS void flushNAVRELPOSNED(); //Mark all the data as read/stale void logNAVRELPOSNED(bool enabled = true); // Log data to file buffer + bool getAOPSTATUS(uint16_t maxWait = defaultMaxWait); //Query module for latest AssistNow Autonomous status and load global vars:. If autoAOPSTATUS is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new AOPSTATUS is available. + bool setAutoAOPSTATUS(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic AOPSTATUS reports at the navigation frequency + bool setAutoAOPSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic AOPSTATUS 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 setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic AOPSTATUS reports + bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and AOPSTATUS is send cyclically already + void flushAOPSTATUS(); //Mark all the AOPSTATUS data as read/stale + void logNAVAOPSTATUS(bool enabled = true); // Log data to file buffer + // Receiver Manager Messages (RXM) bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX @@ -1244,6 +1254,11 @@ class SFE_UBLOX_GNSS float getRelPosAccE(uint16_t maxWait = defaultMaxWait); // Returned as m float getRelPosAccD(uint16_t maxWait = defaultMaxWait); // Returned as m + // Helper functions for AOPSTATUS + + uint8_t getAOPSTATUSuseAOP(uint16_t maxWait = defaultMaxWait); // Returns the UBX-NAV-AOPSTATUS useAOP flag. Don't confuse this with getAopCfg - which returns the aopCfg byte from UBX-CFG-NAVX5 + uint8_t getAOPSTATUSstatus(uint16_t maxWait = defaultMaxWait); // Returns the UBX-NAV-AOPSTATUS status field. A host application can determine the optimal time to shut down the receiver by monitoring the status field for a steady 0. + // Helper functions for ESF float getESFroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees @@ -1290,6 +1305,7 @@ class SFE_UBLOX_GNSS UBX_NAV_TIMELS_t *packetUBXNAVTIMELS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_SVIN_t *packetUBXNAVSVIN = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_RELPOSNED_t *packetUBXNAVRELPOSNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_AOPSTATUS_t *packetUBXNAVAOPSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1371,6 +1387,7 @@ class SFE_UBLOX_GNSS bool initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it bool initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it + bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it bool initPacketUBXCFGRATE(); // Allocate RAM for packetUBXCFGRATE and initialize it diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index ac38510..4fe38b9 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -65,6 +65,8 @@ struct ubxAutomaticFlags } flags; }; +// NAV-specific structs + // UBX-NAV-POSECEF (0x01 0x01): Position solution in ECEF const uint16_t UBX_NAV_POSECEF_LEN = 20; @@ -1071,6 +1073,51 @@ typedef struct UBX_NAV_RELPOSNED_data_t *callbackData; } UBX_NAV_RELPOSNED_t; +// UBX-NAV-AOPSTATUS (0x01 0x60): AssistNow Autonomous status +const uint16_t UBX_NAV_AOPSTATUS_LEN = 16; + +typedef struct +{ + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + union + { + uint8_t all; + struct + { + uint8_t useAOP : 1; // AOP enabled flag + } bits; + } aopCfg; // AssistNow Autonomous configuration + uint8_t status; // AssistNow Autonomous subsystem is idle (0) or running (not 0) + uint8_t reserved1[10]; +} UBX_NAV_AOPSTATUS_data_t; + +typedef struct +{ + union + { + uint32_t all; + struct + { + uint32_t all : 1; + + uint32_t iTOW : 1; + + uint32_t useAOP : 1; + + uint32_t status : 1; + } bits; + } moduleQueried; +} UBX_NAV_AOPSTATUS_moduleQueried_t; + +typedef struct +{ + ubxAutomaticFlags automaticFlags; + UBX_NAV_AOPSTATUS_data_t data; + UBX_NAV_AOPSTATUS_moduleQueried_t moduleQueried; + void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t); + UBX_NAV_AOPSTATUS_data_t *callbackData; +} UBX_NAV_AOPSTATUS_t; + // RXM-specific structs // UBX-RXM-SFRBX (0x02 0x13): Broadcast navigation data subframe From 33b8e1deb2b8df86618651c40f28e94ef6ead5b6 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 29 Nov 2021 18:44:01 +0000 Subject: [PATCH 014/122] Create Example1_AssistNowAutonomous_Read.ino --- .../Example1_AssistNowAutonomous_Read.ino | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino diff --git a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino new file mode 100644 index 0000000..38f80bf --- /dev/null +++ b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino @@ -0,0 +1,97 @@ +/* + Read the AssistNow Autonomous data from the module + By: SparkFun Electronics / Paul Clark + Date: November 29th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to enable, check the status of, and read the AssistNow Autonomous data from the module. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + + Wire.begin(); //Start I2C + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Enable AssistNow Autonomous data collection. + + if (myGNSS.setAopCfg(1) == true) + { + Serial.println(F("aopCfg enabled")); + } + else + { + Serial.println(F("Could not enable aopCfg. Please check wiring. Freezing.")); + while (1); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Keep calling getAOPSTATUSstatus until it returns zero (indicating AssistNow Autonomous data collection si complete) + // or the user presses a key + + Serial.println(F("AssistNow Autonomous data collection is in progress. Press any key to quit.")); + + bool keepGoing = true; + while (Serial.available()) Serial.read(); // Empty the serial buffer + + while (keepGoing && !Serial.available()); // Wait keepGoing to go false, or for the arrival of a keypress + { + delay(1000); + Serial.print(F("NAV AOPSTATUS status is: ")); + uint8_t aopStatus = myGNSS.getAOPSTATUSstatus(); + Serial.print(aopStatus); + Serial.println(F(". (Don't worry! This could take a _long_ time...)")); + if (aopStatus == 0) // aopStatus will be zero when the AssistNow Autonomous subsystem is idle - i.e. data collection is complete + keepGoing = false; + } + + if (!keepGoing) + Serial.print(F("AssistNow Autonomous data collection is complete!")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Read the AssistNow Autonomous data from the module and pretty-print it (so it can be copied and pasted into Example2) + +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ +} From d0143181fed8d2fdcc2ce43de251242039f06550 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 30 Nov 2021 20:09:59 +0000 Subject: [PATCH 015/122] Add readNavigationDatabase. Update the AssistNow Autonomous example. --- Theory.md | 2 +- .../Example1_AssistNowAutonomous_Read.ino | 74 ++++- examples/AssistNow/README.md | 30 ++ keywords.txt | 1 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 313 +++++++++++++++++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 21 +- src/u-blox_structs.h | 24 ++ 7 files changed, 441 insertions(+), 24 deletions(-) diff --git a/Theory.md b/Theory.md index eb8bdd3..5b67bc8 100644 --- a/Theory.md +++ b/Theory.md @@ -5,7 +5,6 @@ When the user calls one of the methods the library will poll the u-blox module f * Wait for a minimum of 25 ms between polls (configured dynamically when update rate is set) * Write 0xFD to module * Read two bytes (0xFD and 0xFE) for bytes available -* If 0x7F or 0xFF then no bytes are available * Otherwise, read number of bytes and process into NMEA, UBX, or RTCM frame. * If checksum is valid, flag frame as complete. @@ -58,6 +57,7 @@ In v2.0, the full list of messages which can be processed and logged automatical - UBX-NAV-CLOCK (0x01 0x22): Clock solution - UBX-NAV-SVIN (0x01 0x3B): Survey-in data (**only with High Precision GNSS products**) - UBX-NAV-RELPOSNED (0x01 0x3C): Relative positioning information in NED frame (**only with High Precision GNSS products**) +- UBX-NAV-AOPSTATUS (0x01 0x60): AssistNow Autonomous status - UBX-RXM-SFRBX (0x02 0x13): Broadcast navigation data subframe - UBX-RXM-RAWX (0x02 0x15): Multi-GNSS raw measurement data (**only with ADR or High Precision GNSS or Time Sync products**) - UBX-TIM-TM2 (0x0D 0x03): Time mark data diff --git a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino index 38f80bf..024ceb4 100644 --- a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino +++ b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino @@ -7,6 +7,10 @@ This example shows how to enable, check the status of, and read the AssistNow Autonomous data from the module. + Note: this example will only work on boards which have plenty of RAM available. + The database can be several kBytes in length and needs to be stored twice: + once inside the library (by readNavigationDatabase); and again in this example code. + Feel like supporting open source hardware? Buy a board from SparkFun! SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 @@ -49,6 +53,8 @@ void setup() myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + //myGNSS.enableDebugging(Serial, true); // Uncomment this line to see helpful debug messages on Serial + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Enable AssistNow Autonomous data collection. @@ -63,30 +69,79 @@ void setup() } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // Keep calling getAOPSTATUSstatus until it returns zero (indicating AssistNow Autonomous data collection si complete) + // Keep calling getAOPSTATUSstatus until it returns zero (indicating AssistNow Autonomous data collection is complete) // or the user presses a key Serial.println(F("AssistNow Autonomous data collection is in progress. Press any key to quit.")); + Serial.println(F("NAV AOPSTATUS status indicates when the AssistNow Autonomous subsystem is idle (0) or running (not 0).")); bool keepGoing = true; + int zerosSeen = 0; // Keep track of how many times aopStatus has been zero while (Serial.available()) Serial.read(); // Empty the serial buffer - while (keepGoing && !Serial.available()); // Wait keepGoing to go false, or for the arrival of a keypress + while (keepGoing && !Serial.available()) // Wait for keepGoing to go false, or for the arrival of a keypress { delay(1000); - Serial.print(F("NAV AOPSTATUS status is: ")); uint8_t aopStatus = myGNSS.getAOPSTATUSstatus(); - Serial.print(aopStatus); - Serial.println(F(". (Don't worry! This could take a _long_ time...)")); + Serial.print(F("NAV AOPSTATUS status is: ")); + Serial.println(aopStatus); if (aopStatus == 0) // aopStatus will be zero when the AssistNow Autonomous subsystem is idle - i.e. data collection is complete - keepGoing = false; + { + zerosSeen++; // Keep track of how long aopStatus has been zero + if (zerosSeen >= 30) + keepGoing = false; // Stop after seeing 30 consecutive zeros + } + else + { + zerosSeen = 0; // Reset the number of zeros seen + } } if (!keepGoing) - Serial.print(F("AssistNow Autonomous data collection is complete!")); + Serial.println(F("AssistNow Autonomous data collection is complete!")); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // Read the AssistNow Autonomous data from the module and pretty-print it (so it can be copied and pasted into Example2) + // Read the AssistNow Autonomous data from the module and pretty-print it (so it can be copied and pasted into Example2) + + #define MAX_DATABASE_LENGTH 32768 // Allocate 32kBytes to store the navigation database + size_t maxDatabaseLen = MAX_DATABASE_LENGTH; + uint8_t *database = new uint8_t[MAX_DATABASE_LENGTH]; // The database will be stored here + + Serial.println(F("Storage has been allocated for the database.")); Serial.flush(); + + size_t actualDatabaseLen = myGNSS.readNavigationDatabase(database, maxDatabaseLen); // Read the database + + Serial.print(F("The Navigation Database length was ")); + Serial.println(actualDatabaseLen); + + if (actualDatabaseLen == maxDatabaseLen) + Serial.println(F("There was not enough memory to store the entire database. Some data will have been lost!")); + + // Pretty-print the database so it can be copied into Example2 + Serial.println(F("Copy and paste the following into Example2, so you can write it back to the module:")); + Serial.println(); + Serial.print(F("size_t databaseLen = ")); + Serial.print(actualDatabaseLen); + Serial.println(F(";")); + Serial.print(F("const uint8_t database[")); + Serial.print(actualDatabaseLen); + Serial.println(F("] = {")); + size_t i; + for(i = 0; i < actualDatabaseLen; i++) + { + if ((i % 32) == 0) + Serial.print(F(" 0x")); + if (*(database + i) < 0x10) // Print leading zero + Serial.print(F("0")); + Serial.print(*(database + i), HEX); + if (i == (actualDatabaseLen - 1)) + Serial.println(); + else if ((i % 32) == 31) + Serial.println(F(",")); + else + Serial.print(F(", 0x")); + } + Serial.println(F("};")); } @@ -94,4 +149,5 @@ void setup() void loop() { -} + // Nothing to do here +} \ No newline at end of file diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 413e5de..14282ec 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -174,3 +174,33 @@ AssistNow Autonomous is disabled by default. You can enable it by calling ```set * set ```aopCfg``` to 1 to enable AssistNow Autonomous, or 0 to disable it * ```aopOrbMaxErr``` is used to set the 'lifetime' of the AssistNow data. It is recommended to set aopOrbMaxErr to 0 (the default value). This instructs the module to use the firmware default value that corresponds to a default orbit data validity of approximately three days (for GPS satellites observed once) and up to six days (for GPS and GLONASS satellites observed multiple times over a period of at least half a day). + +Once AssistNow Autonomous is enabled, you can monitor its progress via the ```status``` field in the UBX-NAV-AOPSTATUS message. You can read the ```status``` by calling ```getAOPSTATUSstatus```. It will return zero when the AssistNow Autonomous data collection is complete. Non-zero values indicate that data collection is still in progress. + +* uint8_t getAOPSTATUSstatus(uint16_t maxWait); +* uint8_t getAOPSTATUSuseAOP(uint16_t maxWait); + +We have included full 'auto' support for UBX-NAV-AOPSTATUS, so you can have the message delivered periodically, add a callback for it, and/or log it to the file buffer: + +* bool getAOPSTATUS(uint16_t maxWait); +* bool setAutoAOPSTATUS(bool enabled, uint16_t maxWait); +* bool setAutoAOPSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait); +* bool setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait); +* bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait); +* bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate); +* void flushAOPSTATUS(); +* void logNAVAOPSTATUS(bool enabled); + +The AssistNow Autonomous data is stored in the module's RAM memory. If that RAM is Battery-Backed - all SparkFun GNSS boards include battery back-up - then the data will be available after the module is powered down and powered back up again. However, you can also read (poll) the navigation database and store the contents in processor memory. ```readNavigationDatabase``` allows you to do that: + +* size_t readNavigationDatabase(uint8_t *dataBytes, size_t maxNumDataBytes, uint16_t maxWait); + +Data is written to ```dataBytes```. Set ```maxNumDataBytes``` to the (maximum) size of dataBytes. If the database exceeds maxNumDataBytes, the excess bytes will be lost. + +```readNavigationDatabase``` returns the number of database bytes written to ```dataBytes```. The return value will be equal to ```maxNumDataBytes``` if excess data was received. + +```readNavigationDatabase``` will timeout after ```maxWait``` milliseconds - in case the final UBX-MGA-ACK was missed. + +You can then write the database back into the module using ```pushAssistNowData```. Don't forget to call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. + +Note: UBX-MGA-DBD messages are only intended to be sent back to the same receiver that generated them. They are firmware-specific. diff --git a/keywords.txt b/keywords.txt index cdfccd2..69af91c 100644 --- a/keywords.txt +++ b/keywords.txt @@ -95,6 +95,7 @@ setUTCTimeAssistance KEYWORD2 setPositionAssistanceXYZ KEYWORD2 setPositionAssistanceLLH KEYWORD2 findMGAANOForDate KEYWORD2 +readNavigationDatabase KEYWORD2 setFileBufferSize KEYWORD2 getFileBufferSize KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 6ceb543..7d450e9 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -350,6 +350,12 @@ void SFE_UBLOX_GNSS::end(void) packetUBXMGAACK = NULL; // Redundant? } + if (packetUBXMGADBD != NULL) + { + delete packetUBXMGADBD; + packetUBXMGADBD = NULL; // Redundant? + } + if (packetUBXHNRATT != NULL) { if (packetUBXHNRATT->callbackData != NULL) @@ -1096,7 +1102,15 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) break; case UBX_CLASS_MGA: { - if (packetUBXMGAACK != NULL) result = true; + switch (ID) + { + case UBX_MGA_ACK_DATA0: + if (packetUBXMGAACK != NULL) result = true; + break; + case UBX_MGA_DBD: + if (packetUBXMGADBD != NULL) result = true; + break; + } } break; case UBX_CLASS_HNR: @@ -1234,7 +1248,15 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) break; case UBX_CLASS_MGA: { - maxSize = UBX_MGA_ACK_DATA0_LEN; + switch (ID) + { + case UBX_MGA_ACK_DATA0: + maxSize = UBX_MGA_ACK_DATA0_LEN; + break; + case UBX_MGA_DBD: + maxSize = UBX_MGA_DBD_LEN; // UBX_MGA_DBD_LEN is actually a maximum length. The packets could be shorter than this. + break; + } } break; case UBX_CLASS_HNR: @@ -1263,7 +1285,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r { if ((currentSentence == NONE) || (currentSentence == NMEA)) { - if (incoming == 0xB5) //UBX binary frames start with 0xB5, aka μ + if (incoming == UBX_SYNCH_1) //UBX binary frames start with 0xB5, aka μ { //This is the start of a binary sentence. Reset flags. //We still don't know the response class @@ -1295,9 +1317,9 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r if (currentSentence == UBX) { //Decide what type of response this is - if ((ubxFrameCounter == 0) && (incoming != 0xB5)) //ISO 'μ' + if ((ubxFrameCounter == 0) && (incoming != UBX_SYNCH_1)) //ISO 'μ' currentSentence = NONE; //Something went wrong. Reset. - else if ((ubxFrameCounter == 1) && (incoming != 0x62)) //ASCII 'b' + else if ((ubxFrameCounter == 1) && (incoming != UBX_SYNCH_2)) //ASCII 'b' currentSentence = NONE; //Something went wrong. Reset. // Note to future self: // There may be some duplication / redundancy in the next few lines as processUBX will also @@ -2809,6 +2831,61 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) if (packetUBXMGAACK->head == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) packetUBXMGAACK->head = 0; } + else + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("processUBXpacket: packetUBXMGAACK is full. ACK will be lost!")); + } + } + } + } + else if (msg->id == UBX_MGA_DBD && msg->len <= UBX_MGA_DBD_LEN) // Message length may be less than UBX_MGA_DBD_LEN. UBX_MGA_DBD_LEN is the maximum it will be. + { + //Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXMGADBD != NULL) + { + // Calculate how many DBDs are already stored in the ring buffer + uint8_t dbdBufferContains; + if (packetUBXMGADBD->head >= packetUBXMGADBD->tail) // Check if wrap-around has occurred + { + // Wrap-around has not occurred so do a simple subtraction + dbdBufferContains = packetUBXMGADBD->head - packetUBXMGADBD->tail; + } + else + { + // Wrap-around has occurred so do a simple subtraction but add in the buffer length (UBX_MGA_DBD_RINGBUFFER_LEN) + dbdBufferContains = ((uint8_t)(((uint16_t)packetUBXMGADBD->head + (uint16_t)UBX_MGA_DBD_RINGBUFFER_LEN) - (uint16_t)packetUBXMGADBD->tail)); + } + // Have we got space to store this DBD? + if (dbdBufferContains < (UBX_MGA_DBD_RINGBUFFER_LEN - 1)) + { + // Yes, we have, so store it + // We need to save the entire message - header, payload and checksum + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryHeader1 = UBX_SYNCH_1; + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryHeader2 = UBX_SYNCH_2; + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryClass = UBX_CLASS_MGA; + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryID = UBX_MGA_DBD; + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryLenLSB = (uint8_t)(msg->len & 0xFF); // We need to store the length of the DBD entry. The entry itself does not contain a length... + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryLenMSB = (uint8_t)((msg->len >> 8) & 0xFF); + for (uint16_t i = 0; i < msg->len; i++) + { + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntry[i] = extractByte(msg, i); + } + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryChecksumA = msg->checksumA; + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryChecksumB = msg->checksumB; + // Increment the head + packetUBXMGADBD->head++; + if (packetUBXMGADBD->head == UBX_MGA_DBD_RINGBUFFER_LEN) + packetUBXMGADBD->head = 0; + } + else + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("processUBXpacket: packetUBXMGADBD is full. DBD data will be lost!")); + } + } } } break; @@ -4596,6 +4673,215 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_ return (dataPtr); } +// Read the whole navigation data base. The receiver will send all available data from its internal database. +// Data is written to dataBytes. Set maxNumDataBytes to the (maximum) size of dataBytes. +// If the database exceeds maxNumDataBytes, the excess bytes will be lost. +// The function returns the number of database bytes written to dataBytes. +// The return value will be equal to maxNumDataBytes if excess data was received. +// The function will timeout after maxWait milliseconds - in case the final UBX-MGA-ACK was missed. +size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumDataBytes, uint16_t maxWait) +{ + // Allocate RAM to store the MGA ACK message + if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data + if (packetUBXMGAACK == NULL) //Bail if the RAM allocation failed + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + { + _debugSerial->println(F("readNavigationDatabase: packetUBXMGAACK RAM allocation failed!")); + } +#endif + return ((size_t)0); + } + if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any data? + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + { + _debugSerial->println(F("readNavigationDatabase: packetUBXMGAACK contains unprocessed data. Clearing it.")); + } +#endif + packetUBXMGAACK->tail = packetUBXMGAACK->head; // Clear the buffer by setting the tail equal to the head + } + + // Allocate RAM to store the MGA DBD messages + if (packetUBXMGADBD == NULL) initPacketUBXMGADBD(); //Check that RAM has been allocated for the MGA_DBD data + if (packetUBXMGADBD == NULL) //Bail if the RAM allocation failed + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("readNavigationDatabase: packetUBXMGADBD RAM allocation failed!")); + } +#endif + return ((size_t)0); + } + if (packetUBXMGADBD->head != packetUBXMGADBD->tail) // Does the MGA DBD ringbuffer contain any data? + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + { + _debugSerial->println(F("readNavigationDatabase: packetUBXMGADBD contains unprocessed data. Clearing it.")); + } +#endif + packetUBXMGADBD->tail = packetUBXMGADBD->head; // Clear the buffer by setting the tail equal to the head + } + + // Record what ackAiding is currently set to so we can restore it + uint8_t currentAckAiding = getAckAiding(); + if (currentAckAiding == 255) + currentAckAiding = 0; // If the get failed, disable the ACKs when returning + // Enable ackAiding + setAckAiding(1); + + // Record what i2cPollingWait is currently set to so we can restore it + uint8_t currentI2cPollingWait = i2cPollingWait; + // Set the I2C polling wait to 1ms + i2cPollingWait = 1; + + // Construct the poll message: + uint8_t pollNaviDatabase[8]; // Create the UBX-MGA-DBD message by hand + memset(pollNaviDatabase, 0x00, 8); // Set all unused / reserved bytes and the checksum to zero + + pollNaviDatabase[0] = UBX_SYNCH_1; // Sync char 1 + pollNaviDatabase[1] = UBX_SYNCH_2; // Sync char 2 + pollNaviDatabase[2] = UBX_CLASS_MGA; // Class + pollNaviDatabase[3] = UBX_MGA_DBD; // ID + pollNaviDatabase[4] = 0x00; // Length LSB + pollNaviDatabase[5] = 0x00; // Length MSB + + for (uint8_t i = 2; i < 6; i++) // Calculate the checksum + { + pollNaviDatabase[6] += pollNaviDatabase[i]; + pollNaviDatabase[7] += pollNaviDatabase[6]; + } + + // Push the poll message to the module. + // Do not Wait for an ACK - the DBD data will start arriving immediately. + size_t pushResult = pushAssistNowDataInternal(0, false, pollNaviDatabase, (size_t)8, SFE_UBLOX_MGA_ASSIST_ACK_NO, 0); + + // Check pushResult == 1. Redundant?! + if (pushResult != 1) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + { + _debugSerial->println(F("readNavigationDatabase: pushAssistNowDataInternal failed!")); + } +#endif + i2cPollingWait = currentI2cPollingWait; // Restore i2cPollingWait + setAckAiding(currentAckAiding); // Restore Ack Aiding + return ((size_t)0); + } + + // Now keep checking for the arrival of UBX-MGA-DBD packets and write them to dataBytes + bool keepGoing = true; + unsigned long startTime = millis(); + uint32_t databaseEntriesRX = 0; // Keep track of how many database entries are received + size_t numBytesReceived = 0; // Keep track of how many bytes are received + + while (keepGoing && (millis() < (startTime + maxWait))) + { + checkUblox(); + + while (packetUBXMGADBD->head != packetUBXMGADBD->tail) // Does the MGA DBD ringbuffer contain any data? + { + // The data will be valid - process will have already checked it. So we can simply copy the data into dataBuffer. + // We do not need to check if there is room to store the entire database entry. pushAssistNowData will check the data before pushing it. + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryHeader1; + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryHeader2; + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryClass; + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryID; + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryLenLSB; + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryLenMSB; + size_t msgLen = (((size_t)packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryLenMSB) * 256) + ((size_t)packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryLenLSB); + for (size_t i = 0; i < msgLen; i++) + { + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntry[i]; + } + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryChecksumA; + if (numBytesReceived < maxNumDataBytes) + *(dataBytes + (numBytesReceived++)) = packetUBXMGADBD->data[packetUBXMGADBD->tail].dbdEntryChecksumB; + + // Increment the tail + packetUBXMGADBD->tail++; + if (packetUBXMGADBD->tail == UBX_MGA_DBD_RINGBUFFER_LEN) + packetUBXMGADBD->tail = 0; + + databaseEntriesRX++; // Increment the number of entries received + } + + // The final MGA-ACK is sent at the end of the DBD packets. So, we need to check the ACK buffer _after_ the DBD buffer. + while (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any data? + { + // Check if we've received the correct ACK + bool dataAckd = true; + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == UBX_MGA_DBD); // Check if the message ID matches + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == (uint8_t)(databaseEntriesRX & 0xFF)); // Check if the ACK contents match databaseEntriesRX + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == (uint8_t)((databaseEntriesRX >> 8) & 0xFF)); + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == (uint8_t)((databaseEntriesRX >> 16) & 0xFF)); + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == (uint8_t)((databaseEntriesRX >> 24) & 0xFF)); + + if (dataAckd) // Is the ACK valid? + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("readNavigationDatabase: ACK received. databaseEntriesRX is ")); + _debugSerial->print(databaseEntriesRX); + _debugSerial->print(F(". numBytesReceived is ")); + _debugSerial->print(numBytesReceived); + _debugSerial->print(F(". DBD read complete after ")); + _debugSerial->print(millis() - startTime); + _debugSerial->println(F(" ms")); + } +#endif + keepGoing = false; + } + // Increment the tail + packetUBXMGAACK->tail++; + if (packetUBXMGAACK->tail == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) + packetUBXMGAACK->tail = 0; + } + } + + if (keepGoing) // If keepGoing is still true, we must have timed out + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("readNavigationDatabase: DBD RX timed out!")); + } + } + + i2cPollingWait = currentI2cPollingWait; // Restore i2cPollingWait + setAckAiding(currentAckAiding); // Restore Ack Aiding + + return (numBytesReceived); +} + +// PRIVATE: Allocate RAM for packetUBXMGADBD and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXMGADBD() +{ + packetUBXMGADBD = new UBX_MGA_DBD_t; //Allocate RAM for the main struct + if (packetUBXMGADBD == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXMGADBD: RAM alloc failed!")); + return (false); + } + packetUBXMGADBD->head = 0; // Initialize the ring buffer pointers + packetUBXMGADBD->tail = 0; + return (true); +} + // Support for data logging //Set the file buffer size. This must be called _before_ .begin @@ -4768,7 +5054,7 @@ bool SFE_UBLOX_GNSS::storePacket(ubxPacket *msg) } //Store the two sync chars - uint8_t sync_chars[] = {0xB5, 0x62}; + uint8_t sync_chars[] = {UBX_SYNCH_1, UBX_SYNCH_2}; writeToFileBuffer(sync_chars, 2); //Store the Class & ID @@ -10805,12 +11091,15 @@ uint32_t SFE_UBLOX_GNSS::getProcessNMEAMask() //Max is 40Hz(?!) bool SFE_UBLOX_GNSS::setNavigationFrequency(uint8_t navFreq, uint16_t maxWait) { + if (navFreq == 0) // Return now if navFreq is zero + return (false); + if (navFreq > 40) navFreq = 40; // Limit navFreq to 40Hz so i2cPollingWait is set correctly //Adjust the I2C polling timeout based on update rate //Do this even if the sendCommand fails - i2cPollingWaitNAV = 1000 / (((int)navFreq) * 4); //This is the number of ms to wait between checks for new I2C data + i2cPollingWaitNAV = 1000 / (((int)navFreq) * 4); //This is the number of ms to wait between checks for new I2C data. Max is 250. Min is 6. i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR //Query the module @@ -10861,7 +11150,10 @@ bool SFE_UBLOX_GNSS::setMeasurementRate(uint16_t rate, uint16_t maxWait) rate = 25; //Adjust the I2C polling timeout based on update rate - i2cPollingWaitNAV = rate / 4; //This is the number of ms to wait between checks for new I2C data + if (rate >= 1000) + i2cPollingWaitNAV = 250; + else + i2cPollingWaitNAV = rate / 4; //This is the number of ms to wait between checks for new I2C data i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR //Query the module @@ -12177,12 +12469,15 @@ bool SFE_UBLOX_GNSS::getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensor // Returns true if the setHNRNavigationRate is successful bool SFE_UBLOX_GNSS::setHNRNavigationRate(uint8_t rate, uint16_t maxWait) { + if (rate == 0) // Return now if rate is zero + return (false); + if (rate > 40) rate = 40; // Limit rate to 40Hz so i2cPollingWait is set correctly //Adjust the I2C polling timeout based on update rate //Do this even if the sendCommand is not ACK'd - i2cPollingWaitHNR = 1000 / (((int)rate) * 4); //This is the number of ms to wait between checks for new I2C data + i2cPollingWaitHNR = 1000 / (((int)rate) * 4); //This is the number of ms to wait between checks for new I2C data. Max 250. Min 6. i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR packetCfg.cls = UBX_CLASS_CFG; diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 3ffca28..1dba18a 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -741,6 +741,15 @@ class SFE_UBLOX_GNSS size_t findMGAANOForDate(const String &dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); + // Read the whole navigation data base. The receiver will send all available data from its internal database. + // Data is written to dataBytes. Set maxNumDataBytes to the (maximum) size of dataBytes. + // If the database exceeds maxNumDataBytes, the excess bytes will be lost. + // The function returns the number of database bytes written to dataBytes. + // The return value will be equal to maxNumDataBytes if excess data was received. + // The function will timeout after maxWait milliseconds - in case the final UBX-MGA-ACK was missed. + #define defaultNavDBDMaxWait 3100 + size_t readNavigationDatabase(uint8_t *dataBytes, size_t maxNumDataBytes, uint16_t maxWait = defaultNavDBDMaxWait); + // Support for data logging void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. uint16_t getFileBufferSize(void); // Return the size of the file buffer @@ -878,15 +887,15 @@ class SFE_UBLOX_GNSS uint8_t sendCfgValset16(uint32_t keyID, uint16_t value, uint16_t maxWait = 250); //Add the final KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket and send it uint8_t sendCfgValset32(uint32_t keyID, uint32_t value, uint16_t maxWait = 250); //Add the final KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket and send it -// getPVT will only return data once in each navigation cycle. By default, that is once per second. -// Therefore we should set defaultMaxWait to slightly longer than that. -// If you change the navigation frequency to (e.g.) 4Hz using setNavigationFrequency(4) -// then you should use a shorter maxWait. 300msec would be about right: getPVT(300) - // get and set functions for all of the "automatic" message processing // Navigation (NAV) + // getPVT will only return data once in each navigation cycle. By default, that is once per second. + // Therefore we should set defaultMaxWait to slightly longer than that. + // If you change the navigation frequency to (e.g.) 4Hz using setNavigationFrequency(4) + // then you should use a shorter maxWait. 300msec would be about right: getPVT(300) + bool getNAVPOSECEF(uint16_t maxWait = defaultMaxWait); // NAV POSECEF bool setAutoNAVPOSECEF(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic POSECEF reports at the navigation frequency bool setAutoNAVPOSECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic POSECEF 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 @@ -1325,6 +1334,7 @@ class SFE_UBLOX_GNSS UBX_HNR_INS_t *packetUBXHNRINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_MGA_ACK_DATA0_t *packetUBXMGAACK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_MGA_DBD_t *packetUBXMGADBD = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame @@ -1401,6 +1411,7 @@ class SFE_UBLOX_GNSS bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it + bool initPacketUBXMGADBD(); // Allocate RAM for packetUBXMGADBD and initialize it //Variables TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 4fe38b9..c4561d8 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1728,6 +1728,30 @@ typedef struct UBX_MGA_ACK_DATA0_data_t data[UBX_MGA_ACK_DATA0_RINGBUFFER_LEN]; // Create a storage array for the MGA ACK packets } UBX_MGA_ACK_DATA0_t; +// UBX-MGA-DBD (0x13 0x80): Navigation database dump entry +const uint16_t UBX_MGA_DBD_LEN = 164; // "The maximum payload size for firmware 2.01 onwards is 164 bytes" + +typedef struct +{ + uint8_t dbdEntryHeader1; // We need to save the entire message - header, payload and checksum + uint8_t dbdEntryHeader2; + uint8_t dbdEntryClass; + uint8_t dbdEntryID; + uint8_t dbdEntryLenLSB; // We need to store the length of the DBD entry. The entry itself does not contain a length... + uint8_t dbdEntryLenMSB; + uint8_t dbdEntry[UBX_MGA_DBD_LEN]; + uint8_t dbdEntryChecksumA; + uint8_t dbdEntryChecksumB; +} UBX_MGA_DBD_data_t; + +#define UBX_MGA_DBD_RINGBUFFER_LEN 256 // Provide storage for MGA DBD packets. TO DO: confirm if 256 is large enough! +typedef struct +{ + uint8_t head; + uint8_t tail; + UBX_MGA_DBD_data_t data[UBX_MGA_DBD_RINGBUFFER_LEN]; // Create a storage array for the MGA DBD packets +} UBX_MGA_DBD_t; + // HNR-specific structs // UBX-HNR-PVT (0x28 0x00): High rate output of PVT solution From 235df31840f56793b33f55cbe16fc29efd81fd45 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 30 Nov 2021 20:28:39 +0000 Subject: [PATCH 016/122] Update README.md --- examples/AssistNow/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 14282ec..cbb5e20 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -80,7 +80,7 @@ You can further decrease the time-to-first-fix by providing the receiver's appro ## Support for AssistNow -```pushAssistNowData``` allows the AssistNow Online data or AssistNow Offline data from the u-blox server to be pushed to the module. As the ESP32 HTTP GET function returns a ```String```, we've included overloaded functions which allow you to pass the data as a ```String``` or as ```const uint8_t *```. +```pushAssistNowData``` allows AssistNow Online, Offline or Autonomous data to be pushed to the module. As the ESP32 HTTP GET function returns a ```String```, we've included overloaded functions which allow you to pass the data as a ```String``` or as ```const uint8_t *```. The String-based function declarations are: @@ -125,6 +125,7 @@ AssistNow Online data is valid for 2-4 hours. 'Stale' data can be re-used but: The ```skipTime``` parameter tells ```pushAssistNowData``` to skip any time information in the data. ```skipTime``` is bool. Set it to ```true``` to skip the time information.
+ UTC time can be pushed to the module first by calling ```setUTCTimeAssistance```: * bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); @@ -175,7 +176,7 @@ AssistNow Autonomous is disabled by default. You can enable it by calling ```set * set ```aopCfg``` to 1 to enable AssistNow Autonomous, or 0 to disable it * ```aopOrbMaxErr``` is used to set the 'lifetime' of the AssistNow data. It is recommended to set aopOrbMaxErr to 0 (the default value). This instructs the module to use the firmware default value that corresponds to a default orbit data validity of approximately three days (for GPS satellites observed once) and up to six days (for GPS and GLONASS satellites observed multiple times over a period of at least half a day). -Once AssistNow Autonomous is enabled, you can monitor its progress via the ```status``` field in the UBX-NAV-AOPSTATUS message. You can read the ```status``` by calling ```getAOPSTATUSstatus```. It will return zero when the AssistNow Autonomous data collection is complete. Non-zero values indicate that data collection is still in progress. +Once AssistNow Autonomous is enabled, you can monitor its progress via the ```status``` field in the UBX-NAV-AOPSTATUS message. You can read the ```status``` by calling the helper function ```getAOPSTATUSstatus```. It will return zero when the AssistNow Autonomous data collection is idle. Non-zero values indicate that data collection is in progress. * uint8_t getAOPSTATUSstatus(uint16_t maxWait); * uint8_t getAOPSTATUSuseAOP(uint16_t maxWait); From ef5abaccbd86fff208cc0d055d1fc33271878653 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 1 Dec 2021 12:16:31 +0000 Subject: [PATCH 017/122] Add auto support for NAV SAT. Add NAV SAT callback example. Add final AssistNow Autonomous examples. --- .../Example1_AssistNowAutonomous.ino | 187 ++++++++++++++ ...ple2_AssistNowAutonomous_DatabaseRead.ino} | 113 ++++++--- ...ple3_AssistNowAutonomous_DatabaseWrite.ino | 187 ++++++++++++++ .../database.h | 177 +++++++++++++ .../secrets.h | 6 + examples/AssistNow/README.md | 17 +- .../CallbackExample7_NAV_SAT.ino | 121 +++++++++ keywords.txt | 25 +- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 237 +++++++++++++++++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 15 +- src/u-blox_structs.h | 73 ++++++ 11 files changed, 1112 insertions(+), 46 deletions(-) create mode 100644 examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino rename examples/AssistNow/AssistNow_Autonomous/{Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino => Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino} (52%) create mode 100644 examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino create mode 100644 examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/database.h create mode 100644 examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/secrets.h create mode 100644 examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino diff --git a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino new file mode 100644 index 0000000..2c785c9 --- /dev/null +++ b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino @@ -0,0 +1,187 @@ +/* + Monitor AssistNow Autonomous data collection + By: SparkFun Electronics / Paul Clark + Date: November 29th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to enable and monitor AssistNow Autonomous data collection by the module. + A callback is used to monitor AssistNow Autonomous data availability for each satellite. + A second callback is used to print the AOPSTATUS status. + + If your GNSS board has battery-backup for the RAM - and all SparkFun boards do! - then you can: + wait until the module has AssistNow Autonomous data for a few satellites; + power-cycle the board; + watch how fast it gets its first fix! + + Note: this example will only work on boards which have plenty of RAM available. + The UBX-NAV-SAT information occupies several kBytes. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: printSATdata will be called when new NAV SAT data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_SAT_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSATcallback +// / _____ This _must_ be UBX_NAV_SAT_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printSATdata(UBX_NAV_SAT_data_t ubxDataStruct) +{ + //Serial.println(); + + Serial.print(F("UBX-NAV-SAT contains data for ")); + Serial.print(ubxDataStruct.header.numSvs); + if (ubxDataStruct.header.numSvs == 1) + Serial.println(F(" SV")); + else + Serial.println(F(" SVs")); + + uint16_t numAopAvail = 0; // Count how many SVs have AssistNow Autonomous data available + + for (uint16_t block = 0; block < ubxDataStruct.header.numSvs; block++) // For each SV + { + if (ubxDataStruct.blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set + numAopAvail++; // Increment the number of SVs + } + + Serial.print(F("AssistNow Autonomous data is available for ")); + Serial.print(numAopAvail); + if (numAopAvail == 1) + Serial.println(F(" SV")); + else + Serial.println(F(" SVs")); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: printAOPstatus will be called when new NAV AOPSTATUS data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_AOPSTATUS_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVAOPSTATUScallback +// / _____ This _must_ be UBX_NAV_AOPSTATUS_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printAOPstatus(UBX_NAV_AOPSTATUS_data_t ubxDataStruct) +{ + //Serial.println(); + + Serial.print(F("AOPSTATUS status is ")); + Serial.println(ubxDataStruct.status); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: printPVTdata will be called when new NAV PVT data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallback +// / _____ This _must_ be UBX_NAV_PVT_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) +{ + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + + Serial.println(); + + long latitude = ubxDataStruct.lat; // Print the latitude + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = ubxDataStruct.lon; // Print the longitude + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = ubxDataStruct.hMSL; // Print the height above mean sea level + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte fixType = ubxDataStruct.fixType; // Print the fix type + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + + Wire.begin(); //Start I2C + + //myGNSS.enableDebugging(Serial, true); // Uncomment this line to see the 'major' debug messages on Serial + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Enable AssistNow Autonomous data collection. + + if (myGNSS.setAopCfg(1) == true) + { + Serial.println(F("aopCfg enabled")); + } + else + { + Serial.println(F("Could not enable aopCfg. Please check wiring. Freezing.")); + while (1); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Enable automatic UBX-NAV-SAT and UBX-NAV-AOPSTATUS messages and set up the callbacks + + myGNSS.setNavigationFrequency(1); //Produce one solution per second + + myGNSS.setAutoNAVSATcallback(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata + myGNSS.setAutoAOPSTATUScallback(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus + myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + myGNSS.checkUblox(); // Check for the arrival of new data and process it. + myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. + + Serial.print("."); + delay(50); +} diff --git a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino b/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino similarity index 52% rename from examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino rename to examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino index 024ceb4..899b82e 100644 --- a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous_Read/Example1_AssistNowAutonomous_Read.ino +++ b/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino @@ -1,5 +1,5 @@ /* - Read the AssistNow Autonomous data from the module + Read the AssistNow Autonomous database from the module By: SparkFun Electronics / Paul Clark Date: November 29th, 2021 License: MIT. See license file for more information but you can @@ -8,8 +8,7 @@ This example shows how to enable, check the status of, and read the AssistNow Autonomous data from the module. Note: this example will only work on boards which have plenty of RAM available. - The database can be several kBytes in length and needs to be stored twice: - once inside the library (by readNavigationDatabase); and again in this example code. + The database can be several kBytes in length. Feel like supporting open source hardware? Buy a board from SparkFun! @@ -28,6 +27,59 @@ SFE_UBLOX_GNSS myGNSS; //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// Callback: printSATdata will be called when new NAV SAT data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_SAT_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSATcallback +// / _____ This _must_ be UBX_NAV_SAT_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printSATdata(UBX_NAV_SAT_data_t ubxDataStruct) +{ + Serial.println(); + + Serial.print(F("UBX-NAV-SAT contains data for ")); + Serial.print(ubxDataStruct.header.numSvs); + if (ubxDataStruct.header.numSvs == 1) + Serial.println(F(" SV")); + else + Serial.println(F(" SVs")); + + uint16_t numAopAvail = 0; // Count how many SVs have AssistNow Autonomous data available + + for (uint16_t block = 0; block < ubxDataStruct.header.numSvs; block++) // For each SV + { + if (ubxDataStruct.blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set + numAopAvail++; // Increment the number of SVs + } + + Serial.print(F("AssistNow Autonomous data is available for ")); + Serial.print(numAopAvail); + if (numAopAvail == 1) + Serial.println(F(" SV")); + else + Serial.println(F(" SVs")); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: printAOPstatus will be called when new NAV AOPSTATUS data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_AOPSTATUS_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVAOPSTATUScallback +// / _____ This _must_ be UBX_NAV_AOPSTATUS_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printAOPstatus(UBX_NAV_AOPSTATUS_data_t ubxDataStruct) +{ + //Serial.println(); + + Serial.print(F("AOPSTATUS status is ")); + Serial.println(ubxDataStruct.status); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + void setup() { delay(1000); @@ -69,39 +121,40 @@ void setup() } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // Keep calling getAOPSTATUSstatus until it returns zero (indicating AssistNow Autonomous data collection is complete) - // or the user presses a key + // Enable automatic UBX-NAV-SAT and UBX-NAV-AOPSTATUS messages and set up the callbacks + + myGNSS.setNavigationFrequency(1); //Produce one solution per second + + myGNSS.setAutoNAVSATcallback(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata + myGNSS.setAutoAOPSTATUScallback(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Keep displaying NAV SAT and AOPSTATUS until the user presses a key - Serial.println(F("AssistNow Autonomous data collection is in progress. Press any key to quit.")); - Serial.println(F("NAV AOPSTATUS status indicates when the AssistNow Autonomous subsystem is idle (0) or running (not 0).")); + Serial.println(F("AssistNow Autonomous data collection is in progress. Press any key to quit and read the database.")); - bool keepGoing = true; - int zerosSeen = 0; // Keep track of how many times aopStatus has been zero while (Serial.available()) Serial.read(); // Empty the serial buffer - while (keepGoing && !Serial.available()) // Wait for keepGoing to go false, or for the arrival of a keypress + while (!Serial.available()) // Wait for the arrival of a keypress { - delay(1000); - uint8_t aopStatus = myGNSS.getAOPSTATUSstatus(); - Serial.print(F("NAV AOPSTATUS status is: ")); - Serial.println(aopStatus); - if (aopStatus == 0) // aopStatus will be zero when the AssistNow Autonomous subsystem is idle - i.e. data collection is complete - { - zerosSeen++; // Keep track of how long aopStatus has been zero - if (zerosSeen >= 30) - keepGoing = false; // Stop after seeing 30 consecutive zeros - } - else - { - zerosSeen = 0; // Reset the number of zeros seen - } + myGNSS.checkUblox(); // Check for the arrival of new data and process it. + myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. + + Serial.print("."); + delay(50); } - if (!keepGoing) - Serial.println(F("AssistNow Autonomous data collection is complete!")); + Serial.println(); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Disable the automatic UBX-NAV-SAT and UBX-NAV-AOPSTATUS messages + + myGNSS.setAutoNAVSAT(false); + myGNSS.setAutoAOPSTATUS(false); + delay(1100); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // Read the AssistNow Autonomous data from the module and pretty-print it (so it can be copied and pasted into Example2) + // Read the AssistNow Autonomous database from the module and pretty-print it (so it can be copied and pasted into the next example) #define MAX_DATABASE_LENGTH 32768 // Allocate 32kBytes to store the navigation database size_t maxDatabaseLen = MAX_DATABASE_LENGTH; @@ -117,8 +170,8 @@ void setup() if (actualDatabaseLen == maxDatabaseLen) Serial.println(F("There was not enough memory to store the entire database. Some data will have been lost!")); - // Pretty-print the database so it can be copied into Example2 - Serial.println(F("Copy and paste the following into Example2, so you can write it back to the module:")); + // Pretty-print the database so it can be copied into the next example + Serial.println(F("Copy and paste the following into the next example, so you can write it back to the module:")); Serial.println(); Serial.print(F("size_t databaseLen = ")); Serial.print(actualDatabaseLen); @@ -150,4 +203,4 @@ void setup() void loop() { // Nothing to do here -} \ No newline at end of file +} diff --git a/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino new file mode 100644 index 0000000..c22d531 --- /dev/null +++ b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino @@ -0,0 +1,187 @@ +/* + Write the AssistNow Autonomous database data to the module + By: SparkFun Electronics / Paul Clark + Date: December 1st, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to write the AssistNow Autonomous database date back to the module. + + This example is written for the ESP32. A WiFi connection is used to get network time to pass to the module. + (You could use an RTC instead.) + + Copy and paste the database data from the previous example into database.h. + + Update secrets.h with your: + - WiFi credentials + + Note: this example works best if you have the GNSS RAM battery-backup disabled. + All SparkFun boards have battery-backup for the RAM which will means the database is retained if you disconnect the power. + The module will use the database data from the battery-backed RAM when you turn the power back on. + You will only see the improvement in the time-to-first-fix if you disable the battery first - or you are using a non-SparkFun + board that does not have the backup battery. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 "database.h" // <- Copy and paste the database data from the previous example into database.h + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include "secrets.h" + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "time.h" + +const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + + Wire.begin(); //Start I2C + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + + //myGNSS.enableDebugging(Serial, true); // Uncomment this line to see helpful debug messages on Serial + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to WiFi. + + Serial.print(F("Connecting to local WiFi")); + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.println(F("WiFi connected!")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Set the RTC using network time. (Code taken from the SimpleTime example.) + + // Request the time from the NTP server and use it to set the ESP32's RTC. + configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time. + + struct tm timeinfo; + if(!getLocalTime(&timeinfo)) + { + Serial.println("Failed to obtain time"); + } + else + { + Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the RTC time to the module + + // Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent + //myGNSS.enableDebugging(Serial, true); + + if(getLocalTime(&timeinfo)) + { + // setUTCTimeAssistance uses a default time accuracy of 2 seconds which should be OK here. + // Have a look at the library source code for more details. + myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + } + else + { + Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly."); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the AssistNow Autonomous data to the module + + size_t bytesPushed = myGNSS.pushAssistNowData(database, databaseLen); + + Serial.print(F("Pushed ")); + Serial.print(bytesPushed); + Serial.println(F(" bytes of AssistNow Autonomous data to the module")); + + if (bytesPushed != databaseLen) + Serial.println(F("Warning: bytesPushed does not match databaseLen! Maybe the database contains bad data? Or there was a communication error?")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Disconnect the WiFi as it's no longer needed + + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + Serial.println(F("WiFi disconnected")); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte SIV = myGNSS.getSIV(); + Serial.print(F(" SIV: ")); + Serial.print(SIV); + + byte fixType = myGNSS.getFixType(); + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); +} diff --git a/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/database.h b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/database.h new file mode 100644 index 0000000..46656b9 --- /dev/null +++ b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/database.h @@ -0,0 +1,177 @@ +// Paste the AssistNow Autonomous database data from the previous example here: + +size_t databaseLen = 5480; +const uint8_t database[5480] = { + 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x02, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x01, 0x08, 0xC4, 0x04, 0x26, 0xFE, 0x02, 0x54, 0xBA, 0xA9, + 0xFF, 0xDA, 0x8C, 0x05, 0xA3, 0xC1, 0xCD, 0x85, 0x86, 0x0A, 0x14, 0x20, 0xAA, 0xE6, 0xB4, 0xD3, 0x4F, 0x27, 0x12, 0xE0, 0xE6, 0xC3, 0xE4, 0x79, 0x0E, 0xA1, 0xD3, 0x49, 0xF4, 0xFF, 0xAF, 0xF7, + 0x67, 0x2E, 0x93, 0xF9, 0x6A, 0x1B, 0x2D, 0x10, 0xD3, 0x49, 0xBD, 0xFF, 0x26, 0x01, 0x00, 0x1E, 0x81, 0x22, 0xA1, 0xE4, 0x2A, 0x00, 0x10, 0x50, 0x04, 0x00, 0xB7, 0xBF, 0xB5, 0x62, 0x13, 0x80, + 0x54, 0x00, 0x01, 0x00, 0x00, 0x05, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x04, 0x1E, 0xC4, 0x44, 0x72, 0x2F, 0x02, 0x71, 0xAD, 0xA4, 0xFF, 0xE8, 0xAE, 0xFA, + 0x42, 0x25, 0xD1, 0x0F, 0x0D, 0x03, 0xCB, 0x71, 0xCF, 0x12, 0x6F, 0x89, 0x0F, 0x27, 0xF3, 0x49, 0x7B, 0x29, 0x4B, 0xF1, 0x0C, 0xA1, 0xD4, 0x49, 0xF5, 0xFF, 0xB6, 0x03, 0x98, 0x36, 0xA0, 0x03, + 0xBB, 0x0F, 0x72, 0x1D, 0xD4, 0x49, 0xEE, 0xFF, 0x17, 0x00, 0x00, 0xC0, 0x85, 0x22, 0x2F, 0xF0, 0x3D, 0x00, 0x3C, 0x50, 0x04, 0x00, 0x1A, 0x35, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, + 0x00, 0x07, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x06, 0x5B, 0xC4, 0x44, 0xD8, 0xEC, 0x02, 0x4E, 0x79, 0xAC, 0xFF, 0xE8, 0x8A, 0x1D, 0xBC, 0x9F, 0xE8, 0x86, + 0xD9, 0x07, 0x45, 0xD0, 0x05, 0x6A, 0x05, 0x06, 0xC3, 0x26, 0xB5, 0x7D, 0x4A, 0xA2, 0x86, 0xCA, 0x0D, 0xA1, 0xD4, 0x49, 0x2B, 0x00, 0x62, 0x07, 0x63, 0x2F, 0xF5, 0x05, 0x1E, 0x1A, 0x98, 0x10, + 0xD4, 0x49, 0x38, 0x00, 0xBA, 0xFF, 0x00, 0xCB, 0xBE, 0x22, 0xF4, 0x59, 0x09, 0x00, 0xB6, 0x50, 0x04, 0x00, 0x2E, 0x9B, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x09, 0x15, 0x0C, + 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x08, 0x5E, 0xC4, 0x44, 0xFA, 0x7B, 0x02, 0x4E, 0x1B, 0xA5, 0xFF, 0x03, 0x6E, 0x07, 0xF5, 0x25, 0xF3, 0xB8, 0x36, 0x01, 0xDB, 0x4F, + 0x56, 0x3E, 0x8D, 0xA6, 0xD7, 0x26, 0x82, 0xFE, 0xA8, 0x4A, 0x7A, 0x44, 0x0D, 0xA1, 0xD4, 0x49, 0x05, 0x00, 0x7A, 0xFA, 0x1C, 0x37, 0xDC, 0xFA, 0x33, 0x0E, 0x7E, 0x1E, 0xD4, 0x49, 0xE5, 0xFF, + 0xFC, 0xFF, 0x00, 0xB7, 0xBA, 0x22, 0x87, 0x2A, 0x34, 0x00, 0xBC, 0x50, 0x04, 0x00, 0xDF, 0x11, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x0B, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, + 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0A, 0x2F, 0xC4, 0x44, 0xC7, 0x68, 0x00, 0xF6, 0x09, 0xAA, 0xFF, 0xED, 0xB8, 0x38, 0x24, 0x1C, 0xE8, 0xC5, 0x30, 0x00, 0xD0, 0x23, 0x17, 0xEC, 0xF7, 0x92, + 0x2D, 0x27, 0x7C, 0x39, 0x2C, 0x6B, 0x66, 0xF5, 0x0D, 0xA1, 0xD4, 0x49, 0xEA, 0xFF, 0x27, 0xF9, 0x09, 0x2F, 0x2B, 0xFA, 0x6A, 0x1B, 0xFB, 0x0F, 0xD4, 0x49, 0x01, 0x00, 0x0F, 0x00, 0x00, 0xC1, + 0x82, 0x22, 0x2A, 0x8A, 0x80, 0xFF, 0x5E, 0x50, 0x04, 0x00, 0x52, 0xBB, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x0D, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0x0C, 0x96, 0xC4, 0x44, 0x8E, 0xBD, 0x02, 0xE4, 0x39, 0xA6, 0xFF, 0xE8, 0x7E, 0xBE, 0x5F, 0xFE, 0xF3, 0xCA, 0xF0, 0x02, 0x5D, 0x9F, 0x84, 0x44, 0x3A, 0xC9, 0x6F, 0x27, 0xFD, 0x1B, + 0xDB, 0x27, 0x60, 0x63, 0x0D, 0xA1, 0xD4, 0x49, 0x32, 0x00, 0x4B, 0xFA, 0xA6, 0x33, 0x2C, 0xFB, 0x5C, 0x10, 0xB8, 0x1C, 0xD4, 0x49, 0x0E, 0x00, 0x1E, 0x00, 0x00, 0x0D, 0xB9, 0x22, 0x3A, 0x4D, + 0x07, 0x00, 0x2C, 0x51, 0x04, 0x00, 0x76, 0x2E, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x10, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0F, 0x22, + 0xC4, 0x44, 0x47, 0xD2, 0x02, 0x47, 0xEA, 0xA3, 0xFF, 0xEA, 0x53, 0xBB, 0xBD, 0x37, 0xBE, 0x0A, 0x5B, 0x06, 0x85, 0x4F, 0x13, 0x98, 0x48, 0x33, 0x95, 0x27, 0xC8, 0x3B, 0xE7, 0x1B, 0x37, 0x8F, + 0x0C, 0xA1, 0xD4, 0x49, 0xC9, 0xFF, 0x09, 0x0C, 0x98, 0x30, 0xB3, 0x0A, 0x16, 0x09, 0x14, 0x26, 0xD4, 0x49, 0xB3, 0xFF, 0x4E, 0x00, 0x00, 0xE0, 0x81, 0x22, 0x2D, 0xCD, 0x31, 0x00, 0x44, 0x50, + 0x04, 0x00, 0x39, 0x9B, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x14, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x13, 0x1B, 0xC4, 0x44, 0x6A, 0xD2, + 0x02, 0xE9, 0x7C, 0xA3, 0xFF, 0xEE, 0xD1, 0x59, 0xEE, 0xE7, 0x56, 0x56, 0xCC, 0x02, 0xE4, 0x2C, 0x39, 0x0E, 0xB6, 0x13, 0x56, 0x26, 0xDF, 0xE5, 0x41, 0x7C, 0xDA, 0x86, 0x0D, 0xA1, 0xD4, 0x49, + 0xFE, 0xFF, 0x81, 0x04, 0x73, 0x3A, 0x0F, 0x04, 0x54, 0x10, 0x59, 0x1B, 0xD4, 0x49, 0x37, 0x00, 0xDF, 0xFF, 0x00, 0x21, 0x87, 0x22, 0x0B, 0xF8, 0x10, 0x00, 0x36, 0x50, 0x04, 0x00, 0x75, 0x76, + 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x1D, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1C, 0x31, 0xC4, 0xC4, 0x58, 0xF9, 0x02, 0xFC, 0xD0, 0xA5, + 0xFF, 0xEA, 0x04, 0x79, 0x3B, 0x17, 0xD6, 0x48, 0xEF, 0x00, 0xB9, 0x34, 0x1C, 0xC2, 0x1E, 0x93, 0x05, 0x28, 0xA0, 0x7E, 0x9D, 0x60, 0x7C, 0x63, 0x0C, 0xA1, 0xD4, 0x49, 0xD2, 0xFF, 0x51, 0xF4, + 0xD6, 0x2D, 0xD9, 0xF5, 0x45, 0x08, 0x41, 0x27, 0xD4, 0x49, 0x23, 0x00, 0xFE, 0xFF, 0x00, 0x7C, 0xBC, 0x22, 0x15, 0x51, 0x31, 0x00, 0x62, 0x50, 0x04, 0x00, 0xEC, 0xE1, 0xB5, 0x62, 0x13, 0x80, + 0x54, 0x00, 0x01, 0x00, 0x00, 0x1E, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1D, 0x22, 0xC4, 0x04, 0x53, 0x24, 0x02, 0xF4, 0x99, 0xA8, 0xFF, 0x08, 0x62, 0xE5, + 0x6F, 0x9E, 0x9C, 0x48, 0xBC, 0x02, 0xB4, 0x07, 0x9B, 0x6A, 0x21, 0x82, 0x28, 0x26, 0x78, 0x77, 0x0C, 0x90, 0x2F, 0xF9, 0x0C, 0xA1, 0xD4, 0x49, 0xE5, 0xFF, 0x34, 0x08, 0x30, 0x33, 0xC0, 0x06, + 0x34, 0x1B, 0x7C, 0x0E, 0xD4, 0x49, 0xF7, 0xFF, 0xEE, 0xFF, 0x00, 0x19, 0xBE, 0x22, 0x6F, 0xC0, 0x2F, 0x00, 0x44, 0x50, 0x04, 0x00, 0x93, 0x6D, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00, + 0x06, 0x07, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xA5, 0xB9, 0xC6, 0x04, 0x16, 0x44, 0x02, 0xC6, 0xE0, 0xD9, 0x21, 0x1C, 0xC0, 0xE0, 0xF8, 0xD5, 0x3D, 0x6E, + 0x01, 0x56, 0x21, 0xC1, 0x0F, 0x39, 0xF8, 0x70, 0x2D, 0x10, 0x7F, 0xFF, 0x10, 0x38, 0xEE, 0xA5, 0x80, 0x00, 0x00, 0xE8, 0x55, 0x0C, 0x1C, 0xEB, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00, + 0x06, 0x0F, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xAD, 0xB9, 0xC6, 0x04, 0x6F, 0x28, 0x02, 0x17, 0x5C, 0xB7, 0xE5, 0xF7, 0x80, 0x1F, 0x46, 0x2A, 0xDE, 0xBE, + 0xF0, 0x59, 0x45, 0x5C, 0xCE, 0x39, 0x75, 0x99, 0xF7, 0x10, 0x1B, 0x7B, 0xFF, 0x78, 0x18, 0x5D, 0xFE, 0x00, 0x00, 0xE8, 0x55, 0x07, 0xC8, 0x8F, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00, + 0x06, 0x10, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xAE, 0xB9, 0xC6, 0x84, 0x26, 0x63, 0x02, 0x0C, 0x60, 0x9D, 0xDA, 0x44, 0x5E, 0xE2, 0x3C, 0x27, 0xDD, 0xED, + 0xF5, 0x3B, 0xDE, 0xC1, 0xDE, 0x39, 0xA7, 0xDD, 0xF9, 0x20, 0x11, 0x54, 0x2A, 0x80, 0xFB, 0x6C, 0x80, 0x00, 0xFF, 0xEF, 0x55, 0x06, 0x17, 0x43, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00, + 0x06, 0x15, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xB3, 0xB9, 0xC6, 0x04, 0x6F, 0xC3, 0x02, 0xF0, 0xC6, 0x33, 0xC1, 0x45, 0x3F, 0x28, 0xC9, 0xBB, 0xBF, 0x1B, + 0x1B, 0xEC, 0x14, 0xF1, 0xF5, 0x39, 0x55, 0x25, 0x06, 0x30, 0x84, 0xAE, 0xC7, 0xA8, 0x89, 0x3D, 0x44, 0x00, 0xFD, 0xEF, 0x55, 0x0B, 0x89, 0xE0, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00, + 0x06, 0x17, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xB5, 0xB9, 0xC6, 0x04, 0x34, 0xBC, 0x02, 0xF5, 0xBE, 0x0D, 0x15, 0xEA, 0x21, 0xA3, 0xC8, 0xDB, 0x1E, 0x3A, + 0x31, 0x5A, 0x38, 0xB6, 0x20, 0x39, 0x8B, 0x4A, 0xD9, 0x30, 0xDF, 0x66, 0xF8, 0xB8, 0x9D, 0x5B, 0x00, 0x02, 0xFF, 0xEF, 0x55, 0x0A, 0x20, 0x5A, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, + 0x00, 0x01, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x00, 0x7B, 0xB0, 0x04, 0xC5, 0xE4, 0x01, 0x73, 0x47, 0x5B, 0xAE, 0x1C, 0x18, 0x0D, 0xA1, 0x00, 0x65, 0xFD, + 0x00, 0x7B, 0x41, 0x2C, 0xEA, 0x00, 0x14, 0x16, 0x24, 0x00, 0xF1, 0x02, 0x67, 0x00, 0x06, 0xEA, 0x3F, 0x8A, 0xA4, 0x7B, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x02, 0x15, 0x0C, + 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x01, 0x7B, 0xB0, 0x44, 0x66, 0x1F, 0x03, 0xC2, 0x82, 0xA8, 0x90, 0x0E, 0x1C, 0x0E, 0xA1, 0x00, 0x4E, 0xFD, 0x00, 0x7B, 0x4F, 0x99, + 0xE6, 0x00, 0xF3, 0xEB, 0xC3, 0x00, 0xE8, 0x8A, 0x6E, 0x00, 0x5C, 0x05, 0x00, 0x8A, 0xDF, 0xF9, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x03, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, + 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x02, 0x7B, 0xB0, 0x04, 0x96, 0x8D, 0x01, 0xEB, 0x94, 0x1F, 0x20, 0x13, 0x6B, 0x0D, 0xA1, 0x00, 0x69, 0xFD, 0x00, 0x7B, 0xC1, 0x59, 0x14, 0x00, 0x8A, 0xAC, + 0x28, 0x00, 0xDD, 0x24, 0x37, 0x00, 0xE0, 0xEF, 0x3F, 0x8A, 0x0F, 0xED, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x04, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0x03, 0x7B, 0xB0, 0x44, 0x8F, 0x51, 0x01, 0xFF, 0xCA, 0x0C, 0xA8, 0x0B, 0xD6, 0x0C, 0xA1, 0x00, 0x44, 0xFD, 0x00, 0x7B, 0x3F, 0x67, 0x40, 0x00, 0x77, 0x26, 0x80, 0x00, 0x3A, 0x7C, + 0xB2, 0x00, 0x2E, 0x07, 0x00, 0x8A, 0xD8, 0xB6, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x05, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x04, 0x00, + 0xB0, 0x14, 0xB8, 0x76, 0x03, 0xEA, 0xD0, 0x30, 0x92, 0x0A, 0xF1, 0x0C, 0xA1, 0x00, 0x25, 0xFD, 0xD4, 0x49, 0x71, 0xCF, 0x12, 0x00, 0x49, 0x7B, 0x29, 0x00, 0xFA, 0x42, 0x25, 0x00, 0xBE, 0xFF, + 0x3F, 0x8A, 0xD6, 0xA9, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x06, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x05, 0x7B, 0xB0, 0x44, 0xBB, 0x76, + 0x01, 0x15, 0x1F, 0x14, 0x47, 0x1C, 0xB5, 0x0C, 0xA1, 0x00, 0x63, 0xFD, 0x00, 0x7B, 0x16, 0xD6, 0xE9, 0x00, 0xEC, 0xC2, 0xD5, 0x00, 0xAB, 0x35, 0x77, 0x00, 0x8C, 0x18, 0x80, 0x8A, 0x81, 0xB1, + 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x07, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x06, 0x00, 0xB0, 0x14, 0x33, 0xF6, 0x03, 0x49, 0x98, 0x7D, + 0xC9, 0x05, 0xCA, 0x0D, 0xA1, 0x00, 0x63, 0xFD, 0xD4, 0x49, 0xD0, 0x05, 0x6A, 0x00, 0x7D, 0x4A, 0xA2, 0x00, 0x1D, 0xBC, 0x9F, 0x00, 0x2B, 0x09, 0x00, 0x8A, 0x4B, 0xEC, 0xB5, 0x62, 0x13, 0x80, + 0x34, 0x00, 0x02, 0x00, 0x00, 0x08, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x07, 0x7B, 0xB0, 0x04, 0x04, 0xE8, 0x01, 0xB3, 0x40, 0x38, 0xDD, 0x0E, 0x13, 0x0D, + 0xA1, 0x00, 0x22, 0xFD, 0x00, 0x7B, 0x33, 0x39, 0xBE, 0x00, 0x60, 0x6D, 0x02, 0x00, 0xAF, 0xE0, 0xC5, 0x00, 0xCF, 0x07, 0x80, 0x8A, 0x59, 0x50, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, + 0x00, 0x09, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x08, 0x00, 0xB0, 0x14, 0x50, 0xB2, 0x03, 0x0A, 0x6B, 0x13, 0x14, 0x07, 0x44, 0x0D, 0xA1, 0x00, 0x28, 0xFD, + 0xD4, 0x49, 0x4F, 0x56, 0x3E, 0x00, 0xFE, 0xA8, 0x4A, 0x00, 0x07, 0xF5, 0x25, 0x00, 0x85, 0x06, 0x00, 0x8A, 0x09, 0xB0, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0A, 0x15, 0x0C, + 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x09, 0x7B, 0xB0, 0x44, 0x94, 0x64, 0x01, 0x0C, 0xB3, 0x3B, 0x06, 0x13, 0x0D, 0x0D, 0xA1, 0x00, 0x6E, 0xFD, 0x00, 0x7B, 0x68, 0x3C, + 0x14, 0x00, 0x15, 0x6E, 0x97, 0x00, 0x53, 0x99, 0x16, 0x00, 0xEF, 0xF6, 0xBF, 0x8A, 0xC1, 0xA9, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0B, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, + 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0A, 0x7B, 0xB0, 0x04, 0xF5, 0x0B, 0x01, 0xDE, 0x10, 0x03, 0x70, 0x0C, 0x97, 0x0D, 0xA1, 0xFF, 0x52, 0xFD, 0x00, 0x7B, 0x7A, 0x06, 0xEC, 0x00, 0xA3, 0x44, + 0x6B, 0x00, 0xA1, 0xEB, 0xC8, 0x00, 0x11, 0xF8, 0xBF, 0x8A, 0xB4, 0x35, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0x0B, 0x7B, 0xB0, 0x04, 0xFD, 0x31, 0x01, 0x09, 0xE0, 0x44, 0xFA, 0x12, 0xD4, 0x0C, 0xA1, 0x00, 0x54, 0xFD, 0x00, 0x7B, 0xBC, 0x3F, 0x97, 0x00, 0x0C, 0x17, 0x32, 0x00, 0x5D, 0xE0, + 0x30, 0x00, 0x72, 0xF7, 0xBF, 0x8A, 0x91, 0x2E, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0D, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0C, 0x00, + 0xB0, 0x14, 0x82, 0xD3, 0x03, 0x6F, 0x0C, 0x2F, 0x96, 0x10, 0x63, 0x0D, 0xA1, 0x00, 0x31, 0xFD, 0xD4, 0x49, 0x9F, 0x84, 0x44, 0x00, 0x1B, 0xDB, 0x27, 0x00, 0xBE, 0x5F, 0xFE, 0x00, 0xE9, 0x08, + 0x00, 0x8A, 0x4A, 0x74, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0E, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0D, 0x7B, 0xB0, 0x44, 0x3E, 0xB1, + 0x01, 0x66, 0xD7, 0x09, 0x30, 0x08, 0xCD, 0x0C, 0xA1, 0x00, 0x4A, 0xFD, 0x00, 0x7B, 0x72, 0x05, 0x96, 0x00, 0x85, 0x34, 0x7E, 0x00, 0xFE, 0xFB, 0x2F, 0x00, 0xCC, 0xF7, 0xBF, 0x8A, 0x3C, 0x14, + 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0F, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0E, 0x7B, 0xB0, 0x44, 0x92, 0xB0, 0x01, 0xBF, 0xF2, 0x71, + 0x4F, 0xF7, 0x0E, 0x0D, 0xA1, 0x00, 0x26, 0xFD, 0x00, 0x7B, 0x66, 0x06, 0x3A, 0x00, 0xAE, 0x39, 0x2B, 0x00, 0xEF, 0x2D, 0x9C, 0x00, 0x95, 0x0F, 0x80, 0x8A, 0x3F, 0x35, 0xB5, 0x62, 0x13, 0x80, + 0x34, 0x00, 0x02, 0x00, 0x00, 0x10, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0F, 0x00, 0xB0, 0x14, 0x96, 0x34, 0x03, 0x8E, 0xB0, 0x65, 0xEC, 0x12, 0x8F, 0x0C, + 0xA1, 0x00, 0x1F, 0xFD, 0xD4, 0x49, 0x4F, 0x13, 0x98, 0x00, 0x3B, 0xE7, 0x1B, 0x00, 0xBB, 0xBD, 0x37, 0x00, 0x39, 0xF6, 0x3F, 0x8A, 0xF3, 0x43, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, + 0x00, 0x11, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x10, 0x7B, 0xB0, 0x04, 0x5E, 0xE6, 0x01, 0xF3, 0xDF, 0x70, 0xA4, 0x18, 0x50, 0x0D, 0xA1, 0x00, 0x34, 0xFD, + 0x00, 0x7B, 0x86, 0x84, 0xC1, 0x00, 0x0F, 0xBA, 0xC1, 0x00, 0xF9, 0x59, 0xC2, 0x00, 0x39, 0x0A, 0x80, 0x8A, 0x83, 0x21, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x12, 0x15, 0x0C, + 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x11, 0x7B, 0xB0, 0x04, 0x92, 0xB3, 0x01, 0xCD, 0x23, 0x11, 0x1A, 0x12, 0xC7, 0x0C, 0xA1, 0x00, 0x57, 0xFD, 0x00, 0x7B, 0x1B, 0x89, + 0xEA, 0x00, 0x3E, 0x35, 0x7D, 0x00, 0x7D, 0xB8, 0x6F, 0x00, 0x2B, 0xF1, 0xBF, 0x8A, 0x1F, 0x89, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x13, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, + 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x12, 0x7B, 0xB0, 0x44, 0xDE, 0x29, 0x01, 0x15, 0x35, 0x49, 0xCA, 0x17, 0xF3, 0x0C, 0xA1, 0x00, 0x30, 0xFD, 0x00, 0x7B, 0xBE, 0x59, 0xC3, 0x00, 0xEA, 0xA7, + 0x50, 0x00, 0xBF, 0x3E, 0x23, 0x00, 0x5C, 0x08, 0x80, 0x8A, 0x31, 0x50, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x14, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0x13, 0x00, 0xB0, 0x14, 0x3E, 0x72, 0x03, 0xA1, 0xC5, 0x2C, 0xFA, 0xFE, 0x86, 0x0D, 0xA1, 0x00, 0x1B, 0xFD, 0xD4, 0x49, 0x2C, 0x39, 0x0E, 0x00, 0xE5, 0x41, 0x7C, 0x00, 0x59, 0xEE, + 0xE7, 0x00, 0x1F, 0xFA, 0x3F, 0x8A, 0x05, 0x19, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x15, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x14, 0x7B, + 0xB0, 0x44, 0x9E, 0xFA, 0x01, 0xD6, 0x02, 0xC7, 0xCD, 0x0A, 0x8B, 0x0C, 0xA1, 0x00, 0x4C, 0xFD, 0x00, 0x7B, 0x38, 0x8D, 0xE6, 0x00, 0x0D, 0x36, 0xD5, 0x00, 0xBA, 0x5E, 0xC7, 0x00, 0xA0, 0x00, + 0x80, 0x8A, 0x7F, 0x6E, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x16, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x15, 0x7B, 0xB0, 0x44, 0x9E, 0x17, + 0x01, 0x24, 0x81, 0x37, 0xE8, 0xFC, 0xEA, 0x0C, 0xA1, 0x00, 0x4C, 0xFD, 0x00, 0x7B, 0xDE, 0x06, 0x10, 0x00, 0xD1, 0x69, 0xDC, 0x00, 0xC5, 0x18, 0x94, 0x00, 0x28, 0x16, 0x80, 0x8A, 0xBE, 0x20, + 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x17, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x16, 0x7B, 0xB0, 0x44, 0x2E, 0xDB, 0x01, 0x43, 0xB7, 0x0F, + 0xCC, 0x0F, 0x25, 0x0D, 0xA1, 0x00, 0x68, 0xFD, 0x00, 0x7B, 0x32, 0x3D, 0x13, 0x00, 0x85, 0x6C, 0x73, 0x00, 0xE0, 0xD5, 0x4F, 0x00, 0x1B, 0xF8, 0xBF, 0x8A, 0x13, 0xA5, 0xB5, 0x62, 0x13, 0x80, + 0x34, 0x00, 0x02, 0x00, 0x00, 0x18, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x17, 0x7B, 0xB0, 0x04, 0xAC, 0x23, 0x01, 0x3F, 0x2F, 0x63, 0xE2, 0xFA, 0x29, 0x0D, + 0xA1, 0x00, 0x4A, 0xFD, 0x00, 0x7B, 0x90, 0xA3, 0x66, 0x00, 0x3C, 0x04, 0x20, 0x00, 0x7B, 0x4A, 0x74, 0x00, 0x1E, 0x09, 0x80, 0x8A, 0x67, 0xDD, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, + 0x00, 0x19, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x18, 0x7B, 0xB0, 0x04, 0xF3, 0x84, 0x01, 0x2A, 0xEE, 0x52, 0xCB, 0x0A, 0x9F, 0x0D, 0xA1, 0x00, 0x4E, 0xFD, + 0x00, 0x7B, 0xFC, 0x28, 0x94, 0x00, 0x03, 0x3B, 0x27, 0x00, 0x5D, 0xC2, 0x28, 0x00, 0x06, 0x11, 0x00, 0x8A, 0xBF, 0x71, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1A, 0x15, 0x0C, + 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x19, 0x7B, 0xB0, 0x44, 0x12, 0x8B, 0x01, 0xA4, 0xBC, 0x35, 0x56, 0xFE, 0xF0, 0x0C, 0xA1, 0x00, 0x43, 0xFD, 0x00, 0x7B, 0x47, 0x4D, + 0x92, 0x00, 0xCE, 0xEF, 0x0C, 0x00, 0x55, 0x6B, 0x0E, 0x00, 0xA9, 0x08, 0x00, 0x8A, 0x09, 0xC6, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1B, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, + 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1A, 0x7B, 0xB0, 0x44, 0x25, 0xAF, 0x01, 0xD4, 0x10, 0x50, 0x81, 0x14, 0xC4, 0x0C, 0xA1, 0x00, 0x29, 0xFD, 0x00, 0x7B, 0xA9, 0xFD, 0xBE, 0x00, 0x17, 0x91, + 0x19, 0x00, 0x63, 0x98, 0xC1, 0x00, 0x12, 0xFF, 0x3F, 0x8A, 0x9F, 0x4C, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1D, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0x1C, 0x00, 0xB0, 0x14, 0x3D, 0x4B, 0x03, 0x1C, 0xF4, 0x0E, 0xF2, 0x19, 0x63, 0x0C, 0xA1, 0x00, 0x2E, 0xFD, 0xD4, 0x49, 0x34, 0x1C, 0xC2, 0x00, 0x7E, 0x9D, 0x60, 0x00, 0x79, 0x3B, + 0x17, 0x00, 0x2A, 0xF6, 0x3F, 0x8A, 0x99, 0x1E, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1E, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1D, 0x00, + 0xB0, 0x14, 0x9C, 0x70, 0x03, 0x50, 0xC4, 0x2B, 0x21, 0xFC, 0xF9, 0x0C, 0xA1, 0x00, 0x44, 0xFD, 0xD4, 0x49, 0x07, 0x9B, 0x6A, 0x00, 0x77, 0x0C, 0x90, 0x00, 0xE5, 0x6F, 0x9E, 0x00, 0xF8, 0xFD, + 0x3F, 0x8A, 0x8C, 0x9F, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1F, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1E, 0x7B, 0xB0, 0x04, 0x9F, 0xDA, + 0x01, 0x5F, 0x6C, 0x55, 0x80, 0x08, 0xD4, 0x0C, 0xA1, 0x00, 0x5E, 0xFD, 0x00, 0x7B, 0xCB, 0xAE, 0x6A, 0x00, 0x9B, 0x04, 0x0E, 0x00, 0x96, 0x65, 0x3A, 0x00, 0x5F, 0x07, 0x80, 0x8A, 0xAA, 0xFA, + 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x20, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1F, 0x7B, 0xB0, 0x44, 0x7E, 0x41, 0x01, 0x92, 0xEF, 0x2A, + 0x99, 0x09, 0x6C, 0x0D, 0xA1, 0x00, 0x40, 0xFD, 0x00, 0x7B, 0x3C, 0xB6, 0x3E, 0x00, 0x0C, 0xA2, 0x9E, 0x00, 0x27, 0x24, 0xDF, 0x00, 0xE0, 0xFF, 0xBF, 0x8A, 0xEB, 0xFB, 0xB5, 0x62, 0x13, 0x80, + 0x24, 0x00, 0x02, 0x00, 0x01, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x23, 0x00, 0xB0, 0x44, 0x55, 0xF1, 0x01, 0x0A, 0x01, 0xB6, 0x8F, 0x10, 0x40, 0x8D, + 0x04, 0x00, 0x8A, 0x08, 0x0E, 0x00, 0x92, 0x02, 0xB5, 0x62, 0x13, 0x80, 0x24, 0x00, 0x02, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x30, 0x00, + 0xB0, 0x44, 0x66, 0xC5, 0x03, 0x31, 0x1B, 0xBF, 0xC2, 0x02, 0x40, 0x8D, 0x04, 0x00, 0x8A, 0x08, 0x0E, 0x00, 0x02, 0x61, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x01, 0x15, 0x0C, + 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x9F, 0xBD, 0xD2, 0x04, 0x7B, 0x94, 0x00, 0x0C, 0xC5, 0x40, 0x6B, 0x08, 0x38, 0xC3, 0x24, 0xFD, 0xC5, 0xC3, 0xA5, 0x57, 0xE1, 0x21, + 0x3E, 0x01, 0x58, 0x1D, 0x78, 0x3A, 0x38, 0x13, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x02, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA0, 0xBD, + 0xB2, 0x04, 0x91, 0x39, 0x00, 0x56, 0xDD, 0x3F, 0x2B, 0x17, 0x59, 0xC0, 0x82, 0xEF, 0x6C, 0x9A, 0xA8, 0x57, 0x7C, 0x9D, 0x72, 0x07, 0xBA, 0x27, 0x78, 0x3A, 0xB1, 0x11, 0xB5, 0x62, 0x13, 0x80, + 0x2C, 0x00, 0x02, 0x00, 0x06, 0x03, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA1, 0xBD, 0xD2, 0x04, 0xBE, 0x31, 0x00, 0xB5, 0xD6, 0x3F, 0x6B, 0x19, 0x87, 0xDB, + 0x80, 0xFE, 0x42, 0x0C, 0xAB, 0x57, 0xDE, 0xA0, 0x21, 0x07, 0xF9, 0x23, 0x74, 0x3A, 0x7E, 0x46, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x04, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, + 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA2, 0xBD, 0xB2, 0x04, 0x57, 0x31, 0x00, 0x4B, 0xBE, 0x3F, 0xAB, 0x21, 0x5E, 0x0B, 0x3F, 0xFC, 0x75, 0x74, 0xAD, 0x57, 0x5F, 0xB2, 0x07, 0x03, 0x1B, 0x2B, + 0x70, 0x3A, 0xBB, 0x0F, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x05, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA3, 0xBD, 0xD2, 0x04, 0x33, 0x11, + 0x00, 0x49, 0xAC, 0x3F, 0x6B, 0x28, 0xE3, 0x3A, 0x7D, 0xFD, 0x5F, 0xDB, 0xAF, 0x57, 0x9D, 0x88, 0x4D, 0x02, 0x72, 0x2B, 0x6C, 0x3A, 0x3E, 0x71, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, + 0x06, 0x06, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA4, 0xBD, 0xD2, 0x04, 0xEC, 0x1E, 0x00, 0xD0, 0xF5, 0x3F, 0x2B, 0x37, 0x2E, 0xF3, 0xBA, 0x80, 0x9A, 0xA6, + 0xB2, 0x57, 0xF7, 0x5D, 0x55, 0x03, 0xF4, 0x1C, 0x68, 0x3A, 0x19, 0x49, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x07, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0xA5, 0xBD, 0xD2, 0x84, 0xCD, 0x4A, 0x02, 0x75, 0xE1, 0x3F, 0x6B, 0x39, 0x75, 0x51, 0x48, 0x81, 0x45, 0x3F, 0xA1, 0x57, 0x5D, 0xA0, 0x16, 0x06, 0x27, 0x24, 0x84, 0x3A, 0xA8, 0x47, + 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x08, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA6, 0xBD, 0xD2, 0x04, 0x3F, 0xAB, 0x00, 0xC5, 0xCE, 0x3F, + 0xAB, 0x41, 0x2F, 0x8F, 0x06, 0x82, 0x68, 0x8F, 0xA3, 0x57, 0xB1, 0xB2, 0x4E, 0x07, 0x51, 0x24, 0x90, 0x3A, 0x81, 0x71, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x09, 0x15, 0x0C, + 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA7, 0xBD, 0xD2, 0x04, 0xEF, 0x93, 0x00, 0x15, 0x7A, 0x40, 0xAB, 0x4F, 0xD9, 0xD5, 0x4F, 0xFF, 0xD6, 0x42, 0xA5, 0x57, 0xAC, 0x90, + 0x39, 0x06, 0x3F, 0x11, 0x94, 0x3B, 0xA2, 0xFC, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0A, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA8, 0xBD, + 0xD2, 0x84, 0x00, 0xC3, 0x00, 0xBA, 0x16, 0x40, 0x6B, 0x56, 0xF5, 0x1B, 0x8E, 0x82, 0xD8, 0x8B, 0xA7, 0x57, 0x1B, 0x06, 0xE9, 0x06, 0x2D, 0x21, 0x94, 0x3B, 0x71, 0x55, 0xB5, 0x62, 0x13, 0x80, + 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0B, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA9, 0xBD, 0xD2, 0x04, 0xD3, 0x18, 0x00, 0x90, 0x2C, 0x40, 0x2B, 0x58, 0xCF, 0x2D, + 0x8C, 0x7E, 0xEF, 0x12, 0xAA, 0x57, 0xD2, 0xB1, 0xAD, 0x01, 0x45, 0x27, 0x94, 0x3B, 0x8F, 0x20, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0C, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, + 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAA, 0xBD, 0xD2, 0x04, 0x7F, 0x3D, 0x00, 0x5E, 0x7A, 0x40, 0xEB, 0x67, 0x2C, 0x45, 0xCA, 0xF6, 0x48, 0xA8, 0xAC, 0x57, 0xF8, 0xD5, 0x66, 0x04, 0x36, 0x22, + 0x94, 0x3B, 0x5B, 0x01, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0D, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAB, 0xBD, 0xD2, 0x84, 0xC1, 0x1E, + 0x00, 0xC6, 0xFF, 0x3F, 0xAB, 0x6F, 0xFE, 0x69, 0x28, 0x82, 0xE4, 0x06, 0xAF, 0x57, 0x3D, 0x34, 0x38, 0x02, 0xFB, 0x20, 0x94, 0x3B, 0xC8, 0xB3, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, + 0x06, 0x0E, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAC, 0xBD, 0xB2, 0x04, 0x41, 0xAE, 0x00, 0xFC, 0x51, 0x40, 0x6B, 0x76, 0x2D, 0x7B, 0xA6, 0xFD, 0x9C, 0x9F, + 0xB1, 0x57, 0xDA, 0xAF, 0xDE, 0x01, 0xB5, 0x1B, 0x98, 0x3B, 0x8D, 0x75, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0F, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0xAD, 0xBD, 0xD2, 0x04, 0x32, 0x99, 0x02, 0x17, 0x61, 0x40, 0x2B, 0x78, 0x76, 0xB4, 0xD3, 0xFC, 0x10, 0x45, 0xA0, 0x57, 0x67, 0xC7, 0xEF, 0x02, 0x93, 0x20, 0x90, 0x3B, 0xC3, 0x1E, + 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x10, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAE, 0xBD, 0xD2, 0x04, 0x70, 0x64, 0x02, 0x10, 0xC5, 0x40, + 0xEB, 0x87, 0x72, 0x87, 0xF1, 0x80, 0x8E, 0xF2, 0xA2, 0x57, 0x57, 0x0A, 0x76, 0x0C, 0xD9, 0x17, 0x88, 0x3B, 0x91, 0xAA, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x11, 0x15, 0x0C, + 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAF, 0xBD, 0xD2, 0x04, 0x95, 0xB0, 0x00, 0x24, 0x2D, 0x40, 0x2B, 0x89, 0x3B, 0x4D, 0x5B, 0xF0, 0xAB, 0x5C, 0xA4, 0x57, 0x50, 0x95, + 0x23, 0x04, 0xB1, 0x3A, 0x0C, 0x3A, 0x59, 0x64, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x12, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB0, 0xBD, + 0xD2, 0x04, 0x61, 0xBD, 0x00, 0xC7, 0x14, 0x40, 0x6B, 0x97, 0x82, 0x8D, 0xD9, 0xFC, 0xB9, 0xB4, 0xA6, 0x57, 0x71, 0xE6, 0x0F, 0x05, 0x96, 0x40, 0x10, 0x3A, 0xD3, 0x7B, 0xB5, 0x62, 0x13, 0x80, + 0x2C, 0x00, 0x02, 0x00, 0x06, 0x13, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB1, 0xBD, 0xD2, 0x04, 0x61, 0x35, 0x00, 0xC3, 0xC6, 0x3F, 0xEB, 0x98, 0x44, 0x01, + 0x98, 0x85, 0xA8, 0xE9, 0xA8, 0x57, 0xC2, 0xA4, 0x0D, 0x01, 0xFD, 0x45, 0x10, 0x3A, 0x94, 0x41, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x14, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, + 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB2, 0xBD, 0xD2, 0x04, 0xB1, 0x18, 0x00, 0x5D, 0x11, 0x40, 0xAB, 0xA0, 0xC8, 0xDF, 0x15, 0x82, 0xB1, 0xB9, 0xAB, 0x57, 0xF1, 0xE9, 0xC1, 0x03, 0x4A, 0x46, + 0x10, 0x3A, 0xA7, 0x43, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x15, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB3, 0xBD, 0xD2, 0x04, 0x28, 0x00, + 0x02, 0x5E, 0x5E, 0x40, 0x2B, 0xA9, 0x27, 0xA6, 0x73, 0x88, 0xE6, 0x73, 0xAE, 0x57, 0xCC, 0x8C, 0xAD, 0x02, 0x36, 0x3F, 0x14, 0x3A, 0xAF, 0x7C, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, + 0x06, 0x16, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB4, 0xBD, 0xD2, 0x04, 0x85, 0xEC, 0x00, 0x91, 0xEE, 0x3F, 0x6B, 0xB7, 0x72, 0xF2, 0xD1, 0x84, 0x7D, 0xBE, + 0xB0, 0x57, 0xEE, 0x05, 0x09, 0x08, 0x71, 0x43, 0x18, 0x3A, 0x1D, 0x65, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x17, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, + 0x01, 0x03, 0xB5, 0xBD, 0xD2, 0x04, 0xB1, 0x72, 0x02, 0x0E, 0xDA, 0x3E, 0xEB, 0xB8, 0xE4, 0xB4, 0xAF, 0x80, 0x21, 0xAF, 0xB3, 0x57, 0x7C, 0x50, 0x49, 0x00, 0x24, 0x43, 0x18, 0x3A, 0x26, 0xE7, + 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x18, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB6, 0xBD, 0xD2, 0x04, 0xE1, 0x9D, 0x00, 0xA2, 0x0C, 0x40, + 0xAB, 0xC0, 0xEA, 0x39, 0xDD, 0xFD, 0x09, 0xEC, 0xA1, 0x57, 0x92, 0xAE, 0x92, 0x03, 0x96, 0x2B, 0x08, 0x3A, 0x64, 0xD1, 0xB5, 0x62, 0x13, 0x80, 0x78, 0x00, 0x03, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x19, 0x00, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x07, 0x00, 0x8A, 0x08, 0x89, 0x08, 0x12, 0x07, + 0x12, 0x00, 0xC1, 0x03, 0x00, 0x00, 0x19, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0x32, 0x00, 0x00, 0x80, 0xB2, 0x00, 0x00, 0x80, 0xB3, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0xEC, 0x47, 0x00, 0x00, + 0x60, 0xC8, 0x00, 0x00, 0x80, 0xC7, 0x00, 0x00, 0x50, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x22, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x03, 0x00, 0x06, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x12, 0x00, 0x06, 0x07, 0x11, 0x00, 0x06, 0x15, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xBD, 0x3A, 0xBD, 0x02, 0x92, 0xC7, + 0x1E, 0x00, 0xBD, 0x3A, 0x00, 0x00, 0x83, 0xEB, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x02, 0x15, 0x0C, 0x04, 0x14, 0x0F, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x01, 0x5E, + 0xAD, 0x14, 0x0D, 0xD9, 0x01, 0x99, 0x8A, 0x08, 0x57, 0xFD, 0x00, 0x00, 0x00, 0xC4, 0xA0, 0xFF, 0xAF, 0x13, 0x31, 0x04, 0x00, 0xED, 0x07, 0xBB, 0xE2, 0xC1, 0xE2, 0xA6, 0xA2, 0x5F, 0x18, 0xC2, + 0x8E, 0x08, 0x42, 0xC9, 0xD5, 0x17, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x07, 0x20, 0x00, 0x50, 0xF8, 0xAB, 0xA6, 0xD0, 0xC2, 0x7C, 0xE2, 0xDC, 0x80, 0x36, 0x92, 0x07, 0x9C, 0x36, 0xA1, 0x2E, + 0x78, 0x0C, 0x91, 0xCE, 0x7E, 0xE6, 0x3E, 0x63, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x05, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x04, 0x5E, + 0xAD, 0x14, 0xBB, 0x54, 0x01, 0x85, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0xC4, 0xA9, 0xFF, 0xAF, 0x13, 0xEE, 0xD1, 0x3F, 0xF4, 0xE8, 0xBA, 0x02, 0x42, 0xDB, 0xA6, 0xE2, 0x4F, 0x93, 0xCC, + 0x86, 0x08, 0x5E, 0xE0, 0xFB, 0x01, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0xB2, 0xC2, 0xA1, 0xA2, 0x5A, 0xF1, 0x5A, 0x67, 0xD2, 0x32, 0xCB, 0x87, 0x73, 0xEA, 0xA6, 0x22, 0x7E, 0xCE, + 0xB7, 0xF8, 0x59, 0xCB, 0x13, 0xCF, 0x90, 0x3D, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x07, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x06, 0x5E, + 0xAD, 0x14, 0x1C, 0x84, 0x01, 0x3C, 0x8A, 0x08, 0x58, 0x01, 0x00, 0x00, 0x40, 0x44, 0x5B, 0x01, 0xA0, 0x13, 0xB1, 0x77, 0x00, 0xF4, 0xE8, 0xBA, 0x02, 0x02, 0xDC, 0xA6, 0x62, 0x0D, 0x9B, 0x10, + 0x8D, 0x08, 0xE8, 0xB3, 0x12, 0x04, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0xD3, 0xB5, 0xB7, 0x0A, 0x9E, 0x12, 0x42, 0xA2, 0x14, 0xB9, 0xAD, 0xE8, 0xD6, 0xBA, 0xA1, 0x04, 0xEB, 0x56, + 0xE5, 0x29, 0xD2, 0xF1, 0x3E, 0xD4, 0x51, 0xD3, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x09, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x08, 0x5E, + 0xAD, 0x14, 0xAE, 0x75, 0x01, 0xEB, 0x8A, 0x08, 0x58, 0x7D, 0x00, 0x00, 0x40, 0x44, 0x27, 0x00, 0xA0, 0x13, 0x2A, 0x09, 0x80, 0x01, 0xE8, 0xBA, 0x02, 0xC2, 0xDC, 0xA6, 0x42, 0x7D, 0x43, 0x25, + 0x97, 0x08, 0x0E, 0x55, 0xE8, 0x19, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x34, 0x43, 0x60, 0xE2, 0x59, 0x42, 0xAE, 0xE1, 0xE5, 0x34, 0x86, 0x80, 0xA7, 0xDF, 0xA3, 0xE9, 0x4E, 0xB1, + 0xF7, 0x28, 0xB4, 0xBC, 0x8B, 0xD9, 0x5E, 0x5F, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x0D, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x0C, 0x5E, + 0xAD, 0x14, 0x79, 0x8D, 0x01, 0x81, 0x8A, 0x08, 0x58, 0x01, 0x00, 0x00, 0x40, 0x44, 0x91, 0x01, 0xA0, 0x13, 0x16, 0xD5, 0x3F, 0xF4, 0xE8, 0xBA, 0x02, 0x42, 0xDC, 0xA6, 0x62, 0x60, 0x15, 0x2D, + 0x81, 0x08, 0x74, 0x9A, 0x0E, 0x09, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x43, 0x1D, 0xEA, 0x22, 0xB7, 0x2E, 0xD8, 0x3E, 0x59, 0x3A, 0x55, 0x75, 0x09, 0xE7, 0x0A, 0x39, 0xC6, 0x02, + 0x6D, 0xFD, 0xE5, 0xF4, 0x5E, 0xEB, 0x85, 0x41, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x10, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x0F, 0x5E, + 0xAD, 0x14, 0xB3, 0xBB, 0x01, 0x4E, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0xC4, 0x49, 0xFE, 0xAF, 0x13, 0x9A, 0xA4, 0x3F, 0xF5, 0xE8, 0xBA, 0x02, 0x02, 0xDC, 0xA6, 0xA2, 0x33, 0xC9, 0x6D, + 0x90, 0x08, 0x5A, 0x9A, 0xE3, 0x00, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x0D, 0xDD, 0x6D, 0xCD, 0xC2, 0x40, 0x3A, 0x97, 0x5C, 0x01, 0x02, 0x3D, 0x12, 0x48, 0x55, 0xDE, 0xBA, 0x35, + 0x8E, 0xFB, 0xE1, 0xF2, 0x92, 0xCE, 0x5C, 0xFB, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x14, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x13, 0x5E, + 0xAD, 0x14, 0x31, 0xC2, 0x01, 0x0F, 0x8A, 0x08, 0x58, 0x81, 0x00, 0x00, 0x40, 0x44, 0xF0, 0xFF, 0xAF, 0x13, 0x98, 0x87, 0x3F, 0xF7, 0xE8, 0xBA, 0x02, 0xC2, 0xDC, 0xA6, 0x42, 0x50, 0xFF, 0x9B, + 0x8B, 0x08, 0x16, 0xF0, 0x21, 0x1C, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x93, 0x50, 0xE6, 0x06, 0xCF, 0xB8, 0x8C, 0x20, 0xB6, 0x0C, 0x26, 0x4A, 0xC1, 0xC6, 0x7E, 0x22, 0xAC, 0xC6, + 0x13, 0x14, 0x27, 0xFF, 0x18, 0xD2, 0xBA, 0xBA, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x1D, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x1C, 0x5E, + 0xAD, 0x14, 0x13, 0x8D, 0x01, 0xBC, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0xC4, 0x8F, 0xFE, 0xAF, 0x13, 0x52, 0xDC, 0x00, 0xF5, 0xE8, 0xBA, 0x02, 0xC2, 0xDC, 0xA6, 0xC2, 0x76, 0x7B, 0x55, + 0x91, 0x08, 0x2A, 0xA2, 0xE2, 0x18, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x0F, 0xB0, 0x0B, 0x57, 0x2E, 0x66, 0x57, 0xE9, 0x32, 0x5E, 0x4E, 0x14, 0x13, 0x5E, 0xFF, 0x22, 0xFA, 0x2A, + 0x77, 0xDB, 0x2C, 0xC6, 0xC6, 0xDE, 0x74, 0x97, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x1E, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x1D, 0x5E, + 0xAD, 0x14, 0x8D, 0x68, 0x01, 0xBB, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0x44, 0x28, 0xFF, 0xAF, 0x13, 0x5F, 0x5B, 0x00, 0x04, 0xE8, 0xBA, 0x02, 0x42, 0xDC, 0xA6, 0x22, 0x7D, 0x16, 0x76, + 0x89, 0x08, 0xDE, 0x80, 0xDF, 0x08, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0xE3, 0x37, 0xB1, 0x7F, 0xE8, 0xDA, 0x6C, 0x66, 0x21, 0x07, 0x1F, 0x55, 0x27, 0x27, 0x42, 0x1B, 0x68, 0x58, + 0x2E, 0x2E, 0x19, 0xA5, 0xC5, 0xE3, 0xBB, 0x38 +}; diff --git a/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/secrets.h b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/secrets.h new file mode 100644 index 0000000..4eb7a9c --- /dev/null +++ b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/secrets.h @@ -0,0 +1,6 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "hasBigTeeth"; + +//Your AssistNow token +const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index cbb5e20..ec786dc 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -118,6 +118,8 @@ The const uint8_t * function declarations are: * uint8_t getAckAiding(uint16_t maxWait); +```pushAssistNowData``` returns the number of _bytes_ pushed (not the number of _packets_). The return value should be equal to ```numDataBytes``` if all data was valid and pushed successfully. + AssistNow Online data is valid for 2-4 hours. 'Stale' data can be re-used but: * ```pushAssistNowData``` needs to be told to skip the time information contained in the AssistNow data @@ -176,7 +178,7 @@ AssistNow Autonomous is disabled by default. You can enable it by calling ```set * set ```aopCfg``` to 1 to enable AssistNow Autonomous, or 0 to disable it * ```aopOrbMaxErr``` is used to set the 'lifetime' of the AssistNow data. It is recommended to set aopOrbMaxErr to 0 (the default value). This instructs the module to use the firmware default value that corresponds to a default orbit data validity of approximately three days (for GPS satellites observed once) and up to six days (for GPS and GLONASS satellites observed multiple times over a period of at least half a day). -Once AssistNow Autonomous is enabled, you can monitor its progress via the ```status``` field in the UBX-NAV-AOPSTATUS message. You can read the ```status``` by calling the helper function ```getAOPSTATUSstatus```. It will return zero when the AssistNow Autonomous data collection is idle. Non-zero values indicate that data collection is in progress. +Once AssistNow Autonomous is enabled, you can monitor its status via the ```status``` field in the UBX-NAV-AOPSTATUS message. You can read the ```status``` by calling the helper function ```getAOPSTATUSstatus```. It will return zero when the AssistNow Autonomous data collection is idle. Non-zero values indicate that data collection is in progress. Only power-off the receiver when the subsystem is idle (that is, when the status shows a steady zero). * uint8_t getAOPSTATUSstatus(uint16_t maxWait); * uint8_t getAOPSTATUSuseAOP(uint16_t maxWait); @@ -190,7 +192,18 @@ We have included full 'auto' support for UBX-NAV-AOPSTATUS, so you can have the * bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait); * bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate); * void flushAOPSTATUS(); -* void logNAVAOPSTATUS(bool enabled); +* void logAOPSTATUS(bool enabled); + +You can also monitor the AssistNow Autonomous satellite information via the UBX-NAV-SAT message. Again, we have included full 'auto' support for UBX-NAV-SAT. UBX-NAV-SAT contains useful information for each individual satellite which the module has aquired: carrier to noise ratio (signal strength); elevation; azimuth; pseudorange residual; quality indication, health; ephemeris available; almanac available; **AssistNow Offline data availability**; and more. The data can be analyzed using a callback. Please see the AssistNowAutonomous examples for more details. + +* bool getNAVSAT(uint16_t maxWait); +* bool setAutoNAVSAT(bool enabled, uint16_t maxWait); +* bool setAutoNAVSAT(bool enabled, bool implicitUpdate, uint16_t maxWait); +* bool setAutoNAVSATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait); +* bool setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_NAVSAT_data_t), uint16_t maxWait); +* bool assumeAutoNAVSAT(bool enabled, bool implicitUpdate); +* void flushNAVSAT(); +* void logNAVSAT(bool enabled); The AssistNow Autonomous data is stored in the module's RAM memory. If that RAM is Battery-Backed - all SparkFun GNSS boards include battery back-up - then the data will be available after the module is powered down and powered back up again. However, you can also read (poll) the navigation database and store the contents in processor memory. ```readNavigationDatabase``` allows you to do that: diff --git a/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino b/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino new file mode 100644 index 0000000..1a1457d --- /dev/null +++ b/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino @@ -0,0 +1,121 @@ +/* + Configuring the GNSS to automatically send NAV SAT reports over I2C and display them using a callback + By: Paul Clark + SparkFun Electronics + Date: December 1st, 2021 + 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 SAT 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 GPS + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +// Callback: newNAVSAT will be called when new NAV SAT data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_SAT_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSATcallback +// / _____ This _must_ be UBX_NAV_SAT_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void newNAVSAT(UBX_NAV_SAT_data_t ubxDataStruct) +{ + Serial.println(); + + Serial.print(F("New NAV SAT data received. It contains data for ")); + Serial.print(ubxDataStruct.header.numSvs); + if (ubxDataStruct.header.numSvs == 1) + Serial.println(F(" SV.")); + else + Serial.println(F(" SVs.)); + + // Just for giggles, print the signal strength for each SV as a barchart + for (uint16_t block = 0; block < ubxDataStruct.header.numSvs; block++) // For each SV + { + switch (ubxDataStruct.blocks[block].gnssId) // Print the GNSS ID + { + case 0: + Serial.print(F("GPS ")); + break; + case 1: + Serial.print(F("SBAS ")); + break; + case 2: + Serial.print(F("Galileo ")); + break; + case 3: + Serial.print(F("BeiDou ")); + break; + case 4: + Serial.print(F("IMES ")); + break; + case 5: + Serial.print(F("QZSS ")); + break; + case 6: + Serial.print(F("GLONASS ")); + break; + default: + Serial.print(F("UNKNOWN ")); + break; + } + + Serial.print(ubxDataStruct.blocks[block].svId); // Print the SV ID + + if (ubxDataStruct.blocks[block].svId < 10) Serial.print(F(" ")); + else if (ubxDataStruct.blocks[block].svId < 100) Serial.print(F(" ")); + else Serial.print(F(" ")); + + // Print the signal strength as a bar chart + for (uint8_t cno = 0; cno < ubxDataStruct.blocks[block].cno; cno++) + Serial.print(F("=")); + + Serial.println(); + } +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); //Wait for user to open terminal + Serial.println("SparkFun u-blox Example"); + + Wire.begin(); + + //myGNSS.enableDebugging(); // Uncomment this line to enable helpful 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); + } + + myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) + myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR + + myGNSS.setNavigationFrequency(1); //Produce one solution per second + + myGNSS.setAutoNAVSATcallback(&newNAVSAT); // Enable automatic NAV SAT messages with callback to newNAVSAT +} + +void loop() +{ + myGNSS.checkUblox(); // Check for the arrival of new data and process it. + myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. + + Serial.print("."); + delay(50); +} diff --git a/keywords.txt b/keywords.txt index 69af91c..60f06f1 100644 --- a/keywords.txt +++ b/keywords.txt @@ -303,6 +303,15 @@ initPacketUBXNAVTIMELS KEYWORD2 getSurveyStatus KEYWORD2 initPacketUBXNAVSVIN KEYWORD2 +getNAVSAT KEYWORD2 +setAutoNAVSAT KEYWORD2 +setAutoNAVSATrate KEYWORD2 +setAutoNAVSATcallback KEYWORD2 +assumeAutoNAVSAT KEYWORD2 +initPacketUBXNAVSAT KEYWORD2 +flushNAVSAT KEYWORD2 +logNAVSAT KEYWORD2 + getRELPOSNED KEYWORD2 setAutoRELPOSNED KEYWORD2 setAutoRELPOSNEDrate KEYWORD2 @@ -312,14 +321,14 @@ initPacketUBXNAVRELPOSNED KEYWORD2 flushNAVRELPOSNED KEYWORD2 logNAVRELPOSNED KEYWORD2 -getNAVAOPSTATUS KEYWORD2 -setAutoNAVAOPSTATUS KEYWORD2 -setAutoNAVAOPSTATUSrate KEYWORD2 -setAutoNAVAOPSTATUScallback KEYWORD2 -assumeAutoNAVAOPSTATUS KEYWORD2 -initPacketUBXNAVAOPSTATUS KEYWORD2 -flushNAVAOPSTATUS KEYWORD2 -logNAVAOPSTATUS KEYWORD2 +getAOPSTATUS KEYWORD2 +setAutoAOPSTATUS KEYWORD2 +setAutoAOPSTATUSrate KEYWORD2 +setAutoAOPSTATUScallback KEYWORD2 +assumeAutoAOPSTATUS KEYWORD2 +initPacketUBXAOPSTATUS KEYWORD2 +flushAOPSTATUS KEYWORD2 +logAOPSTATUS KEYWORD2 getRXMSFRBX KEYWORD2 setAutoRXMSFRBX KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 7d450e9..28c7200 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -234,6 +234,16 @@ void SFE_UBLOX_GNSS::end(void) packetUBXNAVSVIN = NULL; // Redundant? } + if (packetUBXNAVSAT != NULL) + { + if (packetUBXNAVSAT->callbackData != NULL) + { + delete packetUBXNAVSAT->callbackData; + } + delete packetUBXNAVSAT; + packetUBXNAVSAT = NULL; // Redundant? + } + if (packetUBXNAVRELPOSNED != NULL) { if (packetUBXNAVRELPOSNED->callbackData != NULL) @@ -1036,6 +1046,9 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) case UBX_NAV_SVIN: if (packetUBXNAVSVIN != NULL) result = true; break; + case UBX_NAV_SAT: + if (packetUBXNAVSAT != NULL) result = true; + break; case UBX_NAV_RELPOSNED: if (packetUBXNAVRELPOSNED != NULL) result = true; break; @@ -1182,6 +1195,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) case UBX_NAV_SVIN: maxSize = UBX_NAV_SVIN_LEN; break; + case UBX_NAV_SAT: + maxSize = UBX_NAV_SAT_MAX_LEN; + break; case UBX_NAV_RELPOSNED: maxSize = UBX_NAV_RELPOSNED_LEN_F9; break; @@ -2388,6 +2404,46 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVSVIN->moduleQueried.moduleQueried.all = 0xFFFFFFFF; } } + else if (msg->id == UBX_NAV_SAT) // Note: length is variable + { + //Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXNAVSAT != NULL) + { + packetUBXNAVSAT->data.header.iTOW = extractLong(msg, 0); + packetUBXNAVSAT->data.header.version = extractByte(msg, 4); + packetUBXNAVSAT->data.header.numSvs = extractByte(msg, 5); + + for (uint8_t i = 0; (i < UBX_NAV_SAT_MAX_BLOCKS) && (i < packetUBXNAVSAT->data.header.numSvs) + && ((((uint16_t)i) * 12) < (msg->len - 8)); i++) + { + uint16_t offset = (((uint16_t)i) * 12) + 8; + packetUBXNAVSAT->data.blocks[i].gnssId = extractByte(msg, offset + 0); + packetUBXNAVSAT->data.blocks[i].svId = extractByte(msg, offset + 1); + packetUBXNAVSAT->data.blocks[i].cno = extractByte(msg, offset + 2); + packetUBXNAVSAT->data.blocks[i].elev = extractSignedChar(msg, offset + 3); + packetUBXNAVSAT->data.blocks[i].azim = extractSignedInt(msg, offset + 4); + packetUBXNAVSAT->data.blocks[i].prRes = extractSignedInt(msg, offset + 6); + packetUBXNAVSAT->data.blocks[i].flags.all = extractLong(msg, offset + 8); + } + + //Mark all datums as fresh (not read before) + packetUBXNAVSAT->moduleQueried = true; + + //Check if we need to copy the data for the callback + if ((packetUBXNAVSAT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + { + memcpy(&packetUBXNAVSAT->callbackData->header.iTOW, &packetUBXNAVSAT->data.header.iTOW, sizeof(UBX_NAV_SAT_data_t)); + packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid = true; + } + + //Check if we need to copy the data into the file buffer + if (packetUBXNAVSAT->automaticFlags.flags.bits.addToFileBuffer) + { + storePacket(msg); + } + } + } else if (msg->id == UBX_NAV_RELPOSNED && ((msg->len == UBX_NAV_RELPOSNED_LEN) || (msg->len == UBX_NAV_RELPOSNED_LEN_F9))) { //Parse various byte fields into storage - but only if we have memory allocated for it @@ -3865,6 +3921,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVCLOCK->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->callbackPointer != NULL) // If the pointer to the callback has been defined + && (packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV SAT")); + packetUBXNAVSAT->callbackPointer(*packetUBXNAVSAT->callbackData); // Call the callback + packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + } + if ((packetUBXNAVRELPOSNED != NULL) // If RAM has been allocated for message storage && (packetUBXNAVRELPOSNED->callbackData != NULL) // If RAM has been allocated for the copy of the data && (packetUBXNAVRELPOSNED->callbackPointer != NULL) // If the pointer to the callback has been defined @@ -4119,7 +4186,7 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s // Push MGA AssistNow data to the module. // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE). // Wait for maxWait millis after sending each packet (if mgaAck is NO). -// Return how many MGA packets were pushed successfully. +// Return how many bytes were pushed successfully. // If skipTime is true, any UBX-MGA-INI-TIME_UTC or UBX-MGA-INI-TIME_GNSS packets found in the data will be skipped, // allowing the user to override with their own time data with setUTCTimeAssistance. size_t SFE_UBLOX_GNSS::pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) @@ -4175,6 +4242,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c } size_t packetsProcessed = 0; // Keep count of how many packets have been processed + size_t bytesPushed = 0; // Keep count bool checkForAcks = (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_YES); // If mgaAck is YES, always check for Acks @@ -4247,7 +4315,10 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c } else { - pushRawData((uint8_t *)(dataBytes + dataPtr), packetLength + ((size_t)8)); // Push the data + bool pushResult = pushRawData((uint8_t *)(dataBytes + dataPtr), packetLength + ((size_t)8)); // Push the data + + if (pushResult) + bytesPushed += packetLength + ((size_t)8); // Increment bytesPushed if the push was successful if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { @@ -4356,7 +4427,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c } #endif - return (packetsProcessed); + return (bytesPushed); // Return the number of valid bytes successfully pushed } // PRIVATE: Allocate RAM for packetUBXMGAACK and initialize it @@ -8717,6 +8788,164 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSVIN() return (true); } +// ***** NAV SAT automatic support + +//Signal information +//Returns true if commands was successful +bool SFE_UBLOX_GNSS::getNAVSAT(uint16_t maxWait) +{ + if (packetUBXNAVSAT == NULL) initPacketUBXNAVSAT(); //Check that RAM has been allocated for the NAVSAT data + if (packetUBXNAVSAT == NULL) //Bail if the RAM allocation failed + return (false); + + if (packetUBXNAVSAT->automaticFlags.flags.bits.automatic && packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate) + { + //The GPS is automatically reporting, we just check whether we got unread data + checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_SAT); + return packetUBXNAVSAT->moduleQueried; + } + else if (packetUBXNAVSAT->automaticFlags.flags.bits.automatic && !packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate) + { + //Someone else has to call checkUblox for us... + return (false); + } + else + { + //The GPS is not automatically reporting NAVSAT so we have to poll explicitly + packetCfg.cls = UBX_CLASS_NAV; + packetCfg.id = UBX_NAV_SAT; + 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 NAVSAT message generation by the GNSS. This changes the way getNAVSAT +//works. +bool SFE_UBLOX_GNSS::setAutoNAVSAT(bool enable, uint16_t maxWait) +{ + return setAutoNAVSATrate(enable ? 1 : 0, true, maxWait); +} + +//Enable or disable automatic NAVSAT message generation by the GNSS. This changes the way getNAVSAT +//works. +bool SFE_UBLOX_GNSS::setAutoNAVSAT(bool enable, bool implicitUpdate, uint16_t maxWait) +{ + return setAutoNAVSATrate(enable ? 1 : 0, implicitUpdate, maxWait); +} + +//Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getNAVSAT +//works. +bool SFE_UBLOX_GNSS::setAutoNAVSATrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) +{ + if (packetUBXNAVSAT == NULL) initPacketUBXNAVSAT(); //Check that RAM has been allocated for the data + if (packetUBXNAVSAT == 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_SAT; + payloadCfg[2] = rate; // rate relative to navigation freq. + + bool ok = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK + if (ok) + { + packetUBXNAVSAT->automaticFlags.flags.bits.automatic = (rate > 0); + packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + packetUBXNAVSAT->moduleQueried = false; // Mark data as stale + return ok; +} + +//Enable automatic navigation message generation by the GNSS. +bool SFE_UBLOX_GNSS::setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_data_t), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVSAT(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVSAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVSAT->callbackData = new UBX_NAV_SAT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVSAT->callbackData == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setAutoNAVSATcallback: RAM alloc failed!")); + return (false); + } + + packetUBXNAVSAT->callbackPointer = callbackPointer; + return (true); +} + +//In case no config access to the GNSS is possible and HNR attitude is send cyclically already +//set config to suitable parameters +bool SFE_UBLOX_GNSS::assumeAutoNAVSAT(bool enabled, bool implicitUpdate) +{ + if (packetUBXNAVSAT == NULL) initPacketUBXNAVSAT(); //Check that RAM has been allocated for the NAVSAT data + if (packetUBXNAVSAT == NULL) //Bail if the RAM allocation failed + return (false); + + bool changes = packetUBXNAVSAT->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; + if (changes) + { + packetUBXNAVSAT->automaticFlags.flags.bits.automatic = enabled; + packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + return changes; +} + +// PRIVATE: Allocate RAM for packetUBXNAVSAT and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXNAVSAT() +{ + packetUBXNAVSAT = new UBX_NAV_SAT_t ; //Allocate RAM for the main struct + if (packetUBXNAVSAT == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXNAVSAT: RAM alloc failed!")); + return (false); + } + packetUBXNAVSAT->automaticFlags.flags.all = 0; + packetUBXNAVSAT->callbackPointer = NULL; + packetUBXNAVSAT->callbackData = NULL; + packetUBXNAVSAT->moduleQueried = false; + return (true); +} + +//Mark all the data as read/stale +void SFE_UBLOX_GNSS::flushNAVSAT() +{ + if (packetUBXNAVSAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSAT->moduleQueried = false; //Mark all datums as stale (read before) +} + +//Log this data in file buffer +void SFE_UBLOX_GNSS::logNAVSAT(bool enabled) +{ + if (packetUBXNAVSAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSAT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; +} + // ***** NAV RELPOSNED automatic support //Relative Positioning Information in NED frame @@ -9048,7 +9277,7 @@ void SFE_UBLOX_GNSS::flushAOPSTATUS() } //Log this data in file buffer -void SFE_UBLOX_GNSS::logNAVAOPSTATUS(bool enabled) +void SFE_UBLOX_GNSS::logAOPSTATUS(bool enabled) { if (packetUBXNAVAOPSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 1dba18a..dcbe999 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -709,7 +709,7 @@ class SFE_UBLOX_GNSS // Push MGA AssistNow data to the module. // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE). // Wait for maxWait millis after sending each packet (if mgaAck is NO). - // Return how many MGA packets were pushed successfully. + // Return how many bytes were pushed successfully. // If skipTime is true, any UBX-MGA-INI-TIME_UTC or UBX-MGA-INI-TIME_GNSS packets found in the data will be skipped, // allowing the user to override with their own time data with setUTCTimeAssistance. // offset allows a sub-set of the data to be sent - starting from offset. @@ -1002,6 +1002,15 @@ class SFE_UBLOX_GNSS // Add "auto" support for NAV TIMELS - to avoid needing 'global' storage bool getLeapSecondEvent(uint16_t maxWait); //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 + bool setAutoNAVSAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic NAVSAT 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 setAutoNAVSATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic NAVSAT reports + bool setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic NAVSAT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVSAT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and NAVSAT is send cyclically already + void flushNAVSAT(); //Mark all the NAVSAT data as read/stale + void logNAVSAT(bool enabled = true); // Log data to file buffer + bool getRELPOSNED(uint16_t maxWait = defaultMaxWait); //Get Relative Positioning Information of the NED frame bool setAutoRELPOSNED(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RELPOSNED reports bool setAutoRELPOSNED(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RELPOSNED, 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 @@ -1018,7 +1027,7 @@ class SFE_UBLOX_GNSS bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and AOPSTATUS is send cyclically already void flushAOPSTATUS(); //Mark all the AOPSTATUS data as read/stale - void logNAVAOPSTATUS(bool enabled = true); // Log data to file buffer + void logAOPSTATUS(bool enabled = true); // Log data to file buffer // Receiver Manager Messages (RXM) @@ -1313,6 +1322,7 @@ class SFE_UBLOX_GNSS UBX_NAV_CLOCK_t *packetUBXNAVCLOCK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_TIMELS_t *packetUBXNAVTIMELS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_SVIN_t *packetUBXNAVSVIN = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_SAT_t *packetUBXNAVSAT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_RELPOSNED_t *packetUBXNAVRELPOSNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_AOPSTATUS_t *packetUBXNAVAOPSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1396,6 +1406,7 @@ class SFE_UBLOX_GNSS bool initPacketUBXNAVCLOCK(); // Allocate RAM for packetUBXNAVCLOCK and initialize it bool initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it bool initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it + bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index c4561d8..be78cfe 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -916,6 +916,79 @@ typedef struct UBX_NAV_TIMELS_data_t *callbackData; } UBX_NAV_TIMELS_t; +// UBX-NAV-SAT (0x01 0x35): Satellite Information +const uint16_t UBX_NAV_SAT_MAX_BLOCKS = 256; // TO DO: confirm if this is large enough for all modules +const uint16_t UBX_NAV_SAT_MAX_LEN = 8 + (12 * UBX_NAV_SAT_MAX_BLOCKS); + +typedef struct +{ + uint32_t iTOW; // GPS time of week + uint8_t version; // Message version (0x01 for this version) + uint8_t numSvs; // Number of satellites + uint8_t reserved1[2]; +} UBX_NAV_SAT_header_t; + +typedef struct +{ + uint8_t gnssId; // GNSS identifier + uint8_t svId; // Satellite identifier + uint8_t cno; // Carrier-to-noise density ratio: dB-Hz + int8_t elev; // Elevation (range: +/-90): deg + int16_t azim; // Azimuth (range 0-360): deg + int16_t prRes; // Pseudorange residual: m * 0.1 + union + { + uint32_t all; + struct + { + uint32_t qualityInd : 3; // Signal quality indicator: 0: no signal + // 1: searching signal + // 2: signal acquired + // 3: signal detected but unusable + // 4: code locked and time synchronized + // 5, 6, 7: code and carrier locked and time synchronized + uint32_t svUsed : 1; // 1 = Signal in the subset specified in Signal Identifiers is currently being used for navigation + uint32_t health : 2; // Signal health flag: 0: unknown 1: healthy 2: unhealthy + uint32_t diffCorr : 1; // 1 = differential correction data is available for this SV + uint32_t smoothed : 1; // 1 = carrier smoothed pseudorange used + uint32_t orbitSource : 3; // Orbit source: 0: no orbit information is available for this SV + // 1: ephemeris is used + // 2: almanac is used + // 3: AssistNow Offline orbit is used + // 4: AssistNow Autonomous orbit is used + // 5, 6, 7: other orbit information is used + uint32_t ephAvail : 1; // 1 = ephemeris is available for this SV + uint32_t almAvail : 1; // 1 = almanac is available for this SV + uint32_t anoAvail : 1; // 1 = AssistNow Offline data is available for this SV + uint32_t aopAvail : 1; // 1 = AssistNow Autonomous data is available for this SV + uint32_t reserved1 : 1; + uint32_t sbasCorrUsed : 1; // 1 = SBAS corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t rtcmCorrUsed : 1; // 1 = RTCM corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t slasCorrUsed : 1; // 1 = QZSS SLAS corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t spartnCorrUsed : 1; // 1 = SPARTN corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t prCorrUsed : 1; // 1 = Pseudorange corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t crCorrUsed : 1; // 1 = Carrier range corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t doCorrUsed : 1; // 1 = Range rate (Doppler) corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t reserved2 : 9; + } bits; + } flags; +} UBX_NAV_SAT_block_t; + +typedef struct +{ + UBX_NAV_SAT_header_t header; + UBX_NAV_SAT_block_t blocks[UBX_NAV_SAT_MAX_BLOCKS]; +} UBX_NAV_SAT_data_t; + +typedef struct +{ + ubxAutomaticFlags automaticFlags; + UBX_NAV_SAT_data_t data; + bool moduleQueried; + void (*callbackPointer)(UBX_NAV_SAT_data_t); + UBX_NAV_SAT_data_t *callbackData; +} UBX_NAV_SAT_t; + // UBX-NAV-SVIN (0x01 0x3B): Survey-in data const uint16_t UBX_NAV_SVIN_LEN = 40; From e21a1b2353bdc83465896a3c7c46b9650ed239af Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 1 Dec 2021 12:20:26 +0000 Subject: [PATCH 018/122] v2.1.0 --- examples/AssistNow/README.md | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index ec786dc..b731080 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -194,7 +194,7 @@ We have included full 'auto' support for UBX-NAV-AOPSTATUS, so you can have the * void flushAOPSTATUS(); * void logAOPSTATUS(bool enabled); -You can also monitor the AssistNow Autonomous satellite information via the UBX-NAV-SAT message. Again, we have included full 'auto' support for UBX-NAV-SAT. UBX-NAV-SAT contains useful information for each individual satellite which the module has aquired: carrier to noise ratio (signal strength); elevation; azimuth; pseudorange residual; quality indication, health; ephemeris available; almanac available; **AssistNow Offline data availability**; and more. The data can be analyzed using a callback. Please see the AssistNowAutonomous examples for more details. +You can also monitor the AssistNow Autonomous satellite information via the UBX-NAV-SAT message. Again, we have included full 'auto' support for UBX-NAV-SAT. UBX-NAV-SAT contains useful information for each individual satellite which the module has acquired: carrier to noise ratio (signal strength); elevation; azimuth; pseudorange residual; quality indication, health; ephemeris available; almanac available; **AssistNow Offline data availability**; and more. The data can be analyzed using a callback. Please see the AssistNowAutonomous examples for more details. * bool getNAVSAT(uint16_t maxWait); * bool setAutoNAVSAT(bool enabled, uint16_t maxWait); diff --git a/library.properties b/library.properties index 94897cd..08eb80d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.0.18 +version=2.1.0 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial Communication with u-blox GNSS modules

From 52cb8f2b46b6b305a4dadb9070a0cb2f0bf3b114 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 1 Dec 2021 12:43:10 +0000 Subject: [PATCH 019/122] Update CallbackExample7_NAV_SAT.ino --- .../CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino b/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino index 1a1457d..2612e47 100644 --- a/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino +++ b/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino @@ -40,7 +40,7 @@ void newNAVSAT(UBX_NAV_SAT_data_t ubxDataStruct) if (ubxDataStruct.header.numSvs == 1) Serial.println(F(" SV.")); else - Serial.println(F(" SVs.)); + Serial.println(F(" SVs.")); // Just for giggles, print the signal strength for each SV as a barchart for (uint16_t block = 0; block < ubxDataStruct.header.numSvs; block++) // For each SV From 467d2fbb1796a5870e3dbf9cb281c1a15179350e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 1 Dec 2021 13:35:41 +0000 Subject: [PATCH 020/122] Add note re. AssistNow Autonomous not supported on ZED-F9P --- .../Example1_AssistNowAutonomous.ino | 3 ++- .../Example2_AssistNowAutonomous_DatabaseRead.ino | 3 ++- .../Example3_AssistNowAutonomous_DatabaseWrite.ino | 3 ++- examples/AssistNow/README.md | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino index 2c785c9..d772dfc 100644 --- a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino +++ b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino @@ -17,10 +17,11 @@ Note: this example will only work on boards which have plenty of RAM available. The UBX-NAV-SAT information occupies several kBytes. + Note: this example will not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only." + Feel like supporting open source hardware? Buy a board from SparkFun! SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 - ZED-F9P RTK2: https://www.sparkfun.com/products/16481 SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 Hardware Connections: diff --git a/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino b/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino index 899b82e..f083d15 100644 --- a/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino +++ b/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino @@ -10,10 +10,11 @@ Note: this example will only work on boards which have plenty of RAM available. The database can be several kBytes in length. + Note: this example will not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only." + Feel like supporting open source hardware? Buy a board from SparkFun! SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 - ZED-F9P RTK2: https://www.sparkfun.com/products/16481 SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 Hardware Connections: diff --git a/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino index c22d531..8494530 100644 --- a/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino +++ b/examples/AssistNow/AssistNow_Autonomous/Example3_AssistNowAutonomous_DatabaseWrite/Example3_AssistNowAutonomous_DatabaseWrite.ino @@ -15,6 +15,8 @@ Update secrets.h with your: - WiFi credentials + Note: this example will not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only." + Note: this example works best if you have the GNSS RAM battery-backup disabled. All SparkFun boards have battery-backup for the RAM which will means the database is retained if you disconnect the power. The module will use the database data from the battery-backed RAM when you turn the power back on. @@ -24,7 +26,6 @@ Feel like supporting open source hardware? Buy a board from SparkFun! SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 - ZED-F9P RTK2: https://www.sparkfun.com/products/16481 SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 Hardware Connections: diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index b731080..d103235 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -37,6 +37,8 @@ AssistNow Autonomous offers augmentation for up to 6 days. Please see the [AssistNow_Autonomous](./AssistNow_Autonomous) examples for more details. +**Note: AssistNow Autonomous does not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only."** + The new functions we've added to the library to support AssistNow Autonomous are described [Support for AssistNow Autonomous below](#Support-for-AssistNow-Autonomous). ## AssistNow Service Token From 0f5f8ebed5f310eb4799a0bdef567c98fbb23504 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 1 Dec 2021 14:12:40 +0000 Subject: [PATCH 021/122] Correct the return value checks for pushAssistNowDataInternal --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 28c7200..a8e1e1f 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4486,7 +4486,7 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t } // Return true if the one packet was pushed successfully - return (pushAssistNowDataInternal(0, false, iniTimeUTC, 32, mgaAck, maxWait) == 1); + return (pushAssistNowDataInternal(0, false, iniTimeUTC, 32, mgaAck, maxWait) == 32); } // Provide initial position assistance @@ -4541,7 +4541,7 @@ bool SFE_UBLOX_GNSS::setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int3 } // Return true if the one packet was pushed successfully - return (pushAssistNowDataInternal(0, false, iniPosXYZ, 28, mgaAck, maxWait) == 1); + return (pushAssistNowDataInternal(0, false, iniPosXYZ, 28, mgaAck, maxWait) == 28); } // The units for lat and lon are degrees * 1e-7 (WGS84) @@ -4596,7 +4596,7 @@ bool SFE_UBLOX_GNSS::setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t } // Return true if the one packet was pushed successfully - return (pushAssistNowDataInternal(0, false, iniPosLLH, 28, mgaAck, maxWait) == 1); + return (pushAssistNowDataInternal(0, false, iniPosLLH, 28, mgaAck, maxWait) == 28); } // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day @@ -4831,8 +4831,8 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD // Do not Wait for an ACK - the DBD data will start arriving immediately. size_t pushResult = pushAssistNowDataInternal(0, false, pollNaviDatabase, (size_t)8, SFE_UBLOX_MGA_ASSIST_ACK_NO, 0); - // Check pushResult == 1. Redundant?! - if (pushResult != 1) + // Check pushResult == 8 + if (pushResult != 8) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) From 9c52398855c57c03bc72ecd565b8fb412294a4d3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 09:53:26 +0000 Subject: [PATCH 022/122] Correct DBD_RINGBUFFER_LEN. Correct SAT_NAV MAX_BLOCKS checking. Remove negative size_t checks. Add extra diagnostic for readNavigationDatabase. --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 44 ++++++++++++-------- src/u-blox_structs.h | 9 +++- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index a8e1e1f..391355e 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2413,10 +2413,11 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVSAT->data.header.version = extractByte(msg, 4); packetUBXNAVSAT->data.header.numSvs = extractByte(msg, 5); - for (uint8_t i = 0; (i < UBX_NAV_SAT_MAX_BLOCKS) && (i < packetUBXNAVSAT->data.header.numSvs) - && ((((uint16_t)i) * 12) < (msg->len - 8)); i++) + // The NAV SAT message could contain data for 255 SVs max. (numSvs is uint8_t. UBX_NAV_SAT_MAX_BLOCKS is 255) + for (uint16_t i = 0; (i < UBX_NAV_SAT_MAX_BLOCKS) && (i < ((uint16_t)packetUBXNAVSAT->data.header.numSvs)) + && ((i * 12) < (msg->len - 8)); i++) { - uint16_t offset = (((uint16_t)i) * 12) + 8; + uint16_t offset = (i * 12) + 8; packetUBXNAVSAT->data.blocks[i].gnssId = extractByte(msg, offset + 0); packetUBXNAVSAT->data.blocks[i].svId = extractByte(msg, offset + 1); packetUBXNAVSAT->data.blocks[i].cno = extractByte(msg, offset + 2); @@ -4217,7 +4218,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c { size_t dataPtr = offset; // Pointer into dataBytes - if ((offset >= numDataBytes) || (offset < 0)) // Sanity check. Return now if offset is invalid. + if (offset >= numDataBytes) // Sanity check. Return now if offset is invalid. { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -4230,17 +4231,6 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c return ((size_t)0); } - if (numDataBytes < 0) // Sanity check. Return now if numDataBytes is negative. - { -#ifndef SFE_UBLOX_REDUCED_PROG_MEM - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->println(F("pushAssistNowData: numDataBytes is negative! Aborting...")); - } -#endif - return ((size_t)0); - } - size_t packetsProcessed = 0; // Keep count of how many packets have been processed size_t bytesPushed = 0; // Keep count @@ -4894,14 +4884,15 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD while (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any data? { // Check if we've received the correct ACK + bool idMatch = (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == UBX_MGA_DBD); // Check if the message ID matches + bool dataAckd = true; - dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == UBX_MGA_DBD); // Check if the message ID matches dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == (uint8_t)(databaseEntriesRX & 0xFF)); // Check if the ACK contents match databaseEntriesRX dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == (uint8_t)((databaseEntriesRX >> 8) & 0xFF)); dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == (uint8_t)((databaseEntriesRX >> 16) & 0xFF)); dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == (uint8_t)((databaseEntriesRX >> 24) & 0xFF)); - if (dataAckd) // Is the ACK valid? + if (idMatch && dataAckd) // Is the ACK valid? { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -4917,6 +4908,25 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD #endif keepGoing = false; } + else if (idMatch) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("readNavigationDatabase: unexpected ACK received. databaseEntriesRX is 0x")); + _debugSerial->print(databaseEntriesRX, HEX); + _debugSerial->print(F(". msgPayloadStart is 0x")); + for (uint8_t i = 4; i > 0; i--) + { + if (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[i - 1] < 0x10) + _debugSerial->print(F("0")); + _debugSerial->print(packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[i - 1], HEX); + } + _debugSerial->println(); + } +#endif + } + // Increment the tail packetUBXMGAACK->tail++; if (packetUBXMGAACK->tail == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index be78cfe..4a6791d 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -917,7 +917,7 @@ typedef struct } UBX_NAV_TIMELS_t; // UBX-NAV-SAT (0x01 0x35): Satellite Information -const uint16_t UBX_NAV_SAT_MAX_BLOCKS = 256; // TO DO: confirm if this is large enough for all modules +const uint16_t UBX_NAV_SAT_MAX_BLOCKS = 255; // numSvs is 8-bit const uint16_t UBX_NAV_SAT_MAX_LEN = 8 + (12 * UBX_NAV_SAT_MAX_BLOCKS); typedef struct @@ -1817,7 +1817,12 @@ typedef struct uint8_t dbdEntryChecksumB; } UBX_MGA_DBD_data_t; -#define UBX_MGA_DBD_RINGBUFFER_LEN 256 // Provide storage for MGA DBD packets. TO DO: confirm if 256 is large enough! +#if defined(ARDUINO_AVR_UNO) +#define UBX_MGA_DBD_RINGBUFFER_LEN 3 // Fix to let the code compile on the UNO. (The UNO does not have enough RAM to store the database.) +#else +#define UBX_MGA_DBD_RINGBUFFER_LEN 250 // Provide storage for MGA DBD packets. TO DO: confirm if 250 is large enough for all modules! +#endif + typedef struct { uint8_t head; From 1b7ba984c3352196a1649175c4ca9944e58cae25 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 10:15:08 +0000 Subject: [PATCH 023/122] Add tree/GITHUB_REF to yml file so Compile Sketch runs on the current branch, not main --- .github/workflows/compile-sketch.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 97efba1..6dc5f7a 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -1,7 +1,7 @@ name: Compile Sketch on: - # - push + - push - pull_request @@ -88,13 +88,16 @@ jobs: - name: Checkout uses: actions/checkout@v2 + - name: Branch name + run: echo running on branch ${GITHUB_REF##*/} + - name: Compile Sketch uses: arduino/compile-sketches@v1 with: platforms: ${{ matrix.board.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | - - source-url: https://github.com/${{github.repository}}.git + - source-url: https://github.com/${{github.repository}}/tree/${GITHUB_REF##*/}.git sketch-paths: | - examples/Example10_AltitudeMSL - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C From 93d947352f49f97a59188ef9c6944adcb1e1f1a9 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 10:37:38 +0000 Subject: [PATCH 024/122] Update compile-sketch.yml --- .github/workflows/compile-sketch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 6dc5f7a..dc606ab 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -97,7 +97,7 @@ jobs: platforms: ${{ matrix.board.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | - - source-url: https://github.com/${{github.repository}}/tree/${GITHUB_REF##*/}.git + - source-url: https://github.com/${{github.repository}}/tree/${{GITHUB_REF##*/}}.git sketch-paths: | - examples/Example10_AltitudeMSL - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C From b82a1293bbadfad274c4a963aca77cd4cb9dfa9d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 11:37:44 +0000 Subject: [PATCH 025/122] Update compile-sketch.yml --- .github/workflows/compile-sketch.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index dc606ab..445febf 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -87,7 +87,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - + - name: Branch name run: echo running on branch ${GITHUB_REF##*/} @@ -97,7 +97,7 @@ jobs: platforms: ${{ matrix.board.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | - - source-url: https://github.com/${{github.repository}}/tree/${{GITHUB_REF##*/}}.git + - source-url: https://github.com/tree/AssistNow.git sketch-paths: | - examples/Example10_AltitudeMSL - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C @@ -106,7 +106,6 @@ jobs: - examples/Example14_DebugOutput - examples/Example15_GetDateTime - examples/Example16_Nanosecond_MaxOutput - - examples/Example16_PartialSecond_MaxOutput - examples/Example18_PowerSaveMode - examples/Example19_DynamicModel - examples/Example20_SendCustomCommand From e59588acc55519c7683acd587604220ded5dd978 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 11:39:59 +0000 Subject: [PATCH 026/122] Update compile-sketch.yml --- .github/workflows/compile-sketch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 445febf..c8cf6bc 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -97,7 +97,7 @@ jobs: platforms: ${{ matrix.board.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | - - source-url: https://github.com/tree/AssistNow.git + - source-url: https://github.com/${{github.repository}}/tree/AssistNow.git sketch-paths: | - examples/Example10_AltitudeMSL - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C From c30d0b88d25884e4919b63bc93a40417032164b7 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 11:44:07 +0000 Subject: [PATCH 027/122] Update compile-sketch.yml --- .github/workflows/compile-sketch.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index c8cf6bc..d0dbb79 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -97,7 +97,8 @@ jobs: platforms: ${{ matrix.board.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | - - source-url: https://github.com/${{github.repository}}/tree/AssistNow.git + # - source-url: https://github.com/${{github.repository}}.git + - source-path: /tree/AssistNow sketch-paths: | - examples/Example10_AltitudeMSL - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C From 29b7294ce719834c53651bd28f62fd8f13faef5e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 11:56:16 +0000 Subject: [PATCH 028/122] Update compile-sketch.yml --- .github/workflows/compile-sketch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index d0dbb79..28670c1 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -97,7 +97,7 @@ jobs: platforms: ${{ matrix.board.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | - # - source-url: https://github.com/${{github.repository}}.git + - source-url: https://github.com/${{github.repository}}.git - source-path: /tree/AssistNow sketch-paths: | - examples/Example10_AltitudeMSL From b7b366673b8a61268ca665916267343aa55dcf09 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 11:59:54 +0000 Subject: [PATCH 029/122] Update compile-sketch.yml --- .github/workflows/compile-sketch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 28670c1..78b1457 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -98,7 +98,7 @@ jobs: fqbn: ${{ matrix.board.fqbn }} libraries: | - source-url: https://github.com/${{github.repository}}.git - - source-path: /tree/AssistNow + - source-path: ${{github.ref[11:]}} sketch-paths: | - examples/Example10_AltitudeMSL - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C From b2ca3e23600c235a4f1e47497f1a410b7fa0a28c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 12:24:56 +0000 Subject: [PATCH 030/122] Update compile-sketch.yml --- .github/workflows/compile-sketch.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 78b1457..65354a1 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -97,8 +97,7 @@ jobs: platforms: ${{ matrix.board.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | - - source-url: https://github.com/${{github.repository}}.git - - source-path: ${{github.ref[11:]}} + - source-path: ./ sketch-paths: | - examples/Example10_AltitudeMSL - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C From 3a49e47347d0dc3310a9f0bb503ed7823e230d8f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 12:37:44 +0000 Subject: [PATCH 031/122] Deliberately re-introduce a compiler warning - just to test the yml --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 391355e..744d716 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3164,7 +3164,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t //Returns false if sensor fails to respond to I2C traffic sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait) { - uint16_t ignoreMe = maxWait; ignoreMe += 0; // Do something with maxWait just to avoid the pesky compiler warnings! + //uint16_t ignoreMe = maxWait; ignoreMe += 0; // Do something with maxWait just to avoid the pesky compiler warnings! // From the integration guide: // "The receiver does not provide any write access except for writing UBX and NMEA messages to the From 2b4330a42a899011fad6ff9cefd455cd5a9305d7 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 12:40:05 +0000 Subject: [PATCH 032/122] Revert "Deliberately re-introduce a compiler warning - just to test the yml" This reverts commit 3a49e47347d0dc3310a9f0bb503ed7823e230d8f. --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 744d716..391355e 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3164,7 +3164,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t //Returns false if sensor fails to respond to I2C traffic sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait) { - //uint16_t ignoreMe = maxWait; ignoreMe += 0; // Do something with maxWait just to avoid the pesky compiler warnings! + uint16_t ignoreMe = maxWait; ignoreMe += 0; // Do something with maxWait just to avoid the pesky compiler warnings! // From the integration guide: // "The receiver does not provide any write access except for writing UBX and NMEA messages to the From 3cab7acd3f0fcfaa1445936498e6b4db93685382 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 12:44:00 +0000 Subject: [PATCH 033/122] yml: enable-deltas-report; disable compile on push --- .github/workflows/compile-sketch.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 65354a1..8a225b7 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -1,7 +1,7 @@ name: Compile Sketch on: - - push + # - push - pull_request @@ -110,6 +110,7 @@ jobs: - examples/Example19_DynamicModel - examples/Example20_SendCustomCommand enable-warnings-report: true + enable-deltas-report: true # verbose: true # outputs: From 38440b5a0b96f856991809dfb2dcf6d84cccaa99 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 12:44:51 +0000 Subject: [PATCH 034/122] v2.1.1 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 08eb80d..2201468 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.1.0 +version=2.1.1 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial Communication with u-blox GNSS modules

From c0cb443a19416f375bc8b29fd061eff329d35e7e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 2 Dec 2021 18:20:47 +0000 Subject: [PATCH 035/122] Add Example4_AssistNowOnline_Serial --- .../Example4_AssistNowOnline_Serial.ino | 232 ++++++++++++++++++ .../Example4_AssistNowOnline_Serial/secrets.h | 6 + 2 files changed, 238 insertions(+) create mode 100644 examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/Example4_AssistNowOnline_Serial.ino create mode 100644 examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/secrets.h diff --git a/examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/Example4_AssistNowOnline_Serial.ino b/examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/Example4_AssistNowOnline_Serial.ino new file mode 100644 index 0000000..0c127f9 --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/Example4_AssistNowOnline_Serial.ino @@ -0,0 +1,232 @@ +/* + Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream + By: SparkFun Electronics / Paul Clark + Date: November 24th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi + and push it to a u-blox module using Serial. + + You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. + + Update secrets.h with your: + - WiFi credentials + - AssistNow token string + + Uncomment the "#define USE_MGA_ACKs" below to test the more robust method of using the + UBX_MGA_ACK_DATA0 acknowledgements to confirm that each MGA message has been accepted. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +*/ + +//#define USE_MGA_ACKs // Uncomment this line to use the UBX_MGA_ACK_DATA0 acknowledgements + +#include +#include +#include "secrets.h" + +const char assistNowServer[] = "https://online-live1.services.u-blox.com"; +//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server + +const char getQuery[] = "GetOnlineData.ashx?"; +const char tokenPrefix[] = "token="; +const char tokenSuffix[] = ";"; +const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal +const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +#define mySerial Serial1 // Use Serial1 to communicate with the GNSS module + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress + + mySerial.begin(9600); // Use 9600 baud (for u-blox M8) + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to the GNSS. + + if (myGNSS.begin(mySerial) == false) //Connect to the Ublox module using mySerial + { + Serial.println(F("u-blox GPS not detected. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART port to output UBX only + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to WiFi. + + Serial.print(F("Connecting to local WiFi")); + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.println(F("WiFi connected!")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Use HTTP GET to receive the AssistNow_Online data + + const int URL_BUFFER_SIZE = 256; + char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL + int payloadSize = 0; // This will be updated with the length of the data we get from the server + String payload; // This will store the data we get from the server + + // Assemble the URL + // Note the slash after the first %s (assistNowServer) + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getDataType); + + Serial.print(F("HTTP URL is: ")); + Serial.println(theURL); + + HTTPClient http; + + http.begin(theURL); + + int httpCode = http.GET(); // HTTP GET + + // httpCode will be negative on error + if(httpCode > 0) + { + // HTTP header has been sent and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\r\n", httpCode); + + // If the GET was successful, read the data + if(httpCode == HTTP_CODE_OK) // Check for code 200 + { + payloadSize = http.getSize(); + Serial.printf("Server returned %d bytes\r\n", payloadSize); + + payload = http.getString(); // Get the payload + + // Pretty-print the payload as HEX + /* + int i; + for(i = 0; i < payloadSize; i++) + { + if (payload[i] < 0x10) // Print leading zero + Serial.print("0"); + Serial.print(payload[i], HEX); + Serial.print(" "); + if ((i % 16) == 15) + Serial.println(); + } + if ((i % 16) != 15) + Serial.println(); + */ + } + } + else + { + Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the AssistNow data to the module + + if (payloadSize > 0) + { + // Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent + //myGNSS.enableDebugging(Serial, true); + +#ifndef USE_MGA_ACKs + + // ***** Don't use the UBX_MGA_ACK_DATA0 messages ***** + + // Push all the AssistNow data. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages. + myGNSS.pushAssistNowData(payload, (size_t)payloadSize); + +#else + + // ***** Use the UBX_MGA_ACK_DATA0 messages ***** + + // Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data + myGNSS.setAckAiding(1); + + // Push all the AssistNow data. + // We have called setAckAiding(1) to instruct the module to return MGA-ACK messages. + // So, we could set the pushAssistNowData mgaAck parameter to SFE_UBLOX_MGA_ASSIST_ACK_YES. + // But, just for giggles, let's use SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE just to confirm that the + // MGA-ACK messages are actually enabled. + // Wait for up to 100ms for each ACK to arrive! 100ms is a bit excessive... 7ms is nearer the mark. + myGNSS.pushAssistNowData(payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE, 100); + +#endif + + } + + Serial.println(F("Here we go!")); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte SIV = myGNSS.getSIV(); + Serial.print(F(" SIV: ")); + Serial.print(SIV); + + byte fixType = myGNSS.getFixType(); + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); +} diff --git a/examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/secrets.h b/examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/secrets.h new file mode 100644 index 0000000..4eb7a9c --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example4_AssistNowOnline_Serial/secrets.h @@ -0,0 +1,6 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "hasBigTeeth"; + +//Your AssistNow token +const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; From d6575f3c0d38402a26c72a40aba9895d1f9e15a9 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 8 Dec 2021 13:07:56 +0000 Subject: [PATCH 036/122] v2.1.2 - fix issue #87 --- library.properties | 2 +- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 2 +- src/u-blox_structs.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library.properties b/library.properties index 2201468..c52c9b2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.1.1 +version=2.1.2 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial Communication with u-blox GNSS modules

diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index dcbe999..d66c57e 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -60,7 +60,7 @@ //#define SFE_UBLOX_REDUCED_PROG_MEM // Uncommenting this line will delete the minor debug messages to save memory //The code just about fills the program memory on the ATmega328P (Arduino Uno), so let's delete the minor debug messages anyway -#if !defined(SFE_UBLOX_REDUCED_PROG_MEM) && defined(ARDUINO_AVR_UNO) +#if !defined(SFE_UBLOX_REDUCED_PROG_MEM) && defined(ARDUINO_ARCH_AVR) #define SFE_UBLOX_REDUCED_PROG_MEM #endif diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 4a6791d..a749ce4 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1817,8 +1817,8 @@ typedef struct uint8_t dbdEntryChecksumB; } UBX_MGA_DBD_data_t; -#if defined(ARDUINO_AVR_UNO) -#define UBX_MGA_DBD_RINGBUFFER_LEN 3 // Fix to let the code compile on the UNO. (The UNO does not have enough RAM to store the database.) +#if defined(ARDUINO_ARCH_AVR) +#define UBX_MGA_DBD_RINGBUFFER_LEN 190 // Fix to let the code compile on AVR platforms - including the UNO. #else #define UBX_MGA_DBD_RINGBUFFER_LEN 250 // Provide storage for MGA DBD packets. TO DO: confirm if 250 is large enough for all modules! #endif From 6357b31d28d18c137321db1d6e7084ac1660e1c7 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 8 Dec 2021 13:56:42 -0700 Subject: [PATCH 037/122] Moving prints to flash. --- .../Example15_NTRIPClient.ino | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/examples/ZED-F9P/Example15_NTRIPClient/Example15_NTRIPClient.ino b/examples/ZED-F9P/Example15_NTRIPClient/Example15_NTRIPClient.ino index 7e9fb72..f739b9e 100644 --- a/examples/ZED-F9P/Example15_NTRIPClient/Example15_NTRIPClient.ino +++ b/examples/ZED-F9P/Example15_NTRIPClient/Example15_NTRIPClient.ino @@ -16,6 +16,9 @@ This is a proof of concept to show how to connect to a caster via HTTP. Using WiFi for a rover is generally a bad idea because of limited WiFi range in the field. + For more information about NTRIP Clients and the differences between Rev1 and Rev2 of the protocol + please see: https://www.use-snip.com/kb/knowledge-base/ntrip-rev1-versus-rev2-formats/ + Feel like supporting open source hardware? Buy a board from SparkFun! ZED-F9P RTK2: https://www.sparkfun.com/products/16481 @@ -50,7 +53,7 @@ int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame af void setup() { Serial.begin(115200); - Serial.println("NTRIP testing"); + Serial.println(F("NTRIP testing")); Wire.begin(); //Start I2C @@ -66,15 +69,15 @@ void setup() myGNSS.setNavigationFrequency(1); //Set output in Hz. - Serial.print("Connecting to local WiFi"); + Serial.print(F("Connecting to local WiFi")); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); - Serial.print("."); + Serial.print(F(".")); } Serial.println(); - Serial.print("WiFi connected with IP: "); + Serial.print(F("WiFi connected with IP: ")); Serial.println(WiFi.localIP()); while (Serial.available()) Serial.read(); @@ -82,7 +85,11 @@ void setup() void loop() { - if (Serial.available()) beginClient(); + if (Serial.available()) + { + beginClient(); + while (Serial.available()) Serial.read(); //Empty buffer of any newline chars + } Serial.println(F("Press any key to start NTRIP Client.")); @@ -95,36 +102,37 @@ void beginClient() WiFiClient ntripClient; long rtcmCount = 0; - Serial.println("Subscribing to Caster. Press key to stop"); + Serial.println(F("Subscribing to Caster. Press key to stop")); delay(10); //Wait for any serial to arrive while (Serial.available()) Serial.read(); //Flush while (Serial.available() == 0) { - //Connect if we are not already + //Connect if we are not already. Limit to 5s between attempts. if (ntripClient.connected() == false) { - Serial.print("Opening socket to"); + Serial.print(F("Opening socket to ")); Serial.println(casterHost); if (ntripClient.connect(casterHost, casterPort) == false) //Attempt connection { - Serial.println("Connection to caster failed"); + Serial.println(F("Connection to caster failed")); + return; } else { - Serial.print("Connected to "); + Serial.print(F("Connected to ")); Serial.print(casterHost); - Serial.print(": "); + Serial.print(F(": ")); Serial.println(casterPort); - Serial.print("Requesting NTRIP Data from mount point "); + Serial.print(F("Requesting NTRIP Data from mount point ")); Serial.println(mountPoint); const int SERVER_BUFFER_SIZE = 512; char serverRequest[SERVER_BUFFER_SIZE]; - snprintf(serverRequest, SERVER_BUFFER_SIZE, "GET /%s HTTP/1.0\r\nUser-Agent: SparkFun u-blox NTRIPClient v1.0\r\n", + snprintf(serverRequest, SERVER_BUFFER_SIZE, "GET /%s HTTP/1.0\r\nUser-Agent: NTRIP SparkFun u-blox Client v1.0\r\n", mountPoint); char credentials[512]; @@ -138,7 +146,7 @@ void beginClient() char userCredentials[sizeof(casterUser) + sizeof(casterUserPW) + 1]; //The ':' takes up a spot snprintf(userCredentials, sizeof(userCredentials), "%s:%s", casterUser, casterUserPW); - Serial.print("Sending credentials: "); + Serial.print(F("Sending credentials: ")); Serial.println(userCredentials); #if defined(ARDUINO_ARCH_ESP32) @@ -158,13 +166,13 @@ void beginClient() strncat(serverRequest, credentials, SERVER_BUFFER_SIZE); strncat(serverRequest, "\r\n", SERVER_BUFFER_SIZE); - Serial.print("serverRequest size: "); + Serial.print(F("serverRequest size: ")); Serial.print(strlen(serverRequest)); - Serial.print(" of "); + Serial.print(F(" of ")); Serial.print(sizeof(serverRequest)); - Serial.println(" bytes available"); + Serial.println(F(" bytes available")); - Serial.println("Sending server request:"); + Serial.println(F("Sending server request:")); Serial.println(serverRequest); ntripClient.write(serverRequest, strlen(serverRequest)); @@ -174,7 +182,7 @@ void beginClient() { if (millis() - timeout > 5000) { - Serial.println("Mountpoint timed out!"); + Serial.println(F("Caster timed out!")); ntripClient.stop(); return; } @@ -194,23 +202,26 @@ void beginClient() connectionSuccess = true; if (strstr(response, "401") > 0) //Look for '401 Unauthorized' { - Serial.println("Hey - your credentials look bad! Check you caster username and password."); + Serial.println(F("Hey - your credentials look bad! Check you caster username and password.")); connectionSuccess = false; } } response[responseSpot] = '\0'; + Serial.print(F("Caster responded with: ")); + Serial.println(response); + if (connectionSuccess == false) { - Serial.print("Failed to connect to "); + Serial.print(F("Failed to connect to ")); Serial.print(casterHost); - Serial.print(": "); + Serial.print(F(": ")); Serial.println(response); - delay(5000); //Don't spam with lots of connection attempts + return; } else { - Serial.print("Connected to "); + Serial.print(F("Connected to ")); Serial.println(casterHost); lastReceivedRTCM_ms = millis(); //Reset timeout } @@ -236,7 +247,7 @@ void beginClient() //Push RTCM to GNSS module over I2C myGNSS.pushRawData(rtcmData, rtcmCount, false); - Serial.print("RTCM pushed to ZED: "); + Serial.print(F("RTCM pushed to ZED: ")); Serial.println(rtcmCount); } } @@ -244,7 +255,7 @@ void beginClient() //Close socket if we don't have new data for 10s if (millis() - lastReceivedRTCM_ms > maxTimeBeforeHangup_ms) { - Serial.println("RTCM timeout. Disconnecting..."); + Serial.println(F("RTCM timeout. Disconnecting...")); if (ntripClient.connected() == true) ntripClient.stop(); return; @@ -253,9 +264,7 @@ void beginClient() delay(10); } - Serial.println("User pressed a key"); - Serial.println("Disconnecting..."); + Serial.println(F("User pressed a key")); + Serial.println(F("Disconnecting...")); ntripClient.stop(); - - while (Serial.available()) Serial.read(); //Empty buffer of any newline chars -} +} \ No newline at end of file From ec4a7c4a3758e120ee569cf527c8dc52a142bb45 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 8 Dec 2021 14:00:03 -0700 Subject: [PATCH 038/122] Add maxWait to begin functions --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 24 ++++++++++---------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 68130fa..ecf50f1 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -406,7 +406,7 @@ void SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) } //Initialize the I2C port -bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress) +bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t maxWait) { commType = COMM_TYPE_I2C; _i2cPort = &wirePort; //Grab which port the user wants us to use @@ -429,19 +429,19 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress) createFileBuffer(); // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored - bool connected = isConnected(); + bool connected = isConnected(maxWait); if (!connected) - connected = isConnected(); + connected = isConnected(maxWait); if (!connected) - connected = isConnected(); + connected = isConnected(maxWait); return (connected); } //Initialize the Serial port -bool SFE_UBLOX_GNSS::begin(Stream &serialPort) +bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait) { commType = COMM_TYPE_SERIAL; _serialPort = &serialPort; //Grab which port the user wants us to use @@ -454,19 +454,19 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort) createFileBuffer(); // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored - bool connected = isConnected(); + bool connected = isConnected(maxWait); if (!connected) - connected = isConnected(); + connected = isConnected(maxWait); if (!connected) - connected = isConnected(); + connected = isConnected(maxWait); return (connected); } // Initialize for SPI -bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed) +bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait) { commType = COMM_TYPE_SPI; _spiPort = &spiPort; @@ -507,13 +507,13 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed) } // Call isConnected up to three times - bool connected = isConnected(); + bool connected = isConnected(maxWait); if (!connected) - connected = isConnected(); + connected = isConnected(maxWait); if (!connected) - connected = isConnected(); + connected = isConnected(maxWait); return (connected); } diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 1bc37b9..6a1740b 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -576,11 +576,11 @@ class SFE_UBLOX_GNSS void setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize //By default use the default I2C address, and use Wire port - bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42); //Returns true if module is detected + bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait); //Returns true if module is detected //serialPort needs to be perviously initialized to correct baud rate - bool begin(Stream &serialPort); //Returns true if module is detected + bool begin(Stream &serialPort, uint16_t maxWait); //Returns true if module is detected //SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz) - bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed); + bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait); void end(void); //Stop all automatic message processing. Free all used RAM From d47d02a351a19b2fae9090dccb69b030ab459111 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 8 Dec 2021 14:00:58 -0700 Subject: [PATCH 039/122] Add defaults --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 6a1740b..a3946df 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -576,11 +576,11 @@ class SFE_UBLOX_GNSS void setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize //By default use the default I2C address, and use Wire port - bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait); //Returns true if module is detected + bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = 1100); //Returns true if module is detected //serialPort needs to be perviously initialized to correct baud rate - bool begin(Stream &serialPort, uint16_t maxWait); //Returns true if module is detected + bool begin(Stream &serialPort, uint16_t maxWait = 1100); //Returns true if module is detected //SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz) - bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait); + bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = 1100); void end(void); //Stop all automatic message processing. Free all used RAM From 7c799210a81d5883e3e33f62862f061b13617de2 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 9 Dec 2021 11:59:27 +0000 Subject: [PATCH 040/122] Change hard-coded maxWait's to defaultMaxWait --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 5448fe1..e0f866e 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -599,11 +599,11 @@ class SFE_UBLOX_GNSS void setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize //By default use the default I2C address, and use Wire port - bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = 1100); //Returns true if module is detected + bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait); //Returns true if module is detected //serialPort needs to be perviously initialized to correct baud rate - bool begin(Stream &serialPort, uint16_t maxWait = 1100); //Returns true if module is detected + bool begin(Stream &serialPort, uint16_t maxWait = defaultMaxWait); //Returns true if module is detected //SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz) - bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = 1100); + bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = defaultMaxWait); void end(void); //Stop all automatic message processing. Free all used RAM @@ -633,7 +633,7 @@ class SFE_UBLOX_GNSS int8_t getMaxNMEAByteCount(void); //Returns true if device answers on _gpsI2Caddress address or via Serial - bool isConnected(uint16_t maxWait = 1100); + bool isConnected(uint16_t maxWait = defaultMaxWait); // Enable debug messages using the chosen Serial port (Stream) // Boards like the RedBoard Turbo use SerialUSB (not Serial). @@ -826,7 +826,7 @@ class SFE_UBLOX_GNSS bool powerSaveMode(bool power_save = true, uint16_t maxWait = defaultMaxWait); uint8_t getPowerSaveMode(uint16_t maxWait = defaultMaxWait); // Returns 255 if the sendCommand fails bool powerOff(uint32_t durationInMs, uint16_t maxWait = defaultMaxWait); - bool powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, bool forceWhileUsb = true, uint16_t maxWait = 1100); + bool powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, bool forceWhileUsb = true, uint16_t maxWait = defaultMaxWait); //Change the dynamic platform model using UBX-CFG-NAV5 bool setDynamicModel(dynModel newDynamicModel = DYN_MODEL_PORTABLE, uint16_t maxWait = defaultMaxWait); @@ -1235,7 +1235,7 @@ class SFE_UBLOX_GNSS // Helper functions for HPPOSECEF - uint32_t getPositionAccuracy(uint16_t maxWait = 1100); //Returns the 3D accuracy of the current high-precision fix, in mm. Supported on NEO-M8P, ZED-F9P, + uint32_t getPositionAccuracy(uint16_t maxWait = defaultMaxWait); //Returns the 3D accuracy of the current high-precision fix, in mm. Supported on NEO-M8P, ZED-F9P, // Helper functions for HPPOSLLH @@ -1291,8 +1291,8 @@ class SFE_UBLOX_GNSS // Helper functions for HNR - bool setHNRNavigationRate(uint8_t rate, uint16_t maxWait = 1100); // Returns true if the setHNRNavigationRate is successful - uint8_t getHNRNavigationRate(uint16_t maxWait = 1100); // Returns 0 if the getHNRNavigationRate fails + bool setHNRNavigationRate(uint8_t rate, uint16_t maxWait = defaultMaxWait); // Returns true if the setHNRNavigationRate is successful + uint8_t getHNRNavigationRate(uint16_t maxWait = defaultMaxWait); // Returns 0 if the getHNRNavigationRate fails float getHNRroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees float getHNRpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees float getHNRheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees From 33f5dd2024bedcb2f9036853b728d94bccdbfd47 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 9 Dec 2021 13:10:36 +0000 Subject: [PATCH 041/122] Add softReset as an option for .begin --- keywords.txt | 1 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 82 +++++++++++++++++++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 9 ++- 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/keywords.txt b/keywords.txt index 60f06f1..3aad233 100644 --- a/keywords.txt +++ b/keywords.txt @@ -121,6 +121,7 @@ setNMEAOutputPort KEYWORD2 factoryReset KEYWORD2 hardReset KEYWORD2 +softwareResetGNSSOnly KEYWORD2 factoryDefault KEYWORD2 saveConfiguration KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 6fd38aa..8320188 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -438,7 +438,7 @@ void SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) } //Initialize the I2C port -bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t maxWait) +bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t maxWait, bool softReset) { commType = COMM_TYPE_I2C; _i2cPort = &wirePort; //Grab which port the user wants us to use @@ -460,20 +460,40 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t ma //New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) createFileBuffer(); + //Issue a soft reset to clear the buffers + if (softReset) + softwareResetGNSSOnly(); + // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored bool connected = isConnected(maxWait); if (!connected) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: isConnected - second attempt")); + } +#endif connected = isConnected(maxWait); + } if (!connected) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: isConnected - third attempt")); + } +#endif connected = isConnected(maxWait); + } return (connected); } //Initialize the Serial port -bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait) +bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool softReset) { commType = COMM_TYPE_SERIAL; _serialPort = &serialPort; //Grab which port the user wants us to use @@ -485,20 +505,40 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait) //New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) createFileBuffer(); + //Issue a soft reset to clear the buffers + if (softReset) + softwareResetGNSSOnly(); + // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored bool connected = isConnected(maxWait); if (!connected) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: isConnected - second attempt")); + } +#endif connected = isConnected(maxWait); + } if (!connected) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: isConnected - third attempt")); + } +#endif connected = isConnected(maxWait); + } return (connected); } // Initialize for SPI -bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait) +bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait, bool softReset) { commType = COMM_TYPE_SPI; _spiPort = &spiPort; @@ -538,14 +578,34 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, } } - // Call isConnected up to three times + //Issue a soft reset to clear the buffers + if (softReset) + softwareResetGNSSOnly(); + + // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored bool connected = isConnected(maxWait); if (!connected) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: isConnected - second attempt")); + } +#endif connected = isConnected(maxWait); + } if (!connected) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: isConnected - third attempt")); + } +#endif connected = isConnected(maxWait); + } return (connected); } @@ -5413,6 +5473,20 @@ void SFE_UBLOX_GNSS::hardReset() sendCommand(&packetCfg, 0); // don't expect ACK } +void SFE_UBLOX_GNSS::softwareResetGNSSOnly() +{ + // Issue controlled software reset (GNSS only) + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_RST; + packetCfg.len = 4; + packetCfg.startingSpot = 0; + payloadCfg[0] = 0; // hot start + payloadCfg[1] = 0; // hot start + payloadCfg[2] = 0x02; // 0x02 = Controlled software reset (GNSS only) + payloadCfg[3] = 0; // reserved + sendCommand(&packetCfg, 0); // don't expect ACK +} + //Reset module to factory defaults //This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods bool SFE_UBLOX_GNSS::factoryDefault(uint16_t maxWait) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index e0f866e..e5dbb61 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -599,11 +599,11 @@ class SFE_UBLOX_GNSS void setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize //By default use the default I2C address, and use Wire port - bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait); //Returns true if module is detected + bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait, bool softReset = false); //Returns true if module is detected //serialPort needs to be perviously initialized to correct baud rate - bool begin(Stream &serialPort, uint16_t maxWait = defaultMaxWait); //Returns true if module is detected + bool begin(Stream &serialPort, uint16_t maxWait = defaultMaxWait, bool softReset = false); //Returns true if module is detected //SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz) - bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = defaultMaxWait); + bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = defaultMaxWait, bool softReset = false); void end(void); //Stop all automatic message processing. Free all used RAM @@ -780,7 +780,8 @@ class SFE_UBLOX_GNSS void factoryReset(); //Send factory reset sequence (i.e. load "default" configuration and perform hardReset) void hardReset(); //Perform a reset leading to a cold start (zero info start-up) - bool factoryDefault(uint16_t maxWait = defaultMaxWait); //Reset module to factory defaults + void softwareResetGNSSOnly(); //Controlled Software Reset (GNSS only) only restarts the GNSS tasks, without reinitializing the full system or reloading any stored configuration. + bool factoryDefault(uint16_t maxWait = defaultMaxWait); //Reset module to factory defaults //Save configuration to BBR / Flash From 986cdceb945f0fce069b00cefdaa779bc805ab73 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 9 Dec 2021 14:24:52 +0000 Subject: [PATCH 042/122] Add assumeSuccess as a parameter for .begin If you are using Serial, and the module is already outputting messages at high navigation rate, .begin can often fail due to traffic congestion. You can: - use a long maxWait (5 seconds seems to work well) - use a short maxWait and set assumeSuccess to true --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 53 +++++++++++++------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 7 +-- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 8320188..34419a0 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -438,7 +438,7 @@ void SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) } //Initialize the I2C port -bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t maxWait, bool softReset) +bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t maxWait, bool assumeSuccess) { commType = COMM_TYPE_I2C; _i2cPort = &wirePort; //Grab which port the user wants us to use @@ -460,10 +460,6 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t ma //New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) createFileBuffer(); - //Issue a soft reset to clear the buffers - if (softReset) - softwareResetGNSSOnly(); - // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored bool connected = isConnected(maxWait); @@ -489,11 +485,22 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t ma connected = isConnected(maxWait); } + if ((!connected ) && assumeSuccess) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: third attempt failed. Assuming success...")); + } +#endif + return (true); + } + return (connected); } //Initialize the Serial port -bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool softReset) +bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool assumeSuccess) { commType = COMM_TYPE_SERIAL; _serialPort = &serialPort; //Grab which port the user wants us to use @@ -505,10 +512,6 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool softReset) //New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) createFileBuffer(); - //Issue a soft reset to clear the buffers - if (softReset) - softwareResetGNSSOnly(); - // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored bool connected = isConnected(maxWait); @@ -534,11 +537,22 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool softReset) connected = isConnected(maxWait); } + if ((!connected ) && assumeSuccess) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: third attempt failed. Assuming success...")); + } +#endif + return (true); + } + return (connected); } // Initialize for SPI -bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait, bool softReset) +bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait, bool assumeSuccess) { commType = COMM_TYPE_SPI; _spiPort = &spiPort; @@ -578,10 +592,6 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, } } - //Issue a soft reset to clear the buffers - if (softReset) - softwareResetGNSSOnly(); - // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored bool connected = isConnected(maxWait); @@ -607,6 +617,17 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, connected = isConnected(maxWait); } + if ((!connected ) && assumeSuccess) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("begin: third attempt failed. Assuming success...")); + } +#endif + return (true); + } + return (connected); } @@ -9702,9 +9723,7 @@ bool SFE_UBLOX_GNSS::getNavigationFrequencyInternal(uint16_t maxWait) return (true); if (retVal == SFE_UBLOX_STATUS_DATA_OVERWRITTEN) - { return (true); - } return (false); } diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index e5dbb61..6f5bc92 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -598,12 +598,13 @@ class SFE_UBLOX_GNSS //New in v2.0: allow the payload size for packetCfg to be changed void setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize + //Begin communication with the GNSS. Advanced users can assume success if required. Useful if the port is already outputting messages at high navigation rate. //By default use the default I2C address, and use Wire port - bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait, bool softReset = false); //Returns true if module is detected + bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); //Returns true if module is detected //serialPort needs to be perviously initialized to correct baud rate - bool begin(Stream &serialPort, uint16_t maxWait = defaultMaxWait, bool softReset = false); //Returns true if module is detected + bool begin(Stream &serialPort, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); //Returns true if module is detected //SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz) - bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = defaultMaxWait, bool softReset = false); + bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); void end(void); //Stop all automatic message processing. Free all used RAM From 0ecec8b34283904bda8fa3dbc770b8794aed7dd4 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 9 Dec 2021 14:25:32 +0000 Subject: [PATCH 043/122] v2.1.3 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index c52c9b2..b06dd6b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.1.2 +version=2.1.3 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial Communication with u-blox GNSS modules

From 4b582c886014370a45d4f5fb526ede11ebb5c279 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 9 Dec 2021 17:50:14 +0000 Subject: [PATCH 044/122] Add _signsOfLife and isNMEAHeaderValid --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 47 ++++++++++++++++++-- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 5 +++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 34419a0..3170beb 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -442,6 +442,7 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t ma { commType = COMM_TYPE_I2C; _i2cPort = &wirePort; //Grab which port the user wants us to use + _signsOfLife = false; //Clear the _signsOfLife flag. It will be set true if valid traffic is seen. //We expect caller to begin their I2C port, with the speed of their choice external to the library //But if they forget, we start the hardware here. @@ -485,7 +486,7 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t ma connected = isConnected(maxWait); } - if ((!connected ) && assumeSuccess) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + if ((!connected ) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -504,6 +505,7 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool assumeSucc { commType = COMM_TYPE_SERIAL; _serialPort = &serialPort; //Grab which port the user wants us to use + _signsOfLife = false; //Clear the _signsOfLife flag. It will be set true if valid traffic is seen. //New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already) if (packetCfgPayloadSize == 0) @@ -537,7 +539,7 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool assumeSucc connected = isConnected(maxWait); } - if ((!connected ) && assumeSuccess) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + if ((!connected ) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -558,6 +560,7 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, _spiPort = &spiPort; _csPin = csPin; _spiSpeed = spiSpeed; + _signsOfLife = false; //Clear the _signsOfLife flag. It will be set true if valid traffic is seen. // Initialize the chip select pin pinMode(_csPin, OUTPUT); @@ -617,7 +620,7 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, connected = isConnected(maxWait); } - if ((!connected ) && assumeSuccess) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + if ((!connected ) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -1637,6 +1640,11 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r if (nmeaByteCounter == 5) { + if (!_signsOfLife) // If _signsOfLife is not already true, set _signsOfLife to true if the NMEA header is valid + { + _signsOfLife = isNMEAHeaderValid(); + } + // We've just received the end of the address field. Check if it is selected for logging if (logThisNMEA()) { @@ -1710,6 +1718,38 @@ bool SFE_UBLOX_GNSS::logThisNMEA() return (false); } +// PRIVATE: Return true if the NMEA header is valid +bool SFE_UBLOX_GNSS::isNMEAHeaderValid() +{ + if (nmeaAddressField[0] != '*') return (false); + if (nmeaAddressField[1] != 'G') return (false); + if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M')) return (true); + if (nmeaAddressField[3] == 'G') + { + if ((nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q')) return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q')) return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S')) return (true); + if ((nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A')) return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L')) return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q')) return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q')) return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S')) return (true); + if ((nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q')) return (true); + if ((nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q')) return (true); + if ((nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S')) return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A')) return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T')) return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V')) return (true); + } + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M')) return (true); + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C')) return (true); + if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T')) return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W')) return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G')) return (true); + if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A')) return (true); + return (false); +} + // PRIVATE: Return true if we should pass this NMEA message to processNMEA bool SFE_UBLOX_GNSS::processThisNMEA() { @@ -1887,6 +1927,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ if ((incomingUBX->checksumA == rollingChecksumA) && (incomingUBX->checksumB == rollingChecksumB)) { incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_VALID; // Flag the packet as valid + _signsOfLife = true; //The checksum is valid, so set the _signsOfLife flag // Let's check if the class and ID match the requestedClass and requestedID // Remember - this could be a data packet or an ACK packet diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 6f5bc92..2f23313 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1498,6 +1498,7 @@ class SFE_UBLOX_GNSS uint8_t nmeaAddressField[6]; // NMEA Address Field - includes the start character (*) bool logThisNMEA(); // Return true if we should log this NMEA message bool processThisNMEA(); // Return true if we should pass this NMEA message to processNMEA + bool isNMEAHeaderValid(); // Return true if the six byte NMEA header appears valid. Used to set _signsOfLife uint16_t rtcmLen = 0; @@ -1527,6 +1528,10 @@ class SFE_UBLOX_GNSS bool _pushSingleByte = false; uint8_t _pushThisSingleByte; + // .begin will return true if the assumeSuccess parameter is true and if _signsOfLife is true + // _signsOfLife is set to true when: a valid UBX message is seen; a valig NMEA header is seen. + bool _signsOfLife; + }; #endif From af363909243e4f782513156abec85048d7f30e5f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 10 Dec 2021 10:36:05 +0000 Subject: [PATCH 045/122] For Serial, if assumeSuccess is true, also try to clear the buffers For Serial, if the Serial port is congested, .begin can fail when the NAV RATE messages are delayed. This is usually a sign that the baud rate is too low. Clearing the serial buffer first seems to help. --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 28 ++++++++++++++++++-- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 3170beb..0cba6fb 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -514,6 +514,30 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool assumeSucc //New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) createFileBuffer(); + //Get rid of any stale serial data already in the processor's RX buffer + while (_serialPort->available()) + _serialPort->read(); + + //If assumeSuccess is true, the user must really want begin to succeed. So, let's empty the module's serial transmit buffer too! + //Keep discarding new serial data until we see a gap of 2ms - hopefully indicating that the module's TX buffer is empty. + if (assumeSuccess) + { + unsigned long startTime = millis(); + unsigned long lastActivity = startTime; + bool keepGoing = true; + while (keepGoing && (millis() < (startTime + (unsigned long)maxWait))) + { + while (_serialPort->available()) // Discard any new data + { + _serialPort->read(); + lastActivity = millis(); + } + + if (millis() > (lastActivity + (unsigned long)2)) // Check if we have seen no new data for at least 2ms + keepGoing = false; + } + } + // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored bool connected = isConnected(maxWait); @@ -3642,7 +3666,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui packetAuto.classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; unsigned long startTime = millis(); - while (millis() - startTime < maxTime) + while (millis() < (startTime + (unsigned long)maxTime)) { if (checkUbloxInternal(outgoingUBX, requestedClass, requestedID) == true) //See if new data is available. Process bytes as they come in. { @@ -3781,7 +3805,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui } //checkUbloxInternal == true delay(1); // Allow an RTOS to get an elbow in (#11) - } //while (millis() - startTime < maxTime) + } //while (millis() < (startTime + (unsigned long)maxTime)) // We have timed out... // If the outgoingUBX->classAndIDmatch is VALID then we can take a gamble and return DATA_RECEIVED diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 2f23313..4b3194b 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -599,6 +599,7 @@ class SFE_UBLOX_GNSS void setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize //Begin communication with the GNSS. Advanced users can assume success if required. Useful if the port is already outputting messages at high navigation rate. + //Begin will then return true if "signs of life" have been seen: reception of _any_ valid UBX packet or _any_ valid NMEA header. //By default use the default I2C address, and use Wire port bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); //Returns true if module is detected //serialPort needs to be perviously initialized to correct baud rate From 2c47c098db1f6cc28f91fd8a7cf18c63718b87cc Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Sun, 12 Dec 2021 13:58:32 -0700 Subject: [PATCH 046/122] Add example 16: NTRIP Client with GGA support --- .../Example16_NTRIPClient_WithGGA.ino | 400 ++++++++++++++++++ .../Example16_NTRIPClient_WithGGA/secrets.h | 17 + 2 files changed, 417 insertions(+) create mode 100644 examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino create mode 100644 examples/ZED-F9P/Example16_NTRIPClient_WithGGA/secrets.h diff --git a/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino b/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino new file mode 100644 index 0000000..689527f --- /dev/null +++ b/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino @@ -0,0 +1,400 @@ +/* + Use ESP32 WiFi to get RTCM data from RTK2Go (caster) as a Client, and transmit GGA (needed for some Casters) + By: SparkFun Electronics / Nathan Seidle + Date: November 18th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to obtain RTCM data from a NTRIP Caster over WiFi + and push it over I2C to a ZED-F9x. + It's confusing, but the Arduino is acting as a 'client' to a 'caster'. In this case we will + use RTK2Go.com as our caster because it is free. See the NTRIPServer example to see how + to push RTCM data to the caster. + + The rover's location will be broadcast to the Caster every 10s via GGA setence. + + You will need to have a valid mountpoint available. To see available mountpoints go here: http://rtk2go.com:2101/ + + This is a proof of concept to show how to connect to a caster via HTTP. + + For more information about NTRIP Clients and the differences between Rev1 and Rev2 of the protocol + please see: https://www.use-snip.com/kb/knowledge-base/ntrip-rev1-versus-rev2-formats/ + + "In broad protocol terms, the NTRIP client must first connect (get an HTTP “OK” reply) and only then + should it send the sentence. NTRIP protocol revision 2 (which does not have very broad industry + acceptance at this time) does allow sending the sentence in the original header." + https://www.use-snip.com/kb/knowledge-base/subtle-issues-with-using-ntrip-client-nmea-183-strings/ + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + RTK Surveyor: https://www.sparkfun.com/products/18443 + RTK Express: https://www.sparkfun.com/products/18442 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +#include "secrets.h" + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//The ESP32 core has a built in base64 library but not every platform does +//We'll use an external lib if necessary. +#if defined(ARDUINO_ARCH_ESP32) +#include "base64.h" //Built-in ESP32 library +#else +#include //nfriendly library from https://github.com/adamvr/arduino-base64, will work with any platform +#endif + +//Global variables +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long lastReceivedRTCM_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps +int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster + +bool transmitLocation = true; //By default we will transmit the units location via GGA sentence. +int timeBetweenGGAUpdate_ms = 10000; //GGA is required for Rev2 NTRIP casters. Don't transmit but once every 10 seconds +long lastTransmittedGGA_ms = 0; + +//Used for GGA sentence parsing from incoming NMEA +bool ggaSentenceStarted = false; +bool ggaSentenceComplete = false; +bool ggaTransmitComplete = false; //Goes true once we transmit GGA to the caster + +char ggaSentence[128] = {0}; +byte ggaSentenceSpot = 0; +int ggaSentenceEndSpot = 0; +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + Serial.begin(115200); + Serial.println(F("NTRIP testing")); + + Wire.begin(); //Start I2C + + while(myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + delay(2000); + //while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages + myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); //Be sure RTCM3 input is enabled. UBX + RTCM3 is not a valid state. + + myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); //Verify the GGA sentence is enabled + + myGNSS.setNavigationFrequency(1); //Set output in Hz. + + Serial.print(F("Connecting to local WiFi")); + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.print(F("WiFi connected with IP: ")); + Serial.println(WiFi.localIP()); + + while (Serial.available()) Serial.read(); +} + +void loop() +{ + if (Serial.available()) + { + beginClient(); + while (Serial.available()) Serial.read(); //Empty buffer of any newline chars + } + + Serial.println(F("Press any key to start NTRIP Client.")); + + delay(1000); +} + +//Connect to NTRIP Caster, receive RTCM, and push to ZED module over I2C +void beginClient() +{ + WiFiClient ntripClient; + long rtcmCount = 0; + + Serial.println(F("Subscribing to Caster. Press key to stop")); + delay(10); //Wait for any serial to arrive + while (Serial.available()) Serial.read(); //Flush + + while (Serial.available() == 0) + { + myGNSS.checkUblox(); + + //Connect if we are not already. Limit to 5s between attempts. + if (ntripClient.connected() == false) + { + Serial.print(F("Opening socket to ")); + Serial.println(casterHost); + + if (ntripClient.connect(casterHost, casterPort) == false) //Attempt connection + { + Serial.println(F("Connection to caster failed")); + return; + } + else + { + Serial.print(F("Connected to ")); + Serial.print(casterHost); + Serial.print(F(": ")); + Serial.println(casterPort); + + Serial.print(F("Requesting NTRIP Data from mount point ")); + Serial.println(mountPoint); + + const int SERVER_BUFFER_SIZE = 512; + char serverRequest[SERVER_BUFFER_SIZE]; + + snprintf(serverRequest, + SERVER_BUFFER_SIZE, + "GET /%s HTTP/1.0\r\nUser-Agent: NTRIP SparkFun u-blox Client v1.0\r\n", + mountPoint); + + char credentials[512]; + if (strlen(casterUser) == 0) + { + strncpy(credentials, "Accept: */*\r\nConnection: close\r\n", sizeof(credentials)); + } + else + { + //Pass base64 encoded user:pw + char userCredentials[sizeof(casterUser) + sizeof(casterUserPW) + 1]; //The ':' takes up a spot + snprintf(userCredentials, sizeof(userCredentials), "%s:%s", casterUser, casterUserPW); + + Serial.print(F("Sending credentials: ")); + Serial.println(userCredentials); + +#if defined(ARDUINO_ARCH_ESP32) + //Encode with ESP32 built-in library + base64 b; + String strEncodedCredentials = b.encode(userCredentials); + char encodedCredentials[strEncodedCredentials.length() + 1]; + strEncodedCredentials.toCharArray(encodedCredentials, sizeof(encodedCredentials)); //Convert String to char array + snprintf(credentials, sizeof(credentials), "Authorization: Basic %s\r\n", encodedCredentials); +#else + //Encode with nfriendly library + int encodedLen = base64_enc_len(strlen(userCredentials)); + char encodedCredentials[encodedLen]; //Create array large enough to house encoded data + base64_encode(encodedCredentials, userCredentials, strlen(userCredentials)); //Note: Input array is consumed +#endif + } + strncat(serverRequest, credentials, SERVER_BUFFER_SIZE); + strncat(serverRequest, "\r\n", SERVER_BUFFER_SIZE); + + Serial.print(F("serverRequest size: ")); + Serial.print(strlen(serverRequest)); + Serial.print(F(" of ")); + Serial.print(sizeof(serverRequest)); + Serial.println(F(" bytes available")); + + Serial.println(F("Sending server request:")); + Serial.println(serverRequest); + ntripClient.write(serverRequest, strlen(serverRequest)); + + //Wait for response + unsigned long timeout = millis(); + while (ntripClient.available() == 0) + { + if (millis() - timeout > 5000) + { + Serial.println(F("Caster timed out!")); + ntripClient.stop(); + return; + } + delay(10); + } + + //Check reply + bool connectionSuccess = false; + char response[512]; + int responseSpot = 0; + while (ntripClient.available()) + { + if (responseSpot == sizeof(response) - 1) break; + + response[responseSpot++] = ntripClient.read(); + if (strstr(response, "200") > 0) //Look for '200 OK' + connectionSuccess = true; + if (strstr(response, "401") > 0) //Look for '401 Unauthorized' + { + Serial.println(F("Hey - your credentials look bad! Check you caster username and password.")); + connectionSuccess = false; + } + } + response[responseSpot] = '\0'; + + Serial.print(F("Caster responded with: ")); + Serial.println(response); + + if (connectionSuccess == false) + { + Serial.print(F("Failed to connect to ")); + Serial.println(casterHost); + return; + } + else + { + Serial.print(F("Connected to ")); + Serial.println(casterHost); + lastReceivedRTCM_ms = millis(); //Reset timeout + ggaTransmitComplete = true; //Reset to start polling for new GGA data + } + } //End attempt to connect + } //End connected == false + + if (ntripClient.connected() == true) + { + uint8_t rtcmData[512 * 4]; //Most incoming data is around 500 bytes but may be larger + rtcmCount = 0; + + //Print any available RTCM data + while (ntripClient.available()) + { + //Serial.write(ntripClient.read()); //Pipe to serial port is fine but beware, it's a lot of binary data + rtcmData[rtcmCount++] = ntripClient.read(); + if (rtcmCount == sizeof(rtcmData)) break; + } + + if (rtcmCount > 0) + { + lastReceivedRTCM_ms = millis(); + + //Push RTCM to GNSS module over I2C + myGNSS.pushRawData(rtcmData, rtcmCount, false); + Serial.print(F("RTCM pushed to ZED: ")); + Serial.println(rtcmCount); + } + } + + //Provide the caster with our current position as needed + if (ntripClient.connected() == true + && transmitLocation == true + && (millis() - lastTransmittedGGA_ms) > timeBetweenGGAUpdate_ms + && ggaSentenceComplete == true + && ggaTransmitComplete == false + ) + { + Serial.print(F("Pushing GGA to server: ")); + Serial.println(ggaSentence); + + lastTransmittedGGA_ms = millis(); + + //Push our current GGA sentence to caster + ntripClient.print(ggaSentence); + ntripClient.print("\r\n"); + + ggaTransmitComplete = true; + + //Wait for response + unsigned long timeout = millis(); + while (ntripClient.available() == 0) + { + if (millis() - timeout > 5000) + { + Serial.println(F("Caster timed out!")); + ntripClient.stop(); + return; + } + delay(10); + } + + //Check reply + bool connectionSuccess = false; + char response[512]; + int responseSpot = 0; + while (ntripClient.available()) + { + if (responseSpot == sizeof(response) - 1) break; + + response[responseSpot++] = ntripClient.read(); + if (strstr(response, "200") > 0) //Look for '200 OK' + connectionSuccess = true; + if (strstr(response, "401") > 0) //Look for '401 Unauthorized' + { + Serial.println(F("Hey - your credentials look bad! Check you caster username and password.")); + connectionSuccess = false; + } + } + response[responseSpot] = '\0'; + + Serial.print(F("Caster responded with: ")); + Serial.println(response); + } + + //Close socket if we don't have new data for 10s + if (millis() - lastReceivedRTCM_ms > maxTimeBeforeHangup_ms) + { + Serial.println(F("RTCM timeout. Disconnecting...")); + if (ntripClient.connected() == true) + ntripClient.stop(); + return; + } + + delay(10); + } + + Serial.println(F("User pressed a key")); + Serial.println(F("Disconnecting...")); + ntripClient.stop(); +} + +//This function gets called from the SparkFun u-blox Arduino Library +//As each NMEA character comes in you can specify what to do with it +//We will look for and copy the GGA sentence +void SFE_UBLOX_GNSS::processNMEA(char incoming) +{ + //Take the incoming char from the u-blox I2C port and check to see if we should record it or not + if (incoming == '$' && ggaTransmitComplete == true) + { + ggaSentenceStarted = true; + ggaSentenceSpot = 0; + ggaSentenceEndSpot = sizeof(ggaSentence); + ggaSentenceComplete = false; + } + + if (ggaSentenceStarted == true) + { + ggaSentence[ggaSentenceSpot++] = incoming; + + //Make sure we don't go out of bounds + if (ggaSentenceSpot == sizeof(ggaSentence)) + { + //Start over + ggaSentenceStarted = false; + } + //Verify this is the GGA setence + else if (ggaSentenceSpot == 5 && incoming != 'G') + { + //Ignore this sentence, start over + ggaSentenceStarted = false; + } + else if (incoming == '*') + { + //We're near the end. Keep listening for two more bytes to complete the CRC + ggaSentenceEndSpot = ggaSentenceSpot + 2; + } + else if (ggaSentenceSpot == ggaSentenceEndSpot) + { + ggaSentence[ggaSentenceSpot] = '\0'; //Terminate this string + ggaSentenceComplete = true; + ggaTransmitComplete = false; //We are ready for transmission + + //Serial.print("GGA Parsed - "); + //Serial.println(ggaSentence); + + //Start over + ggaSentenceStarted = false; + } + } +} diff --git a/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/secrets.h b/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/secrets.h new file mode 100644 index 0000000..3a6becf --- /dev/null +++ b/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/secrets.h @@ -0,0 +1,17 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "parachutes"; + +//RTK2Go works well and is free +const char casterHost[] = "rtk2go.com"; +const uint16_t casterPort = 2101; +const char casterUser[] = "myEmail@test.com"; //User must provide their own email address to use RTK2Go +const char casterUserPW[] = ""; +const char mountPoint[] = "bldr_SparkFun1"; //The mount point you want to get data from + +//Emlid Caster also works well and is free +//const char casterHost[] = "caster.emlid.com"; +//const uint16_t casterPort = 2101; +//const char casterUser[] = "u99696"; //User name and pw must be obtained through their web portal +//const char casterUserPW[] = "466zez"; +//const char mountPoint[] = "MP1979"; //The mount point you want to get data from From 460836c5c1f9a70479a127d4516c8bda12d60f54 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Sun, 12 Dec 2021 21:36:25 -0700 Subject: [PATCH 047/122] Refactor example 14. Add Emlid as target. --- .../Example14_NTRIPServer.ino | 103 ++++++++++-------- .../ZED-F9P/Example14_NTRIPServer/secrets.h | 18 ++- 2 files changed, 69 insertions(+), 52 deletions(-) diff --git a/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino b/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino index ca01530..86a93a5 100644 --- a/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino +++ b/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino @@ -1,7 +1,5 @@ /* - Note: compiles OK with v2.0 but is currently untested - - Use ESP32 WiFi to push RTCM data to RTK2Go (caster) as a Server + Use ESP32 WiFi to push RTCM data to RTK2Go (Caster) as a Server By: SparkFun Electronics / Nathan Seidle Date: December 14th, 2020 License: MIT. See license file for more information but you can @@ -33,26 +31,21 @@ #include #include "secrets.h" -WiFiClient client; +WiFiClient ntripCaster; -#include //Needed for I2C to GNSS +#include #include //http://librarymanager/All#SparkFun_u-blox_GNSS SFE_UBLOX_GNSS myGNSS; -//Basic Connection settings to RTK2Go NTRIP Caster - See secrets for mount specific credentials +//Global Variables //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -const uint16_t casterPort = 2101; -const char * casterHost = "rtk2go.com"; -const char * ntrip_server_name = "SparkFun_RTK_Surveyor"; - -long lastSentRTCM_ms = 0; //Time of last data pushed to socket +long lastSentRTCM_ms = 0; //Time of last data pushed to socket int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster uint32_t serverBytesSent = 0; //Just a running total +long lastReport_ms = 0; //Time of last report of bytes sent //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -long lastReport_ms = 0; //Time of last report of bytes sent - void setup() { Serial.begin(115200); // You may need to increase this for high navigation rates! @@ -73,7 +66,8 @@ void setup() Serial.print("Connecting to local WiFi"); WiFi.begin(ssid, password); - while (WiFi.status() != WL_CONNECTED) { + while (WiFi.status() != WL_CONNECTED) + { delay(500); Serial.print("."); } @@ -98,7 +92,8 @@ void setup() if (response == false) { Serial.println(F("Failed to disable NMEA. Freezing...")); - while (1); + while (1) + ; } else Serial.println(F("NMEA disabled")); @@ -114,7 +109,8 @@ void setup() if (response == false) { Serial.println(F("Failed to enable RTCM. Freezing...")); - while (1); + while (1) + ; } else Serial.println(F("RTCM sentences enabled")); @@ -129,63 +125,70 @@ void setup() if (response == false) { Serial.println(F("Failed to enter static position. Freezing...")); - while (1); + while (1) + ; } else Serial.println(F("Static position set")); - //You could instead do a survey-in but it takes much longer to start generating RTCM data. See Example4_BaseWithLCD + //Alternatively to setting a static position, you could do a survey-in + //but it takes much longer to start generating RTCM data. See Example4_BaseWithLCD //myGNSS.enableSurveyMode(60, 5.000); //Enable Survey in, 60 seconds, 5.0m if (myGNSS.saveConfiguration() == false) //Save the current settings to flash and BBR - Serial.println(F("Module failed to save.")); + Serial.println(F("Module failed to save")); Serial.println(F("Module configuration complete")); } void loop() { - if (Serial.available()) beginServing(); + if (Serial.available()) + beginServing(); - Serial.println(F("Press any key to start serving.")); + Serial.println(F("Press any key to start serving")); delay(1000); } void beginServing() { - Serial.println("Xmit to RTK2Go. Press any key to stop"); + Serial.println("Begin transmitting to caster. Press any key to stop"); delay(10); //Wait for any serial to arrive - while (Serial.available()) Serial.read(); //Flush + while (Serial.available()) + Serial.read(); //Flush while (Serial.available() == 0) { //Connect if we are not already - if (client.connected() == false) + if (ntripCaster.connected() == false) { Serial.printf("Opening socket to %s\n", casterHost); - if (client.connect(casterHost, casterPort) == true) //Attempt connection + if (ntripCaster.connect(casterHost, casterPort) == true) //Attempt connection { Serial.printf("Connected to %s:%d\n", casterHost, casterPort); - const int SERVER_BUFFER_SIZE = 512; - char serverBuffer[SERVER_BUFFER_SIZE]; + const int SERVER_BUFFER_SIZE = 512; + char serverRequest[SERVER_BUFFER_SIZE]; - snprintf(serverBuffer, SERVER_BUFFER_SIZE, "SOURCE %s /%s\r\nSource-Agent: NTRIP %s/%s\r\n\r\n", - mntpnt_pw, mntpnt, ntrip_server_name, "App Version 1.0"); + snprintf(serverRequest, + SERVER_BUFFER_SIZE, + "SOURCE %s /%s\r\nSource-Agent: NTRIP SparkFun u-blox Server v1.0\r\n\r\n", + mountPointPW, mountPoint); - Serial.printf("Sending credentials:\n%s\n", serverBuffer); - client.write(serverBuffer, strlen(serverBuffer)); + Serial.println(F("Sending server request:")); + Serial.println(serverRequest); + ntripCaster.write(serverRequest, strlen(serverRequest)); //Wait for response unsigned long timeout = millis(); - while (client.available() == 0) + while (ntripCaster.available() == 0) { if (millis() - timeout > 5000) { - Serial.println(">>> Client Timeout !"); - client.stop(); + Serial.println("Caster timed out!"); + ntripCaster.stop(); return; } delay(10); @@ -195,30 +198,34 @@ void beginServing() bool connectionSuccess = false; char response[512]; int responseSpot = 0; - while (client.available()) + while (ntripCaster.available()) { - response[responseSpot++] = client.read(); + response[responseSpot++] = ntripCaster.read(); if (strstr(response, "200") > 0) //Look for 'ICY 200 OK' connectionSuccess = true; - if (responseSpot == 512 - 1) break; + if (responseSpot == 512 - 1) + break; } response[responseSpot] = '\0'; if (connectionSuccess == false) { - Serial.printf("Failed to connect to RTK2Go: %s", response); + Serial.printf("Failed to connect to Caster: %s", response); + return; } } //End attempt to connect else { Serial.println("Connection to host failed"); + return; } } //End connected == false - if (client.connected() == true) + if (ntripCaster.connected() == true) { delay(10); - while (Serial.available()) Serial.read(); //Flush any endlines or carriage returns + while (Serial.available()) + Serial.read(); //Flush any endlines or carriage returns lastReport_ms = millis(); lastSentRTCM_ms = millis(); @@ -226,7 +233,8 @@ void beginServing() //This is the main sending loop. We scan for new ublox data but processRTCM() is where the data actually gets sent out. while (1) { - if (Serial.available()) break; + if (Serial.available()) + break; myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in. @@ -236,7 +244,7 @@ void beginServing() if (millis() - lastSentRTCM_ms > maxTimeBeforeHangup_ms) { Serial.println("RTCM timeout. Disconnecting..."); - client.stop(); + ntripCaster.stop(); return; } @@ -256,10 +264,11 @@ void beginServing() Serial.println("User pressed a key"); Serial.println("Disconnecting..."); - client.stop(); + ntripCaster.stop(); delay(10); - while (Serial.available()) Serial.read(); //Flush any endlines or carriage returns + while (Serial.available()) + Serial.read(); //Flush any endlines or carriage returns } //This function gets called from the SparkFun u-blox Arduino Library. @@ -267,10 +276,10 @@ void beginServing() //Useful for passing the RTCM correction data to a radio, Ntrip broadcaster, etc. void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming) { - if (client.connected() == true) + if (ntripCaster.connected() == true) { - client.write(incoming); //Send this byte to socket + ntripCaster.write(incoming); //Send this byte to socket serverBytesSent++; lastSentRTCM_ms = millis(); } -} +} \ No newline at end of file diff --git a/examples/ZED-F9P/Example14_NTRIPServer/secrets.h b/examples/ZED-F9P/Example14_NTRIPServer/secrets.h index 5dcd50e..8cd0920 100644 --- a/examples/ZED-F9P/Example14_NTRIPServer/secrets.h +++ b/examples/ZED-F9P/Example14_NTRIPServer/secrets.h @@ -1,7 +1,15 @@ //Your WiFi credentials -const char* ssid = "TRex"; -const char* password = "hasBigTeeth"; +const char *ssid = "TRex"; +const char *password = "hasBigTeeth"; -//Your RTK2GO mount point credentials -const char* mntpnt_pw = "WR5wRo4H"; -const char* mntpnt = "bldr_dwntwn2"; +//RTK2Go works well and is free +const char casterHost[] = "rtk2go.com"; +const uint16_t casterPort = 2101; +const char mountPoint[] = "bldr_dwntwn2"; //The mount point you want to push data to +const char mountPointPW[] = "WR5wRo4H"; + +//Emlid Caster also works well and is free +//const char casterHost[] = "caster.emlid.com"; +//const uint16_t casterPort = 2101; +//const char mountPoint[] = "MP1979d"; //The mount point you want to push data to +//const char mountPointPW[] = "296ynq"; From 1b3f033792e5061d70004db8c1fc6665e5c9dffa Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Sun, 12 Dec 2021 21:44:26 -0700 Subject: [PATCH 048/122] Disable save in ex 14 so other examples work. --- .../ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino b/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino index 86a93a5..aebdd31 100644 --- a/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino +++ b/examples/ZED-F9P/Example14_NTRIPServer/Example14_NTRIPServer.ino @@ -135,8 +135,10 @@ void setup() //but it takes much longer to start generating RTCM data. See Example4_BaseWithLCD //myGNSS.enableSurveyMode(60, 5.000); //Enable Survey in, 60 seconds, 5.0m - if (myGNSS.saveConfiguration() == false) //Save the current settings to flash and BBR - Serial.println(F("Module failed to save")); + //If you were setting up a full GNSS station, you would want to save these settings. + //Because setting an incorrect static position will disable the ability to get a lock, we will skip saving during this example + //if (myGNSS.saveConfiguration() == false) //Save the current settings to flash and BBR + // Serial.println(F("Module failed to save")); Serial.println(F("Module configuration complete")); } From 356a43ded63b9bd2b0edefca4673ad7517b847a4 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Sun, 12 Dec 2021 21:46:36 -0700 Subject: [PATCH 049/122] Move snprintf to work with any architecture. --- .../Example16_NTRIPClient_WithGGA.ino | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino b/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino index 689527f..b2506eb 100644 --- a/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino +++ b/examples/ZED-F9P/Example16_NTRIPClient_WithGGA/Example16_NTRIPClient_WithGGA.ino @@ -15,16 +15,16 @@ You will need to have a valid mountpoint available. To see available mountpoints go here: http://rtk2go.com:2101/ - This is a proof of concept to show how to connect to a caster via HTTP. + This is a proof of concept to show how to connect to a caster via HTTP. For more information about NTRIP Clients and the differences between Rev1 and Rev2 of the protocol please see: https://www.use-snip.com/kb/knowledge-base/ntrip-rev1-versus-rev2-formats/ - "In broad protocol terms, the NTRIP client must first connect (get an HTTP “OK” reply) and only then - should it send the sentence. NTRIP protocol revision 2 (which does not have very broad industry + "In broad protocol terms, the NTRIP client must first connect (get an HTTP “OK” reply) and only then + should it send the sentence. NTRIP protocol revision 2 (which does not have very broad industry acceptance at this time) does allow sending the sentence in the original header." https://www.use-snip.com/kb/knowledge-base/subtle-issues-with-using-ntrip-client-nmea-183-strings/ - + Feel like supporting open source hardware? Buy a board from SparkFun! ZED-F9P RTK2: https://www.sparkfun.com/products/16481 @@ -52,10 +52,10 @@ SFE_UBLOX_GNSS myGNSS; //Global variables //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -long lastReceivedRTCM_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps +long lastReceivedRTCM_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster -bool transmitLocation = true; //By default we will transmit the units location via GGA sentence. +bool transmitLocation = true; //By default we will transmit the units location via GGA sentence. int timeBetweenGGAUpdate_ms = 10000; //GGA is required for Rev2 NTRIP casters. Don't transmit but once every 10 seconds long lastTransmittedGGA_ms = 0; @@ -76,7 +76,7 @@ void setup() Wire.begin(); //Start I2C - while(myGNSS.begin() == false) //Connect to the Ublox module using Wire port + while (myGNSS.begin() == false) //Connect to the Ublox module using Wire port { Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); delay(2000); @@ -84,7 +84,7 @@ void setup() } Serial.println(F("u-blox module connected")); - myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages + myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); //Be sure RTCM3 input is enabled. UBX + RTCM3 is not a valid state. myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); //Verify the GGA sentence is enabled @@ -93,7 +93,8 @@ void setup() Serial.print(F("Connecting to local WiFi")); WiFi.begin(ssid, password); - while (WiFi.status() != WL_CONNECTED) { + while (WiFi.status() != WL_CONNECTED) + { delay(500); Serial.print(F(".")); } @@ -102,7 +103,8 @@ void setup() Serial.print(F("WiFi connected with IP: ")); Serial.println(WiFi.localIP()); - while (Serial.available()) Serial.read(); + while (Serial.available()) + Serial.read(); } void loop() @@ -110,7 +112,8 @@ void loop() if (Serial.available()) { beginClient(); - while (Serial.available()) Serial.read(); //Empty buffer of any newline chars + while (Serial.available()) + Serial.read(); //Empty buffer of any newline chars } Serial.println(F("Press any key to start NTRIP Client.")); @@ -126,12 +129,13 @@ void beginClient() Serial.println(F("Subscribing to Caster. Press key to stop")); delay(10); //Wait for any serial to arrive - while (Serial.available()) Serial.read(); //Flush + while (Serial.available()) + Serial.read(); //Flush while (Serial.available() == 0) { myGNSS.checkUblox(); - + //Connect if we are not already. Limit to 5s between attempts. if (ntripClient.connected() == false) { @@ -181,13 +185,14 @@ void beginClient() String strEncodedCredentials = b.encode(userCredentials); char encodedCredentials[strEncodedCredentials.length() + 1]; strEncodedCredentials.toCharArray(encodedCredentials, sizeof(encodedCredentials)); //Convert String to char array - snprintf(credentials, sizeof(credentials), "Authorization: Basic %s\r\n", encodedCredentials); #else //Encode with nfriendly library int encodedLen = base64_enc_len(strlen(userCredentials)); - char encodedCredentials[encodedLen]; //Create array large enough to house encoded data + char encodedCredentials[encodedLen]; //Create array large enough to house encoded data base64_encode(encodedCredentials, userCredentials, strlen(userCredentials)); //Note: Input array is consumed #endif + + snprintf(credentials, sizeof(credentials), "Authorization: Basic %s\r\n", encodedCredentials); } strncat(serverRequest, credentials, SERVER_BUFFER_SIZE); strncat(serverRequest, "\r\n", SERVER_BUFFER_SIZE); @@ -221,7 +226,8 @@ void beginClient() int responseSpot = 0; while (ntripClient.available()) { - if (responseSpot == sizeof(response) - 1) break; + if (responseSpot == sizeof(response) - 1) + break; response[responseSpot++] = ntripClient.read(); if (strstr(response, "200") > 0) //Look for '200 OK' @@ -248,10 +254,10 @@ void beginClient() Serial.print(F("Connected to ")); Serial.println(casterHost); lastReceivedRTCM_ms = millis(); //Reset timeout - ggaTransmitComplete = true; //Reset to start polling for new GGA data + ggaTransmitComplete = true; //Reset to start polling for new GGA data } } //End attempt to connect - } //End connected == false + } //End connected == false if (ntripClient.connected() == true) { @@ -263,7 +269,8 @@ void beginClient() { //Serial.write(ntripClient.read()); //Pipe to serial port is fine but beware, it's a lot of binary data rtcmData[rtcmCount++] = ntripClient.read(); - if (rtcmCount == sizeof(rtcmData)) break; + if (rtcmCount == sizeof(rtcmData)) + break; } if (rtcmCount > 0) @@ -278,12 +285,7 @@ void beginClient() } //Provide the caster with our current position as needed - if (ntripClient.connected() == true - && transmitLocation == true - && (millis() - lastTransmittedGGA_ms) > timeBetweenGGAUpdate_ms - && ggaSentenceComplete == true - && ggaTransmitComplete == false - ) + if (ntripClient.connected() == true && transmitLocation == true && (millis() - lastTransmittedGGA_ms) > timeBetweenGGAUpdate_ms && ggaSentenceComplete == true && ggaTransmitComplete == false) { Serial.print(F("Pushing GGA to server: ")); Serial.println(ggaSentence); @@ -315,7 +317,8 @@ void beginClient() int responseSpot = 0; while (ntripClient.available()) { - if (responseSpot == sizeof(response) - 1) break; + if (responseSpot == sizeof(response) - 1) + break; response[responseSpot++] = ntripClient.read(); if (strstr(response, "200") > 0) //Look for '200 OK' @@ -397,4 +400,4 @@ void SFE_UBLOX_GNSS::processNMEA(char incoming) ggaSentenceStarted = false; } } -} +} \ No newline at end of file From 61b49ce53bb05aefe89cec439861b242108bd499 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 14 Dec 2021 10:45:51 +0000 Subject: [PATCH 050/122] v2.1.4 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index b06dd6b..ce120ad 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.1.3 +version=2.1.4 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial Communication with u-blox GNSS modules

From c64b230da9ec3dd6efd6c4f0cb50b37a23cab137 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 22 Dec 2021 11:28:20 +0000 Subject: [PATCH 051/122] Update UBX_Integrity_Checker.py --- Utils/UBX_Integrity_Checker.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Utils/UBX_Integrity_Checker.py b/Utils/UBX_Integrity_Checker.py index a956881..825678e 100644 --- a/Utils/UBX_Integrity_Checker.py +++ b/Utils/UBX_Integrity_Checker.py @@ -102,7 +102,6 @@ def csum(byte, sum1, sum2): processed = -1 # The number of bytes processed messages = {} # The collected message types -longest = 0 # The length of the longest UBX message keepGoing = True # Sync 'state machine' @@ -132,6 +131,8 @@ def csum(byte, sum1, sum2): ubx_checksum_B = 0 ubx_expected_checksum_A = 0 ubx_expected_checksum_B = 0 +longest_UBX = 0 # The length of the longest UBX message +longest_UBX_candidate = 0 # Candidate for the length of the longest valid UBX message # Storage for NMEA messages nmea_length = 0 @@ -145,8 +146,9 @@ def csum(byte, sum1, sum2): nmea_csum2 = 0 nmea_expected_csum1 = 0 nmea_expected_csum2 = 0 +longest_NMEA = 0 # The length of the longest valid NMEA message -max_nmea_len = 100 # Maximum length for an NMEA message: use this to detect if we have lost sync while receiving an NMEA message +max_nmea_len = 128 # Maximum length for an NMEA message: use this to detect if we have lost sync while receiving an NMEA message sync_lost_at = -1 # Record where we lost sync rewind_to = -1 # Keep a note of where we should rewind to if sync is lost rewind_attempts = 0 # Keep a note of how many rewinds have been attempted @@ -257,8 +259,7 @@ def csum(byte, sum1, sum2): ubx_length = ubx_length + (c * 256) # Add the length MSB ubx_expected_checksum_A = ubx_expected_checksum_A + c # Update the expected checksum ubx_expected_checksum_B = ubx_expected_checksum_B + ubx_expected_checksum_A - if (ubx_length > longest): # Update the longest UBX message length - longest = ubx_length + longest_UBX_candidate = ubx_length + 8 # Update the longest UBX message length candidate. Include the header, class, ID, length and checksum bytes rewind_to = processed # If we lose sync due to dropped bytes then rewind to here ubx_nmea_state = processing_payload # Now look for payload bytes (length: ubx_length) elif (ubx_nmea_state == processing_payload): @@ -287,6 +288,8 @@ def csum(byte, sum1, sum2): messages[message_type] += 1 # if we have, increment its count else: messages[message_type] = 1 # if we have not, set its count to 1 + if (longest_UBX_candidate > longest_UBX): # Update the longest UBX message length + longest_UBX = longest_UBX_candidate rewind_in_progress = False # Clear rewind_in_progress rewind_to = -1 if (resync_in_progress == True): # Check if we are resyncing @@ -330,6 +333,8 @@ def csum(byte, sum1, sum2): else: # ubx_length == 5 nmea_char_5 = c message_type = chr(nmea_char_1) + chr(nmea_char_2) + chr(nmea_char_3) + chr(nmea_char_4) + chr(nmea_char_5) # Record the message type + if (message_type == "PUBX,"): # Remove the comma from PUBX + message_type = "PUBX" # Now check if this is an '*' if (c == 0x2A): # Asterix received @@ -389,6 +394,8 @@ def csum(byte, sum1, sum2): messages[message_type] += 1 # if we have, increment its count else: messages[message_type] = 1 # if we have not, set its count to 1 + if (nmea_length > longest_NMEA): # Update the longest NMEA message length + longest_NMEA = nmea_length # LF was received so go back to looking for B5 or a $ ubx_nmea_state = looking_for_B5_dollar rewind_in_progress = False # Clear rewind_in_progress @@ -441,7 +448,9 @@ def csum(byte, sum1, sum2): print('File size was',filesize) if (processed != filesize): print('FILE SIZE MISMATCH!!') - print('Longest UBX message was %i data bytes'%longest) + print('Longest valid UBX message was %i bytes'%longest_UBX) + if (containsNMEA == True): + print('Longest valid NMEA message was %i characters'%longest_NMEA) if len(messages) > 0: print('Message types and totals were:') for key in messages.keys(): From 1a90ba12c1f90c14f872a0d2754738fcc8ac57e6 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 9 Jan 2022 17:07:41 +0000 Subject: [PATCH 052/122] Correct pushAssistNowDataInternal - it wasn't using numDataBytes correctly. --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 31 +++++++------------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 4 ++- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 0cba6fb..c13e4db 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4363,20 +4363,6 @@ size_t SFE_UBLOX_GNSS::pushAssistNowData(size_t offset, bool skipTime, const uin size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { size_t dataPtr = offset; // Pointer into dataBytes - - if (offset >= numDataBytes) // Sanity check. Return now if offset is invalid. - { -#ifndef SFE_UBLOX_REDUCED_PROG_MEM - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->print(F("pushAssistNowData: offset (")); - _debugSerial->print(offset); - _debugSerial->println(F(") is invalid! Aborting...")); - } -#endif - return ((size_t)0); - } - size_t packetsProcessed = 0; // Keep count of how many packets have been processed size_t bytesPushed = 0; // Keep count @@ -4406,7 +4392,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c return (0); } - while (dataPtr < numDataBytes) // Keep going until we have processed all the bytes + while (dataPtr < (offset + numDataBytes)) // Keep going until we have processed all the bytes { // Start by checking the validity of the packet being pointed to bool dataIsOK = true; @@ -4421,8 +4407,8 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c uint8_t checksumB = 0; // Calculate the checksum bytes // Keep going until the end of the packet is reached (payloadPtr == (dataPtr + packetLength)) - // or we reach the end of the AssistNow data (payloadPtr == numDataBytes) - for (size_t payloadPtr = dataPtr + ((size_t)2); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++) + // or we reach the end of the AssistNow data (payloadPtr == offset + numDataBytes) + for (size_t payloadPtr = dataPtr + ((size_t)2); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < (offset + numDataBytes)); payloadPtr++) { checksumA += *(dataBytes + payloadPtr); checksumB += checksumA; @@ -4431,7 +4417,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c dataIsOK &= (checksumA == *(dataBytes + dataPtr + packetLength + ((size_t)6))); dataIsOK &= (checksumB == *(dataBytes + dataPtr + packetLength + ((size_t)7))); - dataIsOK &= ((dataPtr + packetLength + ((size_t)8)) <= numDataBytes); // Check we haven't overrun + dataIsOK &= ((dataPtr + packetLength + ((size_t)8)) <= (offset + numDataBytes)); // Check we haven't overrun // If the data is valid, push it if (dataIsOK) @@ -4527,7 +4513,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c // We are not checking for Acks, so let's assume the send was successful? packetsProcessed++; // We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data - if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes) + if ((dataPtr + packetLength + ((size_t)8)) < (offset + numDataBytes)) { delay(maxWait); } @@ -4548,7 +4534,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c } #endif - while ((dataPtr < numDataBytes) && (*(dataBytes + ++dataPtr) != UBX_SYNCH_1)) + while ((dataPtr < (offset + numDataBytes)) && (*(dataBytes + ++dataPtr) != UBX_SYNCH_1)) { ; // Increment dataPtr until we are pointing at the next 0xB5 - or we reach the end of the data } @@ -4582,7 +4568,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXMGAACK() } // Provide initial time assistance -bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, + uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, + uint16_t tAccS, uint32_t tAccNs, uint8_t source, + sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { uint8_t iniTimeUTC[32]; // Create the UBX-MGA-INI-TIME_UTC message by hand memset(iniTimeUTC, 0x00, 32); // Set all unused / reserved bytes and the checksum to zero diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 4b3194b..e6406ac 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -727,7 +727,9 @@ class SFE_UBLOX_GNSS #define defaultMGAINITIMEtAccS 2 // Default to setting the seconds time accuracy to 2 seconds #define defaultMGAINITIMEtAccNs 0 // Default to setting the nanoseconds time accuracy to zero #define defaultMGAINITIMEsource 0 // Set default source to none, i.e. on receipt of message (will be inaccurate!) - bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, + uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, + sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); // Provide initial position assistance // The units for ecefX/Y/Z and posAcc (stddev) are cm. From 65a731a4326b67029fea2aced299420af4d81782 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 9 Jan 2022 17:11:08 +0000 Subject: [PATCH 053/122] v2.1.5 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index ce120ad..c3d47aa 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.1.4 +version=2.1.5 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial Communication with u-blox GNSS modules

From 805aab18b6656513bfee473487a437754cd3965d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 10:20:26 +0000 Subject: [PATCH 054/122] Step_1 --- ...eDescription_UBX-21019746_keys_sorted.txt} | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) rename keys/{ZED-F9R-HPS120_Interfacedescription_UBX-19056845_keys_sorted.txt => F9-HPS-1.21_InterfaceDescription_UBX-21019746_keys_sorted.txt} (96%) diff --git a/keys/ZED-F9R-HPS120_Interfacedescription_UBX-19056845_keys_sorted.txt b/keys/F9-HPS-1.21_InterfaceDescription_UBX-21019746_keys_sorted.txt similarity index 96% rename from keys/ZED-F9R-HPS120_Interfacedescription_UBX-19056845_keys_sorted.txt rename to keys/F9-HPS-1.21_InterfaceDescription_UBX-21019746_keys_sorted.txt index aceab1f..ce066e9 100644 --- a/keys/ZED-F9R-HPS120_Interfacedescription_UBX-19056845_keys_sorted.txt +++ b/keys/F9-HPS-1.21_InterfaceDescription_UBX-21019746_keys_sorted.txt @@ -40,6 +40,7 @@ 0x10310022 0x10310024 0x10310025 +0x10340014 0x10360002 0x10360003 0x10360004 @@ -50,7 +51,6 @@ 0x10510003 0x10520005 0x10530005 -0x10530006 0x10640002 0x10640003 0x10640005 @@ -60,26 +60,31 @@ 0x10710001 0x10710002 0x10710004 +0x10710005 0x10720001 0x10720002 0x10730001 0x10730002 0x10730004 +0x10730005 0x10740001 0x10740002 0x10750001 0x10750002 0x10750004 +0x10750005 0x10760001 0x10760002 0x10770001 0x10770002 0x10770004 +0x10770005 0x10780001 0x10780002 0x10790001 0x10790002 0x10790004 +0x10790005 0x107a0001 0x107a0002 0x10930003 @@ -114,6 +119,7 @@ 0x2005000c 0x20050023 0x20050030 +0x20050035 0x20060008 0x20060009 0x20060015 @@ -486,6 +492,21 @@ 0x20910402 0x20910403 0x20910404 +0x20910605 +0x20910606 +0x20910607 +0x20910608 +0x20910609 +0x2091062a +0x2091062b +0x2091062c +0x2091062d +0x2091062e +0x20910634 +0x20910635 +0x20910636 +0x20910637 +0x20910638 0x20920001 0x20920002 0x20920003 From 8895764f237ae494dcd0fa1ae942d487d2e1557f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 10:30:04 +0000 Subject: [PATCH 055/122] Step_2 --- keys/u-blox_config_keys_sorted.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/keys/u-blox_config_keys_sorted.txt b/keys/u-blox_config_keys_sorted.txt index 4da2918..8eee0f4 100644 --- a/keys/u-blox_config_keys_sorted.txt +++ b/keys/u-blox_config_keys_sorted.txt @@ -82,30 +82,35 @@ 0x10710001 0x10710002 0x10710004 +0x10710005 0x10720001 0x10720002 0x10720004 0x10730001 0x10730002 0x10730004 +0x10730005 0x10740001 0x10740002 0x10740004 0x10750001 0x10750002 0x10750004 +0x10750005 0x10760001 0x10760002 0x10760004 0x10770001 0x10770002 0x10770004 +0x10770005 0x10780001 0x10780002 0x10780004 0x10790001 0x10790002 0x10790004 +0x10790005 0x107a0001 0x107a0002 0x107a0004 @@ -732,11 +737,21 @@ 0x20910592 0x20910593 0x20910594 +0x20910605 +0x20910606 +0x20910607 +0x20910608 +0x20910609 0x20910610 0x20910611 0x20910612 0x20910613 0x20910614 +0x2091062a +0x2091062b +0x2091062c +0x2091062d +0x2091062e 0x20910634 0x20910635 0x20910636 From 3609da15f90a7a66b41524e77c6dc3dd76cd362c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 10:56:24 +0000 Subject: [PATCH 056/122] Step_3 --- src/u-blox_config_keys.h | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/u-blox_config_keys.h b/src/u-blox_config_keys.h index 6caba0f..14a2bb5 100644 --- a/src/u-blox_config_keys.h +++ b/src/u-blox_config_keys.h @@ -134,6 +134,7 @@ const uint32_t UBLOX_CFG_I2C_ENABLED = 0x10510003; // Flag to indicate if the I2 const uint32_t UBLOX_CFG_I2CINPROT_UBX = 0x10710001; // Flag to indicate if UBX should be an input protocol on I2C const uint32_t UBLOX_CFG_I2CINPROT_NMEA = 0x10710002; // Flag to indicate if NMEA should be an input protocol on I2C const uint32_t UBLOX_CFG_I2CINPROT_RTCM3X = 0x10710004; // Flag to indicate if RTCM3X should be an input protocol on I2C +const uint32_t UBLOX_CFG_I2CINPROT_SPARTN = 0x10710005; // Flag to indicate if SPARTN should be an input protocol on I2C //CFG-I2COUTPROT: Output protocol configuration of the I2C interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -550,6 +551,16 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_SPI = 0x20910235; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_UART1 = 0x20910232; // Output rate of the UBX-RXM-SFRBX message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_UART2 = 0x20910233; // Output rate of the UBX-RXM-SFRBX message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_USB = 0x20910234; // Output rate of the UBX-RXM-SFRBX message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_I2C = 0x20910605; // Output rate of the UBX-RXM-SPARTN message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_UART1 = 0x20910606; // Output rate of the UBX-RXM-SPARTN message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_UART2 = 0x20910607; // Output rate of the UBX-RXM-SPARTN message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_USB = 0x20910608; // Output rate of the UBX-RXM-SPARTN message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_SPI = 0x20910609; // Output rate of the UBX-RXM-SPARTN message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_I2C = 0x20910634; // Output rate of the UBX-SEC-SIG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_SPI = 0x20910638; // Output rate of the UBX-SEC-SIG message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART1 = 0x20910635; // Output rate of the UBX-SEC-SIG message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART2 = 0x20910636; // Output rate of the UBX-SEC-SIG message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_USB = 0x20910637; // Output rate of the UBX-SEC-SIG message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_I2C = 0x20910178; // Output rate of the UBX-TIM-TM2 message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_SPI = 0x2091017c; // Output rate of the UBX-TIM-TM2 message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_UART1 = 0x20910179; // Output rate of the UBX-TIM-TM2 message on port UART1 @@ -566,7 +577,7 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_UART1 = 0x20910093; // Output rat const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_UART2 = 0x20910094; // Output rate of the UBX-TIM-VRFY message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_USB = 0x20910095; // Output rate of the UBX-TIM-VRFY message on port USB -//Additional CFG_MSGOUT keys for the ZED-F9R HPS120 +//Additional CFG_MSGOUT keys for the ZED-F9R HPS121 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_I2C = 0x20910083; // Output rate of the UBX-NAV-COV message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_UART1 = 0x20910084; // Output rate of the UBX-NAV-COV message on port UART1 @@ -608,6 +619,12 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_UART1 = 0x20910314; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_UART2 = 0x20910315; // Output rate of the UBX-NAV-EELL message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_USB = 0x20910316; // Output rate of the UBX-NAV-EELL message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_SPI = 0x20910317; // Output rate of the UBX-NAV-EELL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_I2C = 0x2091062a; // Output rate of the UBX-NAV-PVAT message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_UART1 = 0x2091062b; // Output rate of the UBX-NAV-PVAT message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_UART2 = 0x2091062c; // Output rate of the UBX-NAV-PVAT message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_USB = 0x2091062d; // Output rate of the UBX-NAV-PVAT message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_SPI = 0x2091062e; // Output rate of the UBX-NAV-PVAT message on port SPI + //Additional CFG_MSGOUT keys for the ZED-F9T //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -761,11 +778,6 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_SPI = 0x2091068d; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_UART1 = 0x2091068a; // Output rate of the UBX-SEC-SIGLOG message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_UART2 = 0x2091068b; // Output rate of the UBX-SEC-SIGLOG message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_USB = 0x2091068c; // Output rate of the UBX-SEC-SIGLOG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_I2C = 0x20910634; // Output rate of the UBX-DBG-SKYMAP message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_SPI = 0x20910638; // Output rate of the UBX-SEC-SIG message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART1 = 0x20910635; // Output rate of the UBX-SEC-SIG message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART2 = 0x20910636; // Output rate of the UBX-SEC-SIG message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_USB = 0x20910637; // Output rate of the UBX-SEC-SIG message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_I2C = 0x20910097; // Output rate of the UBX-TIM-SVIN message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_SPI = 0x2091009b; // Output rate of the UBX-TIM-SVIN message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_UART1 = 0x20910098; // Output rate of the UBX-TIM-SVIN message on port UART1 @@ -976,6 +988,7 @@ const uint32_t UBLOX_CFG_SPI_ENABLED = 0x10640006; // Flag to indicate if the SP const uint32_t UBLOX_CFG_SPIINPROT_UBX = 0x10790001; // Flag to indicate if UBX should be an input protocol on SPI const uint32_t UBLOX_CFG_SPIINPROT_NMEA = 0x10790002; // Flag to indicate if NMEA should be an input protocol on SPI const uint32_t UBLOX_CFG_SPIINPROT_RTCM3X = 0x10790004; // Flag to indicate if RTCM3X should be an input protocol on SPI +const uint32_t UBLOX_CFG_SPIINPROT_SPARTN = 0x10790005; // Flag to indicate if SPARTN should be an input protocol on SPI //CFG-SPIOUTPROT: Output protocol configuration of the SPI interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -1062,6 +1075,7 @@ const uint32_t UBLOX_CFG_UART1_ENABLED = 0x10520005; // Flag to indicate if the const uint32_t UBLOX_CFG_UART1INPROT_UBX = 0x10730001; // Flag to indicate if UBX should be an input protocol on UART1 const uint32_t UBLOX_CFG_UART1INPROT_NMEA = 0x10730002; // Flag to indicate if NMEA should be an input protocol on UART1 const uint32_t UBLOX_CFG_UART1INPROT_RTCM3X = 0x10730004; // Flag to indicate if RTCM3X should be an input protocol on UART1 +const uint32_t UBLOX_CFG_UART1INPROT_SPARTN = 0x10730005; // Flag to indicate if SPARTN should be an input protocol on UART1 //CFG-UART1OUTPROT: Output protocol configuration of the UART1 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -1083,6 +1097,7 @@ const uint32_t UBLOX_CFG_UART2_REMAP = 0x10530006; // UART2 Remapping const uint32_t UBLOX_CFG_UART2INPROT_UBX = 0x10750001; // Flag to indicate if UBX should be an input protocol on UART2 const uint32_t UBLOX_CFG_UART2INPROT_NMEA = 0x10750002; // Flag to indicate if NMEA should be an input protocol on UART2 const uint32_t UBLOX_CFG_UART2INPROT_RTCM3X = 0x10750004; // Flag to indicate if RTCM3X should be an input protocol on UART2 +const uint32_t UBLOX_CFG_UART2INPROT_SPARTN = 0x10750005; // Flag to indicate if SPARTN should be an input protocol on UART2 //CFG-UART2OUTPROT: Output protocol configuration of the UART2 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -1115,6 +1130,7 @@ const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR3 = 0x50650018; // Serial number strin const uint32_t UBLOX_CFG_USBINPROT_UBX = 0x10770001; // Flag to indicate if UBX should be an input protocol on USB const uint32_t UBLOX_CFG_USBINPROT_NMEA = 0x10770002; // Flag to indicate if NMEA should be an input protocol on USB const uint32_t UBLOX_CFG_USBINPROT_RTCM3X = 0x10770004; // Flag to indicate if RTCM3X should be an input protocol on USB +const uint32_t UBLOX_CFG_USBINPROT_SPARTN = 0x10770005; // Flag to indicate if SPARTN should be an input protocol on USB //CFG-USBOUTPROT: Output protocol configuration of the USB interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- From a4ba440c6240e0974c27f40b976a5ddf0fbdb9b6 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 11:44:59 +0000 Subject: [PATCH 057/122] Step_4 --- src/u-blox_structs.h | 174 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index a749ce4..84872bb 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -753,6 +753,180 @@ typedef struct UBX_NAV_HPPOSLLH_data_t *callbackData; } UBX_NAV_HPPOSLLH_t; +// UBX-NAV-PVAT (0x01 0x17): Navigation position velocity attitude time solution +const uint16_t UBX_NAV_PVAT_LEN = 116; + +typedef struct +{ + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint8_t version; // Message version (0x00 for this version) + union + { + uint8_t all; + struct + { + uint8_t validDate : 1; // 1 = valid UTC Date + uint8_t validTime : 1; // 1 = valid UTC time of day + uint8_t fullyResolved : 1; // 1 = UTC time of day has been fully resolved (no seconds uncertainty). + uint8_t validMag : 1; // 1 = valid magnetic declination + } bits; + } valid; + uint16_t year; // Year (UTC) + uint8_t month; // Month, range 1..12 (UTC) + uint8_t day; // Day of month, range 1..31 (UTC) + uint8_t hour; // Hour of day, range 0..23 (UTC) + uint8_t min; // Minute of hour, range 0..59 (UTC) + uint8_t sec; // Seconds of minute, range 0..60 (UTC) + uint8_t reserved0; + uint8_t reserved1[2]; + uint32_t tAcc; // Time accuracy estimate (UTC): ns + int32_t nano; // Fraction of second, range -1e9 .. 1e9 (UTC): ns + uint8_t fixType; // GNSSfix Type: + // 0: no fix + // 1: dead reckoning only + // 2: 2D-fix + // 3: 3D-fix + // 4: GNSS + dead reckoning combined + // 5: time only fix + union + { + uint8_t all; + struct + { + uint8_t gnssFixOK : 1; // 1 = valid fix (i.e within DOP & accuracy masks) + uint8_t diffSoln : 1; // 1 = differential corrections were applied + uint8_t reserved : 1; + uint8_t vehRollValid : 1; // 1 = roll of vehicle is valid, only set if the receiver is in sensor fusion mode + uint8_t vehPitchValid : 1; // 1 = pitch of vehicle is valid, only set if the receiver is in sensor fusion mode + uint8_t vehHeadingValid : 1; // 1 = heading of vehicle is valid, only set if the receiver is in sensor fusion mode + uint8_t carrSoln : 2; // Carrier phase range solution status: + // 0: no carrier phase range solution + // 1: carrier phase range solution with floating ambiguities + // 2: carrier phase range solution with fixed ambiguities + } bits; + } flags; + union + { + uint8_t all; + struct + { + uint8_t reserved : 5; + uint8_t confirmedAvai : 1; // 1 = information about UTC Date and Time of Day validity confirmation is available + uint8_t confirmedDate : 1; // 1 = UTC Date validity could be confirmed + uint8_t confirmedTime : 1; // 1 = UTC Time of Day could be confirmed + } bits; + } flags2; + uint8_t numSV; // Number of satellites used in Nav Solution + int32_t lon; // Longitude: deg * 1e-7 + int32_t lat; // Latitude: deg * 1e-7 + int32_t height; // Height above ellipsoid: mm + int32_t hMSL; // Height above mean sea level: mm + uint32_t hAcc; // Horizontal accuracy estimate: mm + uint32_t vAcc; // Vertical accuracy estimate: mm + int32_t velN; // NED north velocity: mm/s + int32_t velE; // NED east velocity: mm/s + int32_t velD; // NED down velocity: mm/s + int32_t gSpeed; // Ground Speed (2-D): mm/s + uint32_t sAcc; // Speed accuracy estimate: mm/s + int32_t vehRoll; // Vehicle roll: 1e-5 deg + int32_t vehPitch; // Vehicle pitch: 1e-5 deg + int32_t vehHeading; // Vehicle heading: 1e-5 deg + int32_t motHeading; // Motion heading.: 1e-5 deg + uint16_t accRoll; // Vehicle roll accuracy (if null, roll angle is not available): 1e-2 deg + uint16_t accPitch; // Vehicle pitch accuracy (if null, pitch angle is not available): 1e-2 deg + uint16_t accHeading; // Vehicle heading accuracy (if null, heading angle is not available): 1e-2 deg + int16_t magDec; // Magnetic declination: 1e-2 deg + uint16_t magAcc; // Magnetic declination accuracy: 1e-2 deg + uint16_t errEllipseOrient; // Orientation of semi-major axis of error ellipse (degrees from true north): 1e-2 deg + uint32_t errEllipseMajor; // Semi-major axis of error ellipse: mm + uint32_t errEllipseMinor; // Semi-minor axis of error ellipse: mm + uint8_t reserved2[4]; + uint8_t reserved3[4]; +} UBX_NAV_PVAT_data_t; + +typedef struct +{ + union + { + uint32_t all; + struct + { + uint32_t all : 1; + + uint32_t iTOW : 1; + uint32_t version : 1; + + uint32_t validDate : 1; + uint32_t validTime : 1; + uint32_t fullyResolved : 1; + uint32_t validMag : 1; + + uint32_t year : 1; + uint32_t month : 1; + uint32_t day : 1; + uint32_t hour : 1; + uint32_t min : 1; + uint32_t sec : 1; + + uint32_t tAcc : 1; + uint32_t nano : 1; + uint32_t fixType : 1; + + uint32_t gnssFixOK : 1; + uint32_t diffSoln : 1; + uint32_t vehRollValid : 1; + uint32_t vehPitchValid : 1; + uint32_t vehHeadingValid : 1; + uint32_t carrSoln : 1; + + uint32_t confirmedAvai : 1; + uint32_t confirmedDate : 1; + uint32_t confirmedTime : 1; + + uint32_t numSV : 1; + uint32_t lon : 1; + uint32_t lat : 1; + uint32_t height : 1; + uint32_t hMSL : 1; + uint32_t hAcc : 1; + uint32_t vAcc : 1; + } bits; + } moduleQueried1; + union + { + uint32_t all; + struct + { + uint32_t velN : 1; + uint32_t velE : 1; + uint32_t velD : 1; + uint32_t gSpeed : 1; + uint32_t sAcc : 1; + uint32_t vehRoll : 1; + uint32_t vehPitch : 1; + uint32_t vehHeading : 1; + uint32_t motHeading : 1; + uint32_t accRoll : 1; + uint32_t accPitch : 1; + uint32_t accHeading : 1; + uint32_t magDec : 1; + uint32_t magAcc : 1; + uint32_t errEllipseOrient : 1; + uint32_t errEllipseMajor : 1; + uint32_t errEllipseMinor : 1; + } bits; + } moduleQueried2; +} UBX_NAV_PVAT_moduleQueried_t; + +typedef struct +{ + ubxAutomaticFlags automaticFlags; + UBX_NAV_PVAT_data_t data; + UBX_NAV_PVAT_moduleQueried_t moduleQueried; + void (*callbackPointer)(UBX_NAV_PVAT_data_t); + UBX_NAV_PVAT_data_t *callbackData; +} UBX_NAV_PVAT_t; + // UBX-NAV-TIMEUTC (0x01 0x21): UTC time solution const uint16_t UBX_NAV_TIMEUTC_LEN = 20; From 423a1e2ccd418dd679257edc6edeec0bd3029052 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 12:17:54 +0000 Subject: [PATCH 058/122] Step_5 --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index e6406ac..3f2c35a 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -355,6 +355,7 @@ const uint8_t UBX_NAV_ORB = 0x34; //GNSS Orbit Database Info const uint8_t UBX_NAV_POSECEF = 0x01; //Position Solution in ECEF const uint8_t UBX_NAV_POSLLH = 0x02; //Geodetic Position Solution const uint8_t UBX_NAV_PVT = 0x07; //All the things! Position, velocity, time, PDOP, height, h/v accuracies, number of satellites. Navigation Position Velocity Time Solution. +const uint8_t UBX_NAV_PVAT = 0x17; //Navigation position velocity attitude time solution (ZED-F9R only) const uint8_t UBX_NAV_RELPOSNED = 0x3C; //Relative Positioning Information in NED frame const uint8_t UBX_NAV_RESETODO = 0x10; //Reset odometer const uint8_t UBX_NAV_SAT = 0x35; //Satellite Information @@ -983,7 +984,7 @@ class SFE_UBLOX_GNSS void flushNAVHPPOSECEF(); //Mark all the data as read/stale void logNAVHPPOSECEF(bool enabled = true); // Log data to file buffer - bool getHPPOSLLH(uint16_t maxWait = defaultMaxWait); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new HPPOSLLH is available. + bool getHPPOSLLH(uint16_t maxWait = defaultMaxWait); // NAV HPPOSLLH bool setAutoHPPOSLLH(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSLLH reports at the navigation frequency bool setAutoHPPOSLLH(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSLLH 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 setAutoHPPOSLLHrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic HPPOSLLH reports @@ -992,6 +993,15 @@ class SFE_UBLOX_GNSS void flushHPPOSLLH(); //Mark all the HPPPOSLLH data as read/stale. This is handy to get data alignment after CRC failure void logNAVHPPOSLLH(bool enabled = true); // Log data to file buffer + bool getNAVPVAT(uint16_t maxWait = defaultMaxWait); // NAV PVAT + bool setAutoNAVPVAT(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVAT reports at the navigation frequency + bool setAutoNAVPVAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVAT 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 setAutoNAVPVATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic PVAT reports + bool setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVAT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVPVAT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and PVAT is send cyclically already + void flushNAVPVAT(); //Mark all the PVAT data as read/stale + void logNAVPVAT(bool enabled = true); // Log data to file buffer + bool getNAVCLOCK(uint16_t maxWait = defaultMaxWait); // NAV CLOCK bool setAutoNAVCLOCK(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic clock reports at the navigation frequency bool setAutoNAVCLOCK(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic clock 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 @@ -1256,6 +1266,13 @@ class SFE_UBLOX_GNSS uint32_t getHorizontalAccuracy(uint16_t maxWait = defaultMaxWait); uint32_t getVerticalAccuracy(uint16_t maxWait = defaultMaxWait); + // Helper functions for PVAT + + int32_t getVehicleRoll(uint16_t maxWait = defaultMaxWait); // Returns vehicle roll in degrees * 10^-5 + int32_t getVehiclePitch(uint16_t maxWait = defaultMaxWait); // Returns vehicle pitch in degrees * 10^-5 + int32_t getVehicleHeading(uint16_t maxWait = defaultMaxWait); // Returns vehicle heading in degrees * 10^-5 + int32_t getMotionHeading(uint16_t maxWait = defaultMaxWait); // Returns the motion heading in degrees * 10^-5 + // Helper functions for SVIN bool getSurveyInActive(uint16_t maxWait = defaultMaxWait); @@ -1324,6 +1341,7 @@ class SFE_UBLOX_GNSS UBX_NAV_VELNED_t *packetUBXNAVVELNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_HPPOSECEF_t *packetUBXNAVHPPOSECEF = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_HPPOSLLH_t *packetUBXNAVHPPOSLLH = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_PVAT_t *packetUBXNAVPVAT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_CLOCK_t *packetUBXNAVCLOCK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_TIMELS_t *packetUBXNAVTIMELS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_SVIN_t *packetUBXNAVSVIN = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1408,6 +1426,7 @@ class SFE_UBLOX_GNSS bool initPacketUBXNAVVELNED(); // Allocate RAM for packetUBXNAVVELNED and initialize it bool initPacketUBXNAVHPPOSECEF(); // Allocate RAM for packetUBXNAVHPPOSECEF and initialize it bool initPacketUBXNAVHPPOSLLH(); // Allocate RAM for packetUBXNAVHPPOSLLH and initialize it + bool initPacketUBXNAVPVAT(); // Allocate RAM for packetUBXNAVPVAT and initialize it bool initPacketUBXNAVCLOCK(); // Allocate RAM for packetUBXNAVCLOCK and initialize it bool initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it bool initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it From a8fc599b6279f9b31a9edc33b942dc6f3d1f8985 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 12:22:28 +0000 Subject: [PATCH 059/122] Add new dynamic models --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 3f2c35a..2340c7d 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -469,7 +469,9 @@ enum dynModel // Possible values for the dynamic platform model, which provide m DYN_MODEL_AIRBORNE2g, //Airborne <2g acceleration. Recommended for typical airborne environments. No 2D position fixes supported. DYN_MODEL_AIRBORNE4g, //Airborne <4g acceleration. Only recommended for extremely dynamic environments. No 2D position fixes supported. DYN_MODEL_WRIST, // Not supported in protocol versions less than 18. Only recommended for wrist worn applications. Receiver will filter out arm motion. - DYN_MODEL_BIKE, // Supported in protocol versions 19.2 + DYN_MODEL_BIKE, // Supported in protocol versions 19.2. (not available in all products) + DYN_MODEL_MOWER, // Added in HPS 1.21 (not available in all products) + DYN_MODEL_ESCOOTER, // Added in HPS 1.21 (not available in all products) DYN_MODEL_UNKNOWN = 255 // getDynamicModel will return 255 if sendCommand fails }; From 2041d536c101cf02e7318cb316b96e5a0986abd4 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 12:28:39 +0000 Subject: [PATCH 060/122] Add COM_TYPE_SPARTN --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 2340c7d..6af5f88 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -438,6 +438,7 @@ const uint8_t COM_PORT_SPI = 4; const uint8_t COM_TYPE_UBX = (1 << 0); const uint8_t COM_TYPE_NMEA = (1 << 1); const uint8_t COM_TYPE_RTCM3 = (1 << 5); +const uint8_t COM_TYPE_SPARTN = (1 << 6); // Configuration Sub-Section mask definitions for saveConfigSelective (UBX-CFG-CFG) const uint32_t VAL_CFG_SUBSEC_IOPORT = 0x00000001; // ioPort - communications port settings (causes IO system reset!) @@ -770,17 +771,17 @@ class SFE_UBLOX_GNSS //Port configurations bool getPortSettings(uint8_t portID, uint16_t maxWait = defaultMaxWait); //Returns the current protocol bits in the UBX-CFG-PRT command for a given port - bool setPortOutput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure a given port to output UBX, NMEA, RTCM3 or a combination thereof - bool setPortInput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof + bool setPortOutput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure a given port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setPortInput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure a given port to input UBX, NMEA, RTCM3, SPARTN or a combination thereof bool setI2CAddress(uint8_t deviceAddress, uint16_t maxTime = defaultMaxWait); //Changes the I2C address of the u-blox module void setSerialRate(uint32_t baudrate, uint8_t uartPort = COM_PORT_UART1, uint16_t maxTime = defaultMaxWait); //Changes the serial baud rate of the u-blox module, uartPort should be COM_PORT_UART1/2 - bool setI2COutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure I2C port to output UBX, NMEA, RTCM3 or a combination thereof - bool setUART1Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure UART1 port to output UBX, NMEA, RTCM3 or a combination thereof - bool setUART2Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure UART2 port to output UBX, NMEA, RTCM3 or a combination thereof - bool setUSBOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure USB port to output UBX, NMEA, RTCM3 or a combination thereof - bool setSPIOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure SPI port to output UBX, NMEA, RTCM3 or a combination thereof + bool setI2COutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure I2C port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setUART1Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure UART1 port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setUART2Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure UART2 port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setUSBOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure USB port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setSPIOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure SPI port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof void setNMEAOutputPort(Stream &nmeaOutputPort); //Sets the internal variable for the port to direct NMEA characters to //Reset to defaults From 01fd7cac6aa7998c2343ada89b4ce9732d13c3d7 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 12:34:59 +0000 Subject: [PATCH 061/122] Add UBX_RXM_SPARTN --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 6af5f88..8d94e8c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -379,7 +379,8 @@ const uint8_t UBX_RXM_PMREQ = 0x41; //Requests a Power Management task (two diff const uint8_t UBX_RXM_RAWX = 0x15; //Multi-GNSS Raw Measurement Data const uint8_t UBX_RXM_RLM = 0x59; //Galileo SAR Short-RLM report (two different packet sizes) const uint8_t UBX_RXM_RTCM = 0x32; //RTCM input status -const uint8_t UBX_RXM_SFRBX = 0x13; //Boradcast Navigation Data Subframe +const uint8_t UBX_RXM_SFRBX = 0x13; //Broadcast Navigation Data Subframe +const uint8_t UBX_RXM_SPARTN = 0x33; //SPARTN input status //Class: SEC //The following are used to configure the SEC UBX messages (security feature messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) From 35d225e3f1abb316eda3becb7f8e2eb04ff1d17c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 14:30:57 +0000 Subject: [PATCH 062/122] Step_6.1 --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index c13e4db..abc2564 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -214,6 +214,16 @@ void SFE_UBLOX_GNSS::end(void) packetUBXNAVHPPOSLLH = NULL; // Redundant? } + if (packetUBXNAVPVAT != NULL) + { + if (packetUBXNAVPVAT->callbackData != NULL) + { + delete packetUBXNAVPVAT->callbackData; + } + delete packetUBXNAVPVAT; + packetUBXNAVPVAT = NULL; // Redundant? + } + if (packetUBXNAVCLOCK != NULL) { if (packetUBXNAVCLOCK->callbackData != NULL) From b746d8e2742961ede95e2d06d5db3a3a557e571d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 14:32:39 +0000 Subject: [PATCH 063/122] Step_6.2 --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index abc2564..b8ae0b1 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1155,6 +1155,9 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) case UBX_NAV_HPPOSLLH: if (packetUBXNAVHPPOSLLH != NULL) result = true; break; + case UBX_NAV_PVAT: + if (packetUBXNAVPVAT != NULL) result = true; + break; case UBX_NAV_CLOCK: if (packetUBXNAVCLOCK != NULL) result = true; break; From 8eecdd5044f810b0e2b567150ff63a17c219fe8e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 14:48:19 +0000 Subject: [PATCH 064/122] Step_6.3 --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index b8ae0b1..088eb38 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2491,6 +2491,70 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } } } + else if (msg->id == UBX_NAV_PVAT && msg->len == UBX_NAV_PVAT_LEN) + { + //Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXNAVPVAT != NULL) + { + packetUBXNAVPVAT->data.iTOW = extractLong(msg, 0); + packetUBXNAVPVAT->data.version = extractByte(msg, 4); + packetUBXNAVPVAT->data.valid.all = extractByte(msg, 5); + packetUBXNAVPVAT->data.year = extractInt(msg, 6); + packetUBXNAVPVAT->data.month = extractByte(msg, 8); + packetUBXNAVPVAT->data.day = extractByte(msg, 9); + packetUBXNAVPVAT->data.hour = extractByte(msg, 10); + packetUBXNAVPVAT->data.min = extractByte(msg, 11); + packetUBXNAVPVAT->data.sec = extractByte(msg, 12); + packetUBXNAVPVAT->data.tAcc = extractLong(msg, 16); + packetUBXNAVPVAT->data.nano = extractSignedLong(msg, 20); //Includes milliseconds + packetUBXNAVPVAT->data.fixType = extractByte(msg, 24); + packetUBXNAVPVAT->data.flags.all = extractByte(msg, 25); + packetUBXNAVPVAT->data.flags2.all = extractByte(msg, 26); + packetUBXNAVPVAT->data.numSV = extractByte(msg, 27); + packetUBXNAVPVAT->data.lon = extractSignedLong(msg, 28); + packetUBXNAVPVAT->data.lat = extractSignedLong(msg, 32); + packetUBXNAVPVAT->data.height = extractSignedLong(msg, 36); + packetUBXNAVPVAT->data.hMSL = extractSignedLong(msg, 40); + packetUBXNAVPVAT->data.hAcc = extractLong(msg, 44); + packetUBXNAVPVAT->data.vAcc = extractLong(msg, 48); + packetUBXNAVPVAT->data.velN = extractSignedLong(msg, 52); + packetUBXNAVPVAT->data.velE = extractSignedLong(msg, 56); + packetUBXNAVPVAT->data.velD = extractSignedLong(msg, 60); + packetUBXNAVPVAT->data.gSpeed = extractSignedLong(msg, 64); + packetUBXNAVPVAT->data.sAcc = extractLong(msg, 68); + packetUBXNAVPVAT->data.vehRoll = extractSignedLong(msg, 72); + packetUBXNAVPVAT->data.vehPitch = extractSignedLong(msg, 76); + packetUBXNAVPVAT->data.vehHeading = extractSignedLong(msg, 80); + packetUBXNAVPVAT->data.motHeading = extractSignedLong(msg, 84); + packetUBXNAVPVAT->data.accRoll = extractInt(msg, 88); + packetUBXNAVPVAT->data.accPitch = extractInt(msg, 90); + packetUBXNAVPVAT->data.accHeading = extractInt(msg, 92); + packetUBXNAVPVAT->data.magDec = extractSignedInt(msg, 94); + packetUBXNAVPVAT->data.magAcc = extractInt(msg, 96); + packetUBXNAVPVAT->data.errEllipseOrient = extractInt(msg, 98); + packetUBXNAVPVAT->data.errEllipseMajor = extractLong(msg, 100); + packetUBXNAVPVAT->data.errEllipseMinor = extractLong(msg, 104); + + + //Mark all datums as fresh (not read before) + packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0xFFFFFFFF; + packetUBXNAVPVAT->moduleQueried.moduleQueried2.all = 0xFFFFFFFF; + + //Check if we need to copy the data for the callback + if ((packetUBXNAVPVAT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + { + memcpy(&packetUBXNAVPVAT->callbackData->iTOW, &packetUBXNAVPVAT->data.iTOW, sizeof(UBX_NAV_PVAT_data_t)); + packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid = true; + } + + //Check if we need to copy the data into the file buffer + if (packetUBXNAVPVAT->automaticFlags.flags.bits.addToFileBuffer) + { + storePacket(msg); + } + } + } else if (msg->id == UBX_NAV_CLOCK && msg->len == UBX_NAV_CLOCK_LEN) { //Parse various byte fields into storage - but only if we have memory allocated for it From b53bffaa3ae12482cfb268f23796963d0b8519c9 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 14:51:39 +0000 Subject: [PATCH 065/122] Step_6.4 --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 088eb38..8349be2 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4134,6 +4134,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } + if ((packetUBXNAVPVAT != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVPVAT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPVAT->callbackPointer != NULL) // If the pointer to the callback has been defined + && (packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + { + //if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV PVAT")); + packetUBXNAVPVAT->callbackPointer(*packetUBXNAVPVAT->callbackData); // Call the callback + packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + } + if ((packetUBXNAVCLOCK != NULL) // If RAM has been allocated for message storage && (packetUBXNAVCLOCK->callbackData != NULL) // If RAM has been allocated for the copy of the data && (packetUBXNAVCLOCK->callbackPointer != NULL) // If the pointer to the callback has been defined From e394ae003ad38117d150598774d0552059416473 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 15:01:03 +0000 Subject: [PATCH 066/122] Step_6.5 --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 160 +++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 8349be2..6088ab0 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -8785,6 +8785,166 @@ void SFE_UBLOX_GNSS::logNAVHPPOSLLH(bool enabled) packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } +// ***** PVAT automatic support + +//Get the latest Position/Velocity/Time solution and fill all global variables +bool SFE_UBLOX_GNSS::getNAVPVAT(uint16_t maxWait) +{ + if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + return (false); + + if (packetUBXNAVPVAT->automaticFlags.flags.bits.automatic && packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate) + { + checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_PVAT); + return packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all; + } + else if (packetUBXNAVPVAT->automaticFlags.flags.bits.automatic && !packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate) + { + //Someone else has to call checkUblox for us... + return (false); + } + else + { + //The GPS is not automatically reporting navigation position so we have to poll explicitly + packetCfg.cls = UBX_CLASS_NAV; + packetCfg.id = UBX_NAV_PVAT; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + //packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+packetCfgPayloadSize = 84 bytes Note:now hard-coded in processUBX + + //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 navigation message generation by the GNSS. This changes the way getPVAT +//works. +bool SFE_UBLOX_GNSS::setAutoNAVPVAT(bool enable, uint16_t maxWait) +{ + return setAutoNAVPVATrate(enable ? 1 : 0, true, maxWait); +} + +//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT +//works. +bool SFE_UBLOX_GNSS::setAutoNAVPVAT(bool enable, bool implicitUpdate, uint16_t maxWait) +{ + return setAutoNAVPVATrate(enable ? 1 : 0, implicitUpdate, maxWait); +} + +//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT +//works. +bool SFE_UBLOX_GNSS::setAutoNAVPVATrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) +{ + if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == 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_PVAT; + payloadCfg[2] = rate; // rate relative to navigation freq. + + bool ok = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK + if (ok) + { + packetUBXNAVPVAT->automaticFlags.flags.bits.automatic = (rate > 0); + packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + return ok; +} + +//Enable automatic navigation message generation by the GNSS. This changes the way getPVAT works. +bool SFE_UBLOX_GNSS::setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT_data_t), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVPVAT(true, false, maxWait); + if (!result) + return (result); // Bail if setAutoPVAT failed + + if (packetUBXNAVPVAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVPVAT->callbackData = new UBX_NAV_PVAT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVPVAT->callbackData == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setAutoNAVPVATcallback: RAM alloc failed!")); + return (false); + } + + packetUBXNAVPVAT->callbackPointer = callbackPointer; // RAM has been allocated so now update the pointer + + return (true); +} + +//In case no config access to the GNSS is possible and PVAT is send cyclically already +//set config to suitable parameters +bool SFE_UBLOX_GNSS::assumeAutoNAVPVAT(bool enabled, bool implicitUpdate) +{ + if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) //Only attempt this if RAM allocation was successful + return false; + + bool changes = packetUBXNAVPVAT->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; + if (changes) + { + packetUBXNAVPVAT->automaticFlags.flags.bits.automatic = enabled; + packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + return changes; +} + +// PRIVATE: Allocate RAM for packetUBXNAVPVAT and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXNAVPVAT() +{ + packetUBXNAVPVAT = new UBX_NAV_PVAT_t; //Allocate RAM for the main struct + if (packetUBXNAVPVAT == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXNAVPVAT: RAM alloc failed!")); + return (false); + } + packetUBXNAVPVAT->automaticFlags.flags.all = 0; + packetUBXNAVPVAT->callbackPointer = NULL; + packetUBXNAVPVAT->callbackData = NULL; + packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0; + packetUBXNAVPVAT->moduleQueried.moduleQueried2.all = 0; + return (true); +} + +//Mark all the PVAT data as read/stale. This is handy to get data alignment after CRC failure +void SFE_UBLOX_GNSS::flushNAVPVAT() +{ + if (packetUBXNAVPVAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0; //Mark all datums as stale (read before) + packetUBXNAVPVAT->moduleQueried.moduleQueried2.all = 0; +} + +//Log this data in file buffer +void SFE_UBLOX_GNSS::logNAVPVAT(bool enabled) +{ + if (packetUBXNAVPVAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVPVAT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; +} + // ***** NAV CLOCK automatic support bool SFE_UBLOX_GNSS::getNAVCLOCK(uint16_t maxWait) From 318e76383e96d6676bbb57294c25e665c0d4a31f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 15:10:55 +0000 Subject: [PATCH 067/122] Step_6.6 --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 54 ++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 6088ab0..9a3f29d 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -12773,6 +12773,60 @@ uint32_t SFE_UBLOX_GNSS::getVerticalAccuracy(uint16_t maxWait) return (packetUBXNAVHPPOSLLH->data.vAcc); } +// ***** PVAT Helper Functions + +int32_t SFE_UBLOX_GNSS::getVehicleRoll(uint16_t maxWait) +{ + if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + return 0; + + if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehRoll == false) + getNAVPVAT(maxWait); + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehRoll = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + return (packetUBXNAVPVAT->data.vehRoll); +} + +int32_t SFE_UBLOX_GNSS::getVehiclePitch(uint16_t maxWait) +{ + if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + return 0; + + if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehPitch == false) + getNAVPVAT(maxWait); + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehPitch = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + return (packetUBXNAVPVAT->data.vehPitch); +} + +int32_t SFE_UBLOX_GNSS::getVehicleHeading(uint16_t maxWait) +{ + if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + return 0; + + if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehHeading == false) + getNAVPVAT(maxWait); + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehHeading = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + return (packetUBXNAVPVAT->data.vehHeading); +} + +int32_t SFE_UBLOX_GNSS::getMotionHeading(uint16_t maxWait) +{ + if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + return 0; + + if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.motHeading == false) + getNAVPVAT(maxWait); + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.motHeading = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + return (packetUBXNAVPVAT->data.motHeading); +} + // ***** SVIN Helper Functions bool SFE_UBLOX_GNSS::getSurveyInActive(uint16_t maxWait) From 06014dc95f1b9ffae4876fbacfb9390541d7c31d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 15:57:51 +0000 Subject: [PATCH 068/122] Step_8 --- .../Example8_getNAVPVAT.ino | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 examples/Dead_Reckoning/Example8_getNAVPVAT/Example8_getNAVPVAT.ino diff --git a/examples/Dead_Reckoning/Example8_getNAVPVAT/Example8_getNAVPVAT.ino b/examples/Dead_Reckoning/Example8_getNAVPVAT/Example8_getNAVPVAT.ino new file mode 100644 index 0000000..cc8e6e4 --- /dev/null +++ b/examples/Dead_Reckoning/Example8_getNAVPVAT/Example8_getNAVPVAT.ino @@ -0,0 +1,111 @@ +/* + By: Paul CLark + SparkFun Electronics + Date: January, 2022 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9R: https://www.sparkfun.com/products/16344 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a Redboard Qwiic + 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 + + After calibrating the module and securing it to your vehicle such that it's + stable within 2 degrees, and the board is oriented correctly with regards to + the vehicle's frame, you can now read the vehicle's "attitude". The attitude + includes the vehicle's heading, pitch, and roll. + +*/ + +#include //Needed for I2C to GNSS + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +void setup() +{ + Serial.begin(115200); + while (!Serial); //Wait for user to open terminal + Serial.println(F("SparkFun u-blox Example")); + + Wire.begin(); + + 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); + } + + myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) +} + +void loop() +{ + // PVAT data is produced at the navigation rate, so by default we'll get fresh data once per second + if (myGNSS.getNAVPVAT()) // Poll new PVAT + { + Serial.print(F("Roll: ")); + Serial.print((float)myGNSS.getVehicleRoll() / 100000.0, 5); // Use the helper function to get the roll in degrees * 10^-5 + + Serial.print(F(" Pitch: ")); + Serial.print((float)myGNSS.getVehiclePitch() / 100000.0, 5); // Use the helper function to get the pitch in degrees * 10^-5 + + Serial.print(F(" Heading: ")); + Serial.print((float)myGNSS.getVehicleHeading() / 100000.0, 5); // Use the helper function to get the heading in degrees * 10^-5 + + // We don't have helper functions to extract the roll, pitch and heading valid flags from the PVAT message. But we can do it manually: + + Serial.print(F(" Roll Valid: ")); + Serial.print(myGNSS.packetUBXNAVPVAT->data.flags.bits.vehRollValid); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.vehRollValid = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + Serial.print(F(" Pitch Valid: ")); + Serial.print(myGNSS.packetUBXNAVPVAT->data.flags.bits.vehPitchValid); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.vehPitchValid = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + Serial.print(F(" Heading Valid: ")); + Serial.print(myGNSS.packetUBXNAVPVAT->data.flags.bits.vehHeadingValid); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.vehHeadingValid = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + // We don't have helper functions to extract the roll, pitch and heading accuracy from the PVAT message. But we can do it manually: + + Serial.print(F(" Roll Acc: ")); + Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.accRoll) / 100, 2); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.accRoll = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + Serial.print(F(" Pitch Acc: ")); + Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.accPitch) / 100, 2); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.accPitch = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + Serial.print(F(" Heading Acc: ")); + Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.accHeading) / 100, 2); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.accHeading = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + // We don't have helper functions to extract the lat and lon from the PVAT message. But we can do it manually: + + Serial.print(F(" Lat: ")); + Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.lat) / 10000000.0, 7); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.lat = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + Serial.print(F(" Lon: ")); + Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.lon) / 10000000.0, 7); + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.lon = false; // Mark the data as stale + myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; + + Serial.println(); + } + + delay(250); +} From 4f0a0ca3c5e6420be9064b91702947c23104bd1b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 16:04:33 +0000 Subject: [PATCH 069/122] Step_8 --- keywords.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/keywords.txt b/keywords.txt index 3aad233..2b01773 100644 --- a/keywords.txt +++ b/keywords.txt @@ -287,6 +287,15 @@ initPacketUBXNAVHPPOSLLH KEYWORD2 flushHPPOSLLH KEYWORD2 logNAVHPPOSLLH KEYWORD2 +getNAVPVAT KEYWORD2 +setAutoNAVPVAT KEYWORD2 +setAutoNAVPVAT KEYWORD2 +setAutoNAVPVATrate KEYWORD2 +setAutoNAVPVATcallback KEYWORD2 +assumeAutoNAVPVAT KEYWORD2 +flushNAVPVAT KEYWORD2 +logNAVPVAT KEYWORD2 + getNAVCLOCK KEYWORD2 setAutoNAVCLOCK KEYWORD2 setAutoNAVCLOCKrate KEYWORD2 @@ -517,6 +526,11 @@ getMeanSeaLevelHp KEYWORD2 getHorizontalAccuracy KEYWORD2 getVerticalAccuracy KEYWORD2 +getVehicleRoll KEYWORD2 +getVehiclePitch KEYWORD2 +getVehicleHeading KEYWORD2 +getMotionHeading KEYWORD2 + getSurveyInActive KEYWORD2 getSurveyInValid KEYWORD2 getSurveyInObservationTime KEYWORD2 @@ -652,6 +666,7 @@ UBX_NAV_HPPOSLLH LITERAL1 UBX_NAV_ODO LITERAL1 UBX_NAV_POSECEF LITERAL1 UBX_NAV_PVT LITERAL1 +UBX_NAV_PVAT LITERAL1 UBX_NAV_RELPOSNED LITERAL1 UBX_NAV_RESETODO LITERAL1 UBX_NAV_STATUS LITERAL1 @@ -662,6 +677,7 @@ UBX_NAV_VELNED LITERAL1 UBX_RXM_RAWX LITERAL1 UBX_RXM_SFRBX LITERAL1 +UBX_RXM_SPARTN LITERAL1 UBX_TIM_TM2 LITERAL1 @@ -706,6 +722,8 @@ DYN_MODEL_AIRBORNE2g LITERAL1 DYN_MODEL_AIRBORNE4g LITERAL1 DYN_MODEL_WRIST LITERAL1 DYN_MODEL_BIKE LITERAL1 +DYN_MODEL_MOWER LITERAL1 +DYN_MODEL_ESCOOTER LITERAL1 DYN_MODEL_UNKNOWN LITERAL1 SFE_UBLOX_GNSS_ID_GPS LITERAL1 From 57f133259245d8071c73797e4be2ff630c2720ab Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 16:08:30 +0000 Subject: [PATCH 070/122] Step_9 --- Theory.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Theory.md b/Theory.md index 5b67bc8..3cb9ef7 100644 --- a/Theory.md +++ b/Theory.md @@ -49,6 +49,7 @@ In v2.0, the full list of messages which can be processed and logged automatical - UBX-NAV-DOP (0x01 0x04): Dilution of precision - UBX-NAV-ATT (0x01 0x05): Attitude solution (**only with ADR or UDR products**) - UBX-NAV-PVT (0x01 0x07): Navigation position velocity time solution +- UBX-NAV-PVAT (0x01 0x17): Navigation position velocity attitude time solution (**only with ADR or UDR products**) - UBX-NAV-ODO (0x01 0x09): Odometer solution - UBX-NAV-VELECEF (0x01 0x11): Velocity solution in ECEF - UBX-NAV-VELNED (0x01 0x12): Velocity solution in NED frame @@ -70,6 +71,8 @@ In v2.0, the full list of messages which can be processed and logged automatical - UBX-HNR-ATT (0x28 0x01): Attitude solution (**only with ADR or UDR products**) - UBX-HNR-INS (0x28 0x02): Vehicle dynamics information (**only with ADR or UDR products**) +Please see [Adding_New_Messages.md](./Adding_New_Messages.md) for details on how to add "auto" support for new messages. + Notes: - UBX-NAV-POSLLH is not supported as UBX-NAV-PVT contains the same information - UBX-NAV-TIMEUTC is not supported as UBX-NAV-PVT contains the same information From 4b0303177d5927654e753641072f69a077a2148f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 16:13:49 +0000 Subject: [PATCH 071/122] Create Adding_New_Messages.md --- Adding_New_Messages.md | 167 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Adding_New_Messages.md diff --git a/Adding_New_Messages.md b/Adding_New_Messages.md new file mode 100644 index 0000000..3205e01 --- /dev/null +++ b/Adding_New_Messages.md @@ -0,0 +1,167 @@ +## How to add new messages to the SparkFun u-blox GNSS Arduino Library + +Based on [this issue](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/issues/97), here is a summary of how to add new messages to the SparkFun u-blox GNSS Arduino Library +- with full "auto" support (for callbacks, logging, etc.). + +Looking at the issue, we see that the library is not supporting the UBX-NAV-PVAT (Navigation Position Velocity Attitude Time solution). +PVAT is a new message added in version 1.21 of the HPS (High Precision Fusion) firmware and version 33.21 of the F9 Interface Description. +This makes us wonder if more new messages have been added which should also be included? + +### Step 1: Check the Interface Description for new keys + +* Download the latest [interface description](https://www.u-blox.com/sites/default/files/ZED-F9R_ProductSummary_UBX-19048775.pdf) from the [u-blox website](https://www.u-blox.com/en/product/zed-f9r-module#tab-documentation-resources) +* Open the interface description in Adobe Acrobat Reader DC (the free version) +* Do a ```File \ Save as Text...``` +* Save the file in ```Text (Accessible) (*.txt)``` format +* Go make a cup of tea - this takes a while +* Open the txt file in Notepad++ or another editor which supports Regular Expressions +* The keys will have been saved as individual lines in the format: 0xnnnnnnnn space CR LF +* So all we need to do is use a regex to delete everything else +* Open Search \ Replace +* Click the Search Mode - Regular Expression button +* In the "Find what :" box enter: ```^(?!.*0x[\dabcdefABCDEF]{8}\s\r\n).*``` +* Clear the "Replace with :" box +* Click "Replace All" +* You are left with just the keys - and a bunch of empty lines, some of which contain form feeds (\f) +* Delete the empty lines (\r\n) by replacing \r\n with nothing - don't panic, this takes a few seconds +* Delete the form feeds by replacing \f with nothing +* Finally replace the remaining spaces (\s) with \r\n +* Delete any spurious lines left at the start of the file. E.g. ROM and BASE and 0x118B2060. These came from the General information section +* The following line (0x10340014) is the first key from the "Configuration Reference" section +* Search for that key number and you will find it again half way through the file. This second copy came from "Configuration Defaults" +* Delete the duplicate keys from that line onwards +* Save the file +* Open it in a spreadsheet, e.g. LibreOffice Calc +* Select the "A" column and click "Sort Ascending A-Z" +* Save the file (as Text CSV) +* Use KDiff3 or another diff package to see the new additions + +You can find the keys in the [keys folder](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/tree/main/keys), saved as sorted text files. +There are separate files for the P, R and T interfaces, plus a combined list (also sorted in ascending order). + +Comparing HPS 1.21 to HPS 1.20, we can see that the following keys have been added: + +* 0x10340014 CFG-BDS-USE_GEO_PRN +* 0x10710005 CFG-I2CINPROT-SPARTN +* 0x10730005 CFG-UART1INPROT-SPARTN +* 0x10750005 CFG-UART2INPROT-SPARTN +* 0x10770005 CFG-USBINPROT-SPARTN +* 0x10790005 CFG-SPIINPROT-SPARTN +* 0x20050035 CFG-TP-DRSTR_TP1 +* 0x20910605 CFG-MSGOUT-UBX_RXM_SPARTN_I2C +* 0x20910606 CFG-MSGOUT-UBX_RXM_SPARTN_UART1 +* 0x20910607 CFG-MSGOUT-UBX_RXM_SPARTN_UART2 +* 0x20910608 CFG-MSGOUT-UBX_RXM_SPARTN_USB +* 0x20910609 CFG-MSGOUT-UBX_RXM_SPARTN_SPI +* 0x2091062a CFG-MSGOUT-UBX_NAV_PVAT_I2C +* 0x2091062b CFG-MSGOUT-UBX_NAV_PVAT_UART1 +* 0x2091062c CFG-MSGOUT-UBX_NAV_PVAT_UART2 +* 0x2091062d CFG-MSGOUT-UBX_NAV_PVAT_USB +* 0x2091062e CFG-MSGOUT-UBX_NAV_PVAT_SPI +* 0x20910634 CFG-MSGOUT-UBX_SEC_SIG_I2C +* 0x20910635 CFG-MSGOUT-UBX_SEC_SIG_UART1 +* 0x20910636 CFG-MSGOUT-UBX_SEC_SIG_UART2 +* 0x20910637 CFG-MSGOUT-UBX_SEC_SIG_USB +* 0x20910638 CFG-MSGOUT-UBX_SEC_SIG_SPI + +Interestingly, we can also see that one key has been deleted: + +* 0x10530006 CFG-UART2-REMAP + +From this we can confirm - as documented by u-blox in the [Release Notes](https://www.u-blox.com/sites/default/files/ZED-F9R-02B_FW1.00HPS1.21_RN_UBX-21035491_1.3.pdf) - +that HPS 1.21: + +* adds support for SPARTN (Safe Position Augmentation for Real-Time Navigation) correction messages +* enables the use of BeiDou geostationary satellites (previously, this configuration item had a different name) +* enables UBX-SEC-SIG message (signal security measures) as output across the different interfaces +* enables UBX_NAV_PVAT message (navigation and altitude position) as output across the different interfaces + +There are also two new dynamic models, robotic lawn mower (11) and e-scooter model (12), which we need to add to the library. + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/805aab18b6656513bfee473487a437754cd3965d) for the changes. + +### Step 2: Update the combined keys file + +Update [u-blox_config_keys_sorted.txt](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/blob/main/keys/u-blox_config_keys_sorted.txt) +to include the new keys. + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/8895764f237ae494dcd0fa1ae942d487d2e1557f) for the changes. + +### Step 3: Update u-blox_config_keys.h + +Update [u-blox_config_keys.h](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/blob/main/src/u-blox_config_keys.h) to include the new keys. +Include the descriptions as defined in the Interface Description. + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/3609da15f90a7a66b41524e77c6dc3dd76cd362c) for the changes. + +### Step 4: Add the new message struct to u-blox_struct.h + +The next step is to add the new struct for UBX-NAV-PVAT to u-blox_struct.h. + +The messages are in ascending class and ID order. So we add UBX-NAV-PVAT (0x01 0x17) after UBX-NAV-HPPOSLLH (0x01 0x14). + +The names and widths of the fields are taken directly from the interface definition. + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/a4ba440c6240e0974c27f40b976a5ddf0fbdb9b6) for the changes. + +### Step 5: Update SparkFun_u-blox_GNSS_Arduino_Library.h + +Add the new message ID: ```const uint8_t UBX_NAV_PVAT = 0x17;``` + +Add the new functions to provide "auto" support for UBX-NAV-PVAT: ```getNAVPVAT```, ```setAutoNAVPVAT```, ..., ```logNAVPVAT``` + +Add new helper functions to access the most important fields: ```getVehicleRoll```, ..., ```getMotionHeading``` + +Add the pointer to the struct storage: ```UBX_NAV_PVAT_t *packetUBXNAVPVAT = NULL;``` + +Add the private init function: ```bool initPacketUBXNAVPVAT();``` + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/423a1e2ccd418dd679257edc6edeec0bd3029052) for the changes. + +### Step 6: Update SparkFun_u-blox_GNSS_Arduino_Library.cpp + +Now we need to update SparkFun_u-blox_GNSS_Arduino_Library.cpp: + +#### Step 6.1: Update end() + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/35d225e3f1abb316eda3becb7f8e2eb04ff1d17c) for the changes. + +#### Step 6.2: Update checkAutomatic() + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/b746d8e2742961ede95e2d06d5db3a3a557e571d) for the changes. + +#### Step 6.3: Update processUBXpacket() + +Take time to double-check that you have used the correct data width, signed/unsigned and position for each field. + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/8eecdd5044f810b0e2b567150ff63a17c219fe8e) for the changes. + +#### Step 6.4: Update checkCallbacks() + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/b53bffaa3ae12482cfb268f23796963d0b8519c9) for the changes. + +#### Step 6.5: Add the "auto" functions + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/e394ae003ad38117d150598774d0552059416473) for the changes. + +#### Step 6.6: Add the helper functions (if any) + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/318e76383e96d6676bbb57294c25e665c0d4a31f) for the changes. + +### Step 7: Add an example + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/06014dc95f1b9ffae4876fbacfb9390541d7c31d) for the changes. + +### Step 8: Update keywords.txt + +Add the new "auto" and helper functions to keywords.txt. + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/4f0a0ca3c5e6420be9064b91702947c23104bd1b) for the changes. + +### Step 9: Update Theory.md + +Add the new message to the list of "auto" messages. + +See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/57f133259245d8071c73797e4be2ff630c2720ab) for the changes. + +That's all folks! \ No newline at end of file From ce6f8ce1bd9036d73732f51fee2b3685729382b0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 16:13:55 +0000 Subject: [PATCH 072/122] Update SparkFun_u-blox_GNSS_Arduino_Library.cpp --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 9a3f29d..83d805b 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2535,7 +2535,6 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVPVAT->data.errEllipseMajor = extractLong(msg, 100); packetUBXNAVPVAT->data.errEllipseMinor = extractLong(msg, 104); - //Mark all datums as fresh (not read before) packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0xFFFFFFFF; packetUBXNAVPVAT->moduleQueried.moduleQueried2.all = 0xFFFFFFFF; From 62967b8e2ac9a34834f417b7ca34f47d1abfdc7c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 16:27:36 +0000 Subject: [PATCH 073/122] Update Adding_New_Messages.md --- Adding_New_Messages.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Adding_New_Messages.md b/Adding_New_Messages.md index 3205e01..e5c6b98 100644 --- a/Adding_New_Messages.md +++ b/Adding_New_Messages.md @@ -1,7 +1,6 @@ ## How to add new messages to the SparkFun u-blox GNSS Arduino Library -Based on [this issue](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/issues/97), here is a summary of how to add new messages to the SparkFun u-blox GNSS Arduino Library -- with full "auto" support (for callbacks, logging, etc.). +Based on [this issue](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/issues/97), here is a summary of how to add new messages to the SparkFun u-blox GNSS Arduino Library with full "auto" support (for callbacks, logging, etc.). Looking at the issue, we see that the library is not supporting the UBX-NAV-PVAT (Navigation Position Velocity Attitude Time solution). PVAT is a new message added in version 1.21 of the HPS (High Precision Fusion) firmware and version 33.21 of the F9 Interface Description. @@ -9,7 +8,7 @@ This makes us wonder if more new messages have been added which should also be i ### Step 1: Check the Interface Description for new keys -* Download the latest [interface description](https://www.u-blox.com/sites/default/files/ZED-F9R_ProductSummary_UBX-19048775.pdf) from the [u-blox website](https://www.u-blox.com/en/product/zed-f9r-module#tab-documentation-resources) +* Download the latest [interface description](https://www.u-blox.com/sites/default/files/F9-HPS-1.21_InterfaceDescription_UBX-21019746.pdf) from the [u-blox website](https://www.u-blox.com/en/product/zed-f9r-module#tab-documentation-resources) * Open the interface description in Adobe Acrobat Reader DC (the free version) * Do a ```File \ Save as Text...``` * Save the file in ```Text (Accessible) (*.txt)``` format From 103bfbeee0a8ee2381affe1962c564838ab08ec0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Jan 2022 16:27:44 +0000 Subject: [PATCH 074/122] Update SparkFun_u-blox_GNSS_Arduino_Library.cpp --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 83d805b..5c3ae5c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -8810,7 +8810,6 @@ bool SFE_UBLOX_GNSS::getNAVPVAT(uint16_t maxWait) packetCfg.id = UBX_NAV_PVAT; packetCfg.len = 0; packetCfg.startingSpot = 0; - //packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+packetCfgPayloadSize = 84 bytes Note:now hard-coded in processUBX //The data is parsed as part of processing the response sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait); From bdfb274549cb41f4b033568ba3be637a8eb986ca Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 11 Jan 2022 21:53:57 +0000 Subject: [PATCH 075/122] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98a4206..54be67c 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ This library can be installed via the Arduino Library manager. Search for **Spar 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 [**23 messages**](./Theory.md#auto-messages), covering the full range of: standard and High Precision position, velocity 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 [**26 messages**](./Theory.md#auto-messages), covering the full range of: standard and High Precision position, velocity 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. * 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. * Each "auto" message has a clearly-defined [data storage struct](./src/u-blox_structs.h) which follows the u-blox protocol specification precisely. From 185c6c200aec7049d0f7ddacf3f1b6e7f1f420bd Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 12 Jan 2022 14:02:46 +0000 Subject: [PATCH 076/122] Add support for automatic NMEA --- .../Example1_getLatestNMEAGPGGA.ino | 125 +++++ src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 471 ++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 24 + src/u-blox_structs.h | 49 ++ 4 files changed, 669 insertions(+) create mode 100644 examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino diff --git a/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino new file mode 100644 index 0000000..bf525a9 --- /dev/null +++ b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino @@ -0,0 +1,125 @@ +/* + Get the GPGGA NMEA sentence using getLatestNMEAGPGGA + By: Paul Clark + SparkFun Electronics + Date: January 12th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to turn on/off the NMEA sentences being output over I2C. + It then demonstrates how to use the new getLatestNMEAGPGGA function to retrieve the latest GPGGA message. + getLatestNMEAGPGGA returns immediately - it is not blocking. + It returns: + 0 if no data is available + 1 if the data is valid but is stale (you have read it before) + 2 if the data is valid and fresh + + This example turns off all sentences except for GPGGA. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/15136 + NEO-M8P RTK: https://www.sparkfun.com/products/15005 + SAM-M8Q: https://www.sparkfun.com/products/15106 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a RedBoard + 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 //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +void setup() +{ + + Serial.begin(115200); + Serial.println(F("SparkFun u-blox GNSS Example")); + + Wire.begin(); + + //myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial + + if (myGNSS.begin() == false) + { + Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing.")); + while (1) + ; + } + + //Disable or enable various NMEA sentences over the I2C interface + myGNSS.setI2COutput(COM_TYPE_NMEA | COM_TYPE_UBX); // Turn on both UBX and NMEA sentences on I2C. (Turn off RTCM and SPARTN) + myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_I2C); // Several of these are on by default on ublox board so let's disable them + myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C); + myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C); + myGNSS.disableNMEAMessage(UBX_NMEA_RMC, COM_PORT_I2C); + myGNSS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C); + myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); // Leave only GGA enabled at current navigation rate + + //myGNSS.saveConfiguration(); //Optional: Save these settings to NVM + + Serial.println(F("Messages configured")); + + //myGNSS.setNMEAOutputPort(Serial); // Uncomment this line to echo all NMEA data to Serial for debugging +} + +void loop() +{ + // getLatestNMEAGPGGA calls checkUblox for us. We don't need to do it here + + NMEA_GGA_data_t data; // Storage for the GPGGA data + uint8_t result = myGNSS.getLatestNMEAGPGGA(&data); // Get the latest GPGGA data (if any) + + if (result == 0) + { + Serial.println(F("No GPGGA data available")); + } + else if (result == 1) + { + Serial.println(F("GPGGA data is available but is stale")); + } + else if (result == 2) + { + // Data contains .length and .nmea + Serial.print(F("NMEA: Length: ")); + Serial.print(data.length); + Serial.print(F("\tData: ")); + Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated) + } + else + { + Serial.print(F("result == ")); + Serial.print(result); + Serial.println(F(". This should be impossible!")); + } + + result = myGNSS.getLatestNMEAGNGGA(&data); // Get the latest GNGGA data (if any) + + if (result == 0) + { + Serial.println(F("No GNGGA data available")); + } + else if (result == 1) + { + Serial.println(F("GNGGA data is available but is stale")); + } + else if (result == 2) + { + // Data contains .length and .nmea + Serial.print(F("NMEA: Length: ")); + Serial.print(data.length); + Serial.print(F("\tData: ")); + Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated) + } + else + { + Serial.print(F("result == ")); + Serial.print(result); + Serial.println(F(". This should be impossible!")); + } + + delay(250); +} diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 5c3ae5c..82eeb09 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -406,6 +406,26 @@ void SFE_UBLOX_GNSS::end(void) packetUBXHNRPVT = NULL; // Redundant? } + if (storageNMEAGPGGA != NULL) + { + if (storageNMEAGPGGA->callbackCopy != NULL) + { + delete storageNMEAGPGGA->callbackCopy; + } + delete storageNMEAGPGGA; + storageNMEAGPGGA = NULL; // Redundant? + } + + if (storageNMEAGNGGA != NULL) + { + if (storageNMEAGNGGA->callbackCopy != NULL) + { + delete storageNMEAGNGGA->callbackCopy; + } + delete storageNMEAGNGGA; + storageNMEAGNGGA = NULL; // Redundant? + } + } //Allow the user to change packetCfgPayloadSize. Handy if you want to process big messages like RAWX @@ -1682,6 +1702,15 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r _signsOfLife = isNMEAHeaderValid(); } + // Check if we have automatic storage for this message + if (isThisNMEAauto()) + { + uint8_t *lengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length + uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + *lengthPtr = 6; // Set the working copy length + memcpy(nmeaPtr, &nmeaAddressField[0], 6); // Copy the start character and address field into the working copy + } + // We've just received the end of the address field. Check if it is selected for logging if (logThisNMEA()) { @@ -1701,6 +1730,24 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r if ((nmeaByteCounter > 5) || (nmeaByteCounter < 0)) // Should we add incoming to the file buffer and/or pass it to processNMEA? { + if (isThisNMEAauto()) + { + uint8_t *lengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length + uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t nmeaMaxLength = getNMEAMaxLength(); + if (*lengthPtr < nmeaMaxLength) + { + *(nmeaPtr + *lengthPtr) = incoming; // Store the character + *lengthPtr = *lengthPtr + 1; // Increment the length + if (*lengthPtr == nmeaMaxLength) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("process: NMEA buffer is full!")); + } + } + } + } if (logThisNMEA()) storeFileBytes(&incoming, 1); // Add incoming to the file buffer if (processThisNMEA()) @@ -1716,7 +1763,85 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r currentSentence = NONE; //Something went wrong. Reset. if (nmeaByteCounter == 0) // Check if we are done + { + if (isThisNMEAauto()) + { + uint8_t *workingLengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length + uint8_t *workingNMEAPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t nmeaMaxLength = getNMEAMaxLength(); + // Check the checksum: the checksum is the exclusive-OR of all characters between the $ and the * + uint8_t nmeaChecksum = 0; + uint8_t charsChecked = 1; // Start after the $ + uint8_t thisChar = '\0'; + while ((charsChecked < (nmeaMaxLength - 1)) + && (charsChecked < ((*workingLengthPtr) - 4)) + && (thisChar != '*')) + { + thisChar = *(workingNMEAPtr + charsChecked); // Get a char from the working copy + if (thisChar != '*') // Ex-or the char into the checksum - but not if it is the '*' + nmeaChecksum ^= thisChar; + charsChecked++; // Increment the counter + } + if (thisChar == '*') // Make sure we found the * + { + uint8_t expectedChecksum1 = (nmeaChecksum >> 4) + '0'; + if (expectedChecksum1 >= ':') // Handle Hex correctly + expectedChecksum1 += 'A' - ':'; + uint8_t expectedChecksum2 = (nmeaChecksum & 0x0F) + '0'; + if (expectedChecksum2 >= ':') // Handle Hex correctly + expectedChecksum2 += 'A' - ':'; + if ((expectedChecksum1 == *(workingNMEAPtr + charsChecked)) + && (expectedChecksum2 == *(workingNMEAPtr + charsChecked + 1))) + { + uint8_t *completeLengthPtr = getNMEACompleteLengthPtr(); // Get a pointer to the complete copy length + uint8_t *completeNMEAPtr = getNMEACompleteNMEAPtr(); // Get a pointer to the complete copy NMEA data + memset(completeNMEAPtr, 0, nmeaMaxLength); // Clear the previous complete copy + memcpy(completeNMEAPtr, workingNMEAPtr, *workingLengthPtr); // Copy the working copy into the complete copy + *completeLengthPtr = *workingLengthPtr; // Update the length + nmeaAutomaticFlags *flagsPtr = getNMEAFlagsPtr(); // Get a pointer to the flags + nmeaAutomaticFlags flagsCopy = *flagsPtr; + flagsCopy.flags.bits.completeCopyValid = 1; // Set the complete copy valid flag + flagsCopy.flags.bits.completeCopyRead = 0; // Clear the complete copy read/stale flag + *flagsPtr = flagsCopy; // Update the flags + // Callback + if (doesThisNMEAHaveCallback()) // Do we need to copy the data into the callback copy? + { + if (flagsCopy.flags.bits.callbackCopyValid == 0) // Has the callback copy valid flag been cleared (by checkCallbacks) + { + uint8_t *callbackLengthPtr = getNMEACallbackLengthPtr(); // Get a pointer to the callback copy length + uint8_t *callbackNMEAPtr = getNMEACallbackNMEAPtr(); // Get a pointer to the callback copy NMEA data + memset(callbackNMEAPtr, 0, nmeaMaxLength); // Clear the previous callback copy + memcpy(callbackNMEAPtr, workingNMEAPtr, *workingLengthPtr); // Copy the working copy into the callback copy + *callbackLengthPtr = *workingLengthPtr; // Update the length + flagsCopy.flags.bits.callbackCopyValid = 1; // Set the callback copy valid flag + *flagsPtr = flagsCopy; // Update the flags + } + } + } + else + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("process: NMEA checksum fail (2)! Expected ")); + _debugSerial->write(expectedChecksum1); + _debugSerial->write(expectedChecksum2); + _debugSerial->print(F(" Got ")); + _debugSerial->write(*(workingNMEAPtr + charsChecked)); + _debugSerial->write(*(workingNMEAPtr + charsChecked + 1)); + _debugSerial->println(); + } + } + } + else + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->println(F("process: NMEA checksum fail (1)!")); + } + } + } currentSentence = NONE; // All done! + } } else if (currentSentence == RTCM) { @@ -1828,6 +1953,194 @@ void SFE_UBLOX_GNSS::processNMEA(char incoming) _nmeaOutputPort->write(incoming); //Echo this byte to the serial port } +// Check if the NMEA message (in nmeaAddressField) is "auto" (i.e. has RAM allocated for it) +bool SFE_UBLOX_GNSS::isThisNMEAauto() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + if (storageNMEAGPGGA != NULL) + return true; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + if (storageNMEAGNGGA != NULL) + return true; + } + + return false; +} + +// Do we need to copy the data into the callback copy? +bool SFE_UBLOX_GNSS::doesThisNMEAHaveCallback() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + if (storageNMEAGPGGA != NULL) + if (storageNMEAGPGGA->callbackCopy != NULL) + if (storageNMEAGPGGA->callbackPointer != NULL) + return true; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + if (storageNMEAGNGGA != NULL) + if (storageNMEAGNGGA->callbackCopy != NULL) + if (storageNMEAGNGGA->callbackPointer != NULL) + return true; + } + + return false; +} + +// Get a pointer to the working copy length +uint8_t * SFE_UBLOX_GNSS::getNMEAWorkingLengthPtr() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGPGGA->workingCopy.length; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGNGGA->workingCopy.length; + } + + return NULL; +} + +// Get a pointer to the working copy NMEA data +uint8_t * SFE_UBLOX_GNSS::getNMEAWorkingNMEAPtr() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGPGGA->workingCopy.nmea[0]; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGNGGA->workingCopy.nmea[0]; + } + + return NULL; +} + +// Get a pointer to the complete copy length +uint8_t * SFE_UBLOX_GNSS::getNMEACompleteLengthPtr() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGPGGA->completeCopy.length; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGNGGA->completeCopy.length; + } + + return NULL; +} + +// Get a pointer to the complete copy NMEA data +uint8_t * SFE_UBLOX_GNSS::getNMEACompleteNMEAPtr() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGPGGA->completeCopy.nmea[0]; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGNGGA->completeCopy.nmea[0]; + } + + return NULL; +} + +// Get a pointer to the callback copy length +uint8_t * SFE_UBLOX_GNSS::getNMEACallbackLengthPtr() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGPGGA->callbackCopy->length; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGNGGA->callbackCopy->length; + } + + return NULL; +} + +// Get a pointer to the callback copy NMEA data +uint8_t * SFE_UBLOX_GNSS::getNMEACallbackNMEAPtr() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGPGGA->callbackCopy->nmea[0]; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGNGGA->callbackCopy->nmea[0]; + } + + return NULL; +} + +// Get the maximum length of this NMEA message +uint8_t SFE_UBLOX_GNSS::getNMEAMaxLength() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return NMEA_GGA_MAX_LENGTH; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return NMEA_GGA_MAX_LENGTH; + } + + return 0; +} + +// Get a pointer to the automatic NMEA flags +nmeaAutomaticFlags * SFE_UBLOX_GNSS::getNMEAFlagsPtr() +{ + char thisNMEA[] = "GPGGA"; + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGPGGA->automaticFlags; + } + + strcpy(thisNMEA, "GNGGA"); + if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) + { + return &storageNMEAGNGGA->automaticFlags; + } + + return NULL; +} + //We need to be able to identify an RTCM packet and then the length //so that we know when the RTCM message is completely received and we then start //listening for other sentences (like NMEA or UBX) @@ -4309,6 +4622,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } + if ((storageNMEAGPGGA != NULL) // If RAM has been allocated for message storage + && (storageNMEAGPGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data + && (storageNMEAGPGGA->callbackPointer != NULL) // If the pointer to the callback has been defined + && (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for GPGGA")); + storageNMEAGPGGA->callbackPointer(*storageNMEAGPGGA->callbackCopy); // Call the callback + storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale + } + checkCallbacksReentrant = false; } @@ -11716,6 +12040,153 @@ uint32_t SFE_UBLOX_GNSS::getProcessNMEAMask() return (_processNMEA.all); } +// Initiate automatic storage of NMEA GPGGA messages + +// Get the most recent GPGGA message +// Return 0 if the message has not been received from the module +// Return 1 if the data is valid but has been read before +// Return 2 if the data is valid and is fresh/unread +uint8_t SFE_UBLOX_GNSS::getLatestNMEAGPGGA(NMEA_GGA_data_t *data) +{ + if (storageNMEAGPGGA == NULL) initStorageNMEAGPGGA(); //Check that RAM has been allocated for the message + if (storageNMEAGPGGA == NULL) //Bail if the RAM allocation failed + return (false); + + checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Use a fake UBX class and ID. + + memcpy(data, &storageNMEAGPGGA->completeCopy, sizeof(NMEA_GGA_data_t)); // Copy the complete copy + + uint8_t result = 0; + if (storageNMEAGPGGA->automaticFlags.flags.bits.completeCopyValid == 1) // Is the complete copy valid? + { + result = 1; + if (storageNMEAGPGGA->automaticFlags.flags.bits.completeCopyRead == 0) // Has the data already been read? + { + result = 2; + storageNMEAGPGGA->automaticFlags.flags.bits.completeCopyRead = 1; // Mark the data as read + } + } + + return (result); +} + +//Enable a callback on the arrival of a GPGGA message +bool SFE_UBLOX_GNSS::setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)) +{ + if (storageNMEAGPGGA == NULL) initStorageNMEAGPGGA(); //Check that RAM has been allocated for the message + if (storageNMEAGPGGA == NULL) //Bail if the RAM allocation failed + return (false); + + if (storageNMEAGPGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy + { + storageNMEAGPGGA->callbackCopy = new NMEA_GGA_data_t; + } + + if (storageNMEAGPGGA->callbackCopy == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setNMEAGPGGAcallback: RAM alloc failed!")); + return (false); + } + + storageNMEAGPGGA->callbackPointer = callbackPointer; + return (true); +} + +// Private: allocate RAM for incoming NMEA GPGGA messages and initialize it +bool SFE_UBLOX_GNSS::initStorageNMEAGPGGA() +{ + storageNMEAGPGGA = new NMEA_GPGGA_t; //Allocate RAM for the main struct + if (storageNMEAGPGGA == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initStorageNMEAGPGGA: RAM alloc failed!")); + return (false); + } + + storageNMEAGPGGA->workingCopy.length = 0; // Clear the data length + memset(storageNMEAGPGGA->workingCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage + storageNMEAGPGGA->completeCopy.length = 0; // Clear the data length + memset(storageNMEAGPGGA->completeCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage + + storageNMEAGPGGA->callbackPointer = NULL; // Clear the callback pointers + storageNMEAGPGGA->callbackCopy = NULL; + + storageNMEAGPGGA->automaticFlags.flags.all = 0; // Mark the data as invalid/stale and unread + + return (true); +} + +uint8_t SFE_UBLOX_GNSS::getLatestNMEAGNGGA(NMEA_GGA_data_t *data) +{ + if (storageNMEAGNGGA == NULL) initStorageNMEAGNGGA(); //Check that RAM has been allocated for the message + if (storageNMEAGNGGA == NULL) //Bail if the RAM allocation failed + return (false); + + checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Use a fake UBX class and ID. + + memcpy(data, &storageNMEAGNGGA->completeCopy, sizeof(NMEA_GGA_data_t)); // Copy the complete copy + + uint8_t result = 0; + if (storageNMEAGNGGA->automaticFlags.flags.bits.completeCopyValid == 1) // Is the complete copy valid? + { + result = 1; + if (storageNMEAGNGGA->automaticFlags.flags.bits.completeCopyRead == 0) // Has the data already been read? + { + result = 2; + storageNMEAGNGGA->automaticFlags.flags.bits.completeCopyRead = 1; // Mark the data as read + } + } + + return (result); +} + +bool SFE_UBLOX_GNSS::setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)) +{ + if (storageNMEAGNGGA == NULL) initStorageNMEAGNGGA(); //Check that RAM has been allocated for the message + if (storageNMEAGNGGA == NULL) //Bail if the RAM allocation failed + return (false); + + if (storageNMEAGNGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy + { + storageNMEAGNGGA->callbackCopy = new NMEA_GGA_data_t; + } + + if (storageNMEAGNGGA->callbackCopy == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setNMEAGNGGAcallback: RAM alloc failed!")); + return (false); + } + + storageNMEAGNGGA->callbackPointer = callbackPointer; + return (true); +} + +// Private: allocate RAM for incoming NMEA GNGGA messages and initialize it +bool SFE_UBLOX_GNSS::initStorageNMEAGNGGA() +{ + storageNMEAGNGGA = new NMEA_GNGGA_t; //Allocate RAM for the main struct + if (storageNMEAGNGGA == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initStorageNMEAGNGGA: RAM alloc failed!")); + return (false); + } + + storageNMEAGNGGA->workingCopy.length = 0; // Clear the data length + memset(storageNMEAGNGGA->workingCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage + storageNMEAGNGGA->completeCopy.length = 0; // Clear the data length + memset(storageNMEAGNGGA->completeCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage + + storageNMEAGNGGA->callbackPointer = NULL; // Clear the callback pointers + storageNMEAGNGGA->callbackCopy = NULL; + + storageNMEAGNGGA->automaticFlags.flags.all = 0; // Mark the data as invalid/stale and unread + + return (true); +} + // ***** CFG RATE Helper Functions //Set the rate at which the module will give us an updated navigation solution diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 8d94e8c..3d51197 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1323,6 +1323,13 @@ class SFE_UBLOX_GNSS float getHNRpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees float getHNRheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees + // Support for "auto" storage of NMEA messages + + uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data + bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message + uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data + bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message + // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket // From v2.0: These are public. The user can call these to extract data from custom packets uint32_t extractLong(ubxPacket *msg, uint8_t spotToStart); //Combine four bytes from payload into long @@ -1373,6 +1380,9 @@ class SFE_UBLOX_GNSS UBX_MGA_ACK_DATA0_t *packetUBXMGAACK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_MGA_DBD_t *packetUBXMGADBD = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + NMEA_GPGGA_t *storageNMEAGPGGA = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + NMEA_GNGGA_t *storageNMEAGNGGA = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame private: @@ -1452,6 +1462,9 @@ class SFE_UBLOX_GNSS bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it bool initPacketUBXMGADBD(); // Allocate RAM for packetUBXMGADBD and initialize it + bool initStorageNMEAGPGGA(); // Allocate RAM for incoming NMEA GPGGA messages and initialize it + bool initStorageNMEAGNGGA(); // Allocate RAM for incoming NMEA GNGGA messages and initialize it + //Variables TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware Stream *_serialPort; //The generic connection to user's chosen Serial hardware @@ -1526,6 +1539,17 @@ class SFE_UBLOX_GNSS bool processThisNMEA(); // Return true if we should pass this NMEA message to processNMEA bool isNMEAHeaderValid(); // Return true if the six byte NMEA header appears valid. Used to set _signsOfLife + bool isThisNMEAauto(); // Check if the NMEA message (in nmeaAddressField) is "auto" (i.e. has RAM allocated for it) + bool doesThisNMEAHaveCallback(); // Do we need to copy the data into the callback copy? + uint8_t *getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length + uint8_t *getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t *getNMEACompleteLengthPtr(); // Get a pointer to the complete copy length + uint8_t *getNMEACompleteNMEAPtr(); // Get a pointer to the complete copy NMEA data + uint8_t *getNMEACallbackLengthPtr(); // Get a pointer to the callback copy length + uint8_t *getNMEACallbackNMEAPtr(); // Get a pointer to the callback copy NMEA data + uint8_t getNMEAMaxLength(); // Get the maximum length of this NMEA message + nmeaAutomaticFlags *getNMEAFlagsPtr(); // Get a pointer to the flags + uint16_t rtcmLen = 0; // Flag to prevent reentry into checkCallbacks diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 84872bb..3d6dcaf 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -2232,4 +2232,53 @@ typedef struct UBX_HNR_INS_data_t *callbackData; } UBX_HNR_INS_t; +// NMEA-specific structs + +//Additional flags and pointers that need to be stored with each message type +struct nmeaAutomaticFlags +{ + union + { + uint8_t all; + struct + { + uint8_t completeCopyValid : 1; // Is the copy of the data struct used by the get function valid/fresh? 0 = invalid/stale, 1 = valid/fresh + uint8_t completeCopyRead : 1; // Has the complete copy been read? 0 = unread, 1 = read + uint8_t callbackCopyValid : 1; // Is the copy of the data struct used by the callback valid/fresh? 0 = invalid/stale, 1 = valid/fresh + } bits; + } flags; +}; + +// The max length for NMEA messages should be 82 bytes, but GGA messages can exceed that if they include the +// extra decimal places for "High Precision". +// +// To be safe, let's allocate 90 bytes to store the message + +const uint8_t NMEA_GGA_MAX_LENGTH = 90; + +typedef struct +{ + uint8_t length; // The number of bytes in nmea + uint8_t nmea[NMEA_GGA_MAX_LENGTH]; +} NMEA_GGA_data_t; + +typedef struct +{ + nmeaAutomaticFlags automaticFlags; + NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy + NMEA_GGA_data_t completeCopy; // The working copy is copied into the complete copy when all data has been received and the checksum is valid + void (*callbackPointer)(NMEA_GGA_data_t); + NMEA_GGA_data_t *callbackCopy; // The callback gets its own preserved copy of the complete copy +} NMEA_GPGGA_t; + +typedef struct +{ + nmeaAutomaticFlags automaticFlags; + NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy + NMEA_GGA_data_t completeCopy; // The working copy is copied into the complete copy when all data has been received and the checksum is valid + void (*callbackPointer)(NMEA_GGA_data_t); + NMEA_GGA_data_t *callbackCopy; // The callback gets its own preserved copy of the complete copy +} NMEA_GNGGA_t; + + #endif From 34b982841a14e2c5f6f18c82763b10edf07e0ca3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 12 Jan 2022 18:02:50 +0000 Subject: [PATCH 077/122] Small tweaks --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 1 + src/u-blox_structs.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 82eeb09..fe36d01 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1769,6 +1769,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r uint8_t *workingLengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length uint8_t *workingNMEAPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data uint8_t nmeaMaxLength = getNMEAMaxLength(); + // Check the checksum: the checksum is the exclusive-OR of all characters between the $ and the * uint8_t nmeaChecksum = 0; uint8_t charsChecked = 1; // Start after the $ diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 3d6dcaf..89d88f5 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -2252,7 +2252,7 @@ struct nmeaAutomaticFlags // The max length for NMEA messages should be 82 bytes, but GGA messages can exceed that if they include the // extra decimal places for "High Precision". // -// To be safe, let's allocate 90 bytes to store the message +// To be safe, let's allocate 90 bytes to store the GGA message const uint8_t NMEA_GGA_MAX_LENGTH = 90; From a1814e32abfbeb458c6d3739a653efa42d6df56f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Jan 2022 10:38:20 +0000 Subject: [PATCH 078/122] Add setMainTalkerID and setHighPrecisionMode --- .../Example1_getLatestNMEAGPGGA.ino | 32 ++++++------ keywords.txt | 26 ++++++++-- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 50 +++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 35 +++++++++---- src/u-blox_structs.h | 6 +-- 5 files changed, 115 insertions(+), 34 deletions(-) diff --git a/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino index bf525a9..bb6b68a 100644 --- a/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino +++ b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino @@ -14,6 +14,10 @@ 1 if the data is valid but is stale (you have read it before) 2 if the data is valid and fresh + If the module is using multiple GNSS constellations, the GGA message will be prefixed with Talker ID "GN" instead of "GP". + The library includes a getLatestNMEAGNGGA function too. + This example shows how to use both functions - and how to change the Talker ID so the GNGGA messages become GPGGA. + This example turns off all sentences except for GPGGA. Feel like supporting open source hardware? @@ -59,7 +63,13 @@ void setup() myGNSS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C); myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); // Leave only GGA enabled at current navigation rate - //myGNSS.saveConfiguration(); //Optional: Save these settings to NVM + // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA + myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); + //myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_DEFAULT); // Uncomment this line to restore the default main talker ID + + myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages + + //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM Serial.println(F("Messages configured")); @@ -81,20 +91,14 @@ void loop() { Serial.println(F("GPGGA data is available but is stale")); } - else if (result == 2) + else // if (result == 2) { // Data contains .length and .nmea - Serial.print(F("NMEA: Length: ")); + Serial.print(F("Latest GPGGA: Length: ")); Serial.print(data.length); Serial.print(F("\tData: ")); Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated) } - else - { - Serial.print(F("result == ")); - Serial.print(result); - Serial.println(F(". This should be impossible!")); - } result = myGNSS.getLatestNMEAGNGGA(&data); // Get the latest GNGGA data (if any) @@ -106,20 +110,14 @@ void loop() { Serial.println(F("GNGGA data is available but is stale")); } - else if (result == 2) + else // if (result == 2) { // Data contains .length and .nmea - Serial.print(F("NMEA: Length: ")); + Serial.print(F("Latest GNGGA: Length: ")); Serial.print(data.length); Serial.print(F("\tData: ")); Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated) } - else - { - Serial.print(F("result == ")); - Serial.print(result); - Serial.println(F(". This should be impossible!")); - } delay(250); } diff --git a/keywords.txt b/keywords.txt index 2b01773..f884576 100644 --- a/keywords.txt +++ b/keywords.txt @@ -446,11 +446,6 @@ initPacketUBXHNRPVT KEYWORD2 flushHNRPVT KEYWORD2 logHNRPVT KEYWORD2 -setNMEALoggingMask KEYWORD2 -getNMEALoggingMask KEYWORD2 -setProcessNMEAMask KEYWORD2 -getProcessNMEAMask KEYWORD2 - setNavigationFrequency KEYWORD2 getNavigationFrequency KEYWORD2 setMeasurementRate KEYWORD2 @@ -559,6 +554,19 @@ getHNRroll KEYWORD2 getHNRpitch KEYWORD2 getHNRheading KEYWORD2 +setNMEALoggingMask KEYWORD2 +getNMEALoggingMask KEYWORD2 +setProcessNMEAMask KEYWORD2 +getProcessNMEAMask KEYWORD2 + +setMainTalkerID KEYWORD2 +setHighPrecisionMode KEYWORD2 + +getLatestNMEAGPGGA KEYWORD2 +setNMEAGPGGAcallback KEYWORD2 +getLatestNMEAGNGGA KEYWORD2 +setNMEAGNGGAcallback KEYWORD2 + extractLong KEYWORD2 extractSignedLong KEYWORD2 extractInt KEYWORD2 @@ -745,3 +753,11 @@ SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH LITERAL1 SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED LITERAL1 SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY LITERAL1 SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN LITERAL1 + +SFE_UBLOX_MAIN_TALKER_ID_DEFAULT LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GP LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GL LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GN LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GA LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GB LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GQ LITERAL1 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index fe36d01..650a15e 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1707,7 +1707,9 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r { uint8_t *lengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t nmeaMaxLength = getNMEAMaxLength(); *lengthPtr = 6; // Set the working copy length + memset(nmeaPtr, 0, nmeaMaxLength); // Clear the working copy memcpy(nmeaPtr, &nmeaAddressField[0], 6); // Copy the start character and address field into the working copy } @@ -12020,6 +12022,54 @@ void SFE_UBLOX_GNSS::logHNRPVT(bool enabled) // ***** Helper Functions for NMEA Logging / Processing +// Set the mainTalkerId used by NMEA messages - allows all NMEA messages except GSV to be prefixed with GP instead of GN +bool SFE_UBLOX_GNSS::setMainTalkerID(sfe_ublox_talker_ids_e id, uint16_t maxWait) +{ + //Get the current extended NMEA protocol configuration (V1) + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NMEA; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + //Ask module for the current settings. Loads into payloadCfg. + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + payloadCfg[9] = (uint8_t)id; + + packetCfg.len = 20; + packetCfg.startingSpot = 0; + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + +// Enable/Disable NMEA High Precision Mode - include extra decimal places in the Lat and Lon +bool SFE_UBLOX_GNSS::setHighPrecisionMode(bool enable, uint16_t maxWait) +{ + //Get the current extended NMEA protocol configuration (V1) + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NMEA; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + //Ask module for the current settings. Loads into payloadCfg. + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + if (enable) + { + payloadCfg[3] |= (1 << 3); // Set the highPrec flag + payloadCfg[3] &= ~((1 << 0) | (1 << 2)); // Clear the compat and limit82 flags + } + else + payloadCfg[3] &= ~(1 << 3); // Clear the highPrec flag + + packetCfg.len = 20; + packetCfg.startingSpot = 0; + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + // Log selected NMEA messages to file buffer - if the messages are enabled and if the file buffer exists // User needs to call setFileBufferSize before .begin void SFE_UBLOX_GNSS::setNMEALoggingMask(uint32_t messages) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 3d51197..5e0252c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -522,6 +522,18 @@ enum sfe_ublox_mga_ack_infocode_e SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN }; +// The mainTalkerId, set by UBX-CFG-NMEA setMainTalkerID +enum sfe_ublox_talker_ids_e +{ + SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, + SFE_UBLOX_MAIN_TALKER_ID_GP, + SFE_UBLOX_MAIN_TALKER_ID_GL, + SFE_UBLOX_MAIN_TALKER_ID_GN, + SFE_UBLOX_MAIN_TALKER_ID_GA, + SFE_UBLOX_MAIN_TALKER_ID_GB, + SFE_UBLOX_MAIN_TALKER_ID_GQ +}; + //-=-=-=-=- #ifndef MAX_PAYLOAD_SIZE @@ -1167,14 +1179,6 @@ class SFE_UBLOX_GNSS void flushHNRPVT(); //Mark all the data as read/stale void logHNRPVT(bool enabled = true); // Log data to file buffer - // Helper functions for NMEA logging - void setNMEALoggingMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Add selected NMEA messages to file buffer - if enabled. Default to adding ALL messages to the file buffer - uint32_t getNMEALoggingMask(); // Return which NMEA messages are selected for logging to the file buffer - if enabled - - // Helper functions to control which NMEA messages are passed to processNMEA - void setProcessNMEAMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Control which NMEA messages are passed to processNMEA. Default to passing ALL messages - uint32_t getProcessNMEAMask(); // Return which NMEA messages are passed to processNMEA - // Helper functions for CFG RATE bool setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = defaultMaxWait); //Set the number of nav solutions sent per second @@ -1323,8 +1327,21 @@ class SFE_UBLOX_GNSS float getHNRpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees float getHNRheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees + // Set the mainTalkerId used by NMEA messages - allows all NMEA messages except GSV to be prefixed with GP instead of GN + bool setMainTalkerID(sfe_ublox_talker_ids_e id = SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, uint16_t maxWait = defaultMaxWait); + + // Enable/Disable NMEA High Precision Mode - include extra decimal places in the Lat and Lon + bool setHighPrecisionMode(bool enable = true, uint16_t maxWait = defaultMaxWait); + + // Helper functions for NMEA logging + void setNMEALoggingMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Add selected NMEA messages to file buffer - if enabled. Default to adding ALL messages to the file buffer + uint32_t getNMEALoggingMask(); // Return which NMEA messages are selected for logging to the file buffer - if enabled + + // Helper functions to control which NMEA messages are passed to processNMEA + void setProcessNMEAMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Control which NMEA messages are passed to processNMEA. Default to passing ALL messages + uint32_t getProcessNMEAMask(); // Return which NMEA messages are passed to processNMEA + // Support for "auto" storage of NMEA messages - uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 89d88f5..31fba28 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -2250,11 +2250,11 @@ struct nmeaAutomaticFlags }; // The max length for NMEA messages should be 82 bytes, but GGA messages can exceed that if they include the -// extra decimal places for "High Precision". +// extra decimal places for "High Precision Mode". // -// To be safe, let's allocate 90 bytes to store the GGA message +// To be safe, let's allocate 100 bytes to store the GGA message -const uint8_t NMEA_GGA_MAX_LENGTH = 90; +const uint8_t NMEA_GGA_MAX_LENGTH = 100; typedef struct { From a08198b27e4cf108efad5c5070408409792beb77 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Jan 2022 12:01:23 +0000 Subject: [PATCH 079/122] Add the new callback example --- .../Example1_getLatestNMEAGPGGA.ino | 2 +- .../Example2_NMEA_GGA_Callbacks.ino | 117 ++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 22 +++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 2 +- src/u-blox_structs.h | 3 +- 5 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino diff --git a/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino index bb6b68a..0e66a56 100644 --- a/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino +++ b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino @@ -18,7 +18,7 @@ The library includes a getLatestNMEAGNGGA function too. This example shows how to use both functions - and how to change the Talker ID so the GNGGA messages become GPGGA. - This example turns off all sentences except for GPGGA. + This example turns off all sentences except for GGA. Feel like supporting open source hardware? Buy a board from SparkFun! diff --git a/examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino b/examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino new file mode 100644 index 0000000..ca6380a --- /dev/null +++ b/examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino @@ -0,0 +1,117 @@ +/* + Get the latest GPGGA / GNGGA NMEA sentence using callbacks + By: Paul Clark + SparkFun Electronics + Date: January 12th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to turn on/off the NMEA sentences being output over I2C. + It then demonstrates how to get the latest GPGGA or GNGGA message autonomously using callbacks. + + If the module is using multiple GNSS constellations, the GGA message will be prefixed with Talker ID "GN" instead of "GP". + This example shows how to change the Talker ID so the GNGGA messages become GPGGA. + It also shows how to enable "high precision mode" to include extra decimal places in the GGA messages. + + This example turns off all sentences except for GGA. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/15136 + NEO-M8P RTK: https://www.sparkfun.com/products/15005 + SAM-M8Q: https://www.sparkfun.com/products/15106 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a RedBoard + 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 //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +// Callback: printGPGGA will be called when new GPGGA NMEA data arrives +// See u-blox_structs.h for the full definition of NMEA_GGA_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPGGAcallback +// / _____ This _must_ be NMEA_GGA_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printGPGGA(NMEA_GGA_data_t nmeaData) +{ + Serial.print(F("\r\nGPGGA: Length: ")); + Serial.print(nmeaData.length); + Serial.print(F("\tData: ")); + Serial.print((const char *)nmeaData.nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end +} + +// Callback: printGNGGA will be called if new GNGGA NMEA data arrives +// See u-blox_structs.h for the full definition of NMEA_GGA_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGNGGAcallback +// / _____ This _must_ be NMEA_GGA_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printGNGGA(NMEA_GGA_data_t nmeaData) +{ + Serial.print(F("\r\nGNGGA: Length: ")); + Serial.print(nmeaData.length); + Serial.print(F("\tData: ")); + Serial.print((const char *)nmeaData.nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end +} + +void setup() +{ + + Serial.begin(115200); + Serial.println(F("SparkFun u-blox GNSS Example")); + + Wire.begin(); + + //myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial + + if (myGNSS.begin() == false) + { + Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing.")); + while (1) + ; + } + + // Disable or enable various NMEA sentences over the I2C interface + myGNSS.setI2COutput(COM_TYPE_NMEA | COM_TYPE_UBX); // Turn on both UBX and NMEA sentences on I2C. (Turn off RTCM and SPARTN) + myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_I2C); // Several of these are on by default on ublox board so let's disable them + myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C); + myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C); + myGNSS.disableNMEAMessage(UBX_NMEA_RMC, COM_PORT_I2C); + myGNSS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C); + myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); // Leave only GGA enabled at current navigation rate + + // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA + myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); + //myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_DEFAULT); // Uncomment this line to restore the default main talker ID + + myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages + + //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM + + Serial.println(F("Messages configured")); + + //myGNSS.setNMEAOutputPort(Serial); // Uncomment this line to echo all NMEA data to Serial for debugging + + // Set up the callback for GPGGA + myGNSS.setNMEAGPGGAcallback(&printGPGGA); + + // Set up the callback for GNGGA + myGNSS.setNMEAGNGGAcallback(&printGNGGA); +} + +void loop() +{ + myGNSS.checkUblox(); // Check for the arrival of new data and process it. + myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. + + Serial.print("."); + delay(50); +} diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 650a15e..43e1665 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1712,6 +1712,13 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r memset(nmeaPtr, 0, nmeaMaxLength); // Clear the working copy memcpy(nmeaPtr, &nmeaAddressField[0], 6); // Copy the start character and address field into the working copy } + else + { + // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + // { + // _debugSerial->println(F("process: non-auto NMEA message")); + // } + } // We've just received the end of the address field. Check if it is selected for logging if (logThisNMEA()) @@ -1804,7 +1811,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r nmeaAutomaticFlags *flagsPtr = getNMEAFlagsPtr(); // Get a pointer to the flags nmeaAutomaticFlags flagsCopy = *flagsPtr; flagsCopy.flags.bits.completeCopyValid = 1; // Set the complete copy valid flag - flagsCopy.flags.bits.completeCopyRead = 0; // Clear the complete copy read/stale flag + flagsCopy.flags.bits.completeCopyRead = 0; // Clear the complete copy read flag *flagsPtr = flagsCopy; // Update the flags // Callback if (doesThisNMEAHaveCallback()) // Do we need to copy the data into the callback copy? @@ -4628,7 +4635,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) if ((storageNMEAGPGGA != NULL) // If RAM has been allocated for message storage && (storageNMEAGPGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data && (storageNMEAGPGGA->callbackPointer != NULL) // If the pointer to the callback has been defined - && (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + && (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callback for GPGGA")); @@ -4636,6 +4643,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale } + if ((storageNMEAGNGGA != NULL) // If RAM has been allocated for message storage + && (storageNMEAGNGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data + && (storageNMEAGNGGA->callbackPointer != NULL) // If the pointer to the callback has been defined + && (storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for GNGGA")); + storageNMEAGNGGA->callbackPointer(*storageNMEAGNGGA->callbackCopy); // Call the callback + storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale + } + checkCallbacksReentrant = false; } diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 5e0252c..77946ce 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1345,7 +1345,7 @@ class SFE_UBLOX_GNSS uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data - bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message + bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GNGGA message // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket // From v2.0: These are public. The user can call these to extract data from custom packets diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 31fba28..eb51598 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -2242,7 +2242,7 @@ struct nmeaAutomaticFlags uint8_t all; struct { - uint8_t completeCopyValid : 1; // Is the copy of the data struct used by the get function valid/fresh? 0 = invalid/stale, 1 = valid/fresh + uint8_t completeCopyValid : 1; // Is the copy of the data struct used by the get function valid/fresh? 0 = invalid, 1 = valid uint8_t completeCopyRead : 1; // Has the complete copy been read? 0 = unread, 1 = read uint8_t callbackCopyValid : 1; // Is the copy of the data struct used by the callback valid/fresh? 0 = invalid/stale, 1 = valid/fresh } bits; @@ -2280,5 +2280,4 @@ typedef struct NMEA_GGA_data_t *callbackCopy; // The callback gets its own preserved copy of the complete copy } NMEA_GNGGA_t; - #endif From 3cede3bfff25510422f5ec62cf9a7ae65d645e2f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Jan 2022 14:06:52 +0000 Subject: [PATCH 080/122] Add setDGNSSConfiguration --- README.md | 12 ++++++++++++ Theory.md | 2 +- keywords.txt | 4 ++++ library.properties | 2 +- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 17 +++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 8 ++++++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 54be67c..cb8aaca 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,18 @@ If you are using the Dead Reckoning Sensor Fusion or High Dynamic Rate messages, v2.1.0 of the library adds support for u-blox AssistNowTM Assisted GNSS (A-GNSS) which can dramatically reduce the time-to-first-fix. You can find further details in the [AssistNow Examples folder](./examples/AssistNow). +## Automatic support for correction services like RTK2go, Emlid Caster and Skylark (Swift Navigation) + +RTK NTRIP corrections services often require you to send them your location in NMEA GPGGA format. v2.2 of the library makes this simple by providing get functions and automatic callbacks +for both GPGGA and GNGGA messages. You can now instruct your module to output GPGGA (e.g.) every 10 seconds and then push it to the correction server directly from the callback! No more polling, no more parsing! + +v2.2 also includes two new functions useful for correction services: + +* ```setMainTalkerID``` : lets you change the NMEA Talker ID (prefix) from "GN" to "GP" - just in case your correction service really does need GPGGA, not GNGGA +* ```setHighPrecisionMode``` : adds extra decimal places in the GGA messages, increasing the resolution of latitude, longitude and altitude + +Please see the [new examples](./examples/Automatic_NMEA) for more details. + ## Memory Usage The u-blox GNSS library has grown considerably over the years and v2.0.8 came very close to completely filling the program memory on platforms like the ATmega328 (Arduino Uno). diff --git a/Theory.md b/Theory.md index 3cb9ef7..b9bf834 100644 --- a/Theory.md +++ b/Theory.md @@ -49,12 +49,12 @@ In v2.0, the full list of messages which can be processed and logged automatical - UBX-NAV-DOP (0x01 0x04): Dilution of precision - UBX-NAV-ATT (0x01 0x05): Attitude solution (**only with ADR or UDR products**) - UBX-NAV-PVT (0x01 0x07): Navigation position velocity time solution -- UBX-NAV-PVAT (0x01 0x17): Navigation position velocity attitude time solution (**only with ADR or UDR products**) - UBX-NAV-ODO (0x01 0x09): Odometer solution - UBX-NAV-VELECEF (0x01 0x11): Velocity solution in ECEF - UBX-NAV-VELNED (0x01 0x12): Velocity solution in NED frame - UBX-NAV-HPPOSECEF (0x01 0x13): High precision position solution in ECEF - UBX-NAV-HPPOSLLH (0x01 0x14): High precision geodetic position solution +- UBX-NAV-PVAT (0x01 0x17): Navigation position velocity attitude time solution (**only with ADR or UDR products**) - UBX-NAV-CLOCK (0x01 0x22): Clock solution - UBX-NAV-SVIN (0x01 0x3B): Survey-in data (**only with High Precision GNSS products**) - UBX-NAV-RELPOSNED (0x01 0x3C): Relative positioning information in NED frame (**only with High Precision GNSS products**) diff --git a/keywords.txt b/keywords.txt index f884576..b40d37e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -140,6 +140,7 @@ setSurveyMode KEYWORD2 enableSurveyMode KEYWORD2 disableSurveyMode KEYWORD2 setStaticPosition KEYWORD2 +setDGNSSConfiguration KEYWORD2 getProtocolVersionHigh KEYWORD2 getProtocolVersionLow KEYWORD2 @@ -761,3 +762,6 @@ SFE_UBLOX_MAIN_TALKER_ID_GN LITERAL1 SFE_UBLOX_MAIN_TALKER_ID_GA LITERAL1 SFE_UBLOX_MAIN_TALKER_ID_GB LITERAL1 SFE_UBLOX_MAIN_TALKER_ID_GQ LITERAL1 + +SFE_UBLOX_DGNSS_MODE_FLOAT LITERAL1 +SFE_UBLOX_DGNSS_MODE_FIXED LITERAL1 diff --git a/library.properties b/library.properties index c3d47aa..efe625a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.1.5 +version=2.2.0 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial 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 43e1665..ac25f36 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -6235,6 +6235,23 @@ bool SFE_UBLOX_GNSS::setStaticPosition(int32_t ecefXOrLat, int32_t ecefYOrLon, i return (setStaticPosition(ecefXOrLat, 0, ecefYOrLon, 0, ecefZOrAlt, 0, latlong, maxWait)); } +// Set the DGNSS differential mode +bool SFE_UBLOX_GNSS::setDGNSSConfiguration(sfe_ublox_dgnss_mode_e dgnssMode, uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_DGNSS; + packetCfg.len = 4; + packetCfg.startingSpot = 0; + + payloadCfg[0] = (uint8_t)dgnssMode; + payloadCfg[1] = 0; // reserved0 + payloadCfg[2] = 0; + payloadCfg[3] = 0; + + return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + + // Module Protocol Version //Get the current protocol version of the u-blox module we're communicating with diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 77946ce..71b1e1b 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -534,6 +534,13 @@ enum sfe_ublox_talker_ids_e SFE_UBLOX_MAIN_TALKER_ID_GQ }; +// The DGNSS differential mode +enum sfe_ublox_dgnss_mode_e +{ + SFE_UBLOX_DGNSS_MODE_FLOAT = 2, // No attempts are made to fix ambiguities + SFE_UBLOX_DGNSS_MODE_FIXED // Ambiguities are fixed whenever possible +}; + //-=-=-=-=- #ifndef MAX_PAYLOAD_SIZE @@ -829,6 +836,7 @@ class SFE_UBLOX_GNSS // For Lat/Lon/Alt the units are: degrees^-7, degrees^-9, degrees^-7, degrees^-9, cm, 0.1mm bool setStaticPosition(int32_t ecefXOrLat, int8_t ecefXOrLatHP, int32_t ecefYOrLon, int8_t ecefYOrLonHP, int32_t ecefZOrAlt, int8_t ecefZOrAltHP, bool latLong = false, uint16_t maxWait = 250); bool setStaticPosition(int32_t ecefXOrLat, int32_t ecefYOrLon, int32_t ecefZOrAlt, bool latLong = false, uint16_t maxWait = 250); + bool setDGNSSConfiguration(sfe_ublox_dgnss_mode_e dgnssMode = SFE_UBLOX_DGNSS_MODE_FIXED, uint16_t maxWait = defaultMaxWait); // Set the DGNSS differential mode //Read the module's protocol version uint8_t getProtocolVersionHigh(uint16_t maxWait = defaultMaxWait); //Returns the PROTVER XX.00 from UBX-MON-VER register From 5558e739431a5e8059d94aacf7e3565f75bac9f1 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Jan 2022 20:40:13 +0000 Subject: [PATCH 081/122] Add Example17_NTRIPClient_With_GGA_Callback --- README.md | 2 +- ...xample17_NTRIPClient_With_GGA_Callback.ino | 497 ++++++++++++++++++ .../secrets.h | 27 + 3 files changed, 525 insertions(+), 1 deletion(-) create mode 100644 examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino create mode 100644 examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/secrets.h diff --git a/README.md b/README.md index cb8aaca..073f039 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ v2.1.0 of the library adds support for u-blox AssistNowTM Assisted GN ## Automatic support for correction services like RTK2go, Emlid Caster and Skylark (Swift Navigation) RTK NTRIP corrections services often require you to send them your location in NMEA GPGGA format. v2.2 of the library makes this simple by providing get functions and automatic callbacks -for both GPGGA and GNGGA messages. You can now instruct your module to output GPGGA (e.g.) every 10 seconds and then push it to the correction server directly from the callback! No more polling, no more parsing! +for both GPGGA and GNGGA messages. You can now instruct your module to output GPGGA (e.g.) every 10 seconds and then push it to the correction server directly from the callback. No more polling, no more parsing! v2.2 also includes two new functions useful for correction services: diff --git a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino new file mode 100644 index 0000000..91751e5 --- /dev/null +++ b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino @@ -0,0 +1,497 @@ +/* + Use ESP32 WiFi to get RTCM data from Swift Navigation's Skylark caster as a Client, and transmit GGA using a callback + By: SparkFun Electronics / Nathan Seidle & Paul Clark + Date: January 13th, 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 obtain RTCM data from a NTRIP Caster over WiFi and push it over I2C to a ZED-F9x. + It's confusing, but the Arduino is acting as a 'client' to a 'caster'. + In this case we will use Skylark. But you can of course use RTK2Go or Emlid's Caster too. Change secrets.h. as required. + + The rover's location will be broadcast to the caster every 10s via GGA setence - automatically using a callback. + + This is a proof of concept to show how to connect to a caster via HTTP and show how the corrections control the accuracy. + + It's a fun thing to disconnect from the caster and watch the accuracy degrade. Then connect again and watch it recover! + + For more information about NTRIP Clients and the differences between Rev1 and Rev2 of the protocol + please see: https://www.use-snip.com/kb/knowledge-base/ntrip-rev1-versus-rev2-formats/ + + "In broad protocol terms, the NTRIP client must first connect (get an HTTP “OK” reply) and only then + should it send the sentence. NTRIP protocol revision 2 (which does not have very broad industry + acceptance at this time) does allow sending the sentence in the original header." + https://www.use-snip.com/kb/knowledge-base/subtle-issues-with-using-ntrip-client-nmea-183-strings/ + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + RTK Surveyor: https://www.sparkfun.com/products/18443 + RTK Express: https://www.sparkfun.com/products/18442 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +#include "secrets.h" + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//The ESP32 core has a built in base64 library but not every platform does +//We'll use an external lib if necessary. +#if defined(ARDUINO_ARCH_ESP32) +#include "base64.h" //Built-in ESP32 library +#else +#include //nfriendly library from https://github.com/adamvr/arduino-base64, will work with any platform +#endif + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//Global variables + +unsigned long lastReceivedRTCM_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps +const unsigned long maxTimeBeforeHangup_ms = 10000UL; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster + +bool transmitLocation = true; //By default we will transmit the unit's location via GGA sentence. + +WiFiClient ntripClient; // The WiFi connection to the NTRIP server. This is global so pushGGA can see if we are connected. + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: pushGPGGA will be called when new GPGGA NMEA data arrives +// See u-blox_structs.h for the full definition of NMEA_GGA_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPGGAcallback +// / _____ This _must_ be NMEA_GGA_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void pushGPGGA(NMEA_GGA_data_t nmeaData) +{ + //Provide the caster with our current position as needed + if ((ntripClient.connected() == true) && (transmitLocation == true)) + { + Serial.print(F("Pushing GGA to server: ")); + Serial.print((const char *)nmeaData.nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end + + //Push our current GGA sentence to caster + ntripClient.print((const char *)nmeaData.nmea); + } +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: printPVTdata will be called when new NAV PVT data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallback +// / _____ This _must_ be UBX_NAV_PVT_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) +{ + long latitude = ubxDataStruct.lat; // Print the latitude + Serial.print(F("Lat: ")); + Serial.print(latitude / 10000000L); + Serial.print(F(".")); + Serial.print(abs(latitude % 10000000L)); + + long longitude = ubxDataStruct.lon; // Print the longitude + Serial.print(F(" Long: ")); + Serial.print(longitude / 10000000L); + Serial.print(F(".")); + Serial.print(abs(longitude % 10000000L)); + + long altitude = ubxDataStruct.hMSL; // Print the height above mean sea level + Serial.print(F(" Height: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + uint8_t fixType = ubxDataStruct.fixType; // Print the fix type + Serial.print(F(" Fix: ")); + Serial.print(fixType); + if (fixType == 0) + Serial.print(F(" (None)")); + else if (fixType == 1) + Serial.print(F(" (Dead Reckoning)")); + else if (fixType == 2) + Serial.print(F(" (2D)")); + else if (fixType == 3) + Serial.print(F(" (3D)")); + else if (fixType == 3) + Serial.print(F(" (GNSS + Dead Reckoning)")); + else if (fixType == 5) + Serial.print(F(" (Time Only)")); + else + Serial.print(F(" (UNKNOWN)")); + + uint8_t carrSoln = ubxDataStruct.flags.bits.carrSoln; // Print the carrier solution + Serial.print(F(" Carrier Solution: ")); + Serial.print(carrSoln); + if (carrSoln == 0) + Serial.print(F(" (None)")); + else if (carrSoln == 1) + Serial.print(F(" (Floating)")); + else if (carrSoln == 2) + Serial.print(F(" (Fixed)")); + else + Serial.print(F(" (UNKNOWN)")); + + uint32_t hAcc = ubxDataStruct.hAcc; // Print the horizontal accuracy estimate + Serial.print(F(" Horizontal Accuracy Estimate: ")); + Serial.print(hAcc); + Serial.print(F(" (mm)")); + + Serial.println(); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + Serial.begin(115200); + Serial.println(F("NTRIP testing")); + + Wire.begin(); //Start I2C + + while (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + delay(2000); + //while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages + myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); //Be sure RTCM3 input is enabled. UBX + RTCM3 is not a valid state. + + myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible + + myGNSS.setNavigationFrequency(1); //Set output in Hz. + + // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA + myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); + + myGNSS.setNMEAGPGGAcallback(&pushGPGGA); // Set up the callback for GPGGA + + myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C, 10); // Tell the module to output GGA every 10 seconds + + myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed + + //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + bool keepTrying = true; + while (keepTrying) + { + Serial.print(F("Connecting to local WiFi")); + + unsigned long startTime = millis(); + WiFi.begin(ssid, password); + while ((WiFi.status() != WL_CONNECTED) && (millis() < (startTime + 10000))) // Timeout after 10 seconds + { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + if (WiFi.status() == WL_CONNECTED) + keepTrying = false; // Connected! + else + { + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + } + } + + Serial.print(F("WiFi connected with IP: ")); + Serial.println(WiFi.localIP()); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + while (Serial.available()) // Empty the serial buffer + Serial.read(); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + myGNSS.checkUblox(); // Check for the arrival of new GNSS data and process it. + myGNSS.checkCallbacks(); // Check if any GNSS callbacks are waiting to be processed. + + enum states // Use a 'state machine' to open and close the connection + { + open_connection, + push_data_and_wait_for_keypress, + close_connection, + waiting_for_keypress + }; + static states state = open_connection; + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + switch (state) + { + case open_connection: + Serial.println(F("Connecting to the NTRIP caster...")); + if (beginClient()) // Try to open the connection to the caster + { + Serial.println(F("Connected to the NTRIP caster! Press any key to disconnect...")); + state = push_data_and_wait_for_keypress; // Move on + } + else + { + Serial.print(F("Could not connect to the caster. Trying again in 5 seconds.")); + for (int i = 0; i < 5; i++) + { + delay(1000); + Serial.print(F(".")); + } + Serial.println(); + } + break; + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + case push_data_and_wait_for_keypress: + // If the connection has dropped or timed out, or if the user has pressed a key + if ((processConnection() == false) || (keyPressed())) + { + state = close_connection; // Move on + } + break; + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + case close_connection: + Serial.println(F("Closing the connection to the NTRIP caster...")); + closeConnection(); + Serial.println(F("Press any key to reconnect...")); + state = waiting_for_keypress; // Move on + break; + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + case waiting_for_keypress: + // If the connection has dropped or timed out, or if the user has pressed a key + if (keyPressed()) + state = open_connection; // Move on + break; + } + +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//Connect to NTRIP Caster. Return true is connection is successful. +bool beginClient() +{ + Serial.print(F("Opening socket to ")); + Serial.println(casterHost); + + if (ntripClient.connect(casterHost, casterPort) == false) //Attempt connection + { + Serial.println(F("Connection to caster failed")); + return (false); + } + else + { + Serial.print(F("Connected to ")); + Serial.print(casterHost); + Serial.print(F(" : ")); + Serial.println(casterPort); + + Serial.print(F("Requesting NTRIP Data from mount point ")); + Serial.println(mountPoint); + + // Set up the server request (GET) + const int SERVER_BUFFER_SIZE = 512; + char serverRequest[SERVER_BUFFER_SIZE]; + snprintf(serverRequest, + SERVER_BUFFER_SIZE, + "GET /%s HTTP/1.0\r\nUser-Agent: NTRIP SparkFun u-blox Client v1.0\r\n", + mountPoint); + + // Set up the credentials + char credentials[512]; + if (strlen(casterUser) == 0) + { + strncpy(credentials, "Accept: */*\r\nConnection: close\r\n", sizeof(credentials)); + } + else + { + //Pass base64 encoded user:pw + char userCredentials[sizeof(casterUser) + sizeof(casterUserPW) + 1]; //The ':' takes up a spot + snprintf(userCredentials, sizeof(userCredentials), "%s:%s", casterUser, casterUserPW); + + Serial.print(F("Sending credentials: ")); + Serial.println(userCredentials); + +#if defined(ARDUINO_ARCH_ESP32) + //Encode with ESP32 built-in library + base64 b; + String strEncodedCredentials = b.encode(userCredentials); + char encodedCredentials[strEncodedCredentials.length() + 1]; + strEncodedCredentials.toCharArray(encodedCredentials, sizeof(encodedCredentials)); //Convert String to char array +#else + //Encode with nfriendly library + int encodedLen = base64_enc_len(strlen(userCredentials)); + char encodedCredentials[encodedLen]; //Create array large enough to house encoded data + base64_encode(encodedCredentials, userCredentials, strlen(userCredentials)); //Note: Input array is consumed +#endif + + snprintf(credentials, sizeof(credentials), "Authorization: Basic %s\r\n", encodedCredentials); + } + + // Add the encoded credentials to the server request + strncat(serverRequest, credentials, SERVER_BUFFER_SIZE); + strncat(serverRequest, "\r\n", SERVER_BUFFER_SIZE); + + Serial.print(F("serverRequest size: ")); + Serial.print(strlen(serverRequest)); + Serial.print(F(" of ")); + Serial.print(sizeof(serverRequest)); + Serial.println(F(" bytes available")); + + // Send the server request + Serial.println(F("Sending server request: ")); + Serial.println(serverRequest); + ntripClient.write(serverRequest, strlen(serverRequest)); + + //Wait up to 5 seconds for response + unsigned long startTime = millis(); + while (ntripClient.available() == 0) + { + if (millis() > (startTime + 5000)) + { + Serial.println(F("Caster timed out!")); + ntripClient.stop(); + return (false); + } + delay(10); + } + + //Check reply + int connectionResult = 0; + char response[512]; + size_t responseSpot = 0; + while (ntripClient.available()) // Read bytes from the caster and store them + { + if (responseSpot == sizeof(response) - 1) // Exit the loop if we get too much data + break; + + response[responseSpot++] = ntripClient.read(); + + if (connectionResult == 0) // Only print success/fail once + { + if (strstr(response, "200") != NULL) //Look for '200 OK' + { + connectionResult = 200; + } + if (strstr(response, "401") != NULL) //Look for '401 Unauthorized' + { + Serial.println(F("Hey - your credentials look bad! Check your caster username and password.")); + connectionResult = 401; + } + } + } + response[responseSpot] = '\0'; // NULL-terminate the response + + //Serial.print(F("Caster responded with: ")); Serial.println(response); // Uncomment this line to see the full response + + if (connectionResult != 200) + { + Serial.print(F("Failed to connect to ")); + Serial.println(casterHost); + return (false); + } + else + { + Serial.print(F("Connected to: ")); + Serial.println(casterHost); + lastReceivedRTCM_ms = millis(); //Reset timeout + } + } //End attempt to connect + + return (true); +} // /beginClient + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//Check for the arrival of any correction data. Push it to the GNSS. +//Return false if: the connection has dropped, or if we receive no data for maxTimeBeforeHangup_ms +bool processConnection() +{ + if (ntripClient.connected() == true) // Check that the connection is still open + { + uint8_t rtcmData[512 * 4]; //Most incoming data is around 500 bytes but may be larger + size_t rtcmCount = 0; + + //Collect any available RTCM data + while (ntripClient.available()) + { + //Serial.write(ntripClient.read()); //Pipe to serial port is fine but beware, it's a lot of binary data! + rtcmData[rtcmCount++] = ntripClient.read(); + if (rtcmCount == sizeof(rtcmData)) + break; + } + + if (rtcmCount > 0) + { + lastReceivedRTCM_ms = millis(); + + //Push RTCM to GNSS module over I2C + myGNSS.pushRawData(rtcmData, rtcmCount); + + Serial.print(F("Pushed ")); + Serial.print(rtcmCount); + Serial.println(F(" RTCM bytes to ZED")); + } + } + else + { + Serial.println(F("Connection dropped!")); + return (false); // Connection has dropped - return false + } + + //Timeout if we don't have new data for maxTimeBeforeHangup_ms + if ((millis() - lastReceivedRTCM_ms) > maxTimeBeforeHangup_ms) + { + Serial.println(F("RTCM timeout!")); + return (false); // Connection has timed out - return false + } + + return (true); +} // /processConnection + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void closeConnection() +{ + if (ntripClient.connected() == true) + { + ntripClient.stop(); + } + Serial.println(F("Disconnected!")); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//Return true if a key has been pressed +bool keyPressed() +{ + if (Serial.available()) // Check for a new key press + { + delay(100); // Wait for any more keystrokes to arrive + while (Serial.available()) // Empty the serial buffer + Serial.read(); + return (true); + } + + return (false); +} diff --git a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/secrets.h b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/secrets.h new file mode 100644 index 0000000..9de9b71 --- /dev/null +++ b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/secrets.h @@ -0,0 +1,27 @@ +//Your WiFi credentials +const char ssid[] = "yourSSID"; +const char password[] = "yourPassword"; + +//RTK2Go works well and is free +//const char casterHost[] = "rtk2go.com"; +//const uint16_t casterPort = 2101; +//const char casterUser[] = "myEmail@test.com"; //User must provide their own email address to use RTK2Go +//const char casterUserPW[] = ""; +//const char mountPoint[] = "bldr_SparkFun1"; //The mount point you want to get data from + +//Emlid Caster also works well and is free +//const char casterHost[] = "caster.emlid.com"; +//const uint16_t casterPort = 2101; +//const char casterUser[] = "u99696"; //User name and pw must be obtained through their web portal +//const char casterUserPW[] = "466zez"; +//const char mountPoint[] = "MP1979"; //The mount point you want to get data from + +// Skylark (Swift Navigation) is awesome - but requires a subscription: +// https://www.swiftnav.com/skylark +// https://account.swiftnav.com/sign-up +// Use the promo-code ONEMONTHFREE for a free one month access to Skylark on one device +const char casterHost[] = "na.skylark.swiftnav.com"; // na = North Americs L1+L2; eu = Europe L1+L2 +const uint16_t casterPort = 2101; +const char casterUser[] = "NTRIPusername+accountSubdomain"; // This is generated when you add a device to your Skylark account +const char casterUserPW[] = "devicePassword"; +const char mountPoint[] = "CRS"; // The mount point you want to get data from. Select CRS (Cloud Reference Station) for the ZED-F9x From 06dd8f9067eb3137e7272bb329252616214a85a0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Jan 2022 08:51:12 +0000 Subject: [PATCH 082/122] v2.2.0 --- README.md | 39 ++++++++++++++++++++++----------------- Theory.md | 2 +- library.properties | 4 ++-- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 073f039..81ce6f3 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,31 @@ u-blox makes some incredible GNSS receivers covering everything from low-cost, h This library can be installed via the Arduino Library manager. Search for **SparkFun u-blox GNSS**. -## v2.0 +## Automatic support for correction services like RTK2go, Emlid Caster and Skylark (Swift Navigation) + +RTK NTRIP corrections services often require you to send them your location in NMEA GPGGA format. v2.2 of the library makes this easy by providing get functions and automatic callbacks +for both GPGGA and GNGGA messages. You can now instruct your module to output GPGGA (e.g.) every 10 seconds and then push it to the correction server directly from the callback. No more polling, no more parsing! + +v2.2 also includes two new functions useful for correction services: + +* ```setMainTalkerID``` : lets you change the NMEA Talker ID (prefix) from "GN" to "GP" - just in case your correction service really does need GPGGA, not GNGGA +* ```setHighPrecisionMode``` : adds extra decimal places in the GGA messages, increasing the resolution of latitude, longitude and altitude + +Please see the new [Automatic_NMEA examples](./examples/Automatic_NMEA) for more details. + +We've also added a new [NTRIP Caster Client example](./examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback) showing how to use these new features to full effect. + +## AssistNowTM + +v2.1.0 of the library adds support for u-blox AssistNowTM Assisted GNSS (A-GNSS) which can dramatically reduce the time-to-first-fix. You can find further details in the [AssistNow Examples folder](./examples/AssistNow). + +## v2 vs. v1 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 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 [**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. + * 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. * Each "auto" message has a clearly-defined [data storage struct](./src/u-blox_structs.h) which follows the u-blox protocol specification precisely. @@ -53,21 +72,7 @@ Migrating to v2.0 is easy. There are two small changes all users will need to ma If you are using the Dead Reckoning Sensor Fusion or High Dynamic Rate messages, you will need to make more small changes to your code. Please see the [dead reckoning examples](./examples/Dead_Reckoning) for more details. There is more detail available in [Theory.md](./Theory.md#migrating-your-code-to-v20) if you need it. -## AssistNowTM - -v2.1.0 of the library adds support for u-blox AssistNowTM Assisted GNSS (A-GNSS) which can dramatically reduce the time-to-first-fix. You can find further details in the [AssistNow Examples folder](./examples/AssistNow). - -## Automatic support for correction services like RTK2go, Emlid Caster and Skylark (Swift Navigation) - -RTK NTRIP corrections services often require you to send them your location in NMEA GPGGA format. v2.2 of the library makes this simple by providing get functions and automatic callbacks -for both GPGGA and GNGGA messages. You can now instruct your module to output GPGGA (e.g.) every 10 seconds and then push it to the correction server directly from the callback. No more polling, no more parsing! - -v2.2 also includes two new functions useful for correction services: - -* ```setMainTalkerID``` : lets you change the NMEA Talker ID (prefix) from "GN" to "GP" - just in case your correction service really does need GPGGA, not GNGGA -* ```setHighPrecisionMode``` : adds extra decimal places in the GGA messages, increasing the resolution of latitude, longitude and altitude - -Please see the [new examples](./examples/Automatic_NMEA) for more details. +There is a [new example](./examples/Dead_Reckoning/Example8_getNAVPVAT) showing how to read the UBX-NAV-PVAT (Position, Velocity, Attitude, Time) with a single function call. UBX-NAV-PVAT has full "auto" callback and data-logging support too! ## Memory Usage diff --git a/Theory.md b/Theory.md index b9bf834..077048d 100644 --- a/Theory.md +++ b/Theory.md @@ -71,7 +71,7 @@ In v2.0, the full list of messages which can be processed and logged automatical - UBX-HNR-ATT (0x28 0x01): Attitude solution (**only with ADR or UDR products**) - UBX-HNR-INS (0x28 0x02): Vehicle dynamics information (**only with ADR or UDR products**) -Please see [Adding_New_Messages.md](./Adding_New_Messages.md) for details on how to add "auto" support for new messages. +Please see [Adding_New_Messages](./Adding_New_Messages.md) for details on how to add "auto" support for new messages. Notes: - UBX-NAV-POSLLH is not supported as UBX-NAV-PVT contains the same information diff --git a/library.properties b/library.properties index efe625a..0a5a6a5 100644 --- a/library.properties +++ b/library.properties @@ -2,8 +2,8 @@ name=SparkFun u-blox GNSS Arduino Library version=2.2.0 author=SparkFun Electronics maintainer=SparkFun Electronics -sentence=Library for I2C and Serial Communication with u-blox GNSS modules

-paragraph=An Arduino Library to enable I2C, Serial and SPI communication for both NMEA reception and binary UBX sending to u-blox modules. Useful for interfacing to the SparkFun GPS-RTK2 ZED-F9P, SparkFun GPS-RTK NEO-M8P-2, the SparkFun SAM-M8Q, and the SparkFun ZOE-M8Q. Library also works with other u-blox based boards.

The ZED-F9P and NEO-M8P-2 modules are top-of-the-line modules for high accuracy GNSS and GPS location solutions including RTK. The ZED-F9P is unique in that it is capable of both rover and base station operations allowing the module to become a base station and produce RTCM 3.x correction data.
+sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules

+paragraph=An Arduino Library to support the full range of u-blox GNSS modules, using both NMEA and UBX protocols over I2C, Serial and SPI. Useful for interfacing to the SparkFun GPS-RTK2 ZED-F9P, SparkFun GPS-RTK NEO-M8P-2, SparkFun SAM-M8Q, SparkFun ZOE-M8Q and all the other SparkFun u-blox GNSS Breakouts.

The ZED-F9P and NEO-M8P-2 modules are top-of-the-line modules for high accuracy GNSS and GPS location solutions including RTK. The ZED-F9P is unique in that it is capable of both rover and base station operations allowing the module to become a base station and produce RTCM 3.x correction data.

Need support for RTK NTRIP Caster services like RTK2go, Emlid Caster and Skylark? This library has functions, callbacks and tried-and-tested examples to let you push RTCM correction data to your module seamlessly!
category=Sensors url=https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library architectures=* From 138787b4319e68ad4431d74c539407f44adeddc1 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Jan 2022 08:51:29 +0000 Subject: [PATCH 083/122] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81ce6f3..6909186 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ We've also added a new [NTRIP Caster Client example](./examples/ZED-F9P/Example1 ## AssistNowTM -v2.1.0 of the library adds support for u-blox AssistNowTM Assisted GNSS (A-GNSS) which can dramatically reduce the time-to-first-fix. You can find further details in the [AssistNow Examples folder](./examples/AssistNow). +v2.1 of the library adds support for u-blox AssistNowTM Assisted GNSS (A-GNSS) which can dramatically reduce the time-to-first-fix. You can find further details in the [AssistNow Examples folder](./examples/AssistNow). ## v2 vs. v1 From 8f7e861d80fa695bbeba96093e063947b1d102ca Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Jan 2022 08:56:05 +0000 Subject: [PATCH 084/122] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6909186..2a64007 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,9 @@ The SPI examples have their [own folder](./examples/SPI). Please check the module datasheets for details on what clock speeds and data rates each module supports. The maximum clock speed is typically 5.5MHz and the maximum transfer rate is typically 125kBytes/s. -## Max (400kHz) I2C Support +## I2C Support -To achieve 400kHz I2C speed please be sure to remove all pull-ups on the I2C bus. Most, if not all, u-blox modules include internal pull ups on the I2C lines (sometimes called DDC in their manuals). Cut all I2C pull up jumpers and/or remove them from peripheral boards. Otherwise, various data glitches can occur. See issues [38](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/38) and [40](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/40) for more information. If possible, run the I2C bus at 100kHz. +For I2C communication, please be sure to remove all additional pull-ups on the I2C bus. u-blox modules include internal pull-ups on the I2C lines (sometimes called DDC in their manuals). Cut all I2C pull-up jumpers and/or remove them from peripheral boards. Otherwise, various data glitches can occur. See issues [38](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/38) and [40](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/40) for more information. We recommend running the I2C bus at 100kHz. ## Contributing From 3cba4d18faef3abed3ada4f5fc5eebb156500a46 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Jan 2022 09:18:43 +0000 Subject: [PATCH 085/122] Only run the YAML bot compiler on a single example. Compiling ten examples was taking far too long and added no value... --- .github/workflows/compile-sketch.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 8a225b7..dea8578 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -99,15 +99,6 @@ jobs: libraries: | - source-path: ./ sketch-paths: | - - examples/Example10_AltitudeMSL - - examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C - - examples/Example13_PVT/Example1_AutoPVT - - examples/Example13_PVT/Example2_AutoPVT_ExplicitUpdate - - examples/Example14_DebugOutput - - examples/Example15_GetDateTime - - examples/Example16_Nanosecond_MaxOutput - - examples/Example18_PowerSaveMode - - examples/Example19_DynamicModel - examples/Example20_SendCustomCommand enable-warnings-report: true enable-deltas-report: true From 9de604cd664e56caf081957cf26261daed981f87 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 31 Jan 2022 09:54:21 +0100 Subject: [PATCH 086/122] Create Example18_PointPerfectClient.ino --- .../Example18_PointPerfectClient.ino | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino diff --git a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino new file mode 100644 index 0000000..8401bd4 --- /dev/null +++ b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino @@ -0,0 +1,170 @@ +/* + Use ESP32 WiFi to get SPARTN data from PointPerfect (broker) as a Client + By: u-blox AG / Michael Ammann + Date: January 27th, 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 obtain SPARTN data from a PointPerfect Broker over WiFi + and push it over I2C to a ZED-F9x. + It's confusing, but the Arduino is acting as a 'client' to the PointPerfect SSR correction service. + + You will need to have a valid u-blox Thingstream account and have a PointPerfect Thinng and Plan. + Thingstream offers continetal SSR corrections to SPARTN cabalble RTK receivers such as the u-blox + ZED-F9 sweries in continental Europ and US. There Network is planned to be expanded to ther regions + over next years. To see sign up go to https://portal.thingstream.io/app/location-services/things + + This is a proof of concept to show how to connect via MQTT to get SPARTN SSR correction. + Using WiFi for a rover is generally a bad idea because of limited WiFi range in the field. + + For more information about MQTT, SPARTN and PointPerfect Correction Services + please see: https://www.u-blox.com/en/product/pointperfect?lang=de + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + RTK Surveyor: https://www.sparkfun.com/products/18443 + RTK Express: https://www.sparkfun.com/products/18442 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + 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 +#include +#include +#include "secrets.h" + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//Global variables +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long lastReceived_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps +int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + Serial.begin(115200); + while (!Serial); + Serial.println(F("PointPerfect testing")); + + Wire.begin(); //Start I2C + Wire.setClock(100000); + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + + Serial.println(F("u-blox module connected")); + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN); // Be sure SPARTN input is enabled. + + myGNSS.setNavigationFrequency(1); //Set output in Hz. + Serial.print(F("Connecting to local WiFi")); + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.print(F("WiFi connected with IP: ")); + Serial.println(WiFi.localIP()); + + while (Serial.available()) Serial.read(); +} + +void loop() +{ + if (Serial.available()) + { + beginClient(); + while (Serial.available()) Serial.read(); //Empty buffer of any newline chars + } + + Serial.println(F("Press any key to start MQTT/SPARTN Client.")); + + delay(1000); +} + +WiFiClientSecure wifiClient = WiFiClientSecure(); +MqttClient mqttClient(wifiClient); + +void mqttMessageHandler(int messageSize) { + uint8_t spartnData[512 * 4]; //Most incoming data is around 500 bytes but may be larger + int spartnCount = 0; + Serial.print(F("Pushed data from ")); + Serial.print(mqttClient.messageTopic()); + Serial.println(F(" topic to ZED")); + while (mqttClient.available()) + { + char ch = mqttClient.read(); + //Serial.write(ch); //Pipe to serial port is fine but beware, it's a lot of binary data + spartnData[spartnCount++] = ch; + if (spartnCount == sizeof(spartnData)) + break; + } + + if (spartnCount > 0) + { + //Push KEYS or SPARTN data to GNSS module over I2C + myGNSS.pushRawData(spartnData, spartnCount, false); + lastReceived_ms = millis(); + } +} + +//Connect to STARTN MQTT broker, receive RTCM, and push to ZED module over I2C +void beginClient() +{ + Serial.println(F("Subscribing to Broker. Press key to stop")); + delay(10); //Wait for any serial to arrive + while (Serial.available()) Serial.read(); //Flush + + while (Serial.available() == 0) + { + //Connect if we are not already + if (wifiClient.connected() == false) + { + // Connect to AWS IoT + wifiClient.setCACert(AWS_CERT_CA); + wifiClient.setCertificate(AWS_CERT_CRT); + wifiClient.setPrivateKey(AWS_CERT_PRIVATE); + if (!mqttClient.connect(AWS_IOT_ENDPOINT, AWS_IOT_PORT)) { + Serial.print(F("MQTT connection failed! Error code = ")); + Serial.println(mqttClient.connectError()); + return; + } else { + Serial.println(F("You're connected to the PointPerfect MQTT broker: ")); + Serial.println(AWS_IOT_ENDPOINT); + // Subscribe to MQTT and register a callback + Serial.println(F("Subscribe to Topics")); + mqttClient.onMessage(mqttMessageHandler); + mqttClient.subscribe(MQTT_TOPIC_KEY); + mqttClient.subscribe(MQTT_TOPIC_SPARTN); + lastReceived_ms = millis(); + } //End attempt to connect + } //End connected == false + else { + mqttClient.poll(); + } + //Close socket if we don't have new data for 10s + if (millis() - lastReceived_ms > maxTimeBeforeHangup_ms) + { + Serial.println(F("SPARTN timeout. Disconnecting...")); + if (mqttClient.connected() == true) + mqttClient.stop(); + return; + } + + delay(10); + } + + Serial.println(F("User pressed a key")); + Serial.println(F("Disconnecting...")); + wifiClient.stop(); +} From 29dda946d649cf78becf025b2336c4366bb42548 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 31 Jan 2022 09:58:21 +0100 Subject: [PATCH 087/122] Create secrets.h --- .../Example18_PointPerfectClient/secrets.h | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 examples/ZED-F9P/Example18_PointPerfectClient/secrets.h diff --git a/examples/ZED-F9P/Example18_PointPerfectClient/secrets.h b/examples/ZED-F9P/Example18_PointPerfectClient/secrets.h new file mode 100644 index 0000000..4353c50 --- /dev/null +++ b/examples/ZED-F9P/Example18_PointPerfectClient/secrets.h @@ -0,0 +1,38 @@ +//Your WiFi credentials +const char ssid[] = ""; +const char password[] = ""; + +// Below infomation you can set after signing up with u-blox Thingstream portal +// and after add a new New PointPerfect Thing +// https://portal.thingstream.io/app/location-services/things +// in the new PointPerfect Thing you go to the credentials page and copy past the values and certificate into this. + +// -> Credentials -> Hostname +const char AWS_IOT_ENDPOINT[] = "pp.services.u-blox.com"; +const unsigned short AWS_IOT_PORT = 8883; +// -> Credentials -> IP key distribution topic +const char MQTT_TOPIC_KEY[] = "/pp/key/ip"; +// -> Credentials -> IP correction topic for EU/US region +const char MQTT_TOPIC_SPARTN[] = "/pp/ip/us"; // choice of {eu, us} + +// -> Credentials -> Amazon Root Certificate +static const char AWS_CERT_CA[] PROGMEM = R"EOF( +-----BEGIN CERTIFICATE----- + +-----END CERTIFICATE----- +)EOF"; + +// -> Credentials -> Client Certificate +static const char AWS_CERT_CRT[] PROGMEM = R"KEY( +-----BEGIN CERTIFICATE----- + +-----END CERTIFICATE----- +)KEY"; + +// Get this from Thingstream Portal +// -> Credentials -> Client Key +static const char AWS_CERT_PRIVATE[] PROGMEM = R"KEY( +-----BEGIN RSA PRIVATE KEY----- + +-----END RSA PRIVATE KEY----- +)KEY"; From 7754abfbd805739d6158828c3616c376a361522b Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 31 Jan 2022 10:00:19 +0100 Subject: [PATCH 088/122] Update Example18_PointPerfectClient.ino --- .../Example18_PointPerfectClient.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino index 8401bd4..6635f26 100644 --- a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino +++ b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino @@ -52,7 +52,6 @@ void setup() Serial.println(F("PointPerfect testing")); Wire.begin(); //Start I2C - Wire.setClock(100000); if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port { From 25ab860f42d5977dcdcd456d4e4214f975a1c9f7 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 31 Jan 2022 10:06:03 +0100 Subject: [PATCH 089/122] Update Example18_PointPerfectClient.ino --- .../Example18_PointPerfectClient.ino | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino index 6635f26..d9f8fd0 100644 --- a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino +++ b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino @@ -9,22 +9,27 @@ and push it over I2C to a ZED-F9x. It's confusing, but the Arduino is acting as a 'client' to the PointPerfect SSR correction service. - You will need to have a valid u-blox Thingstream account and have a PointPerfect Thinng and Plan. - Thingstream offers continetal SSR corrections to SPARTN cabalble RTK receivers such as the u-blox - ZED-F9 sweries in continental Europ and US. There Network is planned to be expanded to ther regions - over next years. To see sign up go to https://portal.thingstream.io/app/location-services/things + You will need to have a valid u-blox Thingstream account and have a PointPerfect Thing and payed plan. + Thingstream offers SSR corrections to SPARTN cabalble RTK receivers such as the u-blox ZED-F9 series + in continental Europ and US. There Network is planned to be expanded to ther regions over next years. + To see sign up go to https://portal.thingstream.io/app/location-services/things This is a proof of concept to show how to connect via MQTT to get SPARTN SSR correction. - Using WiFi for a rover is generally a bad idea because of limited WiFi range in the field. + Using WiFi for a rover is generally a bad idea because of limited WiFi range in the field. + You may use this exmaple in combination with a cell phone with hotspot mode enabled. For more information about MQTT, SPARTN and PointPerfect Correction Services - please see: https://www.u-blox.com/en/product/pointperfect?lang=de + please see: https://www.u-blox.com/en/product/pointperfect Feel like supporting open source hardware? Buy a board from SparkFun! ZED-F9P RTK2: https://www.sparkfun.com/products/16481 RTK Surveyor: https://www.sparkfun.com/products/18443 RTK Express: https://www.sparkfun.com/products/18442 + + Recommended Hardware: + MicroMod GNSS Carrier Board: https://www.sparkfun.com/products/17722 + ESP32 Micromod https://www.sparkfun.com/products/16781 Hardware Connections: Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus From 9bff608dfbe5599166c69260996a1338d472195b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 1 Feb 2022 18:46:27 +0000 Subject: [PATCH 090/122] Add COM_TYPE_SPARTN to keywords.txt --- keywords.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/keywords.txt b/keywords.txt index b40d37e..32d0fcb 100644 --- a/keywords.txt +++ b/keywords.txt @@ -597,6 +597,7 @@ SFE_UBLOX_STATUS_DATA_OVERWRITTEN LITERAL1 COM_TYPE_UBX LITERAL1 COM_TYPE_NMEA LITERAL1 COM_TYPE_RTCM3 LITERAL1 +COM_TYPE_SPARTN LITERAL1 COM_PORT_I2C LITERAL1 COM_PORT_UART1 LITERAL1 From f5b40719cddf33dc4387855c155d0bc3bf323125 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 2 Feb 2022 14:48:29 +0000 Subject: [PATCH 091/122] Add RXM-PMP to u-blox_structs.h --- src/u-blox_structs.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index eb51598..e7588b4 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1463,6 +1463,33 @@ typedef struct UBX_RXM_RAWX_data_t *callbackData; } UBX_RXM_RAWX_t; +// UBX-RXM-PMP (0x02 0x72): PMP raw data (D9 modules) +const uint16_t UBX_RXM_PMP_MAX_LEN = 528; + +typedef struct +{ + uint8_t version; // Message version (0x00 for this version) + uint8_t reserved0[3]; // Reserved + uint32_t timeTag; // Time since startup when frame started : ms + uint32_t uniqueWord[2]; // Received unique words + uint16_t serviceIdentifier; // Received service identifier + uint8_t spare; // Received spare data + uint8_t uniqueWordBitErrors; // Number of bit errors in both unique words + uint8_t userData[504]; // Received user data + uint16_t fecBits; // Number of bits corrected by FEC (forward error correction) + uint8_t ebno; // Energy per bit to noise power spectral density ratio : 2^-3 dB + uint8_t reserved1; // Reserved +} UBX_RXM_PMP_data_t; + +typedef struct +{ + ubxAutomaticFlags automaticFlags; + UBX_RXM_PMP_data_t data; + bool moduleQueried; + void (*callbackPointer)(UBX_RXM_PMP_data_t); + UBX_RXM_PMP_data_t *callbackData; +} UBX_RXM_PMP_t; + // CFG-specific structs // UBX-CFG-RATE (0x06 0x08): Navigation/measurement rate settings From 773cee24c06b521da91105d792276564ef7550a0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 4 Feb 2022 08:45:25 +0000 Subject: [PATCH 092/122] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2a64007..6b233a4 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,10 @@ Please check the module datasheets for details on what clock speeds and data rat For I2C communication, please be sure to remove all additional pull-ups on the I2C bus. u-blox modules include internal pull-ups on the I2C lines (sometimes called DDC in their manuals). Cut all I2C pull-up jumpers and/or remove them from peripheral boards. Otherwise, various data glitches can occur. See issues [38](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/38) and [40](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/40) for more information. We recommend running the I2C bus at 100kHz. +## Compatibility + +v2 of the library provides support for generation 8, 9 and 10 u-blox GNSS modules. For generation 6 and 7, please see [this example (depricated)](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/tree/master/examples/Series_6_7/Example1_GetPositionAndTime_Series_6_7). + ## Contributing If you would like to contribute to this library: please do, we truly appreciate it, but please follow [these guidelines](./CONTRIBUTING.md). Thanks! From 4cad56bc23850a0589378f37fdc3971910d45eeb Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 4 Feb 2022 17:12:08 +0000 Subject: [PATCH 093/122] Add config keys for NEO-D9S --- ...ceDescription_UBX-19048765_keys_sorted.txt | 151 ++++++++++++++++++ keys/u-blox_config_keys_sorted.txt | 19 +++ src/u-blox_config_keys.h | 28 ++++ 3 files changed, 198 insertions(+) create mode 100644 keys/NEO-D9S_InterfaceDescription_UBX-19048765_keys_sorted.txt diff --git a/keys/NEO-D9S_InterfaceDescription_UBX-19048765_keys_sorted.txt b/keys/NEO-D9S_InterfaceDescription_UBX-19048765_keys_sorted.txt new file mode 100644 index 0000000..3196fea --- /dev/null +++ b/keys/NEO-D9S_InterfaceDescription_UBX-19048765_keys_sorted.txt @@ -0,0 +1,151 @@ +0x1041000d +0x10410013 +0x10510002 +0x10510003 +0x10520005 +0x10530005 +0x10530006 +0x10640002 +0x10640003 +0x10640005 +0x10640006 +0x10650001 +0x10650002 +0x10710001 +0x10720001 +0x10730001 +0x10740001 +0x10750001 +0x10760001 +0x10770001 +0x10780001 +0x10790001 +0x107a0001 +0x10a20001 +0x10a20002 +0x10a3002e +0x10a3002f +0x10a30030 +0x10a30031 +0x10a30032 +0x10a30033 +0x10a30034 +0x10a30035 +0x10b10014 +0x10b10016 +0x10b10019 +0x10c70001 +0x10c70002 +0x10d0000c +0x10d0000d +0x10d0000e +0x20210003 +0x20410001 +0x20410002 +0x20410010 +0x20510001 +0x20520002 +0x20520003 +0x20520004 +0x20530002 +0x20530003 +0x20530004 +0x20640001 +0x20910187 +0x20910188 +0x20910189 +0x2091018a +0x2091018b +0x20910196 +0x20910197 +0x20910198 +0x20910199 +0x2091019a +0x2091019b +0x2091019c +0x2091019d +0x2091019e +0x2091019f +0x209101a0 +0x209101a1 +0x209101a2 +0x209101a3 +0x209101a4 +0x209101a5 +0x209101a6 +0x209101a7 +0x209101a8 +0x209101a9 +0x209101b4 +0x209101b5 +0x209101b6 +0x209101b7 +0x209101b8 +0x209101b9 +0x209101ba +0x209101bb +0x209101bc +0x209101bd +0x20910231 +0x20910232 +0x20910233 +0x20910234 +0x20910235 +0x20910259 +0x2091025a +0x2091025b +0x2091025c +0x2091025d +0x2091031d +0x2091031e +0x2091031f +0x20910320 +0x20910321 +0x20920001 +0x20920002 +0x20920003 +0x20920004 +0x20920005 +0x20920006 +0x20920007 +0x20920008 +0x20920009 +0x2092000a +0x20a20003 +0x20a20005 +0x20a30036 +0x20a30037 +0x20a30038 +0x20c70003 +0x20d0000b +0x30210001 +0x30210002 +0x3065000a +0x3065000b +0x3065000c +0x30a20004 +0x30b10012 +0x30b10013 +0x30b10015 +0x30b10017 +0x40520001 +0x40530001 +0x40b10011 +0x40d0000f +0x5065000d +0x5065000e +0x5065000f +0x50650010 +0x50650011 +0x50650012 +0x50650013 +0x50650014 +0x50650015 +0x50650016 +0x50650017 +0x50650018 +0x50b1001a +0x50c70004 +0x50c70005 +0x50c70006 +0x50c70007 diff --git a/keys/u-blox_config_keys_sorted.txt b/keys/u-blox_config_keys_sorted.txt index 8eee0f4..7f0462f 100644 --- a/keys/u-blox_config_keys_sorted.txt +++ b/keys/u-blox_config_keys_sorted.txt @@ -140,8 +140,14 @@ 0x10a30033 0x10a30034 0x10a30035 +0x10b10014 +0x10b10016 +0x10b10019 0x10c70001 0x10c70002 +0x10d0000c +0x10d0000d +0x10d0000e 0x10de0002 0x10de0003 0x10de0004 @@ -567,6 +573,11 @@ 0x2091031a 0x2091031b 0x2091031c +0x2091031d +0x2091031e +0x2091031f +0x20910320 +0x20910321 0x20910336 0x20910337 0x20910338 @@ -821,6 +832,7 @@ 0x20a30055 0x20a30056 0x20c70003 +0x20d0000b 0x30050001 0x30060007 0x3006000a @@ -847,6 +859,10 @@ 0x3065000c 0x30930033 0x30a20004 +0x30b10012 +0x30b10013 +0x30b10015 +0x30b10017 0x30de0005 0x30de0006 0x30de0007 @@ -902,6 +918,8 @@ 0x40240053 0x40520001 0x40530001 +0x40b10011 +0x40d0000f 0x40de0008 0x5005002a 0x5005002b @@ -922,6 +940,7 @@ 0x50650016 0x50650017 0x50650018 +0x50b1001a 0x50c70004 0x50c70005 0x50c70006 diff --git a/src/u-blox_config_keys.h b/src/u-blox_config_keys.h index 14a2bb5..ae043a3 100644 --- a/src/u-blox_config_keys.h +++ b/src/u-blox_config_keys.h @@ -784,6 +784,14 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_UART1 = 0x20910098; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_UART2 = 0x20910099; // Output rate of the UBX-TIM-SVIN message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_USB = 0x2091009a; // Output rate of the UBX-TIM-SVIN message on port USB +//Additional CFG_MSGOUT keys for the NEO-D9S +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C = 0x2091031d; // Output rate of the UBX_RXM_PMP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_SPI = 0x20910321; // Output rate of the UBX_RXM_PMP message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1 = 0x2091031e; // Output rate of the UBX_RXM_PMP message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2 = 0x2091031f; // Output rate of the UBX_RXM_PMP message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_USB = 0x20910320; // Output rate of the UBX_RXM_PMP message on port USB + //CFG-NAV2: Secondary output configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_NAV2_OUT_ENABLED = 0x10170001; // Enable secondary (NAV2) output @@ -865,6 +873,26 @@ const uint32_t UBLOX_CFG_ODO_COGMAXPOSACC = 0x20220022; // Maximum acceptable po const uint32_t UBLOX_CFG_ODO_VELLPGAIN = 0x20220031; // Velocity low-pass filter level const uint32_t UBLOX_CFG_ODO_COGLPGAIN = 0x20220032; // Course over ground low-pass filter level (at speed < 8 m/s) +//CFG-PM: Configuration for receiver power management (NEO-D9S) +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +const uint32_t UBLOX_CFG_PM_EXTINTSEL = 0x20d0000b; // EXTINT pin select +const uint32_t UBLOX_CFG_PM_EXTINTWAKE = 0x10d0000c; // EXTINT pin control (Wake). Enable to keep receiver awake as long as selected EXTINT pin is "high". +const uint32_t UBLOX_CFG_PM_EXTINTBACKUP = 0x10d0000d; // EXTINT pin control (Backup). Enable to force receiver into BACKUP mode when selected EXTINT pin is "low". +const uint32_t UBLOX_CFG_PM_EXTINTINACTIVE = 0x10d0000e; // EXTINT pin control (Inactive). Enable to force backup in case EXTINT Pin is inactive for time longer than CFG-PM-EXTINTINACTIVITY. +const uint32_t UBLOX_CFG_PM_EXTINTINACTIVITY = 0x40d0000f; // Inactivity time out on EXTINT pin if enabled + +//CFG-PMP: Point to multipoint (PMP) configuration (NEO-D9S) +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +const uint32_t UBLOX_CFG_PMP_CENTER_FREQUENCY = 0x40b10011; // Center frequency. The center frequency for the receiver can be set from 1525000000 to 1559000000 Hz. +const uint32_t UBLOX_CFG_PMP_SEARCH_WINDOW = 0x30b10012; // Search window. Search window can be set from 0 to 65535 Hz. It is +/- this value from the center frequency set by CENTER_FREQUENCY. +const uint32_t UBLOX_CFG_PMP_USE_SERVICE_ID = 0x10b10016; // Use service ID. Enable/disable service ID check to confirm the correct service is received. +const uint32_t UBLOX_CFG_PMP_SERVICE_ID = 0x30b10017; // Service identifier. Defines the expected service ID. +const uint32_t UBLOX_CFG_PMP_DATA_RATE = 0x30b10013; // bps Data rate. The data rate of the received data. +const uint32_t UBLOX_CFG_PMP_USE_DESCRAMBLER = 0x10b10014; // Use descrambler. Enables/disables the descrambler. +const uint32_t UBLOX_CFG_PMP_DESCRAMBLER_INIT = 0x30b10015; // Descrambler initialization. Set the intialisation value for the descrambler. +const uint32_t UBLOX_CFG_PMP_USE_PRESCRAMBLING = 0x10b10019; // Use prescrambling. Enables/disables the prescrambling. +const uint32_t UBLOX_CFG_PMP_UNIQUE_WORD = 0x50b1001a; // Unique word. Defines value of unique word. + //CFG-QZSS: QZSS system configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_QZSS_USE_SLAS_DGNSS = 0x10370005; // Apply QZSS SLAS DGNSS corrections From eba80635633fd66a349b1b468a6a3e26a421a6f1 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 4 Feb 2022 18:12:54 +0000 Subject: [PATCH 094/122] Add more support for UBX-RXM-PMP --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 12 +++++++++++- src/u-blox_structs.h | 13 ++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 71b1e1b..aa14ee5 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -375,7 +375,8 @@ const uint8_t UBX_NAV_AOPSTATUS = 0x60; //AssistNow Autonomous status //Class: RXM //The following are used to configure the RXM UBX messages (receiver manager messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) const uint8_t UBX_RXM_MEASX = 0x14; //Satellite Measurements for RRLP -const uint8_t UBX_RXM_PMREQ = 0x41; //Requests a Power Management task (two differenent packet sizes) +const uint8_t UBX_RXM_PMREQ = 0x41; //Requests a Power Management task (two different packet sizes) +const uint8_t UBX_RXM_PMP = 0x72; //PMP raw data (two different versions) (packet size for version 0x01 is variable) const uint8_t UBX_RXM_RAWX = 0x15; //Multi-GNSS Raw Measurement Data const uint8_t UBX_RXM_RLM = 0x59; //Galileo SAR Short-RLM report (two different packet sizes) const uint8_t UBX_RXM_RTCM = 0x32; //RTCM input status @@ -1070,6 +1071,13 @@ class SFE_UBLOX_GNSS // Receiver Manager Messages (RXM) + // Configure a callback for the UBX-RXM-PMP messages produced by the NEO-D9S + // Note: on the NEO-D9S, the UBX-RXM-PMP messages are enabled by default on all ports. + // You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 0) + // The NEO-D9S does not support UBX-CFG-MSG + bool setAutoRXMPMPcallback(void (*callbackPointer)(UBX_RXM_PMP_data_t), uint16_t maxWait = defaultMaxWait); // Callback is passed all of the data. Heavy on the stack. May cause problems on some platforms. + bool setAutoRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *), uint16_t maxWait = defaultMaxWait); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! + bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX bool setAutoRXMSFRBX(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM SFRBX reports at the navigation frequency bool setAutoRXMSFRBX(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM SFRBX 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 @@ -1385,6 +1393,7 @@ class SFE_UBLOX_GNSS UBX_NAV_RELPOSNED_t *packetUBXNAVRELPOSNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_AOPSTATUS_t *packetUBXNAVAOPSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_RXM_PMP_t *packetUBXRXMPMP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1472,6 +1481,7 @@ class SFE_UBLOX_GNSS bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it + bool initPacketUBXRXMPMP(bool usePtr = false); // Allocate RAM for packetUBXRXMPMP and initialize it bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it bool initPacketUBXCFGRATE(); // Allocate RAM for packetUBXCFGRATE and initialize it diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index e7588b4..20e15a6 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1464,21 +1464,27 @@ typedef struct } UBX_RXM_RAWX_t; // UBX-RXM-PMP (0x02 0x72): PMP raw data (D9 modules) +// There are two versions of this message but, fortunately, both have a max len of 528 const uint16_t UBX_RXM_PMP_MAX_LEN = 528; typedef struct { - uint8_t version; // Message version (0x00 for this version) - uint8_t reserved0[3]; // Reserved + uint8_t version; // Message version (0x00 / 0x01) + uint8_t reserved0; // Reserved + uint16_t numBytesUserData; // version 0x00: reserved0 ; version 0x01: Number of bytes the userData block has in this frame (0...504) uint32_t timeTag; // Time since startup when frame started : ms uint32_t uniqueWord[2]; // Received unique words uint16_t serviceIdentifier; // Received service identifier uint8_t spare; // Received spare data uint8_t uniqueWordBitErrors; // Number of bit errors in both unique words - uint8_t userData[504]; // Received user data + + // The position of fecBits, ebno and reserved1 depends on the message version uint16_t fecBits; // Number of bits corrected by FEC (forward error correction) uint8_t ebno; // Energy per bit to noise power spectral density ratio : 2^-3 dB uint8_t reserved1; // Reserved + + uint8_t userData[504]; // Received user data: version 0x00 : starts at byte 20 ; version 0x01 : starts at byte 24 + } UBX_RXM_PMP_data_t; typedef struct @@ -1487,6 +1493,7 @@ typedef struct UBX_RXM_PMP_data_t data; bool moduleQueried; void (*callbackPointer)(UBX_RXM_PMP_data_t); + void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *); UBX_RXM_PMP_data_t *callbackData; } UBX_RXM_PMP_t; From 9e137946f179d05633899465a07505345a726a59 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sat, 5 Feb 2022 14:39:16 +0000 Subject: [PATCH 095/122] Adding callback pointers for all auto messages --- Adding_New_Messages.md | 10 +- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 885 ++++++++++++++++--- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 51 +- src/u-blox_structs.h | 90 ++ 4 files changed, 897 insertions(+), 139 deletions(-) diff --git a/Adding_New_Messages.md b/Adding_New_Messages.md index e5c6b98..41b0728 100644 --- a/Adding_New_Messages.md +++ b/Adding_New_Messages.md @@ -129,21 +129,23 @@ See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Libra See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/b746d8e2742961ede95e2d06d5db3a3a557e571d) for the changes. -#### Step 6.3: Update processUBXpacket() +#### Step 6.3: Update getMaxPayloadSize() + +#### Step 6.4: Update processUBXpacket() Take time to double-check that you have used the correct data width, signed/unsigned and position for each field. See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/8eecdd5044f810b0e2b567150ff63a17c219fe8e) for the changes. -#### Step 6.4: Update checkCallbacks() +#### Step 6.5: Update checkCallbacks() See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/b53bffaa3ae12482cfb268f23796963d0b8519c9) for the changes. -#### Step 6.5: Add the "auto" functions +#### Step 6.6: Add the "auto" functions See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/e394ae003ad38117d150598774d0552059416473) for the changes. -#### Step 6.6: Add the helper functions (if any) +#### Step 6.7: Add the helper functions (if any) See [this commit](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/commit/318e76383e96d6676bbb57294c25e665c0d4a31f) for the changes. diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index ac25f36..c80a9ca 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -274,6 +274,16 @@ void SFE_UBLOX_GNSS::end(void) packetUBXNAVAOPSTATUS = NULL; // Redundant? } + if (packetUBXRXMPMP != NULL) + { + if (packetUBXRXMPMP->callbackData != NULL) + { + delete packetUBXRXMPMP->callbackData; + } + delete packetUBXRXMPMP; + packetUBXRXMPMP = NULL; // Redundant? + } + if (packetUBXRXMSFRBX != NULL) { if (packetUBXRXMSFRBX->callbackData != NULL) @@ -766,8 +776,14 @@ bool SFE_UBLOX_GNSS::isConnected(uint16_t maxWait) return false; //Sensor did not ack } - // Query navigation rate to see whether we get a meaningful response - return (getNavigationFrequencyInternal(maxWait)); + // Query port configuration to see whether we get a meaningful response + // We could simply request the config for any port but, just for giggles, let's request the config for most appropriate port + if (commType == COMM_TYPE_I2C) + return (getPortSettingsInternal(COM_PORT_I2C, maxWait)); + else if (commType == COMM_TYPE_SERIAL) + return (getPortSettingsInternal(COM_PORT_UART1, maxWait)); // Could be UART2 - but this is just a response check + else // if (commType == COMM_TYPE_SPI) + return (getPortSettingsInternal(COM_PORT_SPI, maxWait)); } //Enable or disable the printing of sent/response HEX values. @@ -899,11 +915,13 @@ bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClas uint8_t i2cError = _i2cPort->endTransmission(false); //Always send a restart command. Do not release the bus. ESP32 supports this. if (i2cError != 0) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("checkUbloxI2C: I2C error: endTransmission returned ")); _debugSerial->println(i2cError); } +#endif return (false); //Sensor did not ACK } @@ -911,11 +929,13 @@ bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClas uint8_t bytesReturned = _i2cPort->requestFrom((uint8_t)_gpsI2Caddress, static_cast(2)); if (bytesReturned != 2) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("checkUbloxI2C: I2C error: requestFrom 0xFD returned ")); _debugSerial->println(bytesReturned); } +#endif return (false); //Sensor did not return 2 bytes } else //if (_i2cPort->available()) @@ -1209,6 +1229,9 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) case UBX_RXM_RAWX: if (packetUBXRXMRAWX != NULL) result = true; break; + case UBX_RXM_PMP: + if (packetUBXRXMPMP != NULL) result = true; + break; } } break; @@ -1216,6 +1239,9 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) { switch (ID) { + case UBX_CFG_PRT: + if (packetUBXCFGPRT != NULL) result = true; + break; case UBX_CFG_RATE: if (packetUBXCFGRATE != NULL) result = true; break; @@ -1327,6 +1353,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) case UBX_NAV_HPPOSLLH: maxSize = UBX_NAV_HPPOSLLH_LEN; break; + case UBX_NAV_PVAT: + maxSize = UBX_NAV_PVAT_LEN; + break; case UBX_NAV_CLOCK: maxSize = UBX_NAV_CLOCK_LEN; break; @@ -1358,6 +1387,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) case UBX_RXM_RAWX: maxSize = UBX_RXM_RAWX_MAX_LEN; break; + case UBX_RXM_PMP: + maxSize = UBX_RXM_PMP_MAX_LEN; + break; } } break; @@ -1365,6 +1397,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) { switch (ID) { + case UBX_CFG_PRT: + maxSize = UBX_CFG_PRT_LEN; + break; case UBX_CFG_RATE: maxSize = UBX_CFG_RATE_LEN; break; @@ -1520,6 +1555,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r uint16_t maxPayload = getMaxPayloadSize(packetBuf.cls, packetBuf.id); // Calculate how much RAM we need if (maxPayload == 0) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("process: getMaxPayloadSize returned ZERO!! Class: 0x")); @@ -1527,13 +1563,16 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r _debugSerial->print(F(" ID: 0x")); _debugSerial->println(packetBuf.id); } +#endif } if (payloadAuto != NULL) // Check if memory is already allocated - this should be impossible! { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("process: memory is already allocated for payloadAuto! Deleting...")); } +#endif delete[] payloadAuto; // Created with new[] payloadAuto = NULL; // Redundant? packetAuto.payload = payloadAuto; @@ -1542,6 +1581,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r packetAuto.payload = payloadAuto; if (payloadAuto == NULL) // Check if the alloc failed { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("process: memory allocation failed for \"automatic\" message: Class: 0x")); @@ -1550,6 +1590,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r _debugSerial->println(packetBuf.id, HEX); _debugSerial->println(F("process: \"automatic\" message could overwrite data")); } +#endif // The RAM allocation failed so fall back to using incomingUBX (usually packetCfg) even though we risk overwriting data activePacketBuffer = SFE_UBLOX_PACKET_PACKETCFG; incomingUBX->cls = packetBuf.cls; //Copy the class and ID into incomingUBX (usually packetCfg) @@ -1603,6 +1644,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r { if (packetBuf.len == 0) // Check if length is zero (hopefully this is impossible!) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("process: ZERO LENGTH packet received: Class: 0x")); @@ -1610,6 +1652,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r _debugSerial->print(F(" ID: 0x")); _debugSerial->println(packetBuf.id, HEX); } +#endif //If length is zero (!) this will be the first byte of the checksum so record it packetBuf.checksumA = incoming; } @@ -1654,6 +1697,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r } else // Length is not 2 (hopefully this is impossible!) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("process: ACK received with .len != 2: Class: 0x")); @@ -1663,6 +1707,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r _debugSerial->print(F(" len: ")); _debugSerial->println(packetBuf.len); } +#endif } } } @@ -1750,10 +1795,12 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r *lengthPtr = *lengthPtr + 1; // Increment the length if (*lengthPtr == nmeaMaxLength) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("process: NMEA buffer is full!")); } +#endif } } } @@ -1830,6 +1877,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r } else { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("process: NMEA checksum fail (2)! Expected ")); @@ -1840,14 +1888,17 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r _debugSerial->write(*(workingNMEAPtr + charsChecked + 1)); _debugSerial->println(); } +#endif } } else { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("process: NMEA checksum fail (1)!")); } +#endif } } currentSentence = NONE; // All done! @@ -1991,7 +2042,7 @@ bool SFE_UBLOX_GNSS::doesThisNMEAHaveCallback() { if (storageNMEAGPGGA != NULL) if (storageNMEAGPGGA->callbackCopy != NULL) - if (storageNMEAGPGGA->callbackPointer != NULL) + if ((storageNMEAGPGGA->callbackPointer != NULL) || (storageNMEAGPGGA->callbackPointerPtr != NULL)) return true; } @@ -2000,7 +2051,7 @@ bool SFE_UBLOX_GNSS::doesThisNMEAHaveCallback() { if (storageNMEAGNGGA != NULL) if (storageNMEAGNGGA->callbackCopy != NULL) - if (storageNMEAGNGGA->callbackPointer != NULL) + if ((storageNMEAGNGGA->callbackPointer != NULL) || (storageNMEAGNGGA->callbackPointerPtr != NULL)) return true; } @@ -2235,6 +2286,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ maximum_payload_size = getMaxPayloadSize(incomingUBX->cls, incomingUBX->id); if (maximum_payload_size == 0) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("processUBX: getMaxPayloadSize returned ZERO!! Class: 0x")); @@ -2242,6 +2294,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ _debugSerial->print(F(" ID: 0x")); _debugSerial->println(incomingUBX->id); } +#endif } //} //else @@ -2395,6 +2448,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ digitalWrite((uint8_t)debugPin, HIGH); } +#ifndef SFE_UBLOX_REDUCED_PROG_MEM _debugSerial->print(F("Checksum failed:")); _debugSerial->print(F(" checksumA: ")); _debugSerial->print(incomingUBX->checksumA); @@ -2406,6 +2460,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ _debugSerial->print(F(" rollingChecksumB: ")); _debugSerial->print(rollingChecksumB); _debugSerial->println(); +#endif } } @@ -2448,6 +2503,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ { //Something has gone very wrong currentSentence = NONE; //Reset the sentence to being looking for a new start char +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { if (overrun) @@ -2459,6 +2515,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ _debugSerial->print(F(" maximum_payload_size: ")); _debugSerial->println(maximum_payload_size); } +#endif } //Increment the counter @@ -3086,7 +3143,59 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } break; case UBX_CLASS_RXM: - if (msg->id == UBX_RXM_SFRBX) + if (msg->id == UBX_RXM_PMP) + // Note: length is variable with version 0x01 + // Note: the field positions depend on the version + { + //Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXRXMPMP != NULL) + { + packetUBXRXMPMP->data.version = extractByte(msg, 0); + packetUBXRXMPMP->data.numBytesUserData = extractInt(msg, 2); + packetUBXRXMPMP->data.timeTag = extractLong(msg, 4); + packetUBXRXMPMP->data.uniqueWord[0] = extractLong(msg, 8); + packetUBXRXMPMP->data.uniqueWord[1] = extractLong(msg, 12); + packetUBXRXMPMP->data.serviceIdentifier = extractInt(msg, 16); + packetUBXRXMPMP->data.spare = extractByte(msg, 18); + packetUBXRXMPMP->data.uniqueWordBitErrors = extractByte(msg, 19); + + if (packetUBXRXMPMP->data.version == 0x00) + { + packetUBXRXMPMP->data.fecBits = extractInt(msg, 524); + packetUBXRXMPMP->data.ebno = extractByte(msg, 526); + } + else // if (packetUBXRXMPMP->data.version == 0x01) + { + packetUBXRXMPMP->data.fecBits = extractInt(msg, 20); + packetUBXRXMPMP->data.ebno = extractByte(msg, 22); + } + + uint16_t userDataStart = (packetUBXRXMPMP->data.version == 0x00) ? 20 : 24; + uint16_t userDataLength = (packetUBXRXMPMP->data.version == 0x00) ? 504 : (packetUBXRXMPMP->data.numBytesUserData); + for (uint16_t i = 0; (i < userDataLength) && (i < 504); i++) + { + packetUBXRXMPMP->data.userData[i] = extractByte(msg, i + userDataStart); + } + + //Mark all datums as fresh (not read before) + packetUBXRXMPMP->moduleQueried = true; + + //Check if we need to copy the data for the callbacks + if ((packetUBXRXMPMP->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + { + memcpy(&packetUBXRXMPMP->callbackData->version, &packetUBXRXMPMP->data.version, sizeof(UBX_RXM_PMP_data_t)); + packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = true; + } + + //Check if we need to copy the data into the file buffer + if (packetUBXRXMPMP->automaticFlags.flags.bits.addToFileBuffer) + { + storePacket(msg); + } + } + } + else if (msg->id == UBX_RXM_SFRBX) // Note: length is variable // Note: on protocol version 17: numWords is (0..16) // on protocol version 18+: numWords is (0..10) @@ -3184,6 +3293,24 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } break; case UBX_CLASS_CFG: + if (msg->id == UBX_CFG_PRT && msg->len == UBX_CFG_PRT_LEN) + { + //Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXCFGPRT != NULL) + { + packetUBXCFGPRT->data.portID = extractByte(msg, 0); + packetUBXCFGPRT->data.txReady.all = extractInt(msg, 2); + packetUBXCFGPRT->data.mode = extractLong(msg, 4); + packetUBXCFGPRT->data.baudRate = extractLong(msg, 8); + packetUBXCFGPRT->data.inProtoMask.all = extractInt(msg, 12); + packetUBXCFGPRT->data.outProtoMask.all = extractInt(msg, 14); + packetUBXCFGPRT->data.flags = extractInt(msg, 16); + + //Mark data as valid + packetUBXCFGPRT->dataValid = true; + } + } + break; if (msg->id == UBX_CFG_RATE && msg->len == UBX_CFG_RATE_LEN) { //Parse various byte fields into storage - but only if we have memory allocated for it @@ -3435,10 +3562,12 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("processUBXpacket: packetUBXMGAACK is full. ACK will be lost!")); } +#endif } } } @@ -3483,10 +3612,12 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("processUBXpacket: packetUBXMGADBD is full. DBD data will be lost!")); } +#endif } } } @@ -3885,10 +4016,12 @@ void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX) { if (spiBuffer == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("sendSpiCommand: no memory allocation for SPI Buffer!")); } +#endif return; } @@ -4348,309 +4481,552 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) if ((packetUBXNAVPOSECEF != NULL) // If RAM has been allocated for message storage && (packetUBXNAVPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPOSECEF->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV POSECEF")); - packetUBXNAVPOSECEF->callbackPointer(*packetUBXNAVPOSECEF->callbackData); // Call the callback + if (packetUBXNAVPOSECEF->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV POSECEF")); + packetUBXNAVPOSECEF->callbackPointer(*packetUBXNAVPOSECEF->callbackData); // Call the callback + } + else if (packetUBXNAVPOSECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV POSECEF")); + packetUBXNAVPOSECEF->callbackPointerPtr(packetUBXNAVPOSECEF->callbackData); // Call the callback + } packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVSTATUS != NULL) // If RAM has been allocated for message storage && (packetUBXNAVSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV STATUS")); - packetUBXNAVSTATUS->callbackPointer(*packetUBXNAVSTATUS->callbackData); // Call the callback + if (packetUBXNAVSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV STATUS")); + packetUBXNAVSTATUS->callbackPointer(*packetUBXNAVSTATUS->callbackData); // Call the callback + } + else if (packetUBXNAVSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV STATUS")); + packetUBXNAVSTATUS->callbackPointerPtr(packetUBXNAVSTATUS->callbackData); // Call the callback + } packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVDOP != NULL) // If RAM has been allocated for message storage && (packetUBXNAVDOP->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVDOP->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV DOP")); - packetUBXNAVDOP->callbackPointer(*packetUBXNAVDOP->callbackData); // Call the callback + if (packetUBXNAVDOP->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV DOP")); + packetUBXNAVDOP->callbackPointer(*packetUBXNAVDOP->callbackData); // Call the callback + } + else if (packetUBXNAVDOP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV DOP")); + packetUBXNAVDOP->callbackPointerPtr(packetUBXNAVDOP->callbackData); // Call the callback + } packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVATT != NULL) // If RAM has been allocated for message storage && (packetUBXNAVATT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVATT->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV ATT")); - packetUBXNAVATT->callbackPointer(*packetUBXNAVATT->callbackData); // Call the callback + if (packetUBXNAVATT->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV ATT")); + packetUBXNAVATT->callbackPointer(*packetUBXNAVATT->callbackData); // Call the callback + } + else if (packetUBXNAVATT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV ATT")); + packetUBXNAVATT->callbackPointerPtr(packetUBXNAVATT->callbackData); // Call the callback + } packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVPVT != NULL) // If RAM has been allocated for message storage && (packetUBXNAVPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPVT->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - //if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV PVT")); - packetUBXNAVPVT->callbackPointer(*packetUBXNAVPVT->callbackData); // Call the callback + if (packetUBXNAVPVT->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV PVT")); + packetUBXNAVPVT->callbackPointer(*packetUBXNAVPVT->callbackData); // Call the callback + } + else if (packetUBXNAVPVT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV PVT")); + packetUBXNAVPVT->callbackPointerPtr(packetUBXNAVPVT->callbackData); // Call the callback + } packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVODO != NULL) // If RAM has been allocated for message storage && (packetUBXNAVODO->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVODO->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV ODO")); - packetUBXNAVODO->callbackPointer(*packetUBXNAVODO->callbackData); // Call the callback + if (packetUBXNAVODO->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV ODO")); + packetUBXNAVODO->callbackPointer(*packetUBXNAVODO->callbackData); // Call the callback + } + else if (packetUBXNAVODO->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV ODO")); + packetUBXNAVODO->callbackPointerPtr(packetUBXNAVODO->callbackData); // Call the callback + } packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVVELECEF != NULL) // If RAM has been allocated for message storage && (packetUBXNAVVELECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVVELECEF->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV VELECEF")); - packetUBXNAVVELECEF->callbackPointer(*packetUBXNAVVELECEF->callbackData); // Call the callback + if (packetUBXNAVVELECEF->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV VELECEF")); + packetUBXNAVVELECEF->callbackPointer(*packetUBXNAVVELECEF->callbackData); // Call the callback + } + else if (packetUBXNAVVELECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV VELECEF")); + packetUBXNAVVELECEF->callbackPointerPtr(packetUBXNAVVELECEF->callbackData); // Call the callback + } packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVVELNED != NULL) // If RAM has been allocated for message storage && (packetUBXNAVVELNED->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVVELNED->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV VELNED")); - packetUBXNAVVELNED->callbackPointer(*packetUBXNAVVELNED->callbackData); // Call the callback + if (packetUBXNAVVELNED->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV VELNED")); + packetUBXNAVVELNED->callbackPointer(*packetUBXNAVVELNED->callbackData); // Call the callback + } + else if (packetUBXNAVVELNED->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV VELNED")); + packetUBXNAVVELNED->callbackPointerPtr(packetUBXNAVVELNED->callbackData); // Call the callback + } packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVHPPOSECEF != NULL) // If RAM has been allocated for message storage && (packetUBXNAVHPPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVHPPOSECEF->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV HPPOSECEF")); - packetUBXNAVHPPOSECEF->callbackPointer(*packetUBXNAVHPPOSECEF->callbackData); // Call the callback + if (packetUBXNAVHPPOSECEF->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV HPPOSECEF")); + packetUBXNAVHPPOSECEF->callbackPointer(*packetUBXNAVHPPOSECEF->callbackData); // Call the callback + } + else if (packetUBXNAVHPPOSECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV HPPOSECEF")); + packetUBXNAVHPPOSECEF->callbackPointerPtr(packetUBXNAVHPPOSECEF->callbackData); // Call the callback + } packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVHPPOSLLH != NULL) // If RAM has been allocated for message storage && (packetUBXNAVHPPOSLLH->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVHPPOSLLH->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV HPPOSLLH")); - packetUBXNAVHPPOSLLH->callbackPointer(*packetUBXNAVHPPOSLLH->callbackData); // Call the callback + if (packetUBXNAVHPPOSLLH->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV HPPOSLLH")); + packetUBXNAVHPPOSLLH->callbackPointer(*packetUBXNAVHPPOSLLH->callbackData); // Call the callback + } + else if (packetUBXNAVHPPOSLLH->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV HPPOSLLH")); + packetUBXNAVHPPOSLLH->callbackPointerPtr(packetUBXNAVHPPOSLLH->callbackData); // Call the callback + } packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVPVAT != NULL) // If RAM has been allocated for message storage && (packetUBXNAVPVAT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPVAT->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - //if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV PVAT")); - packetUBXNAVPVAT->callbackPointer(*packetUBXNAVPVAT->callbackData); // Call the callback + if (packetUBXNAVPVAT->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV PVAT")); + packetUBXNAVPVAT->callbackPointer(*packetUBXNAVPVAT->callbackData); // Call the callback + } + else if (packetUBXNAVPVAT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV PVAT")); + packetUBXNAVPVAT->callbackPointerPtr(packetUBXNAVPVAT->callbackData); // Call the callback + } packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVCLOCK != NULL) // If RAM has been allocated for message storage && (packetUBXNAVCLOCK->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVCLOCK->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVCLOCK->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV CLOCK")); - packetUBXNAVCLOCK->callbackPointer(*packetUBXNAVCLOCK->callbackData); // Call the callback + if (packetUBXNAVCLOCK->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV CLOCK")); + packetUBXNAVCLOCK->callbackPointer(*packetUBXNAVCLOCK->callbackData); // Call the callback + } + else if (packetUBXNAVCLOCK->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV CLOCK")); + packetUBXNAVCLOCK->callbackPointerPtr(packetUBXNAVCLOCK->callbackData); // Call the callback + } packetUBXNAVCLOCK->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->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV SAT")); - packetUBXNAVSAT->callbackPointer(*packetUBXNAVSAT->callbackData); // Call the callback + if (packetUBXNAVSAT->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV SAT")); + packetUBXNAVSAT->callbackPointer(*packetUBXNAVSAT->callbackData); // Call the callback + } + else if (packetUBXNAVSAT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV SAT")); + packetUBXNAVSAT->callbackPointerPtr(packetUBXNAVSAT->callbackData); // Call the callback + } packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVRELPOSNED != NULL) // If RAM has been allocated for message storage && (packetUBXNAVRELPOSNED->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVRELPOSNED->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV RELPOSNED")); - packetUBXNAVRELPOSNED->callbackPointer(*packetUBXNAVRELPOSNED->callbackData); // Call the callback + if (packetUBXNAVRELPOSNED->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV RELPOSNED")); + packetUBXNAVRELPOSNED->callbackPointer(*packetUBXNAVRELPOSNED->callbackData); // Call the callback + } + else if (packetUBXNAVRELPOSNED->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV RELPOSNED")); + packetUBXNAVRELPOSNED->callbackPointerPtr(packetUBXNAVRELPOSNED->callbackData); // Call the callback + } packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXNAVAOPSTATUS != NULL) // If RAM has been allocated for message storage && (packetUBXNAVAOPSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVAOPSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for NAV AOPSTATUS")); - packetUBXNAVAOPSTATUS->callbackPointer(*packetUBXNAVAOPSTATUS->callbackData); // Call the callback + if (packetUBXNAVAOPSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for NAV AOPSTATUS")); + packetUBXNAVAOPSTATUS->callbackPointer(*packetUBXNAVAOPSTATUS->callbackData); // Call the callback + } + else if (packetUBXNAVAOPSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV AOPSTATUS")); + packetUBXNAVAOPSTATUS->callbackPointerPtr(packetUBXNAVAOPSTATUS->callbackData); // Call the callback + } packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } + 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->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + { + if (packetUBXRXMPMP->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for RXM PMP")); + packetUBXRXMPMP->callbackPointer(*packetUBXRXMPMP->callbackData); // Call the callback + } + else if (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM PMP")); + packetUBXRXMPMP->callbackPointerPtr(packetUBXRXMPMP->callbackData); // Call the callback + } + packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + } + if ((packetUBXRXMSFRBX != NULL) // If RAM has been allocated for message storage && (packetUBXRXMSFRBX->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMSFRBX->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for RXM SFRBX")); - packetUBXRXMSFRBX->callbackPointer(*packetUBXRXMSFRBX->callbackData); // Call the callback + if (packetUBXRXMSFRBX->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for RXM SFRBX")); + packetUBXRXMSFRBX->callbackPointer(*packetUBXRXMSFRBX->callbackData); // Call the callback + } + else if (packetUBXRXMSFRBX->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM SFRBX")); + packetUBXRXMSFRBX->callbackPointerPtr(packetUBXRXMSFRBX->callbackData); // Call the callback + } packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXRXMRAWX != NULL) // If RAM has been allocated for message storage && (packetUBXRXMRAWX->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMRAWX->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for RXM RAWX")); - packetUBXRXMRAWX->callbackPointer(*packetUBXRXMRAWX->callbackData); // Call the callback + if (packetUBXRXMRAWX->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for RXM RAWX")); + packetUBXRXMRAWX->callbackPointer(*packetUBXRXMRAWX->callbackData); // Call the callback + } + else if (packetUBXRXMRAWX->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM RAWX")); + packetUBXRXMRAWX->callbackPointerPtr(packetUBXRXMRAWX->callbackData); // Call the callback + } packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXTIMTM2 != NULL) // If RAM has been allocated for message storage && (packetUBXTIMTM2->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXTIMTM2->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for TIM TM2")); - packetUBXTIMTM2->callbackPointer(*packetUBXTIMTM2->callbackData); // Call the callback + if (packetUBXTIMTM2->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for TIM TM2")); + packetUBXTIMTM2->callbackPointer(*packetUBXTIMTM2->callbackData); // Call the callback + } + else if (packetUBXTIMTM2->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for TIM TM2")); + packetUBXTIMTM2->callbackPointerPtr(packetUBXTIMTM2->callbackData); // Call the callback + } packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXESFALG != NULL) // If RAM has been allocated for message storage && (packetUBXESFALG->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFALG->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for ESF ALG")); - packetUBXESFALG->callbackPointer(*packetUBXESFALG->callbackData); // Call the callback + if (packetUBXESFALG->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for ESF ALG")); + packetUBXESFALG->callbackPointer(*packetUBXESFALG->callbackData); // Call the callback + } + else if (packetUBXESFALG->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF ALG")); + packetUBXESFALG->callbackPointerPtr(packetUBXESFALG->callbackData); // Call the callback + } packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXESFINS != NULL) // If RAM has been allocated for message storage && (packetUBXESFINS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFINS->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for ESF INS")); - packetUBXESFINS->callbackPointer(*packetUBXESFINS->callbackData); // Call the callback + if (packetUBXESFINS->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for ESF INS")); + packetUBXESFINS->callbackPointer(*packetUBXESFINS->callbackData); // Call the callback + } + else if (packetUBXESFINS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF INS")); + packetUBXESFINS->callbackPointerPtr(packetUBXESFINS->callbackData); // Call the callback + } packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXESFMEAS != NULL) // If RAM has been allocated for message storage && (packetUBXESFMEAS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFMEAS->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for ESF MEAS")); - packetUBXESFMEAS->callbackPointer(*packetUBXESFMEAS->callbackData); // Call the callback + if (packetUBXESFMEAS->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for ESF MEAS")); + packetUBXESFMEAS->callbackPointer(*packetUBXESFMEAS->callbackData); // Call the callback + } + else if (packetUBXESFMEAS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF MEAS")); + packetUBXESFMEAS->callbackPointerPtr(packetUBXESFMEAS->callbackData); // Call the callback + } packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXESFRAW != NULL) // If RAM has been allocated for message storage && (packetUBXESFRAW->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFRAW->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for ESF RAW")); - packetUBXESFRAW->callbackPointer(*packetUBXESFRAW->callbackData); // Call the callback + if (packetUBXESFRAW->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for ESF RAW")); + packetUBXESFRAW->callbackPointer(*packetUBXESFRAW->callbackData); // Call the callback + } + else if (packetUBXESFRAW->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF RAW")); + packetUBXESFRAW->callbackPointerPtr(packetUBXESFRAW->callbackData); // Call the callback + } packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXESFSTATUS != NULL) // If RAM has been allocated for message storage && (packetUBXESFSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for ESF STATUS")); - packetUBXESFSTATUS->callbackPointer(*packetUBXESFSTATUS->callbackData); // Call the callback + if (packetUBXESFSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for ESF STATUS")); + packetUBXESFSTATUS->callbackPointer(*packetUBXESFSTATUS->callbackData); // Call the callback + } + else if (packetUBXESFSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF STATUS")); + packetUBXESFSTATUS->callbackPointerPtr(packetUBXESFSTATUS->callbackData); // Call the callback + } packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXHNRATT != NULL) // If RAM has been allocated for message storage && (packetUBXHNRATT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRATT->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for HNR ATT")); - packetUBXHNRATT->callbackPointer(*packetUBXHNRATT->callbackData); // Call the callback + if (packetUBXHNRATT->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for HNR ATT")); + packetUBXHNRATT->callbackPointer(*packetUBXHNRATT->callbackData); // Call the callback + } + else if (packetUBXHNRATT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for HNR ATT")); + packetUBXHNRATT->callbackPointerPtr(packetUBXHNRATT->callbackData); // Call the callback + } packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXHNRINS != NULL) // If RAM has been allocated for message storage && (packetUBXHNRINS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRINS->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for HNR INS")); - packetUBXHNRINS->callbackPointer(*packetUBXHNRINS->callbackData); // Call the callback + if (packetUBXHNRINS->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for HNR INS")); + packetUBXHNRINS->callbackPointer(*packetUBXHNRINS->callbackData); // Call the callback + } + else if (packetUBXHNRINS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for HNR INS")); + packetUBXHNRINS->callbackPointerPtr(packetUBXHNRINS->callbackData); // Call the callback + } packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((packetUBXHNRPVT != NULL) // If RAM has been allocated for message storage && (packetUBXHNRPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRPVT->callbackPointer != NULL) // If the pointer to the callback has been defined && (packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for HNR PVT")); - packetUBXHNRPVT->callbackPointer(*packetUBXHNRPVT->callbackData); // Call the callback + if (packetUBXHNRPVT->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for HNR PVT")); + packetUBXHNRPVT->callbackPointer(*packetUBXHNRPVT->callbackData); // Call the callback + } + else if (packetUBXHNRPVT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for HNR PVT")); + packetUBXHNRPVT->callbackPointerPtr(packetUBXHNRPVT->callbackData); // Call the callback + } packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } if ((storageNMEAGPGGA != NULL) // If RAM has been allocated for message storage && (storageNMEAGPGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data - && (storageNMEAGPGGA->callbackPointer != NULL) // If the pointer to the callback has been defined && (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for GPGGA")); - storageNMEAGPGGA->callbackPointer(*storageNMEAGPGGA->callbackCopy); // Call the callback + if (storageNMEAGPGGA->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for GPGGA")); + storageNMEAGPGGA->callbackPointer(*storageNMEAGPGGA->callbackCopy); // Call the callback + } + else if (storageNMEAGPGGA->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for GPGGA")); + storageNMEAGPGGA->callbackPointerPtr(storageNMEAGPGGA->callbackCopy); // Call the callback + } storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale } if ((storageNMEAGNGGA != NULL) // If RAM has been allocated for message storage && (storageNMEAGNGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data - && (storageNMEAGNGGA->callbackPointer != NULL) // If the pointer to the callback has been defined && (storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for GNGGA")); - storageNMEAGNGGA->callbackPointer(*storageNMEAGNGGA->callbackCopy); // Call the callback + if (storageNMEAGNGGA->callbackPointer != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callback for GNGGA")); + storageNMEAGNGGA->callbackPointer(*storageNMEAGNGGA->callbackCopy); // Call the callback + } + else if (storageNMEAGNGGA->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for GNGGA")); + storageNMEAGNGGA->callbackPointerPtr(storageNMEAGNGGA->callbackCopy); // Call the callback + } storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale } @@ -4934,10 +5310,12 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c } if (keepGoing) // If keepGoing is still true, we must have timed out { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("pushAssistNowData: packet ack timed out!")); } +#endif } } else @@ -4990,8 +5368,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXMGAACK() packetUBXMGAACK = new UBX_MGA_ACK_DATA0_t; //Allocate RAM for the main struct if (packetUBXMGAACK == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXMGAACK: RAM alloc failed!")); +#endif return (false); } packetUBXMGAACK->head = 0; // Initialize the ring buffer pointers @@ -5503,10 +5883,12 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD if (keepGoing) // If keepGoing is still true, we must have timed out { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("readNavigationDatabase: DBD RX timed out!")); } +#endif } i2cPollingWait = currentI2cPollingWait; // Restore i2cPollingWait @@ -5521,8 +5903,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXMGADBD() packetUBXMGADBD = new UBX_MGA_DBD_t; //Allocate RAM for the main struct if (packetUBXMGADBD == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXMGADBD: RAM alloc failed!")); +#endif return (false); } packetUBXMGADBD->head = 0; // Initialize the ring buffer pointers @@ -5694,10 +6078,12 @@ bool SFE_UBLOX_GNSS::storePacket(ubxPacket *msg) uint16_t totalLength = msg->len + 8; // Total length. Include sync chars, class, id, length and checksum bytes if (totalLength > fileBufferSpaceAvailable()) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("storePacket: insufficient space available! Data will be lost!")); } +#endif return(false); } @@ -5743,10 +6129,12 @@ bool SFE_UBLOX_GNSS::storeFileBytes(uint8_t *theBytes, uint16_t numBytes) // Now, check if there is enough space in the buffer for all of the data if (numBytes > fileBufferSpaceAvailable()) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->println(F("storeFileBytes: insufficient space available! Data will be lost!")); } +#endif return(false); } @@ -6344,8 +6732,10 @@ bool SFE_UBLOX_GNSS::initModuleSWVersion() moduleSWVersion = new moduleSWVersion_t; //Allocate RAM for the main struct if (moduleSWVersion == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initModuleSWVersion: RAM alloc failed!")); +#endif return (false); } moduleSWVersion->versionHigh = 0; @@ -6529,8 +6919,10 @@ bool SFE_UBLOX_GNSS::initGeofenceParams() currentGeofenceParams = new geofenceParams_t; //Allocate RAM for the main struct if (currentGeofenceParams == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initGeofenceParams: RAM alloc failed!")); +#endif return (false); } currentGeofenceParams->numFences = 0; @@ -7609,8 +8001,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFcallback(void (*callbackPointer)(UBX_NAV_P if (packetUBXNAVPOSECEF->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("setAutoNAVPOSECEFcallback: RAM alloc failed!")); +#endif return (false); } @@ -7641,8 +8035,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPOSECEF() packetUBXNAVPOSECEF = new UBX_NAV_POSECEF_t; //Allocate RAM for the main struct if (packetUBXNAVPOSECEF == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVPOSECEF: RAM alloc failed!")); +#endif return (false); } packetUBXNAVPOSECEF->automaticFlags.flags.all = 0; @@ -7766,8 +8162,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVSTATUScallback(void (*callbackPointer)(UBX_NAV_ST if (packetUBXNAVSTATUS->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("setAutoNAVSTATUScallback: RAM alloc failed!")); +#endif return (false); } @@ -7798,8 +8196,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSTATUS() packetUBXNAVSTATUS = new UBX_NAV_STATUS_t; //Allocate RAM for the main struct if (packetUBXNAVSTATUS == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVSTATUS: RAM alloc failed!")); +#endif return (false); } packetUBXNAVSTATUS->automaticFlags.flags.all = 0; @@ -7943,8 +8343,10 @@ bool SFE_UBLOX_GNSS::setAutoDOPcallback(void (*callbackPointer)(UBX_NAV_DOP_data if (packetUBXNAVDOP->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("setAutoDOPcallback: RAM alloc failed!")); +#endif return (false); } @@ -7975,8 +8377,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVDOP() packetUBXNAVDOP = new UBX_NAV_DOP_t; //Allocate RAM for the main struct if (packetUBXNAVDOP == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVDOP: RAM alloc failed!")); +#endif return (false); } packetUBXNAVDOP->automaticFlags.flags.all = 0; @@ -8106,8 +8510,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVATTcallback(void (*callbackPointer)(UBX_NAV_ATT_d if (packetUBXNAVATT->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("setAutoNAVATTcallback: RAM alloc failed!")); +#endif return (false); } @@ -8138,8 +8544,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVATT() packetUBXNAVATT = new UBX_NAV_ATT_t; //Allocate RAM for the main struct if (packetUBXNAVATT == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVATT: RAM alloc failed!")); +#endif return (false); } packetUBXNAVATT->automaticFlags.flags.all = 0; @@ -8286,8 +8694,10 @@ bool SFE_UBLOX_GNSS::setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data if (packetUBXNAVPVT->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("setAutoPVTcallback: RAM alloc failed!")); +#endif return (false); } @@ -8319,8 +8729,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPVT() packetUBXNAVPVT = new UBX_NAV_PVT_t; //Allocate RAM for the main struct if (packetUBXNAVPVT == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVPVT: RAM alloc failed!")); +#endif return (false); } packetUBXNAVPVT->automaticFlags.flags.all = 0; @@ -8445,8 +8857,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_d if (packetUBXNAVODO->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("setAutoNAVODOcallback: RAM alloc failed!")); +#endif return (false); } @@ -8477,8 +8891,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVODO() packetUBXNAVODO = new UBX_NAV_ODO_t; //Allocate RAM for the main struct if (packetUBXNAVODO == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVODO: RAM alloc failed!")); +#endif return (false); } packetUBXNAVODO->automaticFlags.flags.all = 0; @@ -8601,8 +9017,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELECEFcallback(void (*callbackPointer)(UBX_NAV_V if (packetUBXNAVVELECEF->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("setAutoNAVVELECEFcallback: RAM alloc failed!")); +#endif return (false); } @@ -8633,8 +9051,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVVELECEF() packetUBXNAVVELECEF = new UBX_NAV_VELECEF_t; //Allocate RAM for the main struct if (packetUBXNAVVELECEF == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVVELECEF: RAM alloc failed!")); +#endif return (false); } packetUBXNAVVELECEF->automaticFlags.flags.all = 0; @@ -8755,8 +9175,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VE if (packetUBXNAVVELNED->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("setAutoNAVVELNEDcallback: RAM alloc failed!")); +#endif return (false); } @@ -8787,8 +9209,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVVELNED() packetUBXNAVVELNED = new UBX_NAV_VELNED_t; //Allocate RAM for the main struct if (packetUBXNAVVELNED == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVVELNED: RAM alloc failed!")); +#endif return (false); } packetUBXNAVVELNED->automaticFlags.flags.all = 0; @@ -8911,8 +9335,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFcallback(void (*callbackPointer)(UBX_NAV if (packetUBXNAVHPPOSECEF->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("setAutoNAVHPPOSECEFcallback: RAM alloc failed!")); +#endif return (false); } @@ -8943,8 +9369,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSECEF() packetUBXNAVHPPOSECEF = new UBX_NAV_HPPOSECEF_t; //Allocate RAM for the main struct if (packetUBXNAVHPPOSECEF == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVHPPOSECEF: RAM alloc failed!")); +#endif return (false); } packetUBXNAVHPPOSECEF->automaticFlags.flags.all = 0; @@ -9089,8 +9517,10 @@ bool SFE_UBLOX_GNSS::setAutoHPPOSLLHcallback(void (*callbackPointer)(UBX_NAV_HPP if (packetUBXNAVHPPOSLLH->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("setAutoHPPOSLLHcallback: RAM alloc failed!")); +#endif return (false); } @@ -9121,8 +9551,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSLLH() packetUBXNAVHPPOSLLH = new UBX_NAV_HPPOSLLH_t; //Allocate RAM for the main struct if (packetUBXNAVHPPOSLLH == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVHPPOSLLH: RAM alloc failed!")); +#endif return (false); } packetUBXNAVHPPOSLLH->automaticFlags.flags.all = 0; @@ -9245,8 +9677,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT if (packetUBXNAVPVAT->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("setAutoNAVPVATcallback: RAM alloc failed!")); +#endif return (false); } @@ -9278,8 +9712,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPVAT() packetUBXNAVPVAT = new UBX_NAV_PVAT_t; //Allocate RAM for the main struct if (packetUBXNAVPVAT == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVPVAT: RAM alloc failed!")); +#endif return (false); } packetUBXNAVPVAT->automaticFlags.flags.all = 0; @@ -9404,8 +9840,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVCLOCKcallback(void (*callbackPointer)(UBX_NAV_CLO if (packetUBXNAVCLOCK->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("setAutoNAVCLOCKcallback: RAM alloc failed!")); +#endif return (false); } @@ -9436,8 +9874,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVCLOCK() packetUBXNAVCLOCK = new UBX_NAV_CLOCK_t ; //Allocate RAM for the main struct if (packetUBXNAVCLOCK == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVCLOCK: RAM alloc failed!")); +#endif return (false); } packetUBXNAVCLOCK->automaticFlags.flags.all = 0; @@ -9497,8 +9937,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVTIMELS() packetUBXNAVTIMELS = new UBX_NAV_TIMELS_t; //Allocate RAM for the main struct if (packetUBXNAVTIMELS == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVTIMELS: RAM alloc failed!")); +#endif return (false); } packetUBXNAVTIMELS->automaticFlags.flags.all = 0; @@ -9544,8 +9986,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSVIN() packetUBXNAVSVIN = new UBX_NAV_SVIN_t; //Allocate RAM for the main struct if (packetUBXNAVSVIN == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVSVIN: RAM alloc failed!")); +#endif return (false); } packetUBXNAVSVIN->automaticFlags.flags.all = 0; @@ -9656,8 +10100,10 @@ bool SFE_UBLOX_GNSS::setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_d if (packetUBXNAVSAT->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("setAutoNAVSATcallback: RAM alloc failed!")); +#endif return (false); } @@ -9688,8 +10134,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSAT() packetUBXNAVSAT = new UBX_NAV_SAT_t ; //Allocate RAM for the main struct if (packetUBXNAVSAT == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVSAT: RAM alloc failed!")); +#endif return (false); } packetUBXNAVSAT->automaticFlags.flags.all = 0; @@ -9817,8 +10265,10 @@ bool SFE_UBLOX_GNSS::setAutoRELPOSNEDcallback(void (*callbackPointer)(UBX_NAV_RE if (packetUBXNAVRELPOSNED->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("setAutoRELPOSNEDcallback: RAM alloc failed!")); +#endif return (false); } @@ -9849,8 +10299,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVRELPOSNED() packetUBXNAVRELPOSNED = new UBX_NAV_RELPOSNED_t ; //Allocate RAM for the main struct if (packetUBXNAVRELPOSNED == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVRELPOSNED: RAM alloc failed!")); +#endif return (false); } packetUBXNAVRELPOSNED->automaticFlags.flags.all = 0; @@ -9993,8 +10445,10 @@ bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AO if (packetUBXNAVAOPSTATUS->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("setAutoAOPSTATUScallback: RAM alloc failed!")); +#endif return (false); } @@ -10025,8 +10479,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVAOPSTATUS() packetUBXNAVAOPSTATUS = new UBX_NAV_AOPSTATUS_t; //Allocate RAM for the main struct if (packetUBXNAVAOPSTATUS == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXNAVAOPSTATUS: RAM alloc failed!")); +#endif return (false); } packetUBXNAVAOPSTATUS->automaticFlags.flags.all = 0; @@ -10050,6 +10506,78 @@ void SFE_UBLOX_GNSS::logAOPSTATUS(bool enabled) packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } +// ***** RXM PMP automatic support + +// Callback is passed all of the data. Heavy on the stack. May cause problems on some platforms. +bool SFE_UBLOX_GNSS::setAutoRXMPMPcallback(void (*callbackPointer)(UBX_RXM_PMP_data_t)) +{ + if (packetUBXRXMPMP == NULL) initPacketUBXRXMPMP(); //Check that RAM has been allocated for the data + if (packetUBXRXMPMP == NULL) //Only attempt this if RAM allocation was successful + return false; + + if (packetUBXRXMPMP->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXRXMPMP->callbackData = new UBX_RXM_PMP_data_t; //Allocate RAM for the main struct + } + + if (packetUBXRXMPMP->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("setAutoRXMPMPcallback: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXRXMPMP->callbackPointer = callbackPointer; + return (true); +} + +// Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! +bool SFE_UBLOX_GNSS::setAutoRXMPMPcallbackPtr(void (*callbackPointer)(UBX_RXM_PMP_data_t *)) +{ + if (packetUBXRXMPMP == NULL) initPacketUBXRXMPMP(); //Check that RAM has been allocated for the data + if (packetUBXRXMPMP == NULL) //Only attempt this if RAM allocation was successful + return false; + + if (packetUBXRXMPMP->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXRXMPMP->callbackData = new UBX_RXM_PMP_data_t; //Allocate RAM for the main struct + } + + if (packetUBXRXMPMP->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("setAutoRXMPMPcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXRXMPMP->callbackPointerPtr = callbackPointer; + return (true); +} + +// PRIVATE: Allocate RAM for packetUBXRXMPMP and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXRXMPMP() +{ + packetUBXRXMPMP = new UBX_RXM_PMP_t; //Allocate RAM for the main struct + if (packetUBXRXMPMP == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXRXMPMP: RAM alloc failed!")); +#endif + return (false); + } + packetUBXRXMPMP->automaticFlags.flags.all = 0; + packetUBXRXMPMP->callbackPointer = NULL; + packetUBXRXMPMP->callbackPointerPtr = NULL; + packetUBXRXMPMP->callbackData = NULL; + packetUBXRXMPMP->moduleQueried = false; + return (true); +} + // ***** RXM SFRBX automatic support bool SFE_UBLOX_GNSS::getRXMSFRBX(uint16_t maxWait) @@ -10149,8 +10677,10 @@ bool SFE_UBLOX_GNSS::setAutoRXMSFRBXcallback(void (*callbackPointer)(UBX_RXM_SFR if (packetUBXRXMSFRBX->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("setAutoRXMSFRBXcallback: RAM alloc failed!")); +#endif return (false); } @@ -10181,8 +10711,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMSFRBX() packetUBXRXMSFRBX = new UBX_RXM_SFRBX_t; //Allocate RAM for the main struct if (packetUBXRXMSFRBX == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXRXMSFRBX: RAM alloc failed!")); +#endif return (false); } packetUBXRXMSFRBX->automaticFlags.flags.all = 0; @@ -10305,8 +10837,10 @@ bool SFE_UBLOX_GNSS::setAutoRXMRAWXcallback(void (*callbackPointer)(UBX_RXM_RAWX if (packetUBXRXMRAWX->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("setAutoRXMRAWXcallback: RAM alloc failed!")); +#endif return (false); } @@ -10337,8 +10871,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMRAWX() packetUBXRXMRAWX = new UBX_RXM_RAWX_t; //Allocate RAM for the main struct if (packetUBXRXMRAWX == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXRXMRAWX: RAM alloc failed!")); +#endif return (false); } packetUBXRXMRAWX->automaticFlags.flags.all = 0; @@ -10364,7 +10900,62 @@ void SFE_UBLOX_GNSS::logRXMRAWX(bool enabled) // ***** CFG automatic support -//Get the latest CFG RATE - as used by isConnected +//Get the latest CFG PRT - as used by isConnected +// Here's the dilemma: +// The NEO-D9S doesn't support NAV-RATE so, if we want to include the D9 without creating a special class for it, +// we need to use something else as the 'isConnected' test. The D9 does support CFG-PRT so we'll use that. +// BUT many users could already be using getPortSettings and expecting the settings to be returned in packetCfg. +// So, for isConnected ONLY, we need to enable auto support for CFG-PRT and then disable it afterwards so the settings +// go back to being returned in packetCfg... What a tangled web we weave...! +bool SFE_UBLOX_GNSS::getPortSettingsInternal(uint8_t portID, uint16_t maxWait) +{ + if (packetUBXCFGPRT == NULL) initPacketUBXCFGPRT(); //Check that RAM has been allocated for the data + if (packetUBXCFGPRT == NULL) //Bail if the RAM allocation failed + return (false); + + // The CFG PRT message will never be produced automatically - that would be pointless. + // There is no setAutoCFGPRT function. We always need to poll explicitly. + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_PRT; + packetCfg.len = 1; + packetCfg.startingSpot = 0; + + payloadCfg[0] = portID; + + //The data is parsed as part of processing the response + sfe_ublox_status_e result = sendCommand(&packetCfg, maxWait); + bool retVal = false; + + if (result == SFE_UBLOX_STATUS_DATA_RECEIVED) + retVal = true; + + if (result == SFE_UBLOX_STATUS_DATA_OVERWRITTEN) + retVal = true; + + //Now disable automatic support for CFG-RATE (see above) + delete packetUBXCFGPRT; + packetUBXCFGPRT = NULL; + + return (retVal); +} + +// PRIVATE: Allocate RAM for packetUBXCFGPRT and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXCFGPRT() +{ + packetUBXCFGPRT = new UBX_CFG_PRT_t; //Allocate RAM for the main struct + if (packetUBXCFGPRT == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXCFGPRT: RAM alloc failed!")); +#endif + return (false); + } + packetUBXCFGPRT->dataValid = false; + return (true); +} + +//Get the latest CFG RATE bool SFE_UBLOX_GNSS::getNavigationFrequencyInternal(uint16_t maxWait) { if (packetUBXCFGRATE == NULL) initPacketUBXCFGRATE(); //Check that RAM has been allocated for the data @@ -10396,8 +10987,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXCFGRATE() packetUBXCFGRATE = new UBX_CFG_RATE_t; //Allocate RAM for the main struct if (packetUBXCFGRATE == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXCFGRATE: RAM alloc failed!")); +#endif return (false); } packetUBXCFGRATE->automaticFlags.flags.all = 0; // Redundant @@ -10506,8 +11099,10 @@ bool SFE_UBLOX_GNSS::setAutoTIMTM2callback(void (*callbackPointer)(UBX_TIM_TM2_d if (packetUBXTIMTM2->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("setAutoTIMTM2callback: RAM alloc failed!")); +#endif return (false); } @@ -10538,8 +11133,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXTIMTM2() packetUBXTIMTM2 = new UBX_TIM_TM2_t; //Allocate RAM for the main struct if (packetUBXTIMTM2 == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXTIMTM2: RAM alloc failed!")); +#endif return (false); } packetUBXTIMTM2->automaticFlags.flags.all = 0; @@ -10691,8 +11288,10 @@ bool SFE_UBLOX_GNSS::setAutoESFALGcallback(void (*callbackPointer)(UBX_ESF_ALG_d if (packetUBXESFALG->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("setAutoESFALGcallback: RAM alloc failed!")); +#endif return (false); } @@ -10723,8 +11322,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFALG() packetUBXESFALG = new UBX_ESF_ALG_t; //Allocate RAM for the main struct if (packetUBXESFALG == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXESFALG: RAM alloc failed!")); +#endif return (false); } packetUBXESFALG->automaticFlags.flags.all = 0; @@ -10876,8 +11477,10 @@ bool SFE_UBLOX_GNSS::setAutoESFSTATUScallback(void (*callbackPointer)(UBX_ESF_ST if (packetUBXESFSTATUS->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("setAutoESFSTATUScallback: RAM alloc failed!")); +#endif return (false); } @@ -10909,8 +11512,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFSTATUS() if (packetUBXESFSTATUS == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXESFSTATUS: RAM alloc failed!")); +#endif return (false); } packetUBXESFSTATUS->automaticFlags.flags.all = 0; @@ -11062,8 +11667,10 @@ bool SFE_UBLOX_GNSS::setAutoESFINScallback(void (*callbackPointer)(UBX_ESF_INS_d if (packetUBXESFINS->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("setAutoESFINScallback: RAM alloc failed!")); +#endif return (false); } @@ -11094,8 +11701,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFINS() packetUBXESFINS = new UBX_ESF_INS_t; //Allocate RAM for the main struct if (packetUBXESFINS == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXESFINS: RAM alloc failed!")); +#endif return (false); } packetUBXESFINS->automaticFlags.flags.all = 0; @@ -11247,8 +11856,10 @@ bool SFE_UBLOX_GNSS::setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS if (packetUBXESFMEAS->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("setAutoESFMEAScallback: RAM alloc failed!")); +#endif return (false); } @@ -11279,8 +11890,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFMEAS() packetUBXESFMEAS = new UBX_ESF_MEAS_t; //Allocate RAM for the main struct if (packetUBXESFMEAS == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXESFMEAS: RAM alloc failed!")); +#endif return (false); } packetUBXESFMEAS->automaticFlags.flags.all = 0; @@ -11432,8 +12045,10 @@ bool SFE_UBLOX_GNSS::setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_d if (packetUBXESFRAW->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("setAutoESFRAWcallback: RAM alloc failed!")); +#endif return (false); } @@ -11464,8 +12079,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFRAW() packetUBXESFRAW = new UBX_ESF_RAW_t; //Allocate RAM for the main struct if (packetUBXESFRAW == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXESFRAW: RAM alloc failed!")); +#endif return (false); } packetUBXESFRAW->automaticFlags.flags.all = 0; @@ -11622,8 +12239,10 @@ bool SFE_UBLOX_GNSS::setAutoHNRATTcallback(void (*callbackPointer)(UBX_HNR_ATT_d if (packetUBXHNRATT->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("setAutoHNRAttcallback: RAM alloc failed!")); +#endif return (false); } @@ -11654,8 +12273,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRATT() packetUBXHNRATT = new UBX_HNR_ATT_t; //Allocate RAM for the main struct if (packetUBXHNRATT == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXHNRATT: RAM alloc failed!")); +#endif return (false); } packetUBXHNRATT->automaticFlags.flags.all = 0; @@ -11813,8 +12434,10 @@ bool SFE_UBLOX_GNSS::setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_d if (packetUBXHNRINS->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("setAutoHNRDyncallback: RAM alloc failed!")); +#endif return (false); } @@ -11845,8 +12468,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRINS() packetUBXHNRINS = new UBX_HNR_INS_t; //Allocate RAM for the main struct if (packetUBXHNRINS == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXHNRINS: RAM alloc failed!")); +#endif return (false); } packetUBXHNRINS->automaticFlags.flags.all = 0; @@ -11998,8 +12623,10 @@ bool SFE_UBLOX_GNSS::setAutoHNRPVTcallback(void (*callbackPointer)(UBX_HNR_PVT_d if (packetUBXHNRPVT->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("setAutoHNRPVTcallback: RAM alloc failed!")); +#endif return (false); } @@ -12030,8 +12657,10 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRPVT() packetUBXHNRPVT = new UBX_HNR_PVT_t; //Allocate RAM for the main struct if (packetUBXHNRPVT == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initPacketUBXHNRPVT: RAM alloc failed!")); +#endif return (false); } packetUBXHNRPVT->automaticFlags.flags.all = 0; @@ -12170,8 +12799,10 @@ bool SFE_UBLOX_GNSS::setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_ if (storageNMEAGPGGA->callbackCopy == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("setNMEAGPGGAcallback: RAM alloc failed!")); +#endif return (false); } @@ -12185,8 +12816,10 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGPGGA() storageNMEAGPGGA = new NMEA_GPGGA_t; //Allocate RAM for the main struct if (storageNMEAGPGGA == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initStorageNMEAGPGGA: RAM alloc failed!")); +#endif return (false); } @@ -12240,8 +12873,10 @@ bool SFE_UBLOX_GNSS::setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_ if (storageNMEAGNGGA->callbackCopy == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("setNMEAGNGGAcallback: RAM alloc failed!")); +#endif return (false); } @@ -12255,8 +12890,10 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGNGGA() storageNMEAGNGGA = new NMEA_GNGGA_t; //Allocate RAM for the main struct if (storageNMEAGNGGA == NULL) { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("initStorageNMEAGNGGA: RAM alloc failed!")); +#endif return (false); } @@ -13801,7 +14438,7 @@ float SFE_UBLOX_GNSS::getHNRheading(uint16_t maxWait) // Returned as degrees // From v2.0: These are public. The user can call these to extract data from custom packets //Given a spot in the payload array, extract four bytes and build a long -uint32_t SFE_UBLOX_GNSS::extractLong(ubxPacket *msg, uint8_t spotToStart) +uint32_t SFE_UBLOX_GNSS::extractLong(ubxPacket *msg, uint16_t spotToStart) { uint32_t val = 0; val |= (uint32_t)msg->payload[spotToStart + 0] << 8 * 0; @@ -13812,7 +14449,7 @@ uint32_t SFE_UBLOX_GNSS::extractLong(ubxPacket *msg, uint8_t spotToStart) } //Just so there is no ambiguity about whether a uint32_t will cast to a int32_t correctly... -int32_t SFE_UBLOX_GNSS::extractSignedLong(ubxPacket *msg, uint8_t spotToStart) +int32_t SFE_UBLOX_GNSS::extractSignedLong(ubxPacket *msg, uint16_t spotToStart) { union // Use a union to convert from uint32_t to int32_t { @@ -13825,7 +14462,7 @@ int32_t SFE_UBLOX_GNSS::extractSignedLong(ubxPacket *msg, uint8_t spotToStart) } //Given a spot in the payload array, extract two bytes and build an int -uint16_t SFE_UBLOX_GNSS::extractInt(ubxPacket *msg, uint8_t spotToStart) +uint16_t SFE_UBLOX_GNSS::extractInt(ubxPacket *msg, uint16_t spotToStart) { uint16_t val = 0; val |= (uint16_t)msg->payload[spotToStart + 0] << 8 * 0; @@ -13834,7 +14471,7 @@ uint16_t SFE_UBLOX_GNSS::extractInt(ubxPacket *msg, uint8_t spotToStart) } //Just so there is no ambiguity about whether a uint16_t will cast to a int16_t correctly... -int16_t SFE_UBLOX_GNSS::extractSignedInt(ubxPacket *msg, int8_t spotToStart) +int16_t SFE_UBLOX_GNSS::extractSignedInt(ubxPacket *msg, uint16_t spotToStart) { union // Use a union to convert from uint16_t to int16_t { @@ -13847,13 +14484,13 @@ int16_t SFE_UBLOX_GNSS::extractSignedInt(ubxPacket *msg, int8_t spotToStart) } //Given a spot, extract a byte from the payload -uint8_t SFE_UBLOX_GNSS::extractByte(ubxPacket *msg, uint8_t spotToStart) +uint8_t SFE_UBLOX_GNSS::extractByte(ubxPacket *msg, uint16_t spotToStart) { return (msg->payload[spotToStart]); } //Given a spot, extract a signed 8-bit value from the payload -int8_t SFE_UBLOX_GNSS::extractSignedChar(ubxPacket *msg, uint8_t spotToStart) +int8_t SFE_UBLOX_GNSS::extractSignedChar(ubxPacket *msg, uint16_t spotToStart) { union // Use a union to convert from uint8_t to int8_t { diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index aa14ee5..6ba5b06 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -375,8 +375,8 @@ const uint8_t UBX_NAV_AOPSTATUS = 0x60; //AssistNow Autonomous status //Class: RXM //The following are used to configure the RXM UBX messages (receiver manager messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) const uint8_t UBX_RXM_MEASX = 0x14; //Satellite Measurements for RRLP +const uint8_t UBX_RXM_PMP = 0x72; //PMP raw data (NEO-D9S) (two different versions) (packet size for version 0x01 is variable) const uint8_t UBX_RXM_PMREQ = 0x41; //Requests a Power Management task (two different packet sizes) -const uint8_t UBX_RXM_PMP = 0x72; //PMP raw data (two different versions) (packet size for version 0x01 is variable) const uint8_t UBX_RXM_RAWX = 0x15; //Multi-GNSS Raw Measurement Data const uint8_t UBX_RXM_RLM = 0x59; //Galileo SAR Short-RLM report (two different packet sizes) const uint8_t UBX_RXM_RTCM = 0x32; //RTCM input status @@ -932,6 +932,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVPOSECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic POSECEF 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 setAutoNAVPOSECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic POSECEF reports bool setAutoNAVPOSECEFcallback(void (*callbackPointer)(UBX_NAV_POSECEF_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic POSECEF reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_POSECEF_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic POSECEF reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVPOSECEF(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and POSECEF is send cyclically already void flushNAVPOSECEF(); //Mark all the data as read/stale void logNAVPOSECEF(bool enabled = true); // Log data to file buffer @@ -941,6 +942,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic STATUS 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 setAutoNAVSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic STATUS reports bool setAutoNAVSTATUScallback(void (*callbackPointer)(UBX_NAV_STATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_STATUS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and STATUS is send cyclically already void flushNAVSTATUS(); //Mark all the data as read/stale void logNAVSTATUS(bool enabled = true); // Log data to file buffer @@ -950,6 +952,7 @@ class SFE_UBLOX_GNSS bool setAutoDOP(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic DOP 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 setAutoDOPrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic DOP reports bool setAutoDOPcallback(void (*callbackPointer)(UBX_NAV_DOP_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic DOP reports at the navigation frequency. Data is accessed from the callback. + bool setAutoDOPcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_DOP_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic DOP reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoDOP(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and DOP is send cyclically already void flushDOP(); //Mark all the DOP data as read/stale void logNAVDOP(bool enabled = true); // Log data to file buffer @@ -960,6 +963,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVATT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic vehicle attitude 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 setAutoNAVATTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ATT reports bool setAutoNAVATTcallback(void (*callbackPointer)(UBX_NAV_ATT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVATTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ATT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVATT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and vehicle attitude is send cyclically already void flushNAVATT(); //Mark all the data as read/stale void logNAVATT(bool enabled = true); // Log data to file buffer @@ -969,6 +973,7 @@ class SFE_UBLOX_GNSS bool setAutoPVT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVT 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 setAutoPVTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic PVT reports bool setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoPVTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoPVT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and PVT is send cyclically already void flushPVT(); //Mark all the PVT data as read/stale void logNAVPVT(bool enabled = true); // Log data to file buffer @@ -978,6 +983,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVODO(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ODO 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 setAutoNAVODOrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ODO reports bool setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVODOcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ODO_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVODO(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ODO is send cyclically already void flushNAVODO(); //Mark all the data as read/stale void logNAVODO(bool enabled = true); // Log data to file buffer @@ -987,6 +993,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVVELECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELECEF 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 setAutoNAVVELECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic VELECEF reports bool setAutoNAVVELECEFcallback(void (*callbackPointer)(UBX_NAV_VELECEF_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic VELECEF reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVVELECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELECEF_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic VELECEF reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVVELECEF(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and VELECEF is send cyclically already void flushNAVVELECEF(); //Mark all the data as read/stale void logNAVVELECEF(bool enabled = true); // Log data to file buffer @@ -996,6 +1003,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVVELNED(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELNED 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 setAutoNAVVELNEDrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic VELNED reports bool setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VELNED_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic VELNED reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVVELNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELNED_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic VELNED reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVVELNED(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and VELNED is send cyclically already void flushNAVVELNED(); //Mark all the data as read/stale void logNAVVELNED(bool enabled = true); // Log data to file buffer @@ -1005,6 +1013,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSECEF 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 setAutoNAVHPPOSECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic HPPOSECEF reports bool setAutoNAVHPPOSECEFcallback(void (*callbackPointer)(UBX_NAV_HPPOSECEF_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSECEF reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVHPPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSECEF_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSECEF reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HPPOSECEF is send cyclically already void flushNAVHPPOSECEF(); //Mark all the data as read/stale void logNAVHPPOSECEF(bool enabled = true); // Log data to file buffer @@ -1014,6 +1023,7 @@ class SFE_UBLOX_GNSS bool setAutoHPPOSLLH(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSLLH 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 setAutoHPPOSLLHrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic HPPOSLLH reports bool setAutoHPPOSLLHcallback(void (*callbackPointer)(UBX_NAV_HPPOSLLH_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSLLH reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHPPOSLLHcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSLLH_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSLLH reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoHPPOSLLH(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HPPOSLLH is send cyclically already void flushHPPOSLLH(); //Mark all the HPPPOSLLH data as read/stale. This is handy to get data alignment after CRC failure void logNAVHPPOSLLH(bool enabled = true); // Log data to file buffer @@ -1023,6 +1033,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVPVAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVAT 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 setAutoNAVPVATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic PVAT reports bool setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVAT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVPVATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVAT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic PVAT reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVPVAT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and PVAT is send cyclically already void flushNAVPVAT(); //Mark all the PVAT data as read/stale void logNAVPVAT(bool enabled = true); // Log data to file buffer @@ -1032,6 +1043,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVCLOCK(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic clock 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 setAutoNAVCLOCKrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic CLOCK reports bool setAutoNAVCLOCKcallback(void (*callbackPointer)(UBX_NAV_CLOCK_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic CLOCK reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVCLOCKcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_CLOCK_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic CLOCK reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and clock is send cyclically already void flushNAVCLOCK(); //Mark all the data as read/stale void logNAVCLOCK(bool enabled = true); // Log data to file buffer @@ -1047,6 +1059,7 @@ class SFE_UBLOX_GNSS bool setAutoNAVSAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic NAVSAT 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 setAutoNAVSATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic NAVSAT reports bool setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic NAVSAT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVSATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SAT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic NAVSAT reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoNAVSAT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and NAVSAT is send cyclically already void flushNAVSAT(); //Mark all the NAVSAT data as read/stale void logNAVSAT(bool enabled = true); // Log data to file buffer @@ -1056,6 +1069,7 @@ class SFE_UBLOX_GNSS bool setAutoRELPOSNED(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RELPOSNED, 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 setAutoRELPOSNEDrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic RELPOSNEDreports bool setAutoRELPOSNEDcallback(void (*callbackPointer)(UBX_NAV_RELPOSNED_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic RELPOSNED reports at the navigation frequency. Data is accessed from the callback. + bool setAutoRELPOSNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_RELPOSNED_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic RELPOSNED reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoRELPOSNED(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and RELPOSNED is send cyclically already void flushNAVRELPOSNED(); //Mark all the data as read/stale void logNAVRELPOSNED(bool enabled = true); // Log data to file buffer @@ -1065,6 +1079,7 @@ class SFE_UBLOX_GNSS bool setAutoAOPSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic AOPSTATUS 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 setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic AOPSTATUS reports bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoAOPSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_AOPSTATUS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and AOPSTATUS is send cyclically already void flushAOPSTATUS(); //Mark all the AOPSTATUS data as read/stale void logAOPSTATUS(bool enabled = true); // Log data to file buffer @@ -1075,14 +1090,15 @@ class SFE_UBLOX_GNSS // Note: on the NEO-D9S, the UBX-RXM-PMP messages are enabled by default on all ports. // You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 0) // The NEO-D9S does not support UBX-CFG-MSG - bool setAutoRXMPMPcallback(void (*callbackPointer)(UBX_RXM_PMP_data_t), uint16_t maxWait = defaultMaxWait); // Callback is passed all of the data. Heavy on the stack. May cause problems on some platforms. - bool setAutoRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *), uint16_t maxWait = defaultMaxWait); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! + bool setAutoRXMPMPcallback(void (*callbackPointer)(UBX_RXM_PMP_data_t)); // Callback is passed all of the data. Heavy on the stack. May cause problems on some platforms. + bool setAutoRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX bool setAutoRXMSFRBX(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM SFRBX reports at the navigation frequency bool setAutoRXMSFRBX(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM SFRBX 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 setAutoRXMSFRBXrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic SFRBX reports bool setAutoRXMSFRBXcallback(void (*callbackPointer)(UBX_RXM_SFRBX_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic SFRBX reports at the navigation frequency. Data is accessed from the callback. + bool setAutoRXMSFRBXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_SFRBX_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic SFRBX reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoRXMSFRBX(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and RXM SFRBX is send cyclically already void flushRXMSFRBX(); //Mark all the data as read/stale void logRXMSFRBX(bool enabled = true); // Log data to file buffer @@ -1092,13 +1108,15 @@ class SFE_UBLOX_GNSS bool setAutoRXMRAWX(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM RAWX 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 setAutoRXMRAWXrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic RAWX reports bool setAutoRXMRAWXcallback(void (*callbackPointer)(UBX_RXM_RAWX_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic RAWX reports at the navigation frequency. Data is accessed from the callback. + bool setAutoRXMRAWXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_RAWX_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic RAWX reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoRXMRAWX(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and RXM RAWX is send cyclically already void flushRXMRAWX(); //Mark all the data as read/stale void logRXMRAWX(bool enabled = true); // Log data to file buffer // Configuration (CFG) - // Add "auto" support for CFG RATE - because we use it for isConnected (to stop it being mugged by other messages) + // Add "auto" support for CFG PRT - because we use it for isConnected (to stop it being mugged by other messages) + bool getPortSettingsInternal(uint8_t portID, uint16_t maxWait = defaultMaxWait); //Read the port configuration for a given port using UBX-CFG-PRT bool getNavigationFrequencyInternal(uint16_t maxWait = defaultMaxWait); //Get the number of nav solutions sent per second currently being output by module // Timing messages (TIM) @@ -1108,6 +1126,7 @@ class SFE_UBLOX_GNSS bool setAutoTIMTM2(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic TIM TM2 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 setAutoTIMTM2rate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic TIM TM2 reports bool setAutoTIMTM2callback(void (*callbackPointer)(UBX_TIM_TM2_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic TM2 reports at the navigation frequency. Data is accessed from the callback. + bool setAutoTIMTM2callbackPtr(void (*callbackPointerPtr)(UBX_TIM_TM2_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic TM2 reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoTIMTM2(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and TIM TM2 is send cyclically already void flushTIMTM2(); //Mark all the data as read/stale void logTIMTM2(bool enabled = true); // Log data to file buffer @@ -1120,6 +1139,7 @@ class SFE_UBLOX_GNSS bool setAutoESFALG(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF ALG reports, 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 setAutoESFALGrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ALG reports bool setAutoESFALGcallback(void (*callbackPointer)(UBX_ESF_ALG_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ALG reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFALGcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_ALG_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ALG reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoESFALG(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF ALG is send cyclically already void flushESFALG(); //Mark all the data as read/stale void logESFALG(bool enabled = true); // Log data to file buffer @@ -1130,6 +1150,7 @@ class SFE_UBLOX_GNSS bool setAutoESFSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF STATUS reports, 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 setAutoESFSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic STATUS reports bool setAutoESFSTATUScallback(void (*callbackPointer)(UBX_ESF_STATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_STATUS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoESFSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF STATUS is send cyclically already void flushESFSTATUS(); //Mark all the data as read/stale void logESFSTATUS(bool enabled = true); // Log data to file buffer @@ -1140,6 +1161,7 @@ class SFE_UBLOX_GNSS bool setAutoESFINS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF INS reports, 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 setAutoESFINSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic INS reports bool setAutoESFINScallback(void (*callbackPointer)(UBX_ESF_INS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFINScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_INS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoESFINS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF INS is send cyclically already void flushESFINS(); //Mark all the data as read/stale void logESFINS(bool enabled = true); // Log data to file buffer @@ -1150,6 +1172,7 @@ class SFE_UBLOX_GNSS bool setAutoESFMEAS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF MEAS reports, 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 setAutoESFMEASrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic MEAS reports bool setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoESFMEAS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF MEAS is send cyclically already void flushESFMEAS(); //Mark all the data as read/stale void logESFMEAS(bool enabled = true); // Log data to file buffer @@ -1160,6 +1183,7 @@ class SFE_UBLOX_GNSS bool setAutoESFRAW(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF RAW reports, 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 setAutoESFRAWrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic RAW reports bool setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoESFRAW(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF RAW is send cyclically already void flushESFRAW(); //Mark all the data as read/stale void logESFRAW(bool enabled = true); // Log data to file buffer @@ -1172,6 +1196,7 @@ class SFE_UBLOX_GNSS bool setAutoHNRATT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR Attitude reports at the HNR rate, 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 setAutoHNRATTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ATT reports bool setAutoHNRATTcallback(void (*callbackPointer)(UBX_HNR_ATT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHNRATTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_ATT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoHNRATT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HNR Attitude is send cyclically already void flushHNRATT(); //Mark all the data as read/stale void logHNRATT(bool enabled = true); // Log data to file buffer @@ -1182,6 +1207,7 @@ class SFE_UBLOX_GNSS bool setAutoHNRINS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR dynamics reports at the HNR rate, 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 setAutoHNRINSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic INS reports bool setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHNRINScallbackPtr(void (*callbackPointerPtr)(UBX_HNR_INS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoHNRINS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HNR dynamics is send cyclically already void flushHNRINS(); //Mark all the data as read/stale void logHNRINS(bool enabled = true); // Log data to file buffer @@ -1191,6 +1217,7 @@ class SFE_UBLOX_GNSS bool setAutoHNRPVT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR PVT reports at the HNR rate, 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 setAutoHNRPVTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic PVT reports bool setAutoHNRPVTcallback(void (*callbackPointer)(UBX_HNR_PVT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHNRPVTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_PVT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. bool assumeAutoHNRPVT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HNR PVT is send cyclically already void flushHNRPVT(); //Mark all the data as read/stale void logHNRPVT(bool enabled = true); // Log data to file buffer @@ -1365,12 +1392,12 @@ class SFE_UBLOX_GNSS // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket // From v2.0: These are public. The user can call these to extract data from custom packets - uint32_t extractLong(ubxPacket *msg, uint8_t spotToStart); //Combine four bytes from payload into long - int32_t extractSignedLong(ubxPacket *msg, uint8_t spotToStart); //Combine four bytes from payload into signed long (avoiding any ambiguity caused by casting) - uint16_t extractInt(ubxPacket *msg, uint8_t spotToStart); //Combine two bytes from payload into int - int16_t extractSignedInt(ubxPacket *msg, int8_t spotToStart); - uint8_t extractByte(ubxPacket *msg, uint8_t spotToStart); //Get byte from payload - int8_t extractSignedChar(ubxPacket *msg, uint8_t spotToStart); //Get signed 8-bit value from payload + uint32_t extractLong(ubxPacket *msg, uint16_t spotToStart); //Combine four bytes from payload into long + int32_t extractSignedLong(ubxPacket *msg, uint16_t spotToStart); //Combine four bytes from payload into signed long (avoiding any ambiguity caused by casting) + uint16_t extractInt(ubxPacket *msg, uint16_t spotToStart); //Combine two bytes from payload into int + int16_t extractSignedInt(ubxPacket *msg, uint16_t spotToStart); + uint8_t extractByte(ubxPacket *msg, uint16_t spotToStart); //Get byte from payload + int8_t extractSignedChar(ubxPacket *msg, uint16_t spotToStart); //Get signed 8-bit value from payload // Pointers to storage for the "automatic" messages // RAM is allocated for these if/when required. @@ -1397,6 +1424,7 @@ class SFE_UBLOX_GNSS UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_CFG_PRT_t *packetUBXCFGPRT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_CFG_RATE_t *packetUBXCFGRATE = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_TIM_TM2_t *packetUBXTIMTM2 = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1481,9 +1509,10 @@ class SFE_UBLOX_GNSS bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it - bool initPacketUBXRXMPMP(bool usePtr = false); // Allocate RAM for packetUBXRXMPMP and initialize it + bool initPacketUBXRXMPMP(); // Allocate RAM for packetUBXRXMPMP and initialize it bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it + bool initPacketUBXCFGPRT(); // Allocate RAM for packetUBXCFGPRT and initialize it bool initPacketUBXCFGRATE(); // Allocate RAM for packetUBXCFGRATE and initialize it bool initPacketUBXTIMTM2(); // Allocate RAM for packetUBXTIMTM2 and initialize it bool initPacketUBXESFALG(); // Allocate RAM for packetUBXESFALG and initialize it diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 20e15a6..d5a7b10 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -103,6 +103,7 @@ typedef struct UBX_NAV_POSECEF_data_t data; UBX_NAV_POSECEF_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_POSECEF_data_t); + void (*callbackPointerPtr)(UBX_NAV_POSECEF_data_t *); UBX_NAV_POSECEF_data_t *callbackData; } UBX_NAV_POSECEF_t; @@ -146,6 +147,7 @@ typedef struct UBX_NAV_POSLLH_data_t data; UBX_NAV_POSLLH_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_POSLLH_data_t); + void (*callbackPointerPtr)(UBX_NAV_POSLLH_data_t *); UBX_NAV_POSLLH_data_t *callbackData; } UBX_NAV_POSLLH_t; @@ -246,6 +248,7 @@ typedef struct UBX_NAV_STATUS_data_t data; UBX_NAV_STATUS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_STATUS_data_t); + void (*callbackPointerPtr)(UBX_NAV_STATUS_data_t *); UBX_NAV_STATUS_data_t *callbackData; } UBX_NAV_STATUS_t; @@ -291,6 +294,7 @@ typedef struct UBX_NAV_DOP_data_t data; UBX_NAV_DOP_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_DOP_data_t); + void (*callbackPointerPtr)(UBX_NAV_DOP_data_t *); UBX_NAV_DOP_data_t *callbackData; } UBX_NAV_DOP_t; @@ -337,6 +341,7 @@ typedef struct UBX_NAV_ATT_data_t data; UBX_NAV_ATT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_ATT_data_t); + void (*callbackPointerPtr)(UBX_NAV_ATT_data_t *); UBX_NAV_ATT_data_t *callbackData; } UBX_NAV_ATT_t; @@ -500,6 +505,7 @@ typedef struct UBX_NAV_PVT_data_t data; UBX_NAV_PVT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_PVT_data_t); + void (*callbackPointerPtr)(UBX_NAV_PVT_data_t *); UBX_NAV_PVT_data_t *callbackData; } UBX_NAV_PVT_t; @@ -540,6 +546,7 @@ typedef struct UBX_NAV_ODO_data_t data; UBX_NAV_ODO_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_ODO_data_t); + void (*callbackPointerPtr)(UBX_NAV_ODO_data_t *); UBX_NAV_ODO_data_t *callbackData; } UBX_NAV_ODO_t; @@ -579,6 +586,7 @@ typedef struct UBX_NAV_VELECEF_data_t data; UBX_NAV_VELECEF_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_VELECEF_data_t); + void (*callbackPointerPtr)(UBX_NAV_VELECEF_data_t *); UBX_NAV_VELECEF_data_t *callbackData; } UBX_NAV_VELECEF_t; @@ -626,6 +634,7 @@ typedef struct UBX_NAV_VELNED_data_t data; UBX_NAV_VELNED_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_VELNED_data_t); + void (*callbackPointerPtr)(UBX_NAV_VELNED_data_t *); UBX_NAV_VELNED_data_t *callbackData; } UBX_NAV_VELNED_t; @@ -685,6 +694,7 @@ typedef struct UBX_NAV_HPPOSECEF_data_t data; UBX_NAV_HPPOSECEF_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_HPPOSECEF_data_t); + void (*callbackPointerPtr)(UBX_NAV_HPPOSECEF_data_t *); UBX_NAV_HPPOSECEF_data_t *callbackData; } UBX_NAV_HPPOSECEF_t; @@ -750,6 +760,7 @@ typedef struct UBX_NAV_HPPOSLLH_data_t data; UBX_NAV_HPPOSLLH_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_HPPOSLLH_data_t); + void (*callbackPointerPtr)(UBX_NAV_HPPOSLLH_data_t *); UBX_NAV_HPPOSLLH_data_t *callbackData; } UBX_NAV_HPPOSLLH_t; @@ -924,6 +935,7 @@ typedef struct UBX_NAV_PVAT_data_t data; UBX_NAV_PVAT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_PVAT_data_t); + void (*callbackPointerPtr)(UBX_NAV_PVAT_data_t *); UBX_NAV_PVAT_data_t *callbackData; } UBX_NAV_PVAT_t; @@ -988,6 +1000,7 @@ typedef struct UBX_NAV_TIMEUTC_data_t data; UBX_NAV_TIMEUTC_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_TIMEUTC_data_t); + void (*callbackPointerPtr)(UBX_NAV_TIMEUTC_data_t *); UBX_NAV_TIMEUTC_data_t *callbackData; } UBX_NAV_TIMEUTC_t; @@ -1027,6 +1040,7 @@ typedef struct UBX_NAV_CLOCK_data_t data; UBX_NAV_CLOCK_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_CLOCK_data_t); + void (*callbackPointerPtr)(UBX_NAV_CLOCK_data_t *); UBX_NAV_CLOCK_data_t *callbackData; } UBX_NAV_CLOCK_t; @@ -1087,6 +1101,7 @@ typedef struct UBX_NAV_TIMELS_data_t data; UBX_NAV_TIMELS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_TIMELS_data_t); + void (*callbackPointerPtr)(UBX_NAV_TIMELS_data_t *); UBX_NAV_TIMELS_data_t *callbackData; } UBX_NAV_TIMELS_t; @@ -1160,6 +1175,7 @@ typedef struct UBX_NAV_SAT_data_t data; bool moduleQueried; void (*callbackPointer)(UBX_NAV_SAT_data_t); + void (*callbackPointerPtr)(UBX_NAV_SAT_data_t *); UBX_NAV_SAT_data_t *callbackData; } UBX_NAV_SAT_t; @@ -1218,6 +1234,7 @@ typedef struct 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; @@ -1317,6 +1334,7 @@ typedef struct UBX_NAV_RELPOSNED_data_t data; UBX_NAV_RELPOSNED_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_RELPOSNED_data_t); + void (*callbackPointerPtr)(UBX_NAV_RELPOSNED_data_t *); UBX_NAV_RELPOSNED_data_t *callbackData; } UBX_NAV_RELPOSNED_t; @@ -1362,6 +1380,7 @@ typedef struct UBX_NAV_AOPSTATUS_data_t data; UBX_NAV_AOPSTATUS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t); + void (*callbackPointerPtr)(UBX_NAV_AOPSTATUS_data_t *); UBX_NAV_AOPSTATUS_data_t *callbackData; } UBX_NAV_AOPSTATUS_t; @@ -1393,6 +1412,7 @@ typedef struct UBX_RXM_SFRBX_data_t data; bool moduleQueried; void (*callbackPointer)(UBX_RXM_SFRBX_data_t); + void (*callbackPointerPtr)(UBX_RXM_SFRBX_data_t *); UBX_RXM_SFRBX_data_t *callbackData; } UBX_RXM_SFRBX_t; @@ -1460,6 +1480,7 @@ typedef struct UBX_RXM_RAWX_data_t data; bool moduleQueried; void (*callbackPointer)(UBX_RXM_RAWX_data_t); + void (*callbackPointerPtr)(UBX_RXM_RAWX_data_t *); UBX_RXM_RAWX_data_t *callbackData; } UBX_RXM_RAWX_t; @@ -1499,6 +1520,63 @@ typedef struct // CFG-specific structs +// UBX-CFG-PRT (0x06 0x00): Port configuration +// The content changes depending on which port type is being configured +// This struct defines the common structure +const uint16_t UBX_CFG_PRT_LEN = 20; + +typedef struct +{ + uint8_t portID; // Port identifier number + uint8_t reserved0; // Reserved + union + { + uint16_t all; + struct + { + uint16_t en : 1; // Enable TX ready feature for this port + uint16_t pol : 1; // Polarity: 0 High-active; 1 Low-active + uint16_t pin : 5; // PIO to be used (must not be in use by another function) + uint16_t thres : 9; // Threshold + } bits; + } txReady; + uint32_t mode; // Content changes depending on the port type + uint32_t baudRate ; // Content changes depending on the port type + union + { + uint16_t all; + struct + { + uint16_t inUbx : 1; // UBX protocol + uint16_t inNmea : 1; // NMEA protocol + uint16_t inRtcm : 1; // RTCM2 protocol + uint16_t reserved : 2; + uint16_t inRtcm3 : 1; // RTCM3 protocol (not supported for protocol versions less than 20.00) + uint16_t inSPARTN : 1; + } bits; + } inProtoMask; + union + { + uint16_t all; + struct + { + uint16_t outUbx : 1; // UBX protocol + uint16_t outNmea : 1; // NMEA protocol + uint16_t reserved : 3; + uint16_t outRtcm3 : 1; // RTCM3 protocol (not supported for protocol versions less than 20.00) + uint16_t outSPARTN : 1; + } bits; + } outProtoMask; + uint16_t flags; // Content changes depending on the port type + uint16_t reserved1; +} UBX_CFG_PRT_data_t; + +typedef struct +{ + UBX_CFG_PRT_data_t data; + bool dataValid; +} UBX_CFG_PRT_t; + // UBX-CFG-RATE (0x06 0x08): Navigation/measurement rate settings const uint16_t UBX_CFG_RATE_LEN = 6; @@ -1531,6 +1609,7 @@ typedef struct UBX_CFG_RATE_data_t data; UBX_CFG_RATE_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_CFG_RATE_data_t); + void (*callbackPointerPtr)(UBX_CFG_RATE_data_t *); UBX_CFG_RATE_data_t *callbackData; } UBX_CFG_RATE_t; @@ -1637,6 +1716,7 @@ typedef struct UBX_TIM_TM2_data_t data; UBX_TIM_TM2_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_TIM_TM2_data_t); + void (*callbackPointerPtr)(UBX_TIM_TM2_data_t *); UBX_TIM_TM2_data_t *callbackData; } UBX_TIM_TM2_t; @@ -1711,6 +1791,7 @@ typedef struct UBX_ESF_ALG_data_t data; UBX_ESF_ALG_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_ALG_data_t); + void (*callbackPointerPtr)(UBX_ESF_ALG_data_t *); UBX_ESF_ALG_data_t *callbackData; } UBX_ESF_ALG_t; @@ -1777,6 +1858,7 @@ typedef struct UBX_ESF_INS_data_t data; UBX_ESF_INS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_INS_data_t); + void (*callbackPointerPtr)(UBX_ESF_INS_data_t *); UBX_ESF_INS_data_t *callbackData; } UBX_ESF_INS_t; @@ -1847,6 +1929,7 @@ typedef struct UBX_ESF_MEAS_data_t data; UBX_ESF_MEAS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_MEAS_data_t); + void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *); UBX_ESF_MEAS_data_t *callbackData; } UBX_ESF_MEAS_t; @@ -1894,6 +1977,7 @@ typedef struct UBX_ESF_RAW_data_t data; UBX_ESF_RAW_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_RAW_data_t); + void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *); UBX_ESF_RAW_data_t *callbackData; } UBX_ESF_RAW_t; @@ -1981,6 +2065,7 @@ typedef struct UBX_ESF_STATUS_data_t data; UBX_ESF_STATUS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_STATUS_data_t); + void (*callbackPointerPtr)(UBX_ESF_STATUS_data_t *); UBX_ESF_STATUS_data_t *callbackData; } UBX_ESF_STATUS_t; @@ -2151,6 +2236,7 @@ typedef struct UBX_HNR_PVT_data_t data; UBX_HNR_PVT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_HNR_PVT_data_t); + void (*callbackPointerPtr)(UBX_HNR_PVT_data_t *); UBX_HNR_PVT_data_t *callbackData; } UBX_HNR_PVT_t; @@ -2197,6 +2283,7 @@ typedef struct UBX_HNR_ATT_data_t data; UBX_HNR_ATT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_HNR_ATT_data_t); + void (*callbackPointerPtr)(UBX_HNR_ATT_data_t *); UBX_HNR_ATT_data_t *callbackData; } UBX_HNR_ATT_t; @@ -2263,6 +2350,7 @@ typedef struct UBX_HNR_INS_data_t data; UBX_HNR_INS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_HNR_INS_data_t); + void (*callbackPointerPtr)(UBX_HNR_INS_data_t *); UBX_HNR_INS_data_t *callbackData; } UBX_HNR_INS_t; @@ -2302,6 +2390,7 @@ typedef struct NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy NMEA_GGA_data_t completeCopy; // The working copy is copied into the complete copy when all data has been received and the checksum is valid void (*callbackPointer)(NMEA_GGA_data_t); + void (*callbackPointerPtr)(NMEA_GGA_data_t *); NMEA_GGA_data_t *callbackCopy; // The callback gets its own preserved copy of the complete copy } NMEA_GPGGA_t; @@ -2311,6 +2400,7 @@ typedef struct NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy NMEA_GGA_data_t completeCopy; // The working copy is copied into the complete copy when all data has been received and the checksum is valid void (*callbackPointer)(NMEA_GGA_data_t); + void (*callbackPointerPtr)(NMEA_GGA_data_t *); NMEA_GGA_data_t *callbackCopy; // The callback gets its own preserved copy of the complete copy } NMEA_GNGGA_t; From 47348ab0b1cdb04ee6687931c1834ae1fbe687d5 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sat, 5 Feb 2022 17:50:15 +0000 Subject: [PATCH 096/122] Finish adding callback pointers for all auto messages --- keywords.txt | 31 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 803 ++++++++++++++++++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 2 + src/u-blox_structs.h | 3 - 4 files changed, 796 insertions(+), 43 deletions(-) diff --git a/keywords.txt b/keywords.txt index 32d0fcb..1213ac5 100644 --- a/keywords.txt +++ b/keywords.txt @@ -201,6 +201,7 @@ getNAVPOSECEF KEYWORD2 setAutoNAVPOSECEF KEYWORD2 setAutoNAVPOSECEFrate KEYWORD2 setAutoNAVPOSECEFcallback KEYWORD2 +setAutoNAVPOSECEFcallbackPtr KEYWORD2 assumeAutoNAVPOSECEF KEYWORD2 initPacketUBXNAVPOSECEF KEYWORD2 flushNAVPOSECEF KEYWORD2 @@ -210,6 +211,7 @@ getNAVSTATUS KEYWORD2 setAutoNAVSTATUS KEYWORD2 setAutoNAVSTATUSrate KEYWORD2 setAutoNAVSTATUScallback KEYWORD2 +setAutoNAVSTATUScallbackPtr KEYWORD2 assumeAutoNAVSTATUS KEYWORD2 initPacketUBXNAVSTATUS KEYWORD2 flushNAVSTATUS KEYWORD2 @@ -219,6 +221,7 @@ getDOP KEYWORD2 setAutoDOP KEYWORD2 setAutoDOPrate KEYWORD2 setAutoDOPcallback KEYWORD2 +setAutoDOPcallbackPtr KEYWORD2 assumeAutoDOP KEYWORD2 initPacketUBXNAVDOP KEYWORD2 flushDOP KEYWORD2 @@ -229,6 +232,7 @@ getNAVATT KEYWORD2 setAutoNAVATT KEYWORD2 setAutoNAVATTrate KEYWORD2 setAutoNAVATTcallback KEYWORD2 +setAutoNAVATTcallbackPtr KEYWORD2 assumeAutoNAVATT KEYWORD2 initPacketUBXNAVATT KEYWORD2 flushNAVATT KEYWORD2 @@ -238,6 +242,7 @@ getPVT KEYWORD2 setAutoPVT KEYWORD2 setAutoPVTrate KEYWORD2 setAutoPVTcallback KEYWORD2 +setAutoPVTcallbackPtr KEYWORD2 assumeAutoPVT KEYWORD2 initPacketUBXNAVPVT KEYWORD2 flushPVT KEYWORD2 @@ -247,6 +252,7 @@ getNAVODO KEYWORD2 setAutoNAVODO KEYWORD2 setAutoNAVODOrate KEYWORD2 setAutoNAVODOcallback KEYWORD2 +setAutoNAVODOcallbackPtr KEYWORD2 assumeAutoNAVODO KEYWORD2 initPacketUBXNAVODO KEYWORD2 flushNAVODO KEYWORD2 @@ -256,6 +262,7 @@ getNAVVELECEF KEYWORD2 setAutoNAVVELECEF KEYWORD2 setAutoNAVVELECEFrate KEYWORD2 setAutoNAVVELECEFcallback KEYWORD2 +setAutoNAVVELECEFcallbackPtr KEYWORD2 assumeAutoNAVVELECEF KEYWORD2 initPacketUBXNAVVELECEF KEYWORD2 flushNAVVELECEF KEYWORD2 @@ -265,6 +272,7 @@ getNAVVELNED KEYWORD2 setAutoNAVVELNED KEYWORD2 setAutoNAVVELNEDrate KEYWORD2 setAutoNAVVELNEDcallback KEYWORD2 +setAutoNAVVELNEDcallbackPtr KEYWORD2 assumeAutoNAVVELNED KEYWORD2 initPacketUBXNAVVELNED KEYWORD2 flushNAVVELNED KEYWORD2 @@ -274,6 +282,7 @@ getNAVHPPOSECEF KEYWORD2 setAutoNAVHPPOSECEF KEYWORD2 setAutoNAVHPPOSECEFrate KEYWORD2 setAutoNAVHPPOSECEFcallback KEYWORD2 +setAutoNAVHPPOSECEFcallbackPtr KEYWORD2 assumeAutoNAVHPPOSECEF KEYWORD2 initPacketUBXNAVHPPOSECEF KEYWORD2 flushNAVHPPOSECEF KEYWORD2 @@ -283,6 +292,7 @@ getHPPOSLLH KEYWORD2 setAutoHPPOSLLH KEYWORD2 setAutoHPPOSLLHrate KEYWORD2 setAutoHPPOSLLHcallback KEYWORD2 +setAutoHPPOSLLHcallbackPtr KEYWORD2 assumeAutoHPPOSLLH KEYWORD2 initPacketUBXNAVHPPOSLLH KEYWORD2 flushHPPOSLLH KEYWORD2 @@ -293,6 +303,7 @@ setAutoNAVPVAT KEYWORD2 setAutoNAVPVAT KEYWORD2 setAutoNAVPVATrate KEYWORD2 setAutoNAVPVATcallback KEYWORD2 +setAutoNAVPVATcallbackPtr KEYWORD2 assumeAutoNAVPVAT KEYWORD2 flushNAVPVAT KEYWORD2 logNAVPVAT KEYWORD2 @@ -301,6 +312,7 @@ getNAVCLOCK KEYWORD2 setAutoNAVCLOCK KEYWORD2 setAutoNAVCLOCKrate KEYWORD2 setAutoNAVCLOCKcallback KEYWORD2 +setAutoNAVCLOCKcallbackPtr KEYWORD2 assumeAutoNAVCLOCK KEYWORD2 initPacketUBXNAVCLOCK KEYWORD2 flushNAVCLOCK KEYWORD2 @@ -318,6 +330,7 @@ getNAVSAT KEYWORD2 setAutoNAVSAT KEYWORD2 setAutoNAVSATrate KEYWORD2 setAutoNAVSATcallback KEYWORD2 +setAutoNAVSATcallbackPtr KEYWORD2 assumeAutoNAVSAT KEYWORD2 initPacketUBXNAVSAT KEYWORD2 flushNAVSAT KEYWORD2 @@ -327,6 +340,7 @@ getRELPOSNED KEYWORD2 setAutoRELPOSNED KEYWORD2 setAutoRELPOSNEDrate KEYWORD2 setAutoRELPOSNEDcallback KEYWORD2 +setAutoRELPOSNEDcallbackPtr KEYWORD2 assumeAutoRELPOSNED KEYWORD2 initPacketUBXNAVRELPOSNED KEYWORD2 flushNAVRELPOSNED KEYWORD2 @@ -336,15 +350,20 @@ getAOPSTATUS KEYWORD2 setAutoAOPSTATUS KEYWORD2 setAutoAOPSTATUSrate KEYWORD2 setAutoAOPSTATUScallback KEYWORD2 +setAutoAOPSTATUScallbackPtr KEYWORD2 assumeAutoAOPSTATUS KEYWORD2 initPacketUBXAOPSTATUS KEYWORD2 flushAOPSTATUS KEYWORD2 logAOPSTATUS KEYWORD2 +setAutoRXMPMPcallback KEYWORD2 +setAutoRXMPMPcallbackPtr KEYWORD2 + getRXMSFRBX KEYWORD2 setAutoRXMSFRBX KEYWORD2 setAutoRXMSFRBXrate KEYWORD2 setAutoRXMSFRBXcallback KEYWORD2 +setAutoRXMSFRBXcallbackPtr KEYWORD2 assumeAutoRXMSFRBX KEYWORD2 initPacketUBXRXMSFRBX KEYWORD2 flushRXMSFRBX KEYWORD2 @@ -354,6 +373,7 @@ getRXMRAWX KEYWORD2 setAutoRXMRAWX KEYWORD2 setAutoRXMRAWXrate KEYWORD2 setAutoRXMRAWXcallback KEYWORD2 +setAutoRXMRAWXcallbackPtr KEYWORD2 assumeAutoRXMRAWX KEYWORD2 initPacketUBXRXMRAWX KEYWORD2 flushRXMRAWX KEYWORD2 @@ -363,6 +383,7 @@ getTIMTM2 KEYWORD2 setAutoTIMTM2 KEYWORD2 setAutoTIMTM2rate KEYWORD2 setAutoTIMTM2callback KEYWORD2 +setAutoTIMTM2callbackPtr KEYWORD2 assumeAutoTIMTM2 KEYWORD2 initPacketUBXTIMTM2 KEYWORD2 flushTIMTM2 KEYWORD2 @@ -373,6 +394,7 @@ getESFALG KEYWORD2 setAutoESFALG KEYWORD2 setAutoESFALGrate KEYWORD2 setAutoESFALGcallback KEYWORD2 +setAutoESFALGcallbackPtr KEYWORD2 assumeAutoESFALG KEYWORD2 initPacketUBXESFALG KEYWORD2 flushESFALG KEYWORD2 @@ -383,6 +405,7 @@ getESFSTATUS KEYWORD2 setAutoESFSTATUS KEYWORD2 setAutoESFSTATUSrate KEYWORD2 setAutoESFSTATUScallback KEYWORD2 +setAutoESFSTATUScallbackPtr KEYWORD2 assumeAutoESFSTATUS KEYWORD2 initPacketUBXESFSTATUS KEYWORD2 flushESFSTATUS KEYWORD2 @@ -393,6 +416,7 @@ getESFINS KEYWORD2 setAutoESFINS KEYWORD2 setAutoESFINSrate KEYWORD2 setAutoESFINScallback KEYWORD2 +setAutoESFINScallbackPtr KEYWORD2 assumeAutoESFINS KEYWORD2 initPacketUBXESFINS KEYWORD2 flushESFINS KEYWORD2 @@ -403,6 +427,7 @@ getESFMEAS KEYWORD2 setAutoESFMEAS KEYWORD2 setAutoESFMEASrate KEYWORD2 setAutoESFMEAScallback KEYWORD2 +setAutoESFMEAScallbackPtr KEYWORD2 assumeAutoESFMEAS KEYWORD2 initPacketUBXESFMEAS KEYWORD2 flushESFMEAS KEYWORD2 @@ -413,6 +438,7 @@ getESFRAW KEYWORD2 setAutoESFRAW KEYWORD2 setAutoESFRAWrate KEYWORD2 setAutoESFRAWcallback KEYWORD2 +setAutoESFRAWcallbackPtr KEYWORD2 assumeAutoESFRAW KEYWORD2 initPacketUBXESFRAW KEYWORD2 flushESFRAW KEYWORD2 @@ -423,6 +449,7 @@ getHNRATT KEYWORD2 setAutoHNRATT KEYWORD2 setAutoHNRATTrate KEYWORD2 setAutoHNRATTcallback KEYWORD2 +setAutoHNRATTcallbackPtr KEYWORD2 assumeAutoHNRATT KEYWORD2 initPacketUBXHNRATT KEYWORD2 flushHNRATT KEYWORD2 @@ -433,6 +460,7 @@ getHNRINS KEYWORD2 setAutoHNRINS KEYWORD2 setAutoHNRINSrate KEYWORD2 setAutoHNRINScallback KEYWORD2 +setAutoHNRINScallbackPtr KEYWORD2 assumeAutoHNRINS KEYWORD2 initPacketUBXHNRINS KEYWORD2 flushHNRINS KEYWORD2 @@ -442,6 +470,7 @@ getHNRPVT KEYWORD2 setAutoHNRPVT KEYWORD2 setAutoHNRPVTrate KEYWORD2 setAutoHNRPVTcallback KEYWORD2 +setAutoHNRPVTcallbackPtr KEYWORD2 assumeAutoHNRPVT KEYWORD2 initPacketUBXHNRPVT KEYWORD2 flushHNRPVT KEYWORD2 @@ -565,8 +594,10 @@ setHighPrecisionMode KEYWORD2 getLatestNMEAGPGGA KEYWORD2 setNMEAGPGGAcallback KEYWORD2 +setNMEAGPGGAcallbackPtr KEYWORD2 getLatestNMEAGNGGA KEYWORD2 setNMEAGNGGAcallback KEYWORD2 +setNMEAGNGGAcallbackPtr KEYWORD2 extractLong KEYWORD2 extractSignedLong KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index c80a9ca..a1fce79 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -306,10 +306,6 @@ void SFE_UBLOX_GNSS::end(void) if (packetUBXCFGRATE != NULL) { - if (packetUBXCFGRATE->callbackData != NULL) - { - delete packetUBXCFGRATE->callbackData; - } delete packetUBXCFGRATE; packetUBXCFGRATE = NULL; // Redundant? } @@ -4508,7 +4504,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV STATUS")); packetUBXNAVSTATUS->callbackPointer(*packetUBXNAVSTATUS->callbackData); // Call the callback } - else if (packetUBXNAVSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV STATUS")); @@ -4527,7 +4523,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV DOP")); packetUBXNAVDOP->callbackPointer(*packetUBXNAVDOP->callbackData); // Call the callback } - else if (packetUBXNAVDOP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVDOP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV DOP")); @@ -4546,7 +4542,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV ATT")); packetUBXNAVATT->callbackPointer(*packetUBXNAVATT->callbackData); // Call the callback } - else if (packetUBXNAVATT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVATT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV ATT")); @@ -4565,7 +4561,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV PVT")); packetUBXNAVPVT->callbackPointer(*packetUBXNAVPVT->callbackData); // Call the callback } - else if (packetUBXNAVPVT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVPVT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV PVT")); @@ -4584,7 +4580,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV ODO")); packetUBXNAVODO->callbackPointer(*packetUBXNAVODO->callbackData); // Call the callback } - else if (packetUBXNAVODO->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVODO->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV ODO")); @@ -4603,7 +4599,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV VELECEF")); packetUBXNAVVELECEF->callbackPointer(*packetUBXNAVVELECEF->callbackData); // Call the callback } - else if (packetUBXNAVVELECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVVELECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV VELECEF")); @@ -4622,7 +4618,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV VELNED")); packetUBXNAVVELNED->callbackPointer(*packetUBXNAVVELNED->callbackData); // Call the callback } - else if (packetUBXNAVVELNED->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVVELNED->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV VELNED")); @@ -4641,7 +4637,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV HPPOSECEF")); packetUBXNAVHPPOSECEF->callbackPointer(*packetUBXNAVHPPOSECEF->callbackData); // Call the callback } - else if (packetUBXNAVHPPOSECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVHPPOSECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV HPPOSECEF")); @@ -4660,7 +4656,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV HPPOSLLH")); packetUBXNAVHPPOSLLH->callbackPointer(*packetUBXNAVHPPOSLLH->callbackData); // Call the callback } - else if (packetUBXNAVHPPOSLLH->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVHPPOSLLH->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV HPPOSLLH")); @@ -4679,7 +4675,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV PVAT")); packetUBXNAVPVAT->callbackPointer(*packetUBXNAVPVAT->callbackData); // Call the callback } - else if (packetUBXNAVPVAT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVPVAT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV PVAT")); @@ -4698,7 +4694,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV CLOCK")); packetUBXNAVCLOCK->callbackPointer(*packetUBXNAVCLOCK->callbackData); // Call the callback } - else if (packetUBXNAVCLOCK->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVCLOCK->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV CLOCK")); @@ -4717,7 +4713,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV SAT")); packetUBXNAVSAT->callbackPointer(*packetUBXNAVSAT->callbackData); // Call the callback } - else if (packetUBXNAVSAT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVSAT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV SAT")); @@ -4736,7 +4732,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV RELPOSNED")); packetUBXNAVRELPOSNED->callbackPointer(*packetUBXNAVRELPOSNED->callbackData); // Call the callback } - else if (packetUBXNAVRELPOSNED->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVRELPOSNED->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV RELPOSNED")); @@ -4755,7 +4751,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV AOPSTATUS")); packetUBXNAVAOPSTATUS->callbackPointer(*packetUBXNAVAOPSTATUS->callbackData); // Call the callback } - else if (packetUBXNAVAOPSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVAOPSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV AOPSTATUS")); @@ -4774,7 +4770,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for RXM PMP")); packetUBXRXMPMP->callbackPointer(*packetUBXRXMPMP->callbackData); // Call the callback } - else if (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM PMP")); @@ -4793,7 +4789,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for RXM SFRBX")); packetUBXRXMSFRBX->callbackPointer(*packetUBXRXMSFRBX->callbackData); // Call the callback } - else if (packetUBXRXMSFRBX->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXRXMSFRBX->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM SFRBX")); @@ -4812,7 +4808,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for RXM RAWX")); packetUBXRXMRAWX->callbackPointer(*packetUBXRXMRAWX->callbackData); // Call the callback } - else if (packetUBXRXMRAWX->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXRXMRAWX->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM RAWX")); @@ -4831,7 +4827,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for TIM TM2")); packetUBXTIMTM2->callbackPointer(*packetUBXTIMTM2->callbackData); // Call the callback } - else if (packetUBXTIMTM2->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXTIMTM2->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for TIM TM2")); @@ -4850,7 +4846,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for ESF ALG")); packetUBXESFALG->callbackPointer(*packetUBXESFALG->callbackData); // Call the callback } - else if (packetUBXESFALG->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXESFALG->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF ALG")); @@ -4869,7 +4865,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for ESF INS")); packetUBXESFINS->callbackPointer(*packetUBXESFINS->callbackData); // Call the callback } - else if (packetUBXESFINS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXESFINS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF INS")); @@ -4888,7 +4884,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for ESF MEAS")); packetUBXESFMEAS->callbackPointer(*packetUBXESFMEAS->callbackData); // Call the callback } - else if (packetUBXESFMEAS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXESFMEAS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF MEAS")); @@ -4907,7 +4903,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for ESF RAW")); packetUBXESFRAW->callbackPointer(*packetUBXESFRAW->callbackData); // Call the callback } - else if (packetUBXESFRAW->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXESFRAW->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF RAW")); @@ -4926,7 +4922,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for ESF STATUS")); packetUBXESFSTATUS->callbackPointer(*packetUBXESFSTATUS->callbackData); // Call the callback } - else if (packetUBXESFSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXESFSTATUS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for ESF STATUS")); @@ -4945,7 +4941,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for HNR ATT")); packetUBXHNRATT->callbackPointer(*packetUBXHNRATT->callbackData); // Call the callback } - else if (packetUBXHNRATT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXHNRATT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for HNR ATT")); @@ -4964,7 +4960,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for HNR INS")); packetUBXHNRINS->callbackPointer(*packetUBXHNRINS->callbackData); // Call the callback } - else if (packetUBXHNRINS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXHNRINS->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for HNR INS")); @@ -4983,7 +4979,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for HNR PVT")); packetUBXHNRPVT->callbackPointer(*packetUBXHNRPVT->callbackData); // Call the callback } - else if (packetUBXHNRPVT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXHNRPVT->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for HNR PVT")); @@ -5002,7 +4998,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for GPGGA")); storageNMEAGPGGA->callbackPointer(*storageNMEAGPGGA->callbackCopy); // Call the callback } - else if (storageNMEAGPGGA->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (storageNMEAGPGGA->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for GPGGA")); @@ -5021,7 +5017,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for GNGGA")); storageNMEAGNGGA->callbackPointer(*storageNMEAGNGGA->callbackCopy); // Call the callback } - else if (storageNMEAGNGGA->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (storageNMEAGNGGA->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for GNGGA")); @@ -8012,6 +8008,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFcallback(void (*callbackPointer)(UBX_NAV_P return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_POSECEF_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVPOSECEF(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVPOSECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVPOSECEF->callbackData = new UBX_NAV_POSECEF_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVPOSECEF->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("setAutoNAVPOSECEFcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVPOSECEF->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and POSECEF is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVPOSECEF(bool enabled, bool implicitUpdate) @@ -8043,6 +8064,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPOSECEF() } packetUBXNAVPOSECEF->automaticFlags.flags.all = 0; packetUBXNAVPOSECEF->callbackPointer = NULL; + packetUBXNAVPOSECEF->callbackPointerPtr = NULL; packetUBXNAVPOSECEF->callbackData = NULL; packetUBXNAVPOSECEF->moduleQueried.moduleQueried.all = 0; return (true); @@ -8173,6 +8195,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVSTATUScallback(void (*callbackPointer)(UBX_NAV_ST return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_STATUS_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVSTATUS(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVSTATUS->callbackData = new UBX_NAV_STATUS_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVSTATUS->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("setAutoNAVSTATUScallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVSTATUS->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and STATUS is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVSTATUS(bool enabled, bool implicitUpdate) @@ -8204,6 +8251,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSTATUS() } packetUBXNAVSTATUS->automaticFlags.flags.all = 0; packetUBXNAVSTATUS->callbackPointer = NULL; + packetUBXNAVSTATUS->callbackPointerPtr = NULL; packetUBXNAVSTATUS->callbackData = NULL; packetUBXNAVSTATUS->moduleQueried.moduleQueried.all = 0; return (true); @@ -8354,6 +8402,31 @@ bool SFE_UBLOX_GNSS::setAutoDOPcallback(void (*callbackPointer)(UBX_NAV_DOP_data return (true); } +bool SFE_UBLOX_GNSS::setAutoDOPcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_DOP_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoDOP(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVDOP->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVDOP->callbackData = new UBX_NAV_DOP_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVDOP->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("setAutoDOPcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVDOP->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and DOP is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoDOP(bool enabled, bool implicitUpdate) @@ -8521,6 +8594,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVATTcallback(void (*callbackPointer)(UBX_NAV_ATT_d return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVATTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ATT_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVATT(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVATT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVATT->callbackData = new UBX_NAV_ATT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVATT->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("setAutoNAVATTcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVATT->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and NAV ATT attitude is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVATT(bool enabled, bool implicitUpdate) @@ -8552,6 +8650,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVATT() } packetUBXNAVATT->automaticFlags.flags.all = 0; packetUBXNAVATT->callbackPointer = NULL; + packetUBXNAVATT->callbackPointerPtr = NULL; packetUBXNAVATT->callbackData = NULL; packetUBXNAVATT->moduleQueried.moduleQueried.all = 0; return (true); @@ -8706,6 +8805,32 @@ bool SFE_UBLOX_GNSS::setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data return (true); } +bool SFE_UBLOX_GNSS::setAutoPVTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVT_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoPVT(true, false, maxWait); + if (!result) + return (result); // Bail if setAutoPVT failed + + if (packetUBXNAVPVT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVPVT->callbackData = new UBX_NAV_PVT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVPVT->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("setAutoPVTcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVPVT->callbackPointerPtr = callbackPointerPtr; // RAM has been allocated so now update the pointer + + return (true); +} + //In case no config access to the GNSS is possible and PVT is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoPVT(bool enabled, bool implicitUpdate) @@ -8737,6 +8862,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPVT() } packetUBXNAVPVT->automaticFlags.flags.all = 0; packetUBXNAVPVT->callbackPointer = NULL; + packetUBXNAVPVT->callbackPointerPtr = NULL; packetUBXNAVPVT->callbackData = NULL; packetUBXNAVPVT->moduleQueried.moduleQueried1.all = 0; packetUBXNAVPVT->moduleQueried.moduleQueried2.all = 0; @@ -8868,6 +8994,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_d return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVODOcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ODO_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVODO(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVODO->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVODO->callbackData = new UBX_NAV_ODO_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVODO->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("setAutoNAVODOcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVODO->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and ODO is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVODO(bool enabled, bool implicitUpdate) @@ -8899,6 +9050,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVODO() } packetUBXNAVODO->automaticFlags.flags.all = 0; packetUBXNAVODO->callbackPointer = NULL; + packetUBXNAVODO->callbackPointerPtr = NULL; packetUBXNAVODO->callbackData = NULL; packetUBXNAVODO->moduleQueried.moduleQueried.all = 0; return (true); @@ -9028,6 +9180,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELECEFcallback(void (*callbackPointer)(UBX_NAV_V return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVVELECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELECEF_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVVELECEF(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVVELECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVVELECEF->callbackData = new UBX_NAV_VELECEF_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVVELECEF->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("setAutoNAVVELECEFcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVVELECEF->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and VELECEF is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVVELECEF(bool enabled, bool implicitUpdate) @@ -9059,6 +9236,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVVELECEF() } packetUBXNAVVELECEF->automaticFlags.flags.all = 0; packetUBXNAVVELECEF->callbackPointer = NULL; + packetUBXNAVVELECEF->callbackPointerPtr = NULL; packetUBXNAVVELECEF->callbackData = NULL; packetUBXNAVVELECEF->moduleQueried.moduleQueried.all = 0; return (true); @@ -9186,6 +9364,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VE return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVVELNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELNED_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVVELNED(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVVELNED->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVVELNED->callbackData = new UBX_NAV_VELNED_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVVELNED->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("setAutoNAVVELNEDcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVVELNED->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and VELNED is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVVELNED(bool enabled, bool implicitUpdate) @@ -9217,6 +9420,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVVELNED() } packetUBXNAVVELNED->automaticFlags.flags.all = 0; packetUBXNAVVELNED->callbackPointer = NULL; + packetUBXNAVVELNED->callbackPointerPtr = NULL; packetUBXNAVVELNED->callbackData = NULL; packetUBXNAVVELNED->moduleQueried.moduleQueried.all = 0; return (true); @@ -9346,6 +9550,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFcallback(void (*callbackPointer)(UBX_NAV return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSECEF_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVHPPOSECEF(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVHPPOSECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVHPPOSECEF->callbackData = new UBX_NAV_HPPOSECEF_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVHPPOSECEF->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("setAutoNAVHPPOSECEFcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVHPPOSECEF->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and HPPOSECEF is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate) @@ -9377,6 +9606,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSECEF() } packetUBXNAVHPPOSECEF->automaticFlags.flags.all = 0; packetUBXNAVHPPOSECEF->callbackPointer = NULL; + packetUBXNAVHPPOSECEF->callbackPointerPtr = NULL; packetUBXNAVHPPOSECEF->callbackData = NULL; packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.all = 0; return (true); @@ -9528,6 +9758,31 @@ bool SFE_UBLOX_GNSS::setAutoHPPOSLLHcallback(void (*callbackPointer)(UBX_NAV_HPP return (true); } +bool SFE_UBLOX_GNSS::setAutoHPPOSLLHcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSLLH_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoHPPOSLLH(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVHPPOSLLH->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVHPPOSLLH->callbackData = new UBX_NAV_HPPOSLLH_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVHPPOSLLH->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("setAutoHPPOSLLHcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVHPPOSLLH->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and HPPOSLLH is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHPPOSLLH(bool enabled, bool implicitUpdate) @@ -9559,6 +9814,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSLLH() } packetUBXNAVHPPOSLLH->automaticFlags.flags.all = 0; packetUBXNAVHPPOSLLH->callbackPointer = NULL; + packetUBXNAVHPPOSLLH->callbackPointerPtr = NULL; packetUBXNAVHPPOSLLH->callbackData = NULL; packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.all = 0; return (true); @@ -9689,6 +9945,32 @@ bool SFE_UBLOX_GNSS::setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVPVATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVAT_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVPVAT(true, false, maxWait); + if (!result) + return (result); // Bail if setAutoPVAT failed + + if (packetUBXNAVPVAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVPVAT->callbackData = new UBX_NAV_PVAT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVPVAT->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("setAutoNAVPVATcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVPVAT->callbackPointerPtr = callbackPointerPtr; // RAM has been allocated so now update the pointer + + return (true); +} + //In case no config access to the GNSS is possible and PVAT is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVPVAT(bool enabled, bool implicitUpdate) @@ -9720,6 +10002,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPVAT() } packetUBXNAVPVAT->automaticFlags.flags.all = 0; packetUBXNAVPVAT->callbackPointer = NULL; + packetUBXNAVPVAT->callbackPointerPtr = NULL; packetUBXNAVPVAT->callbackData = NULL; packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0; packetUBXNAVPVAT->moduleQueried.moduleQueried2.all = 0; @@ -9851,13 +10134,38 @@ bool SFE_UBLOX_GNSS::setAutoNAVCLOCKcallback(void (*callbackPointer)(UBX_NAV_CLO return (true); } -//In case no config access to the GNSS is possible and HNR attitude is send cyclically already -//set config to suitable parameters -bool SFE_UBLOX_GNSS::assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate) +bool SFE_UBLOX_GNSS::setAutoNAVCLOCKcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_CLOCK_data_t *), uint16_t maxWait) { - if (packetUBXNAVCLOCK == NULL) initPacketUBXNAVCLOCK(); //Check that RAM has been allocated for the CLOCK data - if (packetUBXNAVCLOCK == NULL) //Bail if the RAM allocation failed - return (false); + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVCLOCK(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVCLOCK->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVCLOCK->callbackData = new UBX_NAV_CLOCK_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVCLOCK->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("setAutoNAVCLOCKcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVCLOCK->callbackPointerPtr = callbackPointerPtr; + return (true); +} + +//In case no config access to the GNSS is possible and HNR attitude is send cyclically already +//set config to suitable parameters +bool SFE_UBLOX_GNSS::assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate) +{ + if (packetUBXNAVCLOCK == NULL) initPacketUBXNAVCLOCK(); //Check that RAM has been allocated for the CLOCK data + if (packetUBXNAVCLOCK == NULL) //Bail if the RAM allocation failed + return (false); bool changes = packetUBXNAVCLOCK->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVCLOCK->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; if (changes) @@ -9882,6 +10190,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVCLOCK() } packetUBXNAVCLOCK->automaticFlags.flags.all = 0; packetUBXNAVCLOCK->callbackPointer = NULL; + packetUBXNAVCLOCK->callbackPointerPtr = NULL; packetUBXNAVCLOCK->callbackData = NULL; packetUBXNAVCLOCK->moduleQueried.moduleQueried.all = 0; return (true); @@ -9945,6 +10254,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVTIMELS() } packetUBXNAVTIMELS->automaticFlags.flags.all = 0; packetUBXNAVTIMELS->callbackPointer = NULL; + packetUBXNAVTIMELS->callbackPointerPtr = NULL; packetUBXNAVTIMELS->callbackData = NULL; packetUBXNAVTIMELS->moduleQueried.moduleQueried.all = 0; return (true); @@ -9994,6 +10304,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSVIN() } packetUBXNAVSVIN->automaticFlags.flags.all = 0; packetUBXNAVSVIN->callbackPointer = NULL; + packetUBXNAVSVIN->callbackPointerPtr = NULL; packetUBXNAVSVIN->callbackData = NULL; packetUBXNAVSVIN->moduleQueried.moduleQueried.all = 0; return (true); @@ -10111,6 +10422,31 @@ bool SFE_UBLOX_GNSS::setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_d return (true); } +bool SFE_UBLOX_GNSS::setAutoNAVSATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SAT_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVSAT(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVSAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVSAT->callbackData = new UBX_NAV_SAT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVSAT->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("setAutoNAVSATcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVSAT->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and HNR attitude is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVSAT(bool enabled, bool implicitUpdate) @@ -10142,6 +10478,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSAT() } packetUBXNAVSAT->automaticFlags.flags.all = 0; packetUBXNAVSAT->callbackPointer = NULL; + packetUBXNAVSAT->callbackPointerPtr = NULL; packetUBXNAVSAT->callbackData = NULL; packetUBXNAVSAT->moduleQueried = false; return (true); @@ -10276,6 +10613,31 @@ bool SFE_UBLOX_GNSS::setAutoRELPOSNEDcallback(void (*callbackPointer)(UBX_NAV_RE return (true); } +bool SFE_UBLOX_GNSS::setAutoRELPOSNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_RELPOSNED_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoRELPOSNED(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVRELPOSNED->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVRELPOSNED->callbackData = new UBX_NAV_RELPOSNED_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVRELPOSNED->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("setAutoRELPOSNEDcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVRELPOSNED->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and HNR attitude is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoRELPOSNED(bool enabled, bool implicitUpdate) @@ -10307,6 +10669,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVRELPOSNED() } packetUBXNAVRELPOSNED->automaticFlags.flags.all = 0; packetUBXNAVRELPOSNED->callbackPointer = NULL; + packetUBXNAVRELPOSNED->callbackPointerPtr = NULL; packetUBXNAVRELPOSNED->callbackData = NULL; packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.all = 0; return (true); @@ -10456,6 +10819,31 @@ bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AO return (true); } +bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_AOPSTATUS_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoAOPSTATUS(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVAOPSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXNAVAOPSTATUS->callbackData = new UBX_NAV_AOPSTATUS_data_t; //Allocate RAM for the main struct + } + + if (packetUBXNAVAOPSTATUS->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("setAutoAOPSTATUScallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVAOPSTATUS->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and AOPSTATUS is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate) @@ -10487,6 +10875,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVAOPSTATUS() } packetUBXNAVAOPSTATUS->automaticFlags.flags.all = 0; packetUBXNAVAOPSTATUS->callbackPointer = NULL; + packetUBXNAVAOPSTATUS->callbackPointerPtr = NULL; packetUBXNAVAOPSTATUS->callbackData = NULL; packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.all = 0; return (true); @@ -10688,6 +11077,31 @@ bool SFE_UBLOX_GNSS::setAutoRXMSFRBXcallback(void (*callbackPointer)(UBX_RXM_SFR return (true); } +bool SFE_UBLOX_GNSS::setAutoRXMSFRBXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_SFRBX_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoRXMSFRBX(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXRXMSFRBX->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXRXMSFRBX->callbackData = new UBX_RXM_SFRBX_data_t; //Allocate RAM for the main struct + } + + if (packetUBXRXMSFRBX->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("setAutoRXMSFRBXcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXRXMSFRBX->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and SFRBX is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoRXMSFRBX(bool enabled, bool implicitUpdate) @@ -10719,6 +11133,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMSFRBX() } packetUBXRXMSFRBX->automaticFlags.flags.all = 0; packetUBXRXMSFRBX->callbackPointer = NULL; + packetUBXRXMSFRBX->callbackPointerPtr = NULL; packetUBXRXMSFRBX->callbackData = NULL; packetUBXRXMSFRBX->moduleQueried = false; return (true); @@ -10848,6 +11263,31 @@ bool SFE_UBLOX_GNSS::setAutoRXMRAWXcallback(void (*callbackPointer)(UBX_RXM_RAWX return (true); } +bool SFE_UBLOX_GNSS::setAutoRXMRAWXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_RAWX_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoRXMRAWX(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXRXMRAWX->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXRXMRAWX->callbackData = new UBX_RXM_RAWX_data_t; //Allocate RAM for the main struct + } + + if (packetUBXRXMRAWX->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("setAutoRXMRAWXcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXRXMRAWX->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and VELNED is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoRXMRAWX(bool enabled, bool implicitUpdate) @@ -10879,6 +11319,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMRAWX() } packetUBXRXMRAWX->automaticFlags.flags.all = 0; packetUBXRXMRAWX->callbackPointer = NULL; + packetUBXRXMRAWX->callbackPointerPtr = NULL; packetUBXRXMRAWX->callbackData = NULL; packetUBXRXMRAWX->moduleQueried = false; return (true); @@ -10994,8 +11435,6 @@ bool SFE_UBLOX_GNSS::initPacketUBXCFGRATE() return (false); } packetUBXCFGRATE->automaticFlags.flags.all = 0; // Redundant - packetUBXCFGRATE->callbackPointer = NULL; // Redundant - packetUBXCFGRATE->callbackData = NULL; // Redundant packetUBXCFGRATE->moduleQueried.moduleQueried.all = 0; // Mark all data as stale/read return (true); } @@ -11110,6 +11549,31 @@ bool SFE_UBLOX_GNSS::setAutoTIMTM2callback(void (*callbackPointer)(UBX_TIM_TM2_d return (true); } +bool SFE_UBLOX_GNSS::setAutoTIMTM2callbackPtr(void (*callbackPointerPtr)(UBX_TIM_TM2_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoTIMTM2(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXTIMTM2->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXTIMTM2->callbackData = new UBX_TIM_TM2_data_t; //Allocate RAM for the main struct + } + + if (packetUBXTIMTM2->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("setAutoTIMTM2callbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXTIMTM2->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and VELNED is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoTIMTM2(bool enabled, bool implicitUpdate) @@ -11141,6 +11605,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXTIMTM2() } packetUBXTIMTM2->automaticFlags.flags.all = 0; packetUBXTIMTM2->callbackPointer = NULL; + packetUBXTIMTM2->callbackPointerPtr = NULL; packetUBXTIMTM2->callbackData = NULL; packetUBXTIMTM2->moduleQueried.moduleQueried.all = 0; return (true); @@ -11299,6 +11764,31 @@ bool SFE_UBLOX_GNSS::setAutoESFALGcallback(void (*callbackPointer)(UBX_ESF_ALG_d return (true); } +bool SFE_UBLOX_GNSS::setAutoESFALGcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_ALG_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoESFALG(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXESFALG->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXESFALG->callbackData = new UBX_ESF_ALG_data_t; //Allocate RAM for the main struct + } + + if (packetUBXESFALG->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("setAutoESFALGcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXESFALG->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and ESF ALG is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFALG(bool enabled, bool implicitUpdate) @@ -11330,6 +11820,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFALG() } packetUBXESFALG->automaticFlags.flags.all = 0; packetUBXESFALG->callbackPointer = NULL; + packetUBXESFALG->callbackPointerPtr = NULL; packetUBXESFALG->callbackData = NULL; packetUBXESFALG->moduleQueried.moduleQueried.all = 0; return (true); @@ -11488,6 +11979,31 @@ bool SFE_UBLOX_GNSS::setAutoESFSTATUScallback(void (*callbackPointer)(UBX_ESF_ST return (true); } +bool SFE_UBLOX_GNSS::setAutoESFSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_STATUS_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoESFSTATUS(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXESFSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXESFSTATUS->callbackData = new UBX_ESF_STATUS_data_t; //Allocate RAM for the main struct + } + + if (packetUBXESFSTATUS->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("setAutoESFSTATUScallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXESFSTATUS->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and ESF STATUS is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFSTATUS(bool enabled, bool implicitUpdate) @@ -11520,6 +12036,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFSTATUS() } packetUBXESFSTATUS->automaticFlags.flags.all = 0; packetUBXESFSTATUS->callbackPointer = NULL; + packetUBXESFSTATUS->callbackPointerPtr = NULL; packetUBXESFSTATUS->callbackData = NULL; packetUBXESFSTATUS->moduleQueried.moduleQueried.all = 0; return (true); @@ -11678,6 +12195,31 @@ bool SFE_UBLOX_GNSS::setAutoESFINScallback(void (*callbackPointer)(UBX_ESF_INS_d return (true); } +bool SFE_UBLOX_GNSS::setAutoESFINScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_INS_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoESFINS(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXESFINS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXESFINS->callbackData = new UBX_ESF_INS_data_t; //Allocate RAM for the main struct + } + + if (packetUBXESFINS->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("setAutoESFINScallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXESFINS->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and ESF INS is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFINS(bool enabled, bool implicitUpdate) @@ -11709,6 +12251,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFINS() } packetUBXESFINS->automaticFlags.flags.all = 0; packetUBXESFINS->callbackPointer = NULL; + packetUBXESFINS->callbackPointerPtr = NULL; packetUBXESFINS->callbackData = NULL; packetUBXESFINS->moduleQueried.moduleQueried.all = 0; return (true); @@ -11867,6 +12410,31 @@ bool SFE_UBLOX_GNSS::setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS return (true); } +bool SFE_UBLOX_GNSS::setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoESFMEAS(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXESFMEAS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXESFMEAS->callbackData = new UBX_ESF_MEAS_data_t; //Allocate RAM for the main struct + } + + if (packetUBXESFMEAS->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("setAutoESFMEAScallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXESFMEAS->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and ESF MEAS is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFMEAS(bool enabled, bool implicitUpdate) @@ -11898,6 +12466,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFMEAS() } packetUBXESFMEAS->automaticFlags.flags.all = 0; packetUBXESFMEAS->callbackPointer = NULL; + packetUBXESFMEAS->callbackPointerPtr = NULL; packetUBXESFMEAS->callbackData = NULL; packetUBXESFMEAS->moduleQueried.moduleQueried.all = 0; return (true); @@ -12056,6 +12625,31 @@ bool SFE_UBLOX_GNSS::setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_d return (true); } +bool SFE_UBLOX_GNSS::setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoESFRAW(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXESFRAW->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXESFRAW->callbackData = new UBX_ESF_RAW_data_t; //Allocate RAM for the main struct + } + + if (packetUBXESFRAW->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("setAutoESFRAWcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXESFRAW->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and ESF RAW is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFRAW(bool enabled, bool implicitUpdate) @@ -12087,6 +12681,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFRAW() } packetUBXESFRAW->automaticFlags.flags.all = 0; packetUBXESFRAW->callbackPointer = NULL; + packetUBXESFRAW->callbackPointerPtr = NULL; packetUBXESFRAW->callbackData = NULL; packetUBXESFRAW->moduleQueried.moduleQueried.all = 0; return (true); @@ -12250,6 +12845,31 @@ bool SFE_UBLOX_GNSS::setAutoHNRATTcallback(void (*callbackPointer)(UBX_HNR_ATT_d return (true); } +bool SFE_UBLOX_GNSS::setAutoHNRATTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_ATT_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoHNRATT(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXHNRATT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXHNRATT->callbackData = new UBX_HNR_ATT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXHNRATT->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("setAutoHNRAttcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXHNRATT->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and HNR attitude is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHNRATT(bool enabled, bool implicitUpdate) @@ -12281,6 +12901,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRATT() } packetUBXHNRATT->automaticFlags.flags.all = 0; packetUBXHNRATT->callbackPointer = NULL; + packetUBXHNRATT->callbackPointerPtr = NULL; packetUBXHNRATT->callbackData = NULL; packetUBXHNRATT->moduleQueried.moduleQueried.all = 0; return (true); @@ -12445,6 +13066,31 @@ bool SFE_UBLOX_GNSS::setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_d return (true); } +bool SFE_UBLOX_GNSS::setAutoHNRINScallbackPtr(void (*callbackPointerPtr)(UBX_HNR_INS_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoHNRINS(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXHNRINS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXHNRINS->callbackData = new UBX_HNR_INS_data_t; //Allocate RAM for the main struct + } + + if (packetUBXHNRINS->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("setAutoHNRDyncallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXHNRINS->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and HNR vehicle dynamics is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHNRINS(bool enabled, bool implicitUpdate) @@ -12476,6 +13122,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRINS() } packetUBXHNRINS->automaticFlags.flags.all = 0; packetUBXHNRINS->callbackPointer = NULL; + packetUBXHNRINS->callbackPointerPtr = NULL; packetUBXHNRINS->callbackData = NULL; packetUBXHNRINS->moduleQueried.moduleQueried.all = 0; return (true); @@ -12634,6 +13281,31 @@ bool SFE_UBLOX_GNSS::setAutoHNRPVTcallback(void (*callbackPointer)(UBX_HNR_PVT_d return (true); } +bool SFE_UBLOX_GNSS::setAutoHNRPVTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_PVT_data_t *), uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoHNRPVT(true, false, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXHNRPVT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + { + packetUBXHNRPVT->callbackData = new UBX_HNR_PVT_data_t; //Allocate RAM for the main struct + } + + if (packetUBXHNRPVT->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("setAutoHNRPVTcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXHNRPVT->callbackPointerPtr = callbackPointerPtr; + return (true); +} + //In case no config access to the GNSS is possible and HNR PVT is send cyclically already //set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHNRPVT(bool enabled, bool implicitUpdate) @@ -12665,6 +13337,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRPVT() } packetUBXHNRPVT->automaticFlags.flags.all = 0; packetUBXHNRPVT->callbackPointer = NULL; + packetUBXHNRPVT->callbackPointerPtr = NULL; packetUBXHNRPVT->callbackData = NULL; packetUBXHNRPVT->moduleQueried.moduleQueried.all = 0; return (true); @@ -12810,6 +13483,30 @@ bool SFE_UBLOX_GNSS::setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_ return (true); } +bool SFE_UBLOX_GNSS::setNMEAGPGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)) +{ + if (storageNMEAGPGGA == NULL) initStorageNMEAGPGGA(); //Check that RAM has been allocated for the message + if (storageNMEAGPGGA == NULL) //Bail if the RAM allocation failed + return (false); + + if (storageNMEAGPGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy + { + storageNMEAGPGGA->callbackCopy = new NMEA_GGA_data_t; + } + + if (storageNMEAGPGGA->callbackCopy == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setNMEAGPGGAcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + storageNMEAGPGGA->callbackPointerPtr = callbackPointerPtr; + return (true); +} + // Private: allocate RAM for incoming NMEA GPGGA messages and initialize it bool SFE_UBLOX_GNSS::initStorageNMEAGPGGA() { @@ -12829,6 +13526,7 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGPGGA() memset(storageNMEAGPGGA->completeCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage storageNMEAGPGGA->callbackPointer = NULL; // Clear the callback pointers + storageNMEAGPGGA->callbackPointerPtr = NULL; // Clear the callback pointers storageNMEAGPGGA->callbackCopy = NULL; storageNMEAGPGGA->automaticFlags.flags.all = 0; // Mark the data as invalid/stale and unread @@ -12884,6 +13582,30 @@ bool SFE_UBLOX_GNSS::setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_ return (true); } +bool SFE_UBLOX_GNSS::setNMEAGNGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)) +{ + if (storageNMEAGNGGA == NULL) initStorageNMEAGNGGA(); //Check that RAM has been allocated for the message + if (storageNMEAGNGGA == NULL) //Bail if the RAM allocation failed + return (false); + + if (storageNMEAGNGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy + { + storageNMEAGNGGA->callbackCopy = new NMEA_GGA_data_t; + } + + if (storageNMEAGNGGA->callbackCopy == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("setNMEAGNGGAcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + storageNMEAGNGGA->callbackPointerPtr = callbackPointerPtr; + return (true); +} + // Private: allocate RAM for incoming NMEA GNGGA messages and initialize it bool SFE_UBLOX_GNSS::initStorageNMEAGNGGA() { @@ -12903,6 +13625,7 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGNGGA() memset(storageNMEAGNGGA->completeCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage storageNMEAGNGGA->callbackPointer = NULL; // Clear the callback pointers + storageNMEAGNGGA->callbackPointerPtr = NULL; // Clear the callback pointers storageNMEAGNGGA->callbackCopy = NULL; storageNMEAGNGGA->automaticFlags.flags.all = 0; // Mark the data as invalid/stale and unread diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 6ba5b06..cf0f4aa 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1387,8 +1387,10 @@ class SFE_UBLOX_GNSS // Support for "auto" storage of NMEA messages uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message + bool setNMEAGPGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)); //Enable a callback on the arrival of a GPGGA message uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GNGGA message + bool setNMEAGNGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)); //Enable a callback on the arrival of a GNGGA message // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket // From v2.0: These are public. The user can call these to extract data from custom packets diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index d5a7b10..d20be08 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1608,9 +1608,6 @@ typedef struct ubxAutomaticFlags automaticFlags; UBX_CFG_RATE_data_t data; UBX_CFG_RATE_moduleQueried_t moduleQueried; - void (*callbackPointer)(UBX_CFG_RATE_data_t); - void (*callbackPointerPtr)(UBX_CFG_RATE_data_t *); - UBX_CFG_RATE_data_t *callbackData; } UBX_CFG_RATE_t; // UBX-CFG-TP5 (0x06 0x31): Time pulse parameters From 1ada3d33803baee00b2e0d7d7ef30ce58cd26981 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sat, 5 Feb 2022 17:52:17 +0000 Subject: [PATCH 097/122] Update callback examples to use new callback pointers --- .../CallbackExample1_NAV_PVT.ino | 18 ++++---- .../CallbackExample2_NAV_ODO.ino | 10 ++-- .../CallbackExample3_TIM_TM2.ino | 18 ++++---- .../CallbackExample4_HNR.ino | 30 ++++++------ .../CallbackExample5_ESF.ino | 46 +++++++++---------- .../CallbackExample6_RAWX.ino | 24 +++++----- .../CallbackExample7_NAV_SAT.ino | 20 ++++---- 7 files changed, 83 insertions(+), 83 deletions(-) diff --git a/examples/Callbacks/CallbackExample1_NAV_PVT/CallbackExample1_NAV_PVT.ino b/examples/Callbacks/CallbackExample1_NAV_PVT/CallbackExample1_NAV_PVT.ino index 4b1afba..ff2b740 100644 --- a/examples/Callbacks/CallbackExample1_NAV_PVT/CallbackExample1_NAV_PVT.ino +++ b/examples/Callbacks/CallbackExample1_NAV_PVT/CallbackExample1_NAV_PVT.ino @@ -33,38 +33,38 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) +void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("Time: ")); // Print the time - uint8_t hms = ubxDataStruct.hour; // Print the hours + uint8_t hms = ubxDataStruct->hour; // Print the hours if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(":")); - hms = ubxDataStruct.min; // Print the minutes + hms = ubxDataStruct->min; // Print the minutes if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(":")); - hms = ubxDataStruct.sec; // Print the seconds + hms = ubxDataStruct->sec; // Print the seconds if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(".")); - unsigned long millisecs = ubxDataStruct.iTOW % 1000; // Print the milliseconds + unsigned long millisecs = ubxDataStruct->iTOW % 1000; // Print the milliseconds if (millisecs < 100) Serial.print(F("0")); // Print the trailing zeros correctly if (millisecs < 10) Serial.print(F("0")); Serial.print(millisecs); - long latitude = ubxDataStruct.lat; // Print the latitude + long latitude = ubxDataStruct->lat; // Print the latitude Serial.print(F(" Lat: ")); Serial.print(latitude); - long longitude = ubxDataStruct.lon; // Print the longitude + long longitude = ubxDataStruct->lon; // Print the longitude Serial.print(F(" Long: ")); Serial.print(longitude); Serial.print(F(" (degrees * 10^-7)")); - long altitude = ubxDataStruct.hMSL; // Print the height above mean sea level + long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level Serial.print(F(" Height above MSL: ")); Serial.print(altitude); Serial.println(F(" (mm)")); @@ -91,7 +91,7 @@ void setup() myGNSS.setNavigationFrequency(2); //Produce two solutions per second - myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata + myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata } void loop() diff --git a/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino b/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino index 3e1008c..181824b 100644 --- a/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino +++ b/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino @@ -33,22 +33,22 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printODOdata(UBX_NAV_ODO_data_t ubxDataStruct) +void printODOdata(UBX_NAV_ODO_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("TOW: ")); // Print the Time Of Week - unsigned long iTOW = ubxDataStruct.iTOW; // iTOW is in milliseconds + unsigned long iTOW = ubxDataStruct->iTOW; // iTOW is in milliseconds Serial.print(iTOW); Serial.print(F(" (ms)")); Serial.print(F(" Distance: ")); - unsigned long distance = ubxDataStruct.distance; // Print the distance + unsigned long distance = ubxDataStruct->distance; // Print the distance Serial.print(distance); Serial.print(F(" (m)")); Serial.print(F(" Total Distance: ")); - unsigned long totalDistance = ubxDataStruct.totalDistance; // Print the total distance + unsigned long totalDistance = ubxDataStruct->totalDistance; // Print the total distance Serial.print(totalDistance); Serial.println(F(" (m)")); } @@ -76,7 +76,7 @@ void setup() //myGNSS.resetOdometer(); //Uncomment this line to reset the odometer - myGNSS.setAutoNAVODOcallback(&printODOdata); // Enable automatic NAV ODO messages with callback to printODOdata + myGNSS.setAutoNAVODOcallbackPtr(&printODOdata); // Enable automatic NAV ODO messages with callback to printODOdata } void loop() diff --git a/examples/Callbacks/CallbackExample3_TIM_TM2/CallbackExample3_TIM_TM2.ino b/examples/Callbacks/CallbackExample3_TIM_TM2/CallbackExample3_TIM_TM2.ino index 3737bec..4f3a686 100644 --- a/examples/Callbacks/CallbackExample3_TIM_TM2/CallbackExample3_TIM_TM2.ino +++ b/examples/Callbacks/CallbackExample3_TIM_TM2/CallbackExample3_TIM_TM2.ino @@ -48,30 +48,30 @@ int dotsPrinted = 0; // Print dots in rows of 50 while waiting for a TIM TM2 mes // | / _____ You can use any name you like for the struct // | | / // | | | -void printTIMTM2data(UBX_TIM_TM2_data_t ubxDataStruct) +void printTIMTM2data(UBX_TIM_TM2_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("newFallingEdge: ")); // 1 if a new falling edge was detected - Serial.print(ubxDataStruct.flags.bits.newFallingEdge); + Serial.print(ubxDataStruct->flags.bits.newFallingEdge); Serial.print(F(" newRisingEdge: ")); // 1 if a new rising edge was detected - Serial.print(ubxDataStruct.flags.bits.newRisingEdge); + Serial.print(ubxDataStruct->flags.bits.newRisingEdge); Serial.print(F(" Rising Edge Counter: ")); // Rising edge counter - Serial.print(ubxDataStruct.count); + Serial.print(ubxDataStruct->count); Serial.print(F(" towMsR: ")); // Time Of Week of rising edge (ms) - Serial.print(ubxDataStruct.towMsR); + Serial.print(ubxDataStruct->towMsR); Serial.print(F(" towSubMsR: ")); // Millisecond fraction of Time Of Week of rising edge in nanoseconds - Serial.print(ubxDataStruct.towSubMsR); + Serial.print(ubxDataStruct->towSubMsR); Serial.print(F(" towMsF: ")); // Time Of Week of falling edge (ms) - Serial.print(ubxDataStruct.towMsF); + Serial.print(ubxDataStruct->towMsF); Serial.print(F(" towSubMsF: ")); // Millisecond fraction of Time Of Week of falling edge in nanoseconds - Serial.println(ubxDataStruct.towSubMsF); + Serial.println(ubxDataStruct->towSubMsF); dotsPrinted = 0; // Reset dotsPrinted } @@ -97,7 +97,7 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one solution per second - myGNSS.setAutoTIMTM2callback(&printTIMTM2data); // Enable automatic TIM TM2 messages with callback to printTIMTM2data + myGNSS.setAutoTIMTM2callbackPtr(&printTIMTM2data); // Enable automatic TIM TM2 messages with callback to printTIMTM2data } void loop() diff --git a/examples/Callbacks/CallbackExample4_HNR/CallbackExample4_HNR.ino b/examples/Callbacks/CallbackExample4_HNR/CallbackExample4_HNR.ino index 7c86fa8..9fd1611 100644 --- a/examples/Callbacks/CallbackExample4_HNR/CallbackExample4_HNR.ino +++ b/examples/Callbacks/CallbackExample4_HNR/CallbackExample4_HNR.ino @@ -38,39 +38,39 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printHNRATTdata(UBX_HNR_ATT_data_t ubxDataStruct) +void printHNRATTdata(UBX_HNR_ATT_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("Roll: ")); // Print selected data - Serial.print((float)ubxDataStruct.roll / 100000.0, 2); // Convert roll to degrees + Serial.print((float)ubxDataStruct->roll / 100000.0, 2); // Convert roll to degrees Serial.print(F(" Pitch: ")); - Serial.print((float)ubxDataStruct.pitch / 100000.0, 2); // Convert pitch to degrees + Serial.print((float)ubxDataStruct->pitch / 100000.0, 2); // Convert pitch to degrees Serial.print(F(" Heading: ")); - Serial.println((float)ubxDataStruct.heading / 100000.0, 2); // Convert heading to degrees + Serial.println((float)ubxDataStruct->heading / 100000.0, 2); // Convert heading to degrees } // Callback: printHNRINSdata will be called when new HNR INS data arrives // See u-blox_structs.h for the full definition of UBX_HNR_INS_data_t -void printHNRINSdata(UBX_HNR_INS_data_t ubxDataStruct) +void printHNRINSdata(UBX_HNR_INS_data_t *ubxDataStruct) { Serial.print(F("xAccel: ")); // Print selected data - Serial.print(ubxDataStruct.xAccel); + Serial.print(ubxDataStruct->xAccel); Serial.print(F(" yAccel: ")); - Serial.print(ubxDataStruct.yAccel); + Serial.print(ubxDataStruct->yAccel); Serial.print(F(" zAccel: ")); - Serial.println(ubxDataStruct.zAccel); + Serial.println(ubxDataStruct->zAccel); } // Callback: printHNRPVTdata will be called when new HNR PVT data arrives // See u-blox_structs.h for the full definition of UBX_HNR_PVT_data_t -void printHNRPVTdata(UBX_HNR_PVT_data_t ubxDataStruct) +void printHNRPVTdata(UBX_HNR_PVT_data_t *ubxDataStruct) { Serial.print(F("ns: ")); // Print selected data - Serial.print(ubxDataStruct.nano); + Serial.print(ubxDataStruct->nano); Serial.print(F(" Lat: ")); - Serial.print(ubxDataStruct.lat); + Serial.print(ubxDataStruct->lat); Serial.print(F(" Lon: ")); - Serial.println(ubxDataStruct.lon); + Serial.println(ubxDataStruct->lon); } void setup() @@ -97,13 +97,13 @@ void setup() else Serial.println(F("setHNRNavigationRate was NOT successful")); - if (myGNSS.setAutoHNRATTcallback(&printHNRATTdata) == true) // Enable automatic HNR ATT messages with callback to printHNRATTdata + if (myGNSS.setAutoHNRATTcallbackPtr(&printHNRATTdata) == true) // Enable automatic HNR ATT messages with callback to printHNRATTdata Serial.println(F("setAutoHNRATTcallback successful")); - if (myGNSS.setAutoHNRINScallback(&printHNRINSdata) == true) // Enable automatic HNR INS messages with callback to printHNRINSdata + if (myGNSS.setAutoHNRINScallbackPtr(&printHNRINSdata) == true) // Enable automatic HNR INS messages with callback to printHNRINSdata Serial.println(F("setAutoHNRINScallback successful")); - if (myGNSS.setAutoHNRPVTcallback(&printHNRPVTdata) == true) // Enable automatic HNR PVT messages with callback to printHNRPVTdata + if (myGNSS.setAutoHNRPVTcallbackPtr(&printHNRPVTdata) == true) // Enable automatic HNR PVT messages with callback to printHNRPVTdata Serial.println(F("setAutoHNRPVTcallback successful")); } diff --git a/examples/Callbacks/CallbackExample5_ESF/CallbackExample5_ESF.ino b/examples/Callbacks/CallbackExample5_ESF/CallbackExample5_ESF.ino index bd5a7d6..6b1ebe6 100644 --- a/examples/Callbacks/CallbackExample5_ESF/CallbackExample5_ESF.ino +++ b/examples/Callbacks/CallbackExample5_ESF/CallbackExample5_ESF.ino @@ -35,39 +35,39 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printESFALGdata(UBX_ESF_ALG_data_t ubxDataStruct) +void printESFALGdata(UBX_ESF_ALG_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("TOW: ")); // Print the Time Of Week - unsigned long iTOW = ubxDataStruct.iTOW; // iTOW is in milliseconds + unsigned long iTOW = ubxDataStruct->iTOW; // iTOW is in milliseconds Serial.print(iTOW); Serial.print(F(" (ms)")); Serial.print(F(" Roll: ")); // Print selected data - Serial.print((float)ubxDataStruct.roll / 100.0, 2); // Convert roll to degrees + Serial.print((float)ubxDataStruct->roll / 100.0, 2); // Convert roll to degrees Serial.print(F(" Pitch: ")); - Serial.print((float)ubxDataStruct.pitch / 100.0, 2); // Convert pitch to degrees + Serial.print((float)ubxDataStruct->pitch / 100.0, 2); // Convert pitch to degrees Serial.print(F(" Yaw: ")); - Serial.print((float)ubxDataStruct.yaw / 100.0, 2); // Convert yaw to degrees + Serial.print((float)ubxDataStruct->yaw / 100.0, 2); // Convert yaw to degrees Serial.println(F(" (Degrees)")); } // Callback: printESFINSdata will be called when new ESF INS data arrives // See u-blox_structs.h for the full definition of UBX_ESF_INS_data_t -void printESFINSdata(UBX_ESF_INS_data_t ubxDataStruct) +void printESFINSdata(UBX_ESF_INS_data_t *ubxDataStruct) { Serial.print(F("xAccel: ")); // Print selected data - Serial.print(ubxDataStruct.xAccel); + Serial.print(ubxDataStruct->xAccel); Serial.print(F(" yAccel: ")); - Serial.print(ubxDataStruct.yAccel); + Serial.print(ubxDataStruct->yAccel); Serial.print(F(" zAccel: ")); - Serial.print(ubxDataStruct.zAccel); + Serial.print(ubxDataStruct->zAccel); Serial.println(F(" (m/s^2)")); } @@ -75,23 +75,23 @@ void printESFINSdata(UBX_ESF_INS_data_t ubxDataStruct) // Callback: printESFMEASdata will be called when new ESF MEAS data arrives // See u-blox_structs.h for the full definition of UBX_ESF_MEAS_data_t // and UBX_ESF_MEAS_sensorData_t -void printESFMEASdata(UBX_ESF_MEAS_data_t ubxDataStruct) +void printESFMEASdata(UBX_ESF_MEAS_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("id: ")); // Print selected data - Serial.print(ubxDataStruct.id); + Serial.print(ubxDataStruct->id); Serial.print(F(" numMeas: ")); - Serial.println(ubxDataStruct.flags.bits.numMeas); + Serial.println(ubxDataStruct->flags.bits.numMeas); - for (uint8_t num = 0; num < ubxDataStruct.flags.bits.numMeas; num++) // For each sensor + for (uint8_t num = 0; num < ubxDataStruct->flags.bits.numMeas; num++) // For each sensor { Serial.print(F("Sensor ")); Serial.print(num); UBX_ESF_MEAS_sensorData_t sensorData; - myGNSS.getSensorFusionMeasurement(&sensorData, ubxDataStruct, num); // Extract the data for one sensor + myGNSS.getSensorFusionMeasurement(&sensorData, *ubxDataStruct, num); // Extract the data for one sensor Serial.print(F(": Type: ")); Serial.print(sensorData.data.bits.dataType); @@ -103,21 +103,21 @@ void printESFMEASdata(UBX_ESF_MEAS_data_t ubxDataStruct) // Callback: printESFSTATUSdata will be called when new ESF STATUS data arrives // See u-blox_structs.h for the full definition of UBX_ESF_STATUS_data_t // and UBX_ESF_STATUS_sensorStatus_t -void printESFSTATUSdata(UBX_ESF_STATUS_data_t ubxDataStruct) +void printESFSTATUSdata(UBX_ESF_STATUS_data_t *ubxDataStruct) { Serial.print(F("fusionMode: ")); // Print selected data - Serial.print(ubxDataStruct.fusionMode); + Serial.print(ubxDataStruct->fusionMode); Serial.print(F(" numSens: ")); - Serial.println(ubxDataStruct.numSens); + Serial.println(ubxDataStruct->numSens); - for (uint8_t num = 0; num < ubxDataStruct.numSens; num++) // For each sensor + for (uint8_t num = 0; num < ubxDataStruct->numSens; num++) // For each sensor { Serial.print(F("Sensor ")); Serial.print(num); UBX_ESF_STATUS_sensorStatus_t sensorStatus; - myGNSS.getSensorFusionStatus(&sensorStatus, ubxDataStruct, num); // Extract the data for one sensor + myGNSS.getSensorFusionStatus(&sensorStatus, *ubxDataStruct, num); // Extract the data for one sensor Serial.print(F(": Type: ")); Serial.print(sensorStatus.sensStatus1.bits.type); @@ -156,16 +156,16 @@ void setup() myGNSS.setI2CpollingWait(50); //Allow checkUblox to poll I2C data every 50ms to keep up with the ESF MEAS messages - if (myGNSS.setAutoESFALGcallback(&printESFALGdata) == true) // Enable automatic ESF ALG messages with callback to printESFALGdata + if (myGNSS.setAutoESFALGcallbackPtr(&printESFALGdata) == true) // Enable automatic ESF ALG messages with callback to printESFALGdata Serial.println(F("setAutoESFALGcallback successful")); - if (myGNSS.setAutoESFINScallback(&printESFINSdata) == true) // Enable automatic ESF INS messages with callback to printESFINSdata + if (myGNSS.setAutoESFINScallbackPtr(&printESFINSdata) == true) // Enable automatic ESF INS messages with callback to printESFINSdata Serial.println(F("setAutoESFINScallback successful")); - if (myGNSS.setAutoESFMEAScallback(&printESFMEASdata) == true) // Enable automatic ESF MEAS messages with callback to printESFMEASdata + if (myGNSS.setAutoESFMEAScallbackPtr(&printESFMEASdata) == true) // Enable automatic ESF MEAS messages with callback to printESFMEASdata Serial.println(F("setAutoESFMEAScallback successful")); - if (myGNSS.setAutoESFSTATUScallback(&printESFSTATUSdata) == true) // Enable automatic ESF STATUS messages with callback to printESFSTATUSdata + if (myGNSS.setAutoESFSTATUScallbackPtr(&printESFSTATUSdata) == true) // Enable automatic ESF STATUS messages with callback to printESFSTATUSdata Serial.println(F("setAutoESFSTATUScallback successful")); } diff --git a/examples/Callbacks/CallbackExample6_RAWX/CallbackExample6_RAWX.ino b/examples/Callbacks/CallbackExample6_RAWX/CallbackExample6_RAWX.ino index 2461ccc..7d5180e 100644 --- a/examples/Callbacks/CallbackExample6_RAWX/CallbackExample6_RAWX.ino +++ b/examples/Callbacks/CallbackExample6_RAWX/CallbackExample6_RAWX.ino @@ -31,38 +31,38 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void newRAWX(UBX_RXM_RAWX_data_t ubxDataStruct) +void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("New RAWX data received. It contains ")); - Serial.print(ubxDataStruct.header.numMeas); // Print numMeas (Number of measurements / blocks) + Serial.print(ubxDataStruct->header.numMeas); // Print numMeas (Number of measurements / blocks) Serial.println(F(" data blocks:")); - for (uint8_t block = 0; block < ubxDataStruct.header.numMeas; block++) // For each block + for (uint8_t block = 0; block < ubxDataStruct->header.numMeas; block++) // For each block { Serial.print(F("GNSS ID: ")); - if (ubxDataStruct.blocks[block].gnssId < 100) Serial.print(F(" ")); // Align the gnssId - if (ubxDataStruct.blocks[block].gnssId < 10) Serial.print(F(" ")); // Align the gnssId - Serial.print(ubxDataStruct.blocks[block].gnssId); + if (ubxDataStruct->blocks[block].gnssId < 100) Serial.print(F(" ")); // Align the gnssId + if (ubxDataStruct->blocks[block].gnssId < 10) Serial.print(F(" ")); // Align the gnssId + Serial.print(ubxDataStruct->blocks[block].gnssId); Serial.print(F(" SV ID: ")); - if (ubxDataStruct.blocks[block].svId < 100) Serial.print(F(" ")); // Align the svId - if (ubxDataStruct.blocks[block].svId < 10) Serial.print(F(" ")); // Align the svId - Serial.print(ubxDataStruct.blocks[block].svId); + if (ubxDataStruct->blocks[block].svId < 100) Serial.print(F(" ")); // Align the svId + if (ubxDataStruct->blocks[block].svId < 10) Serial.print(F(" ")); // Align the svId + Serial.print(ubxDataStruct->blocks[block].svId); if (sizeof(double) == 8) // Check if our processor supports 64-bit double { // Convert prMes from uint8_t[8] to 64-bit double // prMes is little-endian double pseudorange; - memcpy(&pseudorange, &ubxDataStruct.blocks[block].prMes, 8); + memcpy(&pseudorange, &ubxDataStruct->blocks[block].prMes, 8); Serial.print(F(" PR: ")); Serial.print(pseudorange, 3); // Convert cpMes from uint8_t[8] to 64-bit double // cpMes is little-endian double carrierPhase; - memcpy(&carrierPhase, &ubxDataStruct.blocks[block].cpMes, 8); + memcpy(&carrierPhase, &ubxDataStruct->blocks[block].cpMes, 8); Serial.print(F(" m CP: ")); Serial.print(carrierPhase, 3); Serial.print(F(" cycles")); @@ -94,7 +94,7 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one solution per second (RAWX produces a _lot_ of data!) - myGNSS.setAutoRXMRAWXcallback(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX + myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX } void loop() diff --git a/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino b/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino index 2612e47..b712126 100644 --- a/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino +++ b/examples/Callbacks/CallbackExample7_NAV_SAT/CallbackExample7_NAV_SAT.ino @@ -31,21 +31,21 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void newNAVSAT(UBX_NAV_SAT_data_t ubxDataStruct) +void newNAVSAT(UBX_NAV_SAT_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("New NAV SAT data received. It contains data for ")); - Serial.print(ubxDataStruct.header.numSvs); - if (ubxDataStruct.header.numSvs == 1) + Serial.print(ubxDataStruct->header.numSvs); + if (ubxDataStruct->header.numSvs == 1) Serial.println(F(" SV.")); else Serial.println(F(" SVs.")); // Just for giggles, print the signal strength for each SV as a barchart - for (uint16_t block = 0; block < ubxDataStruct.header.numSvs; block++) // For each SV + for (uint16_t block = 0; block < ubxDataStruct->header.numSvs; block++) // For each SV { - switch (ubxDataStruct.blocks[block].gnssId) // Print the GNSS ID + switch (ubxDataStruct->blocks[block].gnssId) // Print the GNSS ID { case 0: Serial.print(F("GPS ")); @@ -73,14 +73,14 @@ void newNAVSAT(UBX_NAV_SAT_data_t ubxDataStruct) break; } - Serial.print(ubxDataStruct.blocks[block].svId); // Print the SV ID + Serial.print(ubxDataStruct->blocks[block].svId); // Print the SV ID - if (ubxDataStruct.blocks[block].svId < 10) Serial.print(F(" ")); - else if (ubxDataStruct.blocks[block].svId < 100) Serial.print(F(" ")); + if (ubxDataStruct->blocks[block].svId < 10) Serial.print(F(" ")); + else if (ubxDataStruct->blocks[block].svId < 100) Serial.print(F(" ")); else Serial.print(F(" ")); // Print the signal strength as a bar chart - for (uint8_t cno = 0; cno < ubxDataStruct.blocks[block].cno; cno++) + for (uint8_t cno = 0; cno < ubxDataStruct->blocks[block].cno; cno++) Serial.print(F("=")); Serial.println(); @@ -108,7 +108,7 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one solution per second - myGNSS.setAutoNAVSATcallback(&newNAVSAT); // Enable automatic NAV SAT messages with callback to newNAVSAT + myGNSS.setAutoNAVSATcallbackPtr(&newNAVSAT); // Enable automatic NAV SAT messages with callback to newNAVSAT } void loop() From 0bf94bebdd8832b873e906e01e6cdeaabee026c4 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sat, 5 Feb 2022 18:00:38 +0000 Subject: [PATCH 098/122] Update Example2_NMEA_GGA_Callbacks.ino --- .../Example2_NMEA_GGA_Callbacks.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino b/examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino index ca6380a..839ee35 100644 --- a/examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino +++ b/examples/Automatic_NMEA/Example2_NMEA_GGA_Callbacks/Example2_NMEA_GGA_Callbacks.ino @@ -39,12 +39,12 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printGPGGA(NMEA_GGA_data_t nmeaData) +void printGPGGA(NMEA_GGA_data_t *nmeaData) { Serial.print(F("\r\nGPGGA: Length: ")); - Serial.print(nmeaData.length); + Serial.print(nmeaData->length); Serial.print(F("\tData: ")); - Serial.print((const char *)nmeaData.nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end + Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end } // Callback: printGNGGA will be called if new GNGGA NMEA data arrives @@ -54,12 +54,12 @@ void printGPGGA(NMEA_GGA_data_t nmeaData) // | / _____ You can use any name you like for the struct // | | / // | | | -void printGNGGA(NMEA_GGA_data_t nmeaData) +void printGNGGA(NMEA_GGA_data_t *nmeaData) { Serial.print(F("\r\nGNGGA: Length: ")); - Serial.print(nmeaData.length); + Serial.print(nmeaData->length); Serial.print(F("\tData: ")); - Serial.print((const char *)nmeaData.nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end + Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end } void setup() @@ -101,10 +101,10 @@ void setup() //myGNSS.setNMEAOutputPort(Serial); // Uncomment this line to echo all NMEA data to Serial for debugging // Set up the callback for GPGGA - myGNSS.setNMEAGPGGAcallback(&printGPGGA); + myGNSS.setNMEAGPGGAcallbackPtr(&printGPGGA); // Set up the callback for GNGGA - myGNSS.setNMEAGNGGAcallback(&printGNGGA); + myGNSS.setNMEAGNGGAcallbackPtr(&printGNGGA); } void loop() From 5a4ac25f55d5d2a30acf5c28866aef26492dcf49 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 6 Feb 2022 10:13:53 +0000 Subject: [PATCH 099/122] Update data logging examples 1-3 to use the new callback pointers --- .../DataLoggingExample1_NAV_PVT.ino | 29 +++++++++---------- .../DataLoggingExample2_TIM_TM2.ino | 29 +++++++++---------- ...DataLoggingExample3_RXM_SFRBX_and_RAWX.ino | 29 +++++++++---------- 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/examples/Data_Logging/DataLoggingExample1_NAV_PVT/DataLoggingExample1_NAV_PVT.ino b/examples/Data_Logging/DataLoggingExample1_NAV_PVT/DataLoggingExample1_NAV_PVT.ino index e214c42..93072a2 100644 --- a/examples/Data_Logging/DataLoggingExample1_NAV_PVT/DataLoggingExample1_NAV_PVT.ino +++ b/examples/Data_Logging/DataLoggingExample1_NAV_PVT/DataLoggingExample1_NAV_PVT.ino @@ -22,9 +22,7 @@ Insert a formatted micro-SD card into the socket on the Carrier Board. Connect the Carrier Board to your computer using a USB-C cable. Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3 - This code has been tested using version 2.1.0 of the Apollo3 boards on Arduino IDE 1.8.13. - - Version 2.1.1 of Apollo3 contains a feature which makes I2C communication with u-blox modules problematic - - We recommend using v2.1.0 of Apollo3 until v2.2.0 is released + This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13. Select "Artemis MicroMod Processor" as the board type. Press upload to upload the code onto the Artemis. Open the Serial Monitor at 115200 baud to see the output. @@ -69,6 +67,7 @@ File myFile; //File that all GNSS data is written to #endif #define packetLength 100 // NAV PVT is 92 + 8 bytes in length (including the sync chars, class, id, length and checksum bytes) +uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card // Callback: printPVTdata will be called when new NAV PVT data arrives // See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t @@ -77,38 +76,38 @@ File myFile; //File that all GNSS data is written to // | / _____ You can use any name you like for the struct // | | / // | | | -void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) +void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("Time: ")); // Print the time - uint8_t hms = ubxDataStruct.hour; // Print the hours + uint8_t hms = ubxDataStruct->hour; // Print the hours if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(":")); - hms = ubxDataStruct.min; // Print the minutes + hms = ubxDataStruct->min; // Print the minutes if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(":")); - hms = ubxDataStruct.sec; // Print the seconds + hms = ubxDataStruct->sec; // Print the seconds if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(".")); - unsigned long millisecs = ubxDataStruct.iTOW % 1000; // Print the milliseconds + unsigned long millisecs = ubxDataStruct->iTOW % 1000; // Print the milliseconds if (millisecs < 100) Serial.print(F("0")); // Print the trailing zeros correctly if (millisecs < 10) Serial.print(F("0")); Serial.print(millisecs); - long latitude = ubxDataStruct.lat; // Print the latitude + long latitude = ubxDataStruct->lat; // Print the latitude Serial.print(F(" Lat: ")); Serial.print(latitude); - long longitude = ubxDataStruct.lon; // Print the longitude + long longitude = ubxDataStruct->lon; // Print the longitude Serial.print(F(" Long: ")); Serial.print(longitude); Serial.print(F(" (degrees * 10^-7)")); - long altitude = ubxDataStruct.hMSL; // Print the height above mean sea level + long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level Serial.print(F(" Height above MSL: ")); Serial.print(altitude); Serial.println(F(" (mm)")); @@ -200,10 +199,12 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second - myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata + myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata myGNSS.logNAVPVT(); // Enable NAV PVT data logging + myBuffer = new uint8_t[packetLength]; // Create our own buffer to hold the data while we write it to SD card + Serial.println(F("Press any key to stop logging.")); } @@ -214,9 +215,7 @@ void loop() if (myGNSS.fileBufferAvailable() >= packetLength) // Check to see if a new packetLength-byte NAV PVT message has been stored { - uint8_t myBuffer[packetLength]; // Create our own buffer to hold the data while we write it to SD card - - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, packetLength); // Extract exactly packetLength bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, packetLength); // Extract exactly packetLength bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, packetLength); // Write exactly packetLength bytes from myBuffer to the ubxDataFile on the SD card diff --git a/examples/Data_Logging/DataLoggingExample2_TIM_TM2/DataLoggingExample2_TIM_TM2.ino b/examples/Data_Logging/DataLoggingExample2_TIM_TM2/DataLoggingExample2_TIM_TM2.ino index a06084f..69066c0 100644 --- a/examples/Data_Logging/DataLoggingExample2_TIM_TM2/DataLoggingExample2_TIM_TM2.ino +++ b/examples/Data_Logging/DataLoggingExample2_TIM_TM2/DataLoggingExample2_TIM_TM2.ino @@ -22,9 +22,7 @@ Insert a formatted micro-SD card into the socket on the Carrier Board. Connect the Carrier Board to your computer using a USB-C cable. Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3 - This code has been tested using version 2.1.0 of the Apollo3 boards on Arduino IDE 1.8.13. - - Version 2.1.1 of Apollo3 contains a feature which makes I2C communication with u-blox modules problematic - - We recommend using v2.1.0 of Apollo3 until v2.2.0 is released + This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13. Select "Artemis MicroMod Processor" as the board type. Press upload to upload the code onto the Artemis. Open the Serial Monitor at 115200 baud to see the output. @@ -82,6 +80,7 @@ File myFile; //File that all GNSS data is written to #endif #define packetLength 36 // TIM TM2 is 28 + 8 bytes in length (including the sync chars, class, id, length and checksum bytes) +uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card int dotsPrinted = 0; // Print dots in rows of 50 while waiting for a TIM TM2 message @@ -92,30 +91,30 @@ int dotsPrinted = 0; // Print dots in rows of 50 while waiting for a TIM TM2 mes // | / _____ You can use any name you like for the struct // | | / // | | | -void printTIMTM2data(UBX_TIM_TM2_data_t ubxDataStruct) +void printTIMTM2data(UBX_TIM_TM2_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("newFallingEdge: ")); // 1 if a new falling edge was detected - Serial.print(ubxDataStruct.flags.bits.newFallingEdge); + Serial.print(ubxDataStruct->flags.bits.newFallingEdge); Serial.print(F(" newRisingEdge: ")); // 1 if a new rising edge was detected - Serial.print(ubxDataStruct.flags.bits.newRisingEdge); + Serial.print(ubxDataStruct->flags.bits.newRisingEdge); Serial.print(F(" Rising Edge Counter: ")); // Rising edge counter - Serial.print(ubxDataStruct.count); + Serial.print(ubxDataStruct->count); Serial.print(F(" towMsR: ")); // Time Of Week of rising edge (ms) - Serial.print(ubxDataStruct.towMsR); + Serial.print(ubxDataStruct->towMsR); Serial.print(F(" towSubMsR: ")); // Millisecond fraction of Time Of Week of rising edge in nanoseconds - Serial.print(ubxDataStruct.towSubMsR); + Serial.print(ubxDataStruct->towSubMsR); Serial.print(F(" towMsF: ")); // Time Of Week of falling edge (ms) - Serial.print(ubxDataStruct.towMsF); + Serial.print(ubxDataStruct->towMsF); Serial.print(F(" towSubMsF: ")); // Millisecond fraction of Time Of Week of falling edge in nanoseconds - Serial.println(ubxDataStruct.towSubMsF); + Serial.println(ubxDataStruct->towSubMsF); dotsPrinted = 0; // Reset dotsPrinted } @@ -206,10 +205,12 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second - myGNSS.setAutoTIMTM2callback(&printTIMTM2data); // Enable automatic TIM TM2 messages with callback to printTIMTM2data + myGNSS.setAutoTIMTM2callbackPtr(&printTIMTM2data); // Enable automatic TIM TM2 messages with callback to printTIMTM2data myGNSS.logTIMTM2(); // Enable TIM TM2 data logging + myBuffer = new uint8_t[packetLength]; // Create our own buffer to hold the data while we write it to SD card + Serial.println(F("Press any key to stop logging.")); } @@ -220,9 +221,7 @@ void loop() if (myGNSS.fileBufferAvailable() >= packetLength) // Check to see if a new packetLength-byte TIM TM2 message has been stored { - uint8_t myBuffer[packetLength]; // Create our own buffer to hold the data while we write it to SD card - - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, packetLength); // Extract exactly packetLength bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, packetLength); // Extract exactly packetLength bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, packetLength); // Write exactly packetLength bytes from myBuffer to the ubxDataFile on the SD card diff --git a/examples/Data_Logging/DataLoggingExample3_RXM_SFRBX_and_RAWX/DataLoggingExample3_RXM_SFRBX_and_RAWX.ino b/examples/Data_Logging/DataLoggingExample3_RXM_SFRBX_and_RAWX/DataLoggingExample3_RXM_SFRBX_and_RAWX.ino index 6b0c286..032c27f 100644 --- a/examples/Data_Logging/DataLoggingExample3_RXM_SFRBX_and_RAWX/DataLoggingExample3_RXM_SFRBX_and_RAWX.ino +++ b/examples/Data_Logging/DataLoggingExample3_RXM_SFRBX_and_RAWX/DataLoggingExample3_RXM_SFRBX_and_RAWX.ino @@ -34,9 +34,7 @@ Insert a formatted micro-SD card into the socket on the Carrier Board. Connect the Carrier Board to your computer using a USB-C cable. Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3 - This code has been tested using version 2.1.0 of the Apollo3 boards on Arduino IDE 1.8.13. - - Version 2.1.1 of Apollo3 contains a feature which makes I2C communication with u-blox modules problematic - - We recommend using v2.1.0 of Apollo3 until v2.2.0 is released + This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13. Select "Artemis MicroMod Processor" as the board type. Press upload to upload the code onto the Artemis. Open the Serial Monitor at 115200 baud to see the output. @@ -76,6 +74,7 @@ File myFile; //File that all GNSS data is written to #define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes #define fileBufferSize 16384 // Allocate 16KBytes of RAM for UBX message storage +uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card unsigned long lastPrint; // Record when the last Serial print took place @@ -90,10 +89,10 @@ int numRAWX = 0; // Keep count of how many RAWX message groups have been receive // See u-blox_structs.h for the full definition of UBX_RXMSFRBX_data_t // _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMSFRBXcallback // / _____ This _must_ be UBX_RXM_SFRBX_data_t -// | / _____ You can use any name you like for the struct -// | | / -// | | | -void newSFRBX(UBX_RXM_SFRBX_data_t ubxDataStruct) +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void newSFRBX(UBX_RXM_SFRBX_data_t *ubxDataStruct) { numSFRBX++; // Increment the count } @@ -105,7 +104,7 @@ void newSFRBX(UBX_RXM_SFRBX_data_t ubxDataStruct) // | / _____ You can use any name you like for the struct // | | / // | | | -void newRAWX(UBX_RXM_RAWX_data_t ubxDataStruct) +void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct) { numRAWX++; // Increment the count } @@ -202,14 +201,16 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second (that's plenty for Precise Point Positioning) - myGNSS.setAutoRXMSFRBXcallback(&newSFRBX); // Enable automatic RXM SFRBX messages with callback to newSFRBX + myGNSS.setAutoRXMSFRBXcallbackPtr(&newSFRBX); // Enable automatic RXM SFRBX messages with callback to newSFRBX myGNSS.logRXMSFRBX(); // Enable RXM SFRBX data logging - myGNSS.setAutoRXMRAWXcallback(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX + myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging + myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card + Serial.println(F("Press any key to stop logging.")); lastPrint = millis(); // Initialize lastPrint @@ -228,9 +229,7 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card @@ -273,15 +272,13 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time if (bytesToWrite > sdWriteSize) { bytesToWrite = sdWriteSize; } - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card From fae14c1a0694c91de71b3c388df5b819f7431ec3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 6 Feb 2022 16:57:21 +0000 Subject: [PATCH 100/122] Update data logging examples 4-6 --- .../DataLoggingExample4_RXM_without_Callbacks.ino | 15 ++++++--------- .../DataLoggingExample5_Fast_RXM.ino | 15 ++++++--------- .../DataLoggingExample6_NMEA.ino | 15 ++++++--------- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/examples/Data_Logging/DataLoggingExample4_RXM_without_Callbacks/DataLoggingExample4_RXM_without_Callbacks.ino b/examples/Data_Logging/DataLoggingExample4_RXM_without_Callbacks/DataLoggingExample4_RXM_without_Callbacks.ino index 9391c25..7479d3c 100644 --- a/examples/Data_Logging/DataLoggingExample4_RXM_without_Callbacks/DataLoggingExample4_RXM_without_Callbacks.ino +++ b/examples/Data_Logging/DataLoggingExample4_RXM_without_Callbacks/DataLoggingExample4_RXM_without_Callbacks.ino @@ -35,9 +35,7 @@ Insert a formatted micro-SD card into the socket on the Carrier Board. Connect the Carrier Board to your computer using a USB-C cable. Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3 - This code has been tested using version 2.1.0 of the Apollo3 boards on Arduino IDE 1.8.13. - - Version 2.1.1 of Apollo3 contains a feature which makes I2C communication with u-blox modules problematic - - We recommend using v2.1.0 of Apollo3 until v2.2.0 is released + This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13. Select "Artemis MicroMod Processor" as the board type. Press upload to upload the code onto the Artemis. Open the Serial Monitor at 115200 baud to see the output. @@ -77,6 +75,7 @@ File myFile; //File that all GNSS data is written to #define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes #define fileBufferSize 16384 // Allocate 16KBytes of RAM for UBX message storage +uint8_t *myBuffer; // A buffer to hold the data while we write it to SD card unsigned long lastPrint; // Record when the last Serial print took place unsigned long bytesWritten = 0; // Record how many bytes have been written to SD card @@ -181,6 +180,8 @@ void setup() myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging + myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card + Serial.println(F("Press any key to stop logging.")); lastPrint = millis(); // Initialize lastPrint @@ -198,9 +199,7 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card @@ -242,15 +241,13 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time if (bytesToWrite > sdWriteSize) { bytesToWrite = sdWriteSize; } - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card diff --git a/examples/Data_Logging/DataLoggingExample5_Fast_RXM/DataLoggingExample5_Fast_RXM.ino b/examples/Data_Logging/DataLoggingExample5_Fast_RXM/DataLoggingExample5_Fast_RXM.ino index 1170997..b11484f 100644 --- a/examples/Data_Logging/DataLoggingExample5_Fast_RXM/DataLoggingExample5_Fast_RXM.ino +++ b/examples/Data_Logging/DataLoggingExample5_Fast_RXM/DataLoggingExample5_Fast_RXM.ino @@ -35,9 +35,7 @@ Insert a formatted micro-SD card into the socket on the Carrier Board. Connect the Carrier Board to your computer using a USB-C cable. Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3 - This code has been tested using version 2.1.0 of the Apollo3 boards on Arduino IDE 1.8.13. - - Version 2.1.1 of Apollo3 contains a feature which makes I2C communication with u-blox modules problematic - - We recommend using v2.1.0 of Apollo3 until v2.2.0 is released + This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13. Select "Artemis MicroMod Processor" as the board type. Press upload to upload the code onto the Artemis. Open the Serial Monitor at 115200 baud to see the output. @@ -77,6 +75,7 @@ File myFile; //File that all GNSS data is written to #define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes #define fileBufferSize 32768 // Allocate 32KBytes of RAM for UBX message storage +uint8_t *myBuffer; // A buffer to hold the data while we write it to SD card unsigned long lastPrint; // Record when the last Serial print took place unsigned long bytesWritten = 0; // Record how many bytes have been written to SD card @@ -196,6 +195,8 @@ void setup() myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging + myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card + Serial.println(F("Press any key to stop logging.")); lastPrint = millis(); // Initialize lastPrint @@ -213,9 +214,7 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card @@ -263,15 +262,13 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time if (bytesToWrite > sdWriteSize) { bytesToWrite = sdWriteSize; } - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card diff --git a/examples/Data_Logging/DataLoggingExample6_NMEA/DataLoggingExample6_NMEA.ino b/examples/Data_Logging/DataLoggingExample6_NMEA/DataLoggingExample6_NMEA.ino index 9feee04..996031b 100644 --- a/examples/Data_Logging/DataLoggingExample6_NMEA/DataLoggingExample6_NMEA.ino +++ b/examples/Data_Logging/DataLoggingExample6_NMEA/DataLoggingExample6_NMEA.ino @@ -24,9 +24,7 @@ Insert a formatted micro-SD card into the socket on the Carrier Board. Connect the Carrier Board to your computer using a USB-C cable. Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3 - This code has been tested using version 2.1.0 of the Apollo3 boards on Arduino IDE 1.8.13. - - Version 2.1.1 of Apollo3 contains a feature which makes I2C communication with u-blox modules problematic - - We recommend using v2.1.0 of Apollo3 until v2.2.0 is released + This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13. Select "Artemis MicroMod Processor" as the board type. Press upload to upload the code onto the Artemis. Open the Serial Monitor at 115200 baud to see the output. @@ -68,6 +66,7 @@ File myFile; //File that all GNSS data is written to #define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes #define fileBufferSize 16384 // Allocate 16KBytes of RAM for UBX message storage +uint8_t *myBuffer; // A buffer to hold the data while we write it to SD card unsigned long lastPrint; // Record when the last Serial print took place unsigned long bytesWritten = 0; // Record how many bytes have been written to SD card @@ -175,6 +174,8 @@ void setup() myGNSS.setNMEALoggingMask(SFE_UBLOX_FILTER_NMEA_ALL); // Enable logging of all enabled NMEA messages //myGNSS.setNMEALoggingMask(SFE_UBLOX_FILTER_NMEA_GGA | SFE_UBLOX_FILTER_NMEA_GSA); // Or we can, for example, log only GxGGA & GxGSA and ignore GxGSV + myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card + Serial.println(F("Press any key to stop logging.")); lastPrint = millis(); // Initialize lastPrint @@ -192,9 +193,7 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card @@ -236,15 +235,13 @@ void loop() { digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card - uint8_t myBuffer[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card - uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time if (bytesToWrite > sdWriteSize) { bytesToWrite = sdWriteSize; } - myGNSS.extractFileBufferData((uint8_t *)&myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer + myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card From 7395c25af5537c90acee3daaff77d32fc2f5b84b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 6 Feb 2022 17:34:45 +0000 Subject: [PATCH 101/122] Update AssistNow Autonomous examples to use callback pointers --- .../Example1_AssistNowAutonomous.ino | 30 +++++++++---------- ...mple2_AssistNowAutonomous_DatabaseRead.ino | 18 +++++------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino index d772dfc..1f50815 100644 --- a/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino +++ b/examples/AssistNow/AssistNow_Autonomous/Example1_AssistNowAutonomous/Example1_AssistNowAutonomous.ino @@ -42,22 +42,22 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printSATdata(UBX_NAV_SAT_data_t ubxDataStruct) +void printSATdata(UBX_NAV_SAT_data_t *ubxDataStruct) { //Serial.println(); Serial.print(F("UBX-NAV-SAT contains data for ")); - Serial.print(ubxDataStruct.header.numSvs); - if (ubxDataStruct.header.numSvs == 1) + Serial.print(ubxDataStruct->header.numSvs); + if (ubxDataStruct->header.numSvs == 1) Serial.println(F(" SV")); else Serial.println(F(" SVs")); uint16_t numAopAvail = 0; // Count how many SVs have AssistNow Autonomous data available - for (uint16_t block = 0; block < ubxDataStruct.header.numSvs; block++) // For each SV + for (uint16_t block = 0; block < ubxDataStruct->header.numSvs; block++) // For each SV { - if (ubxDataStruct.blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set + if (ubxDataStruct->blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set numAopAvail++; // Increment the number of SVs } @@ -78,12 +78,12 @@ void printSATdata(UBX_NAV_SAT_data_t ubxDataStruct) // | / _____ You can use any name you like for the struct // | | / // | | | -void printAOPstatus(UBX_NAV_AOPSTATUS_data_t ubxDataStruct) +void printAOPstatus(UBX_NAV_AOPSTATUS_data_t *ubxDataStruct) { //Serial.println(); Serial.print(F("AOPSTATUS status is ")); - Serial.println(ubxDataStruct.status); + Serial.println(ubxDataStruct->status); } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -95,27 +95,27 @@ void printAOPstatus(UBX_NAV_AOPSTATUS_data_t ubxDataStruct) // | / _____ You can use any name you like for the struct // | | / // | | | -void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) +void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) { // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D Serial.println(); - long latitude = ubxDataStruct.lat; // Print the latitude + long latitude = ubxDataStruct->lat; // Print the latitude Serial.print(F("Lat: ")); Serial.print(latitude); - long longitude = ubxDataStruct.lon; // Print the longitude + long longitude = ubxDataStruct->lon; // Print the longitude Serial.print(F(" Long: ")); Serial.print(longitude); Serial.print(F(" (degrees * 10^-7)")); - long altitude = ubxDataStruct.hMSL; // Print the height above mean sea level + long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level Serial.print(F(" Alt: ")); Serial.print(altitude); Serial.print(F(" (mm)")); - byte fixType = ubxDataStruct.fixType; // Print the fix type + byte fixType = ubxDataStruct->fixType; // Print the fix type Serial.print(F(" Fix: ")); if(fixType == 0) Serial.print(F("No fix")); else if(fixType == 1) Serial.print(F("Dead reckoning")); @@ -171,9 +171,9 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one solution per second - myGNSS.setAutoNAVSATcallback(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata - myGNSS.setAutoAOPSTATUScallback(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus - myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata + myGNSS.setAutoNAVSATcallbackPtr(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata + myGNSS.setAutoAOPSTATUScallbackPtr(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus + myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= diff --git a/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino b/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino index f083d15..3e041e8 100644 --- a/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino +++ b/examples/AssistNow/AssistNow_Autonomous/Example2_AssistNowAutonomous_DatabaseRead/Example2_AssistNowAutonomous_DatabaseRead.ino @@ -35,22 +35,22 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printSATdata(UBX_NAV_SAT_data_t ubxDataStruct) +void printSATdata(UBX_NAV_SAT_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("UBX-NAV-SAT contains data for ")); - Serial.print(ubxDataStruct.header.numSvs); - if (ubxDataStruct.header.numSvs == 1) + Serial.print(ubxDataStruct->header.numSvs); + if (ubxDataStruct->header.numSvs == 1) Serial.println(F(" SV")); else Serial.println(F(" SVs")); uint16_t numAopAvail = 0; // Count how many SVs have AssistNow Autonomous data available - for (uint16_t block = 0; block < ubxDataStruct.header.numSvs; block++) // For each SV + for (uint16_t block = 0; block < ubxDataStruct->header.numSvs; block++) // For each SV { - if (ubxDataStruct.blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set + if (ubxDataStruct->blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set numAopAvail++; // Increment the number of SVs } @@ -71,12 +71,12 @@ void printSATdata(UBX_NAV_SAT_data_t ubxDataStruct) // | / _____ You can use any name you like for the struct // | | / // | | | -void printAOPstatus(UBX_NAV_AOPSTATUS_data_t ubxDataStruct) +void printAOPstatus(UBX_NAV_AOPSTATUS_data_t *ubxDataStruct) { //Serial.println(); Serial.print(F("AOPSTATUS status is ")); - Serial.println(ubxDataStruct.status); + Serial.println(ubxDataStruct->status); } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -126,8 +126,8 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one solution per second - myGNSS.setAutoNAVSATcallback(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata - myGNSS.setAutoAOPSTATUScallback(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus + myGNSS.setAutoNAVSATcallbackPtr(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata + myGNSS.setAutoAOPSTATUScallbackPtr(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Keep displaying NAV SAT and AOPSTATUS until the user presses a key From 9a486f9cd7736cd483b0a92bedea4d2a1284b53d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 6 Feb 2022 17:36:40 +0000 Subject: [PATCH 102/122] Update ZED-F9P callback examples --- .../Example13_autoHPPOSLLH_with_Callback.ino | 32 +++++++++---------- ...xample17_NTRIPClient_With_GGA_Callback.ino | 24 +++++++------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/ZED-F9P/Example13_autoHPPOSLLH_with_Callback/Example13_autoHPPOSLLH_with_Callback.ino b/examples/ZED-F9P/Example13_autoHPPOSLLH_with_Callback/Example13_autoHPPOSLLH_with_Callback.ino index 94a6e75..e93464f 100644 --- a/examples/ZED-F9P/Example13_autoHPPOSLLH_with_Callback/Example13_autoHPPOSLLH_with_Callback.ino +++ b/examples/ZED-F9P/Example13_autoHPPOSLLH_with_Callback/Example13_autoHPPOSLLH_with_Callback.ino @@ -41,27 +41,27 @@ SFE_UBLOX_GNSS myGNSS; // | / _____ You can use any name you like for the struct // | | / // | | | -void printHPdata(UBX_NAV_HPPOSLLH_data_t ubxDataStruct) +void printHPdata(UBX_NAV_HPPOSLLH_data_t *ubxDataStruct) { Serial.println(); - long highResLatitude = ubxDataStruct.lat; + long highResLatitude = ubxDataStruct->lat; Serial.print(F("Hi Res Lat: ")); Serial.print(highResLatitude); - int highResLatitudeHp = ubxDataStruct.latHp; + int highResLatitudeHp = ubxDataStruct->latHp; Serial.print(F(" ")); Serial.print(highResLatitudeHp); - long highResLongitude = ubxDataStruct.lon; + long highResLongitude = ubxDataStruct->lon; Serial.print(F(" Hi Res Long: ")); Serial.print(highResLongitude); - int highResLongitudeHp = ubxDataStruct.lonHp; + int highResLongitudeHp = ubxDataStruct->lonHp; Serial.print(F(" ")); Serial.print(highResLongitudeHp); - float horizAccuracy = ((float)ubxDataStruct.hAcc) / 10000.0; // Convert hAcc from mm*0.1 to m + float horizAccuracy = ((float)ubxDataStruct->hAcc) / 10000.0; // Convert hAcc from mm*0.1 to m Serial.print(F(" Horiz accuracy: ")); Serial.println(horizAccuracy); } @@ -73,38 +73,38 @@ void printHPdata(UBX_NAV_HPPOSLLH_data_t ubxDataStruct) // | / _____ You can use any name you like for the struct // | | / // | | | -void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) +void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) { Serial.println(); Serial.print(F("Time: ")); // Print the time - uint8_t hms = ubxDataStruct.hour; // Print the hours + uint8_t hms = ubxDataStruct->hour; // Print the hours if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(":")); - hms = ubxDataStruct.min; // Print the minutes + hms = ubxDataStruct->min; // Print the minutes if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(":")); - hms = ubxDataStruct.sec; // Print the seconds + hms = ubxDataStruct->sec; // Print the seconds if (hms < 10) Serial.print(F("0")); // Print a leading zero if required Serial.print(hms); Serial.print(F(".")); - unsigned long millisecs = ubxDataStruct.iTOW % 1000; // Print the milliseconds + unsigned long millisecs = ubxDataStruct->iTOW % 1000; // Print the milliseconds if (millisecs < 100) Serial.print(F("0")); // Print the trailing zeros correctly if (millisecs < 10) Serial.print(F("0")); Serial.print(millisecs); - long latitude = ubxDataStruct.lat; // Print the latitude + long latitude = ubxDataStruct->lat; // Print the latitude Serial.print(F(" Lat: ")); Serial.print(latitude); - long longitude = ubxDataStruct.lon; // Print the longitude + long longitude = ubxDataStruct->lon; // Print the longitude Serial.print(F(" Long: ")); Serial.print(longitude); Serial.print(F(" (degrees * 10^-7)")); - long altitude = ubxDataStruct.hMSL; // Print the height above mean sea level + long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level Serial.print(F(" Height above MSL: ")); Serial.print(altitude); Serial.println(F(" (mm)")); @@ -135,9 +135,9 @@ void setup() myGNSS.setNavigationFrequency(2); //Produce two solutions per second - myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata + myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata - myGNSS.setAutoHPPOSLLHcallback(&printHPdata); // Enable automatic NAV HPPOSLLH messages with callback to printHPdata + myGNSS.setAutoHPPOSLLHcallbackPtr(&printHPdata); // Enable automatic NAV HPPOSLLH messages with callback to printHPdata } void loop() diff --git a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino index 91751e5..4741b49 100644 --- a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino +++ b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino @@ -69,16 +69,16 @@ WiFiClient ntripClient; // The WiFi connection to the NTRIP server. This is glob // | / _____ You can use any name you like for the struct // | | / // | | | -void pushGPGGA(NMEA_GGA_data_t nmeaData) +void pushGPGGA(NMEA_GGA_data_t *nmeaData) { //Provide the caster with our current position as needed if ((ntripClient.connected() == true) && (transmitLocation == true)) { Serial.print(F("Pushing GGA to server: ")); - Serial.print((const char *)nmeaData.nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end + Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end //Push our current GGA sentence to caster - ntripClient.print((const char *)nmeaData.nmea); + ntripClient.print((const char *)nmeaData->nmea); } } @@ -91,26 +91,26 @@ void pushGPGGA(NMEA_GGA_data_t nmeaData) // | / _____ You can use any name you like for the struct // | | / // | | | -void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) +void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) { - long latitude = ubxDataStruct.lat; // Print the latitude + long latitude = ubxDataStruct->lat; // Print the latitude Serial.print(F("Lat: ")); Serial.print(latitude / 10000000L); Serial.print(F(".")); Serial.print(abs(latitude % 10000000L)); - long longitude = ubxDataStruct.lon; // Print the longitude + long longitude = ubxDataStruct->lon; // Print the longitude Serial.print(F(" Long: ")); Serial.print(longitude / 10000000L); Serial.print(F(".")); Serial.print(abs(longitude % 10000000L)); - long altitude = ubxDataStruct.hMSL; // Print the height above mean sea level + long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level Serial.print(F(" Height: ")); Serial.print(altitude); Serial.print(F(" (mm)")); - uint8_t fixType = ubxDataStruct.fixType; // Print the fix type + uint8_t fixType = ubxDataStruct->fixType; // Print the fix type Serial.print(F(" Fix: ")); Serial.print(fixType); if (fixType == 0) @@ -128,7 +128,7 @@ void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) else Serial.print(F(" (UNKNOWN)")); - uint8_t carrSoln = ubxDataStruct.flags.bits.carrSoln; // Print the carrier solution + uint8_t carrSoln = ubxDataStruct->flags.bits.carrSoln; // Print the carrier solution Serial.print(F(" Carrier Solution: ")); Serial.print(carrSoln); if (carrSoln == 0) @@ -140,7 +140,7 @@ void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) else Serial.print(F(" (UNKNOWN)")); - uint32_t hAcc = ubxDataStruct.hAcc; // Print the horizontal accuracy estimate + uint32_t hAcc = ubxDataStruct->hAcc; // Print the horizontal accuracy estimate Serial.print(F(" Horizontal Accuracy Estimate: ")); Serial.print(hAcc); Serial.print(F(" (mm)")); @@ -175,11 +175,11 @@ void setup() // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); - myGNSS.setNMEAGPGGAcallback(&pushGPGGA); // Set up the callback for GPGGA + myGNSS.setNMEAGPGGAcallbackPtr(&pushGPGGA); // Set up the callback for GPGGA myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C, 10); // Tell the module to output GGA every 10 seconds - myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed + myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM From e59b7b5799707226cb3db2d283c3a632757a6a8e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 6 Feb 2022 18:48:32 +0000 Subject: [PATCH 103/122] Correct typos and add library manager helper links in Example18_PointPerfectClient --- .../Example18_PointPerfectClient.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino index d9f8fd0..b31cfa5 100644 --- a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino +++ b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino @@ -10,9 +10,9 @@ It's confusing, but the Arduino is acting as a 'client' to the PointPerfect SSR correction service. You will need to have a valid u-blox Thingstream account and have a PointPerfect Thing and payed plan. - Thingstream offers SSR corrections to SPARTN cabalble RTK receivers such as the u-blox ZED-F9 series - in continental Europ and US. There Network is planned to be expanded to ther regions over next years. - To see sign up go to https://portal.thingstream.io/app/location-services/things + Thingstream offers SSR corrections to SPARTN capable RTK receivers such as the u-blox ZED-F9 series + in continental Europe and US. Their Network is planned to be expanded to other regions over the next years. + To sign up, go to: https://portal.thingstream.io/app/location-services/things This is a proof of concept to show how to connect via MQTT to get SPARTN SSR correction. Using WiFi for a rover is generally a bad idea because of limited WiFi range in the field. @@ -38,10 +38,10 @@ */ #include #include -#include +#include // Click here to get the library: http://librarymanager/All#ArduinoMqttClient #include "secrets.h" -#include //http://librarymanager/All#SparkFun_u-blox_GNSS +#include // Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS SFE_UBLOX_GNSS myGNSS; //Global variables @@ -55,7 +55,7 @@ void setup() Serial.begin(115200); while (!Serial); Serial.println(F("PointPerfect testing")); - + Wire.begin(); //Start I2C if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port From fcf00c799735449148a2ff53ef54bede2ef1ecdf Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 7 Feb 2022 08:12:03 +0000 Subject: [PATCH 104/122] Add extra config keys for the NEO-D9S --- src/u-blox_config_keys.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/u-blox_config_keys.h b/src/u-blox_config_keys.h index ae043a3..90d7f88 100644 --- a/src/u-blox_config_keys.h +++ b/src/u-blox_config_keys.h @@ -791,6 +791,11 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_SPI = 0x20910321; // Output rate of const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1 = 0x2091031e; // Output rate of the UBX_RXM_PMP message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2 = 0x2091031f; // Output rate of the UBX_RXM_PMP message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_USB = 0x20910320; // Output rate of the UBX_RXM_PMP message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_I2C = 0x20910322; // Output rate of the UBX_MON_PMP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_SPI = 0x20910326; // Output rate of the UBX_MON_PMP message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_UART1 = 0x20910323; // Output rate of the UBX_MON_PMP message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_UART2 = 0x20910324; // Output rate of the UBX_MON_PMP message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_USB = 0x20910325; // Output rate of the UBX_MON_PMP message on port USB //CFG-NAV2: Secondary output configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -1003,6 +1008,10 @@ const uint32_t UBLOX_CFG_SIGNAL_GLO_ENA = 0x10310025; // GLONASS enable const uint32_t UBLOX_CFG_SIGNAL_GLO_L1_ENA = 0x10310018; // GLONASS L1 const uint32_t UBLOX_CFG_SIGNAL_GLO_L2_ENA = 0x1031001a; // GLONASS L2 (only on u-blox F9 platform products) +//CFG-SPARTN: Configuration of the SPARTN interface +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +const uint32_t UBLOX_CFG_SPARTN_USE_SOURCE = 0x20a70001; + //CFG-SPI: Configuration of the SPI interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_SPI_MAXFF = 0x20640001; // Number of bytes containing 0xFF to receive before switching off reception. Range: 0 (mechanism off) - 63 From df4fb4cdaa4a691fd7a9f9b457aebf9b62566775 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 7 Feb 2022 08:42:59 +0000 Subject: [PATCH 105/122] Add 64-bit setval and getval functions --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 145 ++++++++++++++++++- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 7 + 2 files changed, 149 insertions(+), 3 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index a1fce79..f696d63 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -7580,6 +7580,13 @@ uint32_t SFE_UBLOX_GNSS::getVal32(uint32_t key, uint8_t layer, uint16_t maxWait) return (extractLong(&packetCfg, 8)); } +uint64_t SFE_UBLOX_GNSS::getVal64(uint32_t key, uint8_t layer, uint16_t maxWait) +{ + if (getVal(key, layer, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) + return (0); + + return (extractLongLong(&packetCfg, 8)); +} //Given a group, ID and size, return the value of this config spot //The 32-bit key is put together from group/ID/size. See other getVal to send key directly. @@ -7599,6 +7606,11 @@ uint32_t SFE_UBLOX_GNSS::getVal32(uint16_t group, uint16_t id, uint8_t size, uin uint32_t key = createKey(group, id, size); return getVal32(key, layer, maxWait); } +uint64_t SFE_UBLOX_GNSS::getVal64(uint16_t group, uint16_t id, uint8_t size, uint8_t layer, uint16_t maxWait) +{ + uint32_t key = createKey(group, id, size); + return getVal64(key, layer, maxWait); +} //Given a key, set a 16-bit value //This function takes a full 32-bit key @@ -7703,9 +7715,83 @@ uint8_t SFE_UBLOX_GNSS::setVal32(uint32_t key, uint32_t value, uint8_t layer, ui return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } +//Given a key, set a 64-bit value +//This function takes a full 32-bit key +//Default layer is all: RAM+BBR+Flash +//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +uint8_t SFE_UBLOX_GNSS::setVal64(uint32_t key, uint64_t value, uint8_t layer, uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_VALSET; + packetCfg.len = 4 + 4 + 8; //4 byte header, 4 byte key ID, 8 bytes of value + packetCfg.startingSpot = 0; + + //Clear packet payload + memset(payloadCfg, 0, packetCfg.len); + + payloadCfg[0] = 0; //Message Version - set to 0 + payloadCfg[1] = layer; //By default we ask for the BBR layer + + //Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; //Key LSB + payloadCfg[5] = key >> 8 * 1; + payloadCfg[6] = key >> 8 * 2; + payloadCfg[7] = key >> 8 * 3; + + //Load user's value + payloadCfg[8] = value >> 8 * 0; //Value LSB + payloadCfg[9] = value >> 8 * 1; + payloadCfg[10] = value >> 8 * 2; + payloadCfg[11] = value >> 8 * 3; + payloadCfg[12] = value >> 8 * 4; + payloadCfg[13] = value >> 8 * 5; + payloadCfg[14] = value >> 8 * 6; + payloadCfg[15] = value >> 8 * 7; + + //Send VALSET command with this key and value + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + +//Start defining a new UBX-CFG-VALSET ubxPacket +//This function takes a full 32-bit key and 64-bit value +//Default layer is RAM+BBR+Flash +//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +uint8_t SFE_UBLOX_GNSS::newCfgValset64(uint32_t key, uint64_t value, uint8_t layer) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_VALSET; + packetCfg.len = 4 + 4 + 8; //4 byte header, 4 byte key ID, 8 bytes of value + packetCfg.startingSpot = 0; + + //Clear all of packet payload + memset(payloadCfg, 0, packetCfgPayloadSize); + + payloadCfg[0] = 0; //Message Version - set to 0 + payloadCfg[1] = layer; //By default we ask for the BBR layer + + //Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; //Key LSB + payloadCfg[5] = key >> 8 * 1; + payloadCfg[6] = key >> 8 * 2; + payloadCfg[7] = key >> 8 * 3; + + //Load user's value + payloadCfg[8] = value >> 8 * 0; //Value LSB + payloadCfg[9] = value >> 8 * 1; + payloadCfg[10] = value >> 8 * 2; + payloadCfg[11] = value >> 8 * 3; + payloadCfg[12] = value >> 8 * 4; + payloadCfg[13] = value >> 8 * 5; + payloadCfg[14] = value >> 8 * 6; + payloadCfg[15] = value >> 8 * 7; + + //All done + return (true); +} + //Start defining a new UBX-CFG-VALSET ubxPacket //This function takes a full 32-bit key and 32-bit value -//Default layer is BBR +//Default layer is RAM+BBR+Flash //Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::newCfgValset32(uint32_t key, uint32_t value, uint8_t layer) { @@ -7738,7 +7824,7 @@ uint8_t SFE_UBLOX_GNSS::newCfgValset32(uint32_t key, uint32_t value, uint8_t lay //Start defining a new UBX-CFG-VALSET ubxPacket //This function takes a full 32-bit key and 16-bit value -//Default layer is BBR +//Default layer is RAM+BBR+Flash //Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::newCfgValset16(uint32_t key, uint16_t value, uint8_t layer) { @@ -7769,7 +7855,7 @@ uint8_t SFE_UBLOX_GNSS::newCfgValset16(uint32_t key, uint16_t value, uint8_t lay //Start defining a new UBX-CFG-VALSET ubxPacket //This function takes a full 32-bit key and 8-bit value -//Default layer is BBR +//Default layer is RAM+BBR+Flash //Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::newCfgValset8(uint32_t key, uint8_t value, uint8_t layer) { @@ -7797,6 +7883,33 @@ uint8_t SFE_UBLOX_GNSS::newCfgValset8(uint32_t key, uint8_t value, uint8_t layer return (true); } +//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket +//This function takes a full 32-bit key and 64-bit value +uint8_t SFE_UBLOX_GNSS::addCfgValset64(uint32_t key, uint64_t value) +{ + //Load key into outgoing payload + payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB + payloadCfg[packetCfg.len + 1] = key >> 8 * 1; + payloadCfg[packetCfg.len + 2] = key >> 8 * 2; + payloadCfg[packetCfg.len + 3] = key >> 8 * 3; + + //Load user's value + payloadCfg[packetCfg.len + 4] = value >> 8 * 0; //Value LSB + payloadCfg[packetCfg.len + 5] = value >> 8 * 1; + payloadCfg[packetCfg.len + 6] = value >> 8 * 2; + payloadCfg[packetCfg.len + 7] = value >> 8 * 3; + payloadCfg[packetCfg.len + 8] = value >> 8 * 4; + payloadCfg[packetCfg.len + 9] = value >> 8 * 5; + payloadCfg[packetCfg.len + 10] = value >> 8 * 6; + payloadCfg[packetCfg.len + 11] = value >> 8 * 7; + + //Update packet length: 4 byte key ID, 8 bytes of value + packetCfg.len = packetCfg.len + 4 + 8; + + //All done + return (true); +} + //Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket //This function takes a full 32-bit key and 32-bit value uint8_t SFE_UBLOX_GNSS::addCfgValset32(uint32_t key, uint32_t value) @@ -7861,6 +7974,17 @@ uint8_t SFE_UBLOX_GNSS::addCfgValset8(uint32_t key, uint8_t value) return (true); } +//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it +//This function takes a full 32-bit key and 64-bit value +uint8_t SFE_UBLOX_GNSS::sendCfgValset64(uint32_t key, uint64_t value, uint16_t maxWait) +{ + //Load keyID and value into outgoing payload + addCfgValset64(key, value); + + //Send VALSET command with this key and value + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + //Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it //This function takes a full 32-bit key and 32-bit value uint8_t SFE_UBLOX_GNSS::sendCfgValset32(uint32_t key, uint32_t value, uint16_t maxWait) @@ -15160,6 +15284,21 @@ float SFE_UBLOX_GNSS::getHNRheading(uint16_t maxWait) // Returned as degrees // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket // From v2.0: These are public. The user can call these to extract data from custom packets +//Given a spot in the payload array, extract eight bytes and build a uint64_t +uint64_t SFE_UBLOX_GNSS::extractLongLong(ubxPacket *msg, uint16_t spotToStart) +{ + uint64_t val = 0; + val |= (uint64_t)msg->payload[spotToStart + 0] << 8 * 0; + val |= (uint64_t)msg->payload[spotToStart + 1] << 8 * 1; + val |= (uint64_t)msg->payload[spotToStart + 2] << 8 * 2; + val |= (uint64_t)msg->payload[spotToStart + 3] << 8 * 3; + val |= (uint64_t)msg->payload[spotToStart + 4] << 8 * 4; + val |= (uint64_t)msg->payload[spotToStart + 5] << 8 * 5; + val |= (uint64_t)msg->payload[spotToStart + 6] << 8 * 6; + val |= (uint64_t)msg->payload[spotToStart + 7] << 8 * 7; + return (val); +} + //Given a spot in the payload array, extract four bytes and build a long uint32_t SFE_UBLOX_GNSS::extractLong(ubxPacket *msg, uint16_t spotToStart) { diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index cf0f4aa..9c10900 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -901,22 +901,28 @@ class SFE_UBLOX_GNSS uint8_t getVal8(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location uint16_t getVal16(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location uint32_t getVal32(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location + uint64_t getVal64(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location uint8_t getVal8(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location uint16_t getVal16(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location uint32_t getVal32(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location + uint64_t getVal64(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location uint8_t setVal(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 16-bit value at a given group/id/size location uint8_t setVal8(uint32_t keyID, uint8_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 8-bit value at a given group/id/size location uint8_t setVal16(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 16-bit value at a given group/id/size location uint8_t setVal32(uint32_t keyID, uint32_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 32-bit value at a given group/id/size location + uint8_t setVal64(uint32_t keyID, uint64_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 64-bit value at a given group/id/size location uint8_t newCfgValset8(uint32_t keyID, uint8_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 8-bit value uint8_t newCfgValset16(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 16-bit value uint8_t newCfgValset32(uint32_t keyID, uint32_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 32-bit value + uint8_t newCfgValset64(uint32_t keyID, uint64_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 64-bit value uint8_t addCfgValset8(uint32_t keyID, uint8_t value); //Add a new KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket uint8_t addCfgValset16(uint32_t keyID, uint16_t value); //Add a new KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket uint8_t addCfgValset32(uint32_t keyID, uint32_t value); //Add a new KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket + uint8_t addCfgValset64(uint32_t keyID, uint64_t value); //Add a new KeyID and 64-bit value to an existing UBX-CFG-VALSET ubxPacket uint8_t sendCfgValset8(uint32_t keyID, uint8_t value, uint16_t maxWait = 250); //Add the final KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket and send it uint8_t sendCfgValset16(uint32_t keyID, uint16_t value, uint16_t maxWait = 250); //Add the final KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket and send it uint8_t sendCfgValset32(uint32_t keyID, uint32_t value, uint16_t maxWait = 250); //Add the final KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket and send it + uint8_t sendCfgValset64(uint32_t keyID, uint64_t value, uint16_t maxWait = 250); //Add the final KeyID and 64-bit value to an existing UBX-CFG-VALSET ubxPacket and send it // get and set functions for all of the "automatic" message processing @@ -1394,6 +1400,7 @@ class SFE_UBLOX_GNSS // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket // From v2.0: These are public. The user can call these to extract data from custom packets + uint64_t extractLongLong(ubxPacket *msg, uint16_t spotToStart); //Combine eight bytes from payload into uint64_t uint32_t extractLong(ubxPacket *msg, uint16_t spotToStart); //Combine four bytes from payload into long int32_t extractSignedLong(ubxPacket *msg, uint16_t spotToStart); //Combine four bytes from payload into signed long (avoiding any ambiguity caused by casting) uint16_t extractInt(ubxPacket *msg, uint16_t spotToStart); //Combine two bytes from payload into int From 088408e0536574fb6e179f785f48a8f95aa94bfa Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 7 Feb 2022 10:02:45 +0000 Subject: [PATCH 106/122] Remove setAutoRXMPMPcallback. setAutoRXMPMPcallbackPtr is the way to go... --- keywords.txt | 6 +- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 60 ++++---------------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 1 - src/u-blox_structs.h | 1 - 4 files changed, 16 insertions(+), 52 deletions(-) diff --git a/keywords.txt b/keywords.txt index 1213ac5..7ee9bd2 100644 --- a/keywords.txt +++ b/keywords.txt @@ -183,19 +183,24 @@ getVal KEYWORD2 getVal8 KEYWORD2 getVal16 KEYWORD2 getVal32 KEYWORD2 +getVal64 KEYWORD2 setVal KEYWORD2 setVal8 KEYWORD2 setVal16 KEYWORD2 setVal32 KEYWORD2 +setVal64 KEYWORD2 newCfgValset8 KEYWORD2 newCfgValset16 KEYWORD2 newCfgValset32 KEYWORD2 +newCfgValset64 KEYWORD2 addCfgValset8 KEYWORD2 addCfgValset16 KEYWORD2 addCfgValset32 KEYWORD2 +addCfgValset64 KEYWORD2 sendCfgValset8 KEYWORD2 sendCfgValset16 KEYWORD2 sendCfgValset32 KEYWORD2 +sendCfgValset64 KEYWORD2 getNAVPOSECEF KEYWORD2 setAutoNAVPOSECEF KEYWORD2 @@ -356,7 +361,6 @@ initPacketUBXAOPSTATUS KEYWORD2 flushAOPSTATUS KEYWORD2 logAOPSTATUS KEYWORD2 -setAutoRXMPMPcallback KEYWORD2 setAutoRXMPMPcallbackPtr KEYWORD2 getRXMSFRBX KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index f696d63..05da70d 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3183,12 +3183,6 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) memcpy(&packetUBXRXMPMP->callbackData->version, &packetUBXRXMPMP->data.version, sizeof(UBX_RXM_PMP_data_t)); packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = true; } - - //Check if we need to copy the data into the file buffer - if (packetUBXRXMPMP->automaticFlags.flags.bits.addToFileBuffer) - { - storePacket(msg); - } } } else if (msg->id == UBX_RXM_SFRBX) @@ -4485,7 +4479,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) // _debugSerial->println(F("checkCallbacks: calling callback for NAV POSECEF")); packetUBXNAVPOSECEF->callbackPointer(*packetUBXNAVPOSECEF->callbackData); // Call the callback } - else if (packetUBXNAVPOSECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + if (packetUBXNAVPOSECEF->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) // _debugSerial->println(F("checkCallbacks: calling callbackPtr for NAV POSECEF")); @@ -4764,12 +4758,6 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) && (packetUBXRXMPMP->callbackData != NULL) // If RAM has been allocated for the copy of the data && (packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - if (packetUBXRXMPMP->callbackPointer != NULL) // If the pointer to the callback has been defined - { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callback for RXM PMP")); - packetUBXRXMPMP->callbackPointer(*packetUBXRXMPMP->callbackData); // Call the callback - } if (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { // if (_printDebug == true) @@ -11021,31 +11009,6 @@ void SFE_UBLOX_GNSS::logAOPSTATUS(bool enabled) // ***** RXM PMP automatic support -// Callback is passed all of the data. Heavy on the stack. May cause problems on some platforms. -bool SFE_UBLOX_GNSS::setAutoRXMPMPcallback(void (*callbackPointer)(UBX_RXM_PMP_data_t)) -{ - if (packetUBXRXMPMP == NULL) initPacketUBXRXMPMP(); //Check that RAM has been allocated for the data - if (packetUBXRXMPMP == NULL) //Only attempt this if RAM allocation was successful - return false; - - if (packetUBXRXMPMP->callbackData == NULL) //Check if RAM has been allocated for the callback copy - { - packetUBXRXMPMP->callbackData = new UBX_RXM_PMP_data_t; //Allocate RAM for the main struct - } - - if (packetUBXRXMPMP->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("setAutoRXMPMPcallback: RAM alloc failed!")); -#endif - return (false); - } - - packetUBXRXMPMP->callbackPointer = callbackPointer; - return (true); -} - // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! bool SFE_UBLOX_GNSS::setAutoRXMPMPcallbackPtr(void (*callbackPointer)(UBX_RXM_PMP_data_t *)) { @@ -11084,7 +11047,6 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMPMP() return (false); } packetUBXRXMPMP->automaticFlags.flags.all = 0; - packetUBXRXMPMP->callbackPointer = NULL; packetUBXRXMPMP->callbackPointerPtr = NULL; packetUBXRXMPMP->callbackData = NULL; packetUBXRXMPMP->moduleQueried = false; @@ -13069,7 +13031,7 @@ bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) //The GPS is automatically reporting, we just check whether we got unread data // if (_printDebug == true) // { - // _debugSerial->println(F("getHNRDyn: Autoreporting")); + // _debugSerial->println(F("getHNRINS: Autoreporting")); // } checkUbloxInternal(&packetCfg, UBX_CLASS_HNR, UBX_HNR_INS); return packetUBXHNRINS->moduleQueried.moduleQueried.bits.all; @@ -13079,7 +13041,7 @@ bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) //Someone else has to call checkUblox for us... // if (_printDebug == true) // { - // _debugSerial->println(F("getHNRDyn: Exit immediately")); + // _debugSerial->println(F("getHNRINS: Exit immediately")); // } return (false); } @@ -13087,7 +13049,7 @@ bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) { // if (_printDebug == true) // { - // _debugSerial->println(F("getHNRDyn: Polling")); + // _debugSerial->println(F("getHNRINS: Polling")); // } //The GPS is not automatically reporting HNR vehicle dynamics so we have to poll explicitly @@ -13106,14 +13068,14 @@ bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) { // if (_printDebug == true) // { - // _debugSerial->println(F("getHNRDyn: data in packetCfg was OVERWRITTEN by another message (but that's OK)")); + // _debugSerial->println(F("getHNRINS: data in packetCfg was OVERWRITTEN by another message (but that's OK)")); // } return (true); } // if (_printDebug == true) // { - // _debugSerial->print(F("getHNRDyn retVal: ")); + // _debugSerial->print(F("getHNRINS retVal: ")); // _debugSerial->println(statusString(retVal)); // } return (false); @@ -13122,21 +13084,21 @@ bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRDyn +//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS //works. bool SFE_UBLOX_GNSS::setAutoHNRINS(bool enable, uint16_t maxWait) { return setAutoHNRINSrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRDyn +//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS //works. bool SFE_UBLOX_GNSS::setAutoHNRINS(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoHNRINSrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRDyn +//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS //works. bool SFE_UBLOX_GNSS::setAutoHNRINSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { @@ -13181,7 +13143,7 @@ bool SFE_UBLOX_GNSS::setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_d { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - _debugSerial->println(F("setAutoHNRDyncallback: RAM alloc failed!")); + _debugSerial->println(F("setAutoHNRINScallback: RAM alloc failed!")); #endif return (false); } @@ -13206,7 +13168,7 @@ bool SFE_UBLOX_GNSS::setAutoHNRINScallbackPtr(void (*callbackPointerPtr)(UBX_HNR { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - _debugSerial->println(F("setAutoHNRDyncallbackPtr: RAM alloc failed!")); + _debugSerial->println(F("setAutoHNRINScallbackPtr: RAM alloc failed!")); #endif return (false); } diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 9c10900..e675cfe 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1096,7 +1096,6 @@ class SFE_UBLOX_GNSS // Note: on the NEO-D9S, the UBX-RXM-PMP messages are enabled by default on all ports. // You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 0) // The NEO-D9S does not support UBX-CFG-MSG - bool setAutoRXMPMPcallback(void (*callbackPointer)(UBX_RXM_PMP_data_t)); // Callback is passed all of the data. Heavy on the stack. May cause problems on some platforms. bool setAutoRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index d20be08..216c071 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1513,7 +1513,6 @@ typedef struct ubxAutomaticFlags automaticFlags; UBX_RXM_PMP_data_t data; bool moduleQueried; - void (*callbackPointer)(UBX_RXM_PMP_data_t); void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *); UBX_RXM_PMP_data_t *callbackData; } UBX_RXM_PMP_t; From bfe14038fffef7cc83b5f736d46c2b187809bfc2 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 7 Feb 2022 10:50:31 +0000 Subject: [PATCH 107/122] Create Example19_LBand_Corrections_with_NEO-D9S.ino --- ...ample19_LBand_Corrections_with_NEO-D9S.ino | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino diff --git a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino new file mode 100644 index 0000000..72453b3 --- /dev/null +++ b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino @@ -0,0 +1,199 @@ +/* + Use the NEO-D9S L-Band receiver to provide corrections to a ZED-F9x via UBX-RXM-PMP messages + By: SparkFun Electronics / Paul Clark + Based on original code by: u-blox AG / Michael Ammann + Date: February 7th, 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 obtain SPARTN correction data from a NEO-D9S L-Band receiver and push it over I2C to a ZED-F9x. + + This is a proof of concept to show how the UBX-RXM-PMP corrections control the accuracy. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + NEO-D9S: Coming soon! + + Hardware Connections: + Use Qwiic cables to connect the NEO-D9S and ZED-F9x GNSS to your board + 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 //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; // ZED-F9x +SFE_UBLOX_GNSS myLBand; // NEO-D9S + +const uint32_t myLBandFreq = 1556290000; // Uncomment this line to use the US SPARTN 1.8 service +//const uint32_t myLBandFreq = 1545260000; // Uncomment this line to use the EU SPARTN 1.8 service + +#define OK(ok) (ok ? F(" -> OK") : F(" -> ERROR!")) // Convert uint8_t into OK/ERROR + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: pushRXMPMP will be called when new PMP data arrives +// See u-blox_structs.h for the full definition of UBX_RXM_PMP_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMPMPcallbackPtr +// / _____ This _must_ be UBX_RXM_PMP_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void pushRXMPMP(UBX_RXM_PMP_data_t *pmpData) +{ + //Push the PMP data to the GNSS + Serial.print(F("New RXM-PMP data received. Message version is 0x0")); + Serial.print(pmpData->version, HEX); + Serial.print(F(". numBytesUserData is ")); + size_t numDataBytes = 504; // Version 0x00 messages always contain 504 bytes of userData + if (pmpData->version == 0x01) + numDataBytes = pmpData->numBytesUserData; + Serial.print(numDataBytes); + Serial.println(F(". Pushing them to the GNSS...")); + + myGNSS.pushRawData(pmpData->userData, numDataBytes); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Callback: printPVTdata will be called when new NAV PVT data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallbackPtr +// / _____ This _must_ be UBX_NAV_PVT_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) +{ + long latitude = ubxDataStruct->lat; // Print the latitude + Serial.print(F("Lat: ")); + Serial.print(latitude / 10000000L); + Serial.print(F(".")); + Serial.print(abs(latitude % 10000000L)); + + long longitude = ubxDataStruct->lon; // Print the longitude + Serial.print(F(" Long: ")); + Serial.print(longitude / 10000000L); + Serial.print(F(".")); + Serial.print(abs(longitude % 10000000L)); + + long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level + Serial.print(F(" Height: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + uint8_t fixType = ubxDataStruct->fixType; // Print the fix type + Serial.print(F(" Fix: ")); + Serial.print(fixType); + if (fixType == 0) + Serial.print(F(" (None)")); + else if (fixType == 1) + Serial.print(F(" (Dead Reckoning)")); + else if (fixType == 2) + Serial.print(F(" (2D)")); + else if (fixType == 3) + Serial.print(F(" (3D)")); + else if (fixType == 3) + Serial.print(F(" (GNSS + Dead Reckoning)")); + else if (fixType == 5) + Serial.print(F(" (Time Only)")); + else + Serial.print(F(" (UNKNOWN)")); + + uint8_t carrSoln = ubxDataStruct->flags.bits.carrSoln; // Print the carrier solution + Serial.print(F(" Carrier Solution: ")); + Serial.print(carrSoln); + if (carrSoln == 0) + Serial.print(F(" (None)")); + else if (carrSoln == 1) + Serial.print(F(" (Floating)")); + else if (carrSoln == 2) + Serial.print(F(" (Fixed)")); + else + Serial.print(F(" (UNKNOWN)")); + + uint32_t hAcc = ubxDataStruct->hAcc; // Print the horizontal accuracy estimate + Serial.print(F(" Horizontal Accuracy Estimate: ")); + Serial.print(hAcc); + Serial.print(F(" (mm)")); + + Serial.println(); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + Serial.begin(115200); + Serial.println(F("NEO-D9S SPARTN Corrections")); + + Wire.begin(); //Start I2C + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Begin and configure the ZED-F9x + + //myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + while (myGNSS.begin() == false) //Connect to the u-blox module using Wire port + { + Serial.println(F("u-blox GNSS module not detected at default I2C address. Please check wiring.")); + delay(2000); + } + Serial.println(F("u-blox GNSS module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN); //Be sure SPARTN input is enabled + + myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible + + myGNSS.setNavigationFrequency(1); //Set output in Hz. + + myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed + + //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Begin and configure the NEO-D9S L-Band receiver + + //myLBand.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + while (myLBand.begin(Wire, 0x43) == false) //Connect to the u-blox NEO-D9S using Wire port. The D9S default I2C address is 0x43 (not 0x42) + { + Serial.println(F("u-blox NEO-D9S not detected at default I2C address. Please check wiring.")); + delay(2000); + } + Serial.println(F("u-blox NEO-D9S connected")); + + uint8_t ok = myLBand.setVal32(UBLOX_CFG_PMP_CENTER_FREQUENCY, myLBandFreq); // Default 1539812500 Hz + if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SEARCH_WINDOW, 2200); // Default 2200 Hz + if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_SERVICE_ID, 0); // Default 1 + if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SERVICE_ID, 21845); // Default 50821 + if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_DATA_RATE, 2400); // Default 2400 bps + if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_DESCRAMBLER, 1); // Default 1 + if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_DESCRAMBLER_INIT, 26969); // Default 23560 + if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_PRESCRAMBLING, 0); // Default 0 + if (ok) ok = myLBand.setVal64(UBLOX_CFG_PMP_UNIQUE_WORD, 16238547128276412563ull); + if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 1); // Ensure UBX-RXM-PMP is enabled on the I2C port + if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 1); // Output UBX-RXM-PMP on UART1 + if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2, 1); // Output UBX-RXM-PMP on UART2 + if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART1_BAUDRATE, 38400); // match baudrate with ZED default + if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART2_BAUDRATE, 38400); // match baudrate with ZED default + Serial.print(F("L-Band: configuration ")); + Serial.println(OK(ok)); + + myLBand.softwareResetGNSSOnly(); // Do a restart + + myLBand.setAutoRXMPMPcallbackPtr(&pushRXMPMP); // Call pushRXMPMP when new PMP data arrives. Push it to the GNSS + +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + myGNSS.checkUblox(); // Check for the arrival of new GNSS data and process it. + myGNSS.checkCallbacks(); // Check if any GNSS callbacks are waiting to be processed. + + myLBand.checkUblox(); // Check for the arrival of new PMP data and process it. + myLBand.checkCallbacks(); // Check if any LBand callbacks are waiting to be processed. +} From eaccb5f378e8dcf64b92523aa8da5c5ffeff0106 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 7 Feb 2022 11:39:20 +0000 Subject: [PATCH 108/122] Update README - include PointPerfect and NEO-D9S --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6b233a4..0b6e577 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,13 @@ u-blox makes some incredible GNSS receivers covering everything from low-cost, h This library can be installed via the Arduino Library manager. Search for **SparkFun u-blox GNSS**. -## Automatic support for correction services like RTK2go, Emlid Caster and Skylark (Swift Navigation) +## Automatic support for correction services like PointPerfect (u-blox), RTK2go, Emlid Caster and Skylark (Swift Navigation) -RTK NTRIP corrections services often require you to send them your location in NMEA GPGGA format. v2.2 of the library makes this easy by providing get functions and automatic callbacks +u-blox's PointPerfect GNSS augmentation service uses the secure MQTT protocol to download SPARTN format correction data, providing "3-6 cm accuracy and convergence within seconds". Please see the new [PointPerfect Client example](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/tree/main/examples/ZED-F9P/Example18_PointPerfectClient) for more details. + +v2.3 also supports L-band correction services using the new u-blox NEO-D9S correction data receiver. Please see the new [L-band Corrections example](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/tree/main/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S) for more details. + +Other RTK NTRIP corrections services often require you to send them your location in NMEA GPGGA format. v2.2 of the library makes this easy by providing get functions and automatic callbacks for both GPGGA and GNGGA messages. You can now instruct your module to output GPGGA (e.g.) every 10 seconds and then push it to the correction server directly from the callback. No more polling, no more parsing! v2.2 also includes two new functions useful for correction services: From 134299fe27b829566add158e2fc5bd0c73d5eb8d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 10 Feb 2022 11:17:59 +0000 Subject: [PATCH 109/122] Add extra config keys for F9-HPG-1.30 --- ...eDescription_UBX-21046737_keys_sorted.txt} | 190 +++++++++++++++++- keys/u-blox_config_keys_sorted.txt | 32 +++ src/u-blox_config_keys.h | 40 +++- 3 files changed, 257 insertions(+), 5 deletions(-) rename keys/{ZED-F9P_InterfaceDescription_(UBX-18010854)_keys_sorted.txt => u-blox-F9-HPG-1.30_InterfaceDescription_UBX-21046737_keys_sorted.txt} (77%) diff --git a/keys/ZED-F9P_InterfaceDescription_(UBX-18010854)_keys_sorted.txt b/keys/u-blox-F9-HPG-1.30_InterfaceDescription_UBX-21046737_keys_sorted.txt similarity index 77% rename from keys/ZED-F9P_InterfaceDescription_(UBX-18010854)_keys_sorted.txt rename to keys/u-blox-F9-HPG-1.30_InterfaceDescription_UBX-21046737_keys_sorted.txt index c7dd085..7c16f91 100644 --- a/keys/ZED-F9P_InterfaceDescription_(UBX-18010854)_keys_sorted.txt +++ b/keys/u-blox-F9-HPG-1.30_InterfaceDescription_UBX-21046737_keys_sorted.txt @@ -6,6 +6,9 @@ 0x10110013 0x10110025 0x10110061 +0x101100d7 +0x10170001 +0x10170002 0x10220001 0x10220002 0x10220003 @@ -47,7 +50,6 @@ 0x10510003 0x10520005 0x10530005 -0x10530006 0x10640002 0x10640003 0x10640005 @@ -57,30 +59,35 @@ 0x10710001 0x10710002 0x10710004 +0x10710005 0x10720001 0x10720002 0x10720004 0x10730001 0x10730002 0x10730004 +0x10730005 0x10740001 0x10740002 0x10740004 0x10750001 0x10750002 0x10750004 +0x10750005 0x10760001 0x10760002 0x10760004 0x10770001 0x10770002 0x10770004 +0x10770005 0x10780001 0x10780002 0x10780004 0x10790001 0x10790002 0x10790004 +0x10790005 0x107a0001 0x107a0002 0x107a0004 @@ -115,6 +122,7 @@ 0x10de0002 0x10de0003 0x10de0004 +0x10f60009 0x20030001 0x20030002 0x20030006 @@ -126,6 +134,7 @@ 0x2005000c 0x20050023 0x20050030 +0x20050035 0x20090009 0x20110011 0x2011001c @@ -259,6 +268,11 @@ 0x20910080 0x20910081 0x20910082 +0x20910083 +0x20910084 +0x20910085 +0x20910086 +0x20910087 0x20910088 0x20910089 0x2091008a @@ -539,6 +553,176 @@ 0x20910402 0x20910403 0x20910404 +0x20910415 +0x20910416 +0x20910417 +0x20910418 +0x20910419 +0x20910430 +0x20910431 +0x20910432 +0x20910433 +0x20910434 +0x20910435 +0x20910436 +0x20910437 +0x20910438 +0x20910439 +0x20910465 +0x20910466 +0x20910467 +0x20910468 +0x20910469 +0x20910475 +0x20910476 +0x20910477 +0x20910478 +0x20910479 +0x20910480 +0x20910481 +0x20910482 +0x20910483 +0x20910484 +0x20910485 +0x20910486 +0x20910487 +0x20910488 +0x20910489 +0x20910490 +0x20910491 +0x20910492 +0x20910493 +0x20910494 +0x20910495 +0x20910496 +0x20910497 +0x20910498 +0x20910499 +0x20910500 +0x20910501 +0x20910502 +0x20910503 +0x20910504 +0x20910505 +0x20910506 +0x20910507 +0x20910508 +0x20910509 +0x20910510 +0x20910511 +0x20910512 +0x20910513 +0x20910514 +0x20910515 +0x20910516 +0x20910517 +0x20910518 +0x20910519 +0x20910520 +0x20910521 +0x20910522 +0x20910523 +0x20910524 +0x20910525 +0x20910526 +0x20910527 +0x20910528 +0x20910529 +0x20910530 +0x20910531 +0x20910532 +0x20910533 +0x20910534 +0x20910535 +0x20910536 +0x20910537 +0x20910538 +0x20910539 +0x20910540 +0x20910541 +0x20910542 +0x20910543 +0x20910544 +0x20910545 +0x20910546 +0x20910547 +0x20910548 +0x20910549 +0x20910550 +0x20910551 +0x20910552 +0x20910553 +0x20910554 +0x20910555 +0x20910556 +0x20910557 +0x20910558 +0x20910559 +0x20910560 +0x20910561 +0x20910562 +0x20910563 +0x20910564 +0x20910565 +0x20910566 +0x20910567 +0x20910568 +0x20910569 +0x20910575 +0x20910576 +0x20910577 +0x20910578 +0x20910579 +0x20910605 +0x20910606 +0x20910607 +0x20910608 +0x20910609 +0x20910652 +0x20910653 +0x20910654 +0x20910655 +0x20910656 +0x20910657 +0x20910658 +0x20910659 +0x2091065a +0x2091065b +0x2091065c +0x2091065d +0x2091065e +0x2091065f +0x20910660 +0x20910661 +0x20910662 +0x20910663 +0x20910664 +0x20910665 +0x20910666 +0x20910667 +0x20910668 +0x20910669 +0x2091066a +0x20910670 +0x20910671 +0x20910672 +0x20910673 +0x20910674 +0x2091067f +0x20910680 +0x20910681 +0x20910682 +0x20910683 +0x2091069d +0x2091069e +0x2091069f +0x209106a0 +0x209106a1 +0x209106b6 +0x209106b7 +0x209106b8 +0x209106b9 +0x209106ba 0x20920001 0x20920002 0x20920003 @@ -562,6 +746,7 @@ 0x20a30054 0x20a30055 0x20a30056 +0x20a70001 0x20c70003 0x30050001 0x30090001 @@ -575,6 +760,7 @@ 0x30210001 0x30210002 0x3025003b +0x30370008 0x3065000a 0x3065000b 0x3065000c @@ -583,6 +769,8 @@ 0x30de0005 0x30de0006 0x30de0007 +0x30f6000a +0x30f6000b 0x40030003 0x40030004 0x40030005 diff --git a/keys/u-blox_config_keys_sorted.txt b/keys/u-blox_config_keys_sorted.txt index 7f0462f..37026f2 100644 --- a/keys/u-blox_config_keys_sorted.txt +++ b/keys/u-blox_config_keys_sorted.txt @@ -24,6 +24,7 @@ 0x10110019 0x10110025 0x10110061 +0x101100d7 0x10170001 0x10170002 0x10220001 @@ -643,6 +644,11 @@ 0x20910402 0x20910403 0x20910404 +0x20910415 +0x20910416 +0x20910417 +0x20910418 +0x20910419 0x20910430 0x20910431 0x20910432 @@ -693,11 +699,21 @@ 0x20910507 0x20910508 0x20910509 +0x20910510 +0x20910511 +0x20910512 +0x20910513 +0x20910514 0x20910515 0x20910516 0x20910517 0x20910518 0x20910519 +0x20910520 +0x20910521 +0x20910522 +0x20910523 +0x20910524 0x20910525 0x20910526 0x20910527 @@ -743,6 +759,11 @@ 0x20910567 0x20910568 0x20910569 +0x20910575 +0x20910576 +0x20910577 +0x20910578 +0x20910579 0x20910590 0x20910591 0x20910592 @@ -808,6 +829,16 @@ 0x2091068b 0x2091068c 0x2091068d +0x2091069d +0x2091069e +0x2091069f +0x209106a0 +0x209106a1 +0x209106b6 +0x209106b7 +0x209106b8 +0x209106b9 +0x209106ba 0x20920001 0x20920002 0x20920003 @@ -831,6 +862,7 @@ 0x20a30054 0x20a30055 0x20a30056 +0x20a70001 0x20c70003 0x20d0000b 0x30050001 diff --git a/src/u-blox_config_keys.h b/src/u-blox_config_keys.h index 90d7f88..82093ab 100644 --- a/src/u-blox_config_keys.h +++ b/src/u-blox_config_keys.h @@ -381,6 +381,11 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_SPI = 0x2091038f; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART1 = 0x2091038c; // Output rate of the UBX-MON-SPAN message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART2 = 0x2091038d; // Output rate of the UBX-MON-SPAN message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_USB = 0x2091038e; // Output rate of the UBX-MON-SPAN message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_I2C = 0x2091069d; // Output rate of the UBX-MON-SYS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_SPI = 0x209106a1; // Output rate of the UBX-MON-SYS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_UART1 = 0x2091069e; // Output rate of the UBX-MON-SYS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_UART2 = 0x2091069f; // Output rate of the UBX-MON-SYS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_USB = 0x209106a0; // Output rate of the UBX-MON-SYS message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_I2C = 0x2091019b; // Output rate of the UBX-MON-TXBUF message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_SPI = 0x2091019f; // Output rate of the UBX-MON-TXBUF message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_UART1 = 0x2091019c; // Output rate of the UBX-MON-TXBUF message on port UART1 @@ -431,6 +436,11 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_SPI = 0x20910014; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART1 = 0x20910011; // Output rate of the UBX-NAV-ORB message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART2 = 0x20910012; // Output rate of the UBX-NAV-ORB message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_USB = 0x20910013; // Output rate of the UBX-NAV-ORB message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_I2C 0x20910415; // Output rate of the UBX-NAV-PL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_SPI 0x20910419; // Output rate of the UBX-NAV-PL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART1 0x20910416; // Output rate of the UBX-NAV-PL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART2 0x20910417; // Output rate of the UBX-NAV-PL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_USB 0x20910418; // Output rate of the UBX-NAV-PL message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_I2C = 0x20910024; // Output rate of the UBX-NAV-POSECEF message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_SPI = 0x20910028; // Output rate of the UBX-NAV-POSECEF message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_UART1 = 0x20910025;// Output rate of the UBX-NAV-POSECEF message on port UART1 @@ -447,10 +457,10 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_UART1 = 0x20910007; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_UART2 = 0x20910008; // Output rate of the UBX-NAV-PVT message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_USB = 0x20910009; // Output rate of the UBX-NAV-PVT message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_I2C = 0x2091008d; // Output rate of the UBX-NAV-RELPOSNED message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_SPI = 0x20910091;// Output rate of the UBX-NAV-RELPOSNED message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART1 = 0x2091008e;// Output rate of the UBX-NAV-RELPOSNED message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART2 = 0x2091008f;// Output rate of the UBX-NAV-RELPOSNED message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_USB = 0x20910090;// Output rate of the UBX-NAV-RELPOSNED message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_SPI = 0x20910091; // Output rate of the UBX-NAV-RELPOSNED message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART1 = 0x2091008e; // Output rate of the UBX-NAV-RELPOSNED message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART2 = 0x2091008f; // Output rate of the UBX-NAV-RELPOSNED message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_USB = 0x20910090; // Output rate of the UBX-NAV-RELPOSNED message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_I2C = 0x20910015; // Output rate of the UBX-NAV-SAT message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_SPI = 0x20910019; // Output rate of the UBX-NAV-SAT message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_UART1 = 0x20910016; // Output rate of the UBX-NAV-SAT message on port UART1 @@ -526,6 +536,11 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_SPI = 0x20910046; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_UART1 = 0x20910043; // Output rate of the UBX-NAV-VELNED message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_UART2 = 0x20910044; // Output rate of the UBX-NAV-VELNED message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_USB = 0x20910045; // Output rate of the UBX-NAV-VELNED message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_I2C = 0x209106b6; // Output rate of the UBX-RXM-COR message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_SPI = 0x209106ba; // Output rate of the UBX-RXM-COR message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_UART1 = 0x209106b7; // Output rate of the UBX-RXM-COR message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_UART2 = 0x209106b8; // Output rate of the UBX-RXM-COR message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_USB = 0x209106b9; // Output rate of the UBX-RXM-COR message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_I2C = 0x20910204; // Output rate of the UBX-RXM-MEASX message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_SPI = 0x20910208; // Output rate of the UBX-RXM-MEASX message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_UART1 = 0x20910205; // Output rate of the UBX-RXM-MEASX message on port UART1 @@ -718,11 +733,21 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_SPI = 0x20910509; // Output rate of const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_UART1 = 0x20910506; // Output rate of the UBX-NAV2-SIG message onport UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_UART2 = 0x20910507; // Output rate of the UBX-NAV2-SIG message onport UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_USB = 0x20910508; // Output rate of the UBX-NAV2-SIG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_I2C = 0x20910510; // Output rate of the UBX-NAV2-SLAS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_SPI = 0x20910514; // Output rate of the UBX-NAV2-SLAS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_UART1 = 0x20910511; // Output rate of the UBX-NAV2-SLAS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_UART2 = 0x20910512; // Output rate of the UBX-NAV2-SLAS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_USB = 0x20910513; // Output rate of the UBX-NAV2-SLAS message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_I2C = 0x20910515; // Output rate of the UBX-NAV2-STATUS message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_SPI = 0x20910519; // Output rate of the UBX-NAV2-STATUS message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_UART1 = 0x20910516; // Output rate of the UBX-NAV2-STATUS message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_UART2 = 0x20910517; // Output rate of the UBX-NAV2-STATUS message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_USB = 0x20910518; // Output rate of the UBX-NAV2-STATUS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_I2C = 0x20910520; // Output rate of the UBX-NAV2-SVIN message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_SPI = 0x20910524; // Output rate of the UBX-NAV2-SVIN message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_UART1 = 0x20910521; // Output rate of the UBX-NAV2-SVIN message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_UART2 = 0x20910522; // Output rate of the UBX-NAV2-SVIN message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_USB = 0x20910523; // Output rate of the UBX-NAV2-SVIN message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_I2C = 0x20910525; // Output rate of the UBX-NAV2-TIMEBDS message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_SPI = 0x20910529; // Output rate of the UBX-NAV2-TIMEBDS message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_UART1 = 0x20910526; // Output rate of the UBX-NAV2-TIMEBDS message on port UART1 @@ -748,6 +773,11 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_SPI = 0x20910549; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_UART1 = 0x20910546; // Output rate of the UBX-NAV2-TIMELS message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_UART2 = 0x20910547; // Output rate of the UBX-NAV2-TIMELS message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_USB = 0x20910548; // Output rate of the UBX-NAV2-TIMELS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_I2C = 0x20910575; // Output rate of the UBX-NAV2-TIMEQZSS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_SPI = 0x20910579; // Output rate of the UBX-NAV2-TIMEQZSS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_UART1 = 0x20910576; // Output rate of the UBX-NAV2-TIMEQZSS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_UART2 = 0x20910577; // Output rate of the UBX-NAV2-TIMEQZSS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_USB = 0x20910578; // Output rate of the UBX-NAV2-TIMEQZSS message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_I2C = 0x20910550; // Output rate of the UBX-NAV2-TIMEUTC message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_SPI = 0x20910554; // Output rate of the UBX-NAV2-TIMEUTC message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_UART1 = 0x20910551; // Output rate of the UBX-NAV2-TIMEUTC message on port UART1 @@ -840,6 +870,7 @@ const uint32_t UBLOX_CFG_NAVSPG_CONSTR_ALT = 0x401100c1; // Fixed altitude (mean const uint32_t UBLOX_CFG_NAVSPG_CONSTR_ALTVAR = 0x401100c2; // Fixed altitude variance for 2D mode const uint32_t UBLOX_CFG_NAVSPG_CONSTR_DGNSSTO = 0x201100c4; // DGNSS timeout const uint32_t UBLOX_CFG_NAVSPG_SIGATTCOMP = 0x201100d6; // Permanently attenuated signal compensation mode +const uint32_t UBLOX_CFG_NAVSPG_PL_ENA = 0x101100d7; // Enable Protection level. If enabled, protection level computing will be on. //CFG-NMEA: NMEA protocol configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -903,6 +934,7 @@ const uint32_t UBLOX_CFG_PMP_UNIQUE_WORD = 0x50b1001a; // Unique word. Defines v const uint32_t UBLOX_CFG_QZSS_USE_SLAS_DGNSS = 0x10370005; // Apply QZSS SLAS DGNSS corrections const uint32_t UBLOX_CFG_QZSS_USE_SLAS_TESTMODE = 0x10370006; // Use QZSS SLAS data when it is in test mode (SLAS msg 0) const uint32_t UBLOX_CFG_QZSS_USE_SLAS_RAIM_UNCORR = 0x10370007; // Raim out measurements that are not corrected by QZSS SLAS, if at least 5 measurements are corrected +const uint32_t UBLOX_CFG_QZSS_SLAS_MAX_BASELINE = 0x30370008; // Maximum baseline distance to closest Ground Monitoring Station: km //CFG-RATE: Navigation and measurement rate configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- From dba2cffa61be0e5b94ce0df9f118e5caef862522 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 10 Feb 2022 11:20:49 +0000 Subject: [PATCH 110/122] Update u-blox_config_keys_sorted.txt --- keys/u-blox_config_keys_sorted.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/keys/u-blox_config_keys_sorted.txt b/keys/u-blox_config_keys_sorted.txt index 37026f2..e6cc655 100644 --- a/keys/u-blox_config_keys_sorted.txt +++ b/keys/u-blox_config_keys_sorted.txt @@ -886,6 +886,7 @@ 0x30210001 0x30210002 0x3025003b +0x30370008 0x3065000a 0x3065000b 0x3065000c From 1d7621d25e14d73151f6bc86f06059951633df3c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 10 Feb 2022 15:42:53 +0000 Subject: [PATCH 111/122] Add setDynamicSPARTNKey --- keywords.txt | 3 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 134 +++++++++++++++++-- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 18 ++- src/u-blox_config_keys.h | 18 +-- 4 files changed, 154 insertions(+), 19 deletions(-) diff --git a/keywords.txt b/keywords.txt index 7ee9bd2..bba5c7f 100644 --- a/keywords.txt +++ b/keywords.txt @@ -178,6 +178,9 @@ setAckAiding KEYWORD2 getAopCfg KEYWORD2 setAopCfg KEYWORD2 +setDynamicSPARTNKey KEYWORD2 +setDynamicSPARTNKeys KEYWORD2 + createKey KEYWORD2 getVal KEYWORD2 getVal8 KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 05da70d..2b6ea37 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -436,14 +436,17 @@ void SFE_UBLOX_GNSS::end(void) //Allow the user to change packetCfgPayloadSize. Handy if you want to process big messages like RAWX //This can be called before .begin if required / desired -void SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) +bool SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) { + bool success = true; + if ((payloadSize == 0) && (payloadCfg != NULL)) { // Zero payloadSize? Dangerous! But we'll free the memory anyway... delete[] payloadCfg; // Created with new[] payloadCfg = NULL; // Redundant? packetCfg.payload = payloadCfg; + packetCfgPayloadSize = payloadSize; if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("setPacketCfgPayloadSize: Zero payloadSize!")); } @@ -453,24 +456,37 @@ void SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) payloadCfg = new uint8_t[payloadSize]; packetCfg.payload = payloadCfg; if (payloadCfg == NULL) + { + success = false; + packetCfgPayloadSize = 0; if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("setPacketCfgPayloadSize: RAM alloc failed!")); + } + else + packetCfgPayloadSize = payloadSize; } else //Memory has already been allocated - so resize { uint8_t *newPayload = new uint8_t[payloadSize]; - for (size_t i = 0; (i < payloadSize) && (i < packetCfgPayloadSize); i++) // Copy as much existing data as we can - newPayload[i] = payloadCfg[i]; - delete[] payloadCfg; // Created with new[] - payloadCfg = newPayload; - packetCfg.payload = payloadCfg; - if (payloadCfg == NULL) + + if (newPayload == NULL) // Check if the alloc was successful + { + success = false; // Report failure. Don't change payloadCfg, packetCfg.payload or packetCfgPayloadSize if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("setPacketCfgPayloadSize: RAM resize failed!")); + } + else + { + memcpy(newPayload, payloadCfg, payloadSize <= packetCfgPayloadSize ? payloadSize : packetCfgPayloadSize); // Copy as much existing data as we can + delete[] payloadCfg; // Free payloadCfg. Created with new[] + payloadCfg = newPayload; // Point to the newPayload + packetCfg.payload = payloadCfg; // Update the packet pointer + packetCfgPayloadSize = payloadSize; // Update the packet payload size + } } - packetCfgPayloadSize = payloadSize; + return (success); } //Initialize the I2C port @@ -7469,6 +7485,108 @@ bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t m return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } +//SPARTN dynamic keys +//"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. +//"Every time the 'current' key is expired, 'next' takes its place." +//"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. +//The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. +bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait) +{ + // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F + bool isASCIIHex = true; + uint16_t i = 0; + while((i < (uint16_t)keyLengthBytes) && (isASCIIHex == true)) + { + if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + if (isASCIIHex) // Check the second half of the ASCII Hex key + { + while((i < ((uint16_t)keyLengthBytes * 2) && (isASCIIHex == true))) + { + if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + } + + // Check if there is room for the key in packetCfg. Resize the buffer if not. + size_t payloadLength = (size_t)keyLengthBytes + 12; + if (packetCfgPayloadSize < payloadLength) + { + if (!setPacketCfgPayloadSize(payloadLength)) // Check if the resize was successful + { + return (false); + } + } + + // Copy the key etc. into packetCfg + packetCfg.cls = UBX_CLASS_RXM; + packetCfg.id = UBX_RXM_SPARTNKEY; + packetCfg.len = payloadLength; + packetCfg.startingSpot = 0; + + payloadCfg[0] = 0x01; // version + payloadCfg[1] = 0x01; // numKeys + payloadCfg[2] = 0x00; // reserved0 + payloadCfg[3] = 0x00; // reserved0 + payloadCfg[4] = 0x00; // reserved1 + payloadCfg[5] = keyLengthBytes; + payloadCfg[6] = validFromWno & 0xFF; // validFromWno little-endian + payloadCfg[7] = validFromWno >> 8; + payloadCfg[8] = validFromTow & 0xFF; // validFromTow little-endian + payloadCfg[9] = (validFromTow >> 8) & 0xFF; + payloadCfg[10] = (validFromTow >> 16) & 0xFF; + payloadCfg[11] = (validFromTow >> 24) & 0xFF; + + if (isASCIIHex) // Convert ASCII Hex key to binary + { + for(i = 0; i < ((uint16_t)keyLengthBytes * 2); i += 2) + { + if ((key[i] >= '0') && (key[i] <= '9')) + { + payloadCfg[12 + (i >> 1)] = (key[i] - '0') << 4; + } + else if ((key[i] >= 'a') && (key[i] <= 'f')) + { + payloadCfg[12 + (i >> 1)] = (key[i] + 10 - 'a') << 4; + } + else // if ((key[i] >= 'A') && (key[i] <= 'F')) + { + payloadCfg[12 + (i >> 1)] = (key[i] + 10 - 'A') << 4; + } + + if ((key[i + 1] >= '0') && (key[i + 1] <= '9')) + { + payloadCfg[12 + (i >> 1)] |= key[i + 1] - '0'; + } + else if ((key[i + 1] >= 'a') && (key[i + 1] <= 'f')) + { + payloadCfg[12 + (i >> 1)] |= key[i + 1] + 10 - 'a'; + } + else // if ((key[i + 1] >= 'A') && (key[i + 1] <= 'F')) + { + payloadCfg[12 + (i >> 1)] |= key[i + 1] + 10 - 'A'; + } + } + } + else // Binary key + { + memcpy(&payloadCfg[12], key, keyLengthBytes); + } + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + +bool SFE_UBLOX_GNSS::setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const uint8_t *key1, + uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2, uint16_t maxWait) +{ + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + // CONFIGURATION INTERFACE (protocol v27 and above) //Form 32-bit key from group/id/size diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index e675cfe..b8f96cf 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -338,6 +338,8 @@ const uint8_t UBX_MON_PATCH = 0x27; //Output information about installed patches const uint8_t UBX_MON_RF = 0x38; //RF information const uint8_t UBX_MON_RXBUF = 0x07; //Receiver Buffer Status const uint8_t UBX_MON_RXR = 0x21; //Receiver Status Information +const uint8_t UBX_MON_SPAN = 0x31; //Signal characteristics +const uint8_t UBX_MON_SYS = 0x39; //Current system performance information const uint8_t UBX_MON_TXBUF = 0x08; //Transmitter Buffer Status. Used for query tx buffer size/state. const uint8_t UBX_MON_VER = 0x04; //Receiver/Software Version. Used for obtaining Protocol Version. @@ -352,6 +354,7 @@ const uint8_t UBX_NAV_HPPOSECEF = 0x13; //High Precision Position Solution in EC const uint8_t UBX_NAV_HPPOSLLH = 0x14; //High Precision Geodetic Position Solution. Used for obtaining lat/long/alt in high precision const uint8_t UBX_NAV_ODO = 0x09; //Odometer Solution const uint8_t UBX_NAV_ORB = 0x34; //GNSS Orbit Database Info +const uint8_t UBX_NAV_PL = 0x62; //Protection Level Information const uint8_t UBX_NAV_POSECEF = 0x01; //Position Solution in ECEF const uint8_t UBX_NAV_POSLLH = 0x02; //Geodetic Position Solution const uint8_t UBX_NAV_PVT = 0x07; //All the things! Position, velocity, time, PDOP, height, h/v accuracies, number of satellites. Navigation Position Velocity Time Solution. @@ -374,14 +377,16 @@ const uint8_t UBX_NAV_AOPSTATUS = 0x60; //AssistNow Autonomous status //Class: RXM //The following are used to configure the RXM UBX messages (receiver manager messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) +const uint8_t UBX_RXM_COR = 0x34; // Differential correction input status const uint8_t UBX_RXM_MEASX = 0x14; //Satellite Measurements for RRLP -const uint8_t UBX_RXM_PMP = 0x72; //PMP raw data (NEO-D9S) (two different versions) (packet size for version 0x01 is variable) +const uint8_t UBX_RXM_PMP = 0x72; //PMP raw data (NEO-D9S) (two different versions) (packet size for version 0x01 is variable) const uint8_t UBX_RXM_PMREQ = 0x41; //Requests a Power Management task (two different packet sizes) const uint8_t UBX_RXM_RAWX = 0x15; //Multi-GNSS Raw Measurement Data const uint8_t UBX_RXM_RLM = 0x59; //Galileo SAR Short-RLM report (two different packet sizes) const uint8_t UBX_RXM_RTCM = 0x32; //RTCM input status const uint8_t UBX_RXM_SFRBX = 0x13; //Broadcast Navigation Data Subframe const uint8_t UBX_RXM_SPARTN = 0x33; //SPARTN input status +const uint8_t UBX_RXM_SPARTNKEY = 0x36; //Poll/transfer dynamic SPARTN keys //Class: SEC //The following are used to configure the SEC UBX messages (security feature messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) @@ -621,7 +626,7 @@ class SFE_UBLOX_GNSS #endif //New in v2.0: allow the payload size for packetCfg to be changed - void setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize + bool setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize //Begin communication with the GNSS. Advanced users can assume success if required. Useful if the port is already outputting messages at high navigation rate. //Begin will then return true if "signs of life" have been seen: reception of _any_ valid UBX packet or _any_ valid NMEA header. @@ -892,6 +897,15 @@ class SFE_UBLOX_GNSS uint8_t getAopCfg(uint16_t maxWait = defaultMaxWait); // Get the AssistNow Autonomous configuration (aopCfg) - returns 255 if the sendCommand fails bool setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr = 0, uint16_t maxWait = defaultMaxWait); // Set the aopCfg byte and the aopOrdMaxErr word + //SPARTN dynamic keys + //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. + //"Every time the 'current' key is expired, 'next' takes its place." + //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. + //The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. + bool setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait = defaultMaxWait); + bool setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const uint8_t *key1, + uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2, uint16_t maxWait = defaultMaxWait); + //General configuration (used only on protocol v27 and higher - ie, ZED-F9P) //It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic. diff --git a/src/u-blox_config_keys.h b/src/u-blox_config_keys.h index 82093ab..9c273de 100644 --- a/src/u-blox_config_keys.h +++ b/src/u-blox_config_keys.h @@ -382,10 +382,10 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART1 = 0x2091038c; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART2 = 0x2091038d; // Output rate of the UBX-MON-SPAN message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_USB = 0x2091038e; // Output rate of the UBX-MON-SPAN message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_I2C = 0x2091069d; // Output rate of the UBX-MON-SYS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_SPI = 0x209106a1; // Output rate of the UBX-MON-SYS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_UART1 = 0x2091069e; // Output rate of the UBX-MON-SYS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_UART2 = 0x2091069f; // Output rate of the UBX-MON-SYS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBXUBX_MON_SYS_USB = 0x209106a0; // Output rate of the UBX-MON-SYS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_SPI = 0x209106a1; // Output rate of the UBX-MON-SYS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_UART1 = 0x2091069e; // Output rate of the UBX-MON-SYS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_UART2 = 0x2091069f; // Output rate of the UBX-MON-SYS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_USB = 0x209106a0; // Output rate of the UBX-MON-SYS message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_I2C = 0x2091019b; // Output rate of the UBX-MON-TXBUF message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_SPI = 0x2091019f; // Output rate of the UBX-MON-TXBUF message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_UART1 = 0x2091019c; // Output rate of the UBX-MON-TXBUF message on port UART1 @@ -436,11 +436,11 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_SPI = 0x20910014; // Output rate const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART1 = 0x20910011; // Output rate of the UBX-NAV-ORB message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART2 = 0x20910012; // Output rate of the UBX-NAV-ORB message on port UART2 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_USB = 0x20910013; // Output rate of the UBX-NAV-ORB message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_I2C 0x20910415; // Output rate of the UBX-NAV-PL message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_SPI 0x20910419; // Output rate of the UBX-NAV-PL message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART1 0x20910416; // Output rate of the UBX-NAV-PL message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART2 0x20910417; // Output rate of the UBX-NAV-PL message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_USB 0x20910418; // Output rate of the UBX-NAV-PL message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_I2C = 0x20910415; // Output rate of the UBX-NAV-PL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_SPI = 0x20910419; // Output rate of the UBX-NAV-PL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART1 = 0x20910416; // Output rate of the UBX-NAV-PL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART2 = 0x20910417; // Output rate of the UBX-NAV-PL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_USB = 0x20910418; // Output rate of the UBX-NAV-PL message on port USB const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_I2C = 0x20910024; // Output rate of the UBX-NAV-POSECEF message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_SPI = 0x20910028; // Output rate of the UBX-NAV-POSECEF message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_UART1 = 0x20910025;// Output rate of the UBX-NAV-POSECEF message on port UART1 From b70cb1ceacb5f4b3cc8ae619466666ef09d0710d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 11 Feb 2022 13:28:38 +0000 Subject: [PATCH 112/122] VSC whitespace changes... Sorry! --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 6333 +++++++++--------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 2987 +++++---- src/u-blox_config_keys.h | 2157 +++--- src/u-blox_structs.h | 924 +-- 4 files changed, 6377 insertions(+), 6024 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 2b6ea37..6789cc3 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1,43 +1,43 @@ /* - This is a library written for the u-blox ZED-F9P and NEO-M8P-2 - SparkFun sells these at its website: www.sparkfun.com - Do you like this library? Help support SparkFun. Buy a board! - https://www.sparkfun.com/products/16481 - https://www.sparkfun.com/products/15136 - https://www.sparkfun.com/products/15005 - https://www.sparkfun.com/products/15733 - https://www.sparkfun.com/products/15193 - https://www.sparkfun.com/products/15210 + This is a library written for the u-blox ZED-F9P and NEO-M8P-2 + SparkFun sells these at its website: www.sparkfun.com + Do you like this library? Help support SparkFun. Buy a board! + https://www.sparkfun.com/products/16481 + https://www.sparkfun.com/products/15136 + https://www.sparkfun.com/products/15005 + https://www.sparkfun.com/products/15733 + https://www.sparkfun.com/products/15193 + https://www.sparkfun.com/products/15210 Original version by Nathan Seidle @ SparkFun Electronics, September 6th, 2018 - v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 - - This library handles configuring and handling the responses - from a u-blox GPS module. Works with most modules from u-blox including - the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. - - https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library - - Development environment specifics: - Arduino IDE 1.8.13 - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). - The MIT License (MIT) - Copyright (c) 2016 SparkFun Electronics - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - associated documentation files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the Software is furnished to - do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 + + This library handles configuring and handling the responses + from a u-blox GPS module. Works with most modules from u-blox including + the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. + + https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library + + Development environment specifics: + Arduino IDE 1.8.13 + + SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). + The MIT License (MIT) + Copyright (c) 2016 SparkFun Electronics + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the Software is furnished to + do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "SparkFun_u-blox_GNSS_Arduino_Library.h" @@ -51,26 +51,26 @@ SFE_UBLOX_GNSS::SFE_UBLOX_GNSS(void) digitalWrite((uint8_t)debugPin, HIGH); } - _logNMEA.all = 0; // Default to passing no NMEA messages to the file buffer + _logNMEA.all = 0; // Default to passing no NMEA messages to the file buffer _processNMEA.all = SFE_UBLOX_FILTER_NMEA_ALL; // Default to passing all NMEA messages to processNMEA - // Support for platforms like ESP32 which do not support multiple I2C restarts - // If _i2cStopRestart is true, endTransmission will always use a stop. If false, a restart will be used where needed. + // Support for platforms like ESP32 which do not support multiple I2C restarts + // If _i2cStopRestart is true, endTransmission will always use a stop. If false, a restart will be used where needed. #if defined(ARDUINO_ARCH_ESP32) - _i2cStopRestart = true; // Always use a stop + _i2cStopRestart = true; // Always use a stop #else - _i2cStopRestart = false; // Use a restart where needed + _i2cStopRestart = false; // Use a restart where needed #endif } -//Stop all automatic message processing. Free all used RAM +// Stop all automatic message processing. Free all used RAM void SFE_UBLOX_GNSS::end(void) { - //Note: payloadCfg is not deleted + // Note: payloadCfg is not deleted - //Note: payloadAuto is not deleted + // Note: payloadAuto is not deleted - if (ubxFileBuffer != NULL) // Check if RAM has been allocated for the file buffer + if (ubxFileBuffer != NULL) // Check if RAM has been allocated for the file buffer { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) @@ -79,8 +79,8 @@ void SFE_UBLOX_GNSS::end(void) } #endif delete[] ubxFileBuffer; // Created with new[] - ubxFileBuffer = NULL; // Redundant? - fileBufferSize = 0; // Reset file buffer size. User will have to call setFileBufferSize again + ubxFileBuffer = NULL; // Redundant? + fileBufferSize = 0; // Reset file buffer size. User will have to call setFileBufferSize again fileBufferMaxAvail = 0; } @@ -431,11 +431,10 @@ void SFE_UBLOX_GNSS::end(void) delete storageNMEAGNGGA; storageNMEAGNGGA = NULL; // Redundant? } - } -//Allow the user to change packetCfgPayloadSize. Handy if you want to process big messages like RAWX -//This can be called before .begin if required / desired +// Allow the user to change packetCfgPayloadSize. Handy if you want to process big messages like RAWX +// This can be called before .begin if required / desired bool SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) { bool success = true; @@ -444,14 +443,14 @@ bool SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) { // Zero payloadSize? Dangerous! But we'll free the memory anyway... delete[] payloadCfg; // Created with new[] - payloadCfg = NULL; // Redundant? + payloadCfg = NULL; // Redundant? packetCfg.payload = payloadCfg; packetCfgPayloadSize = payloadSize; if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("setPacketCfgPayloadSize: Zero payloadSize!")); } - else if (payloadCfg == NULL) //Memory has not yet been allocated - so use new + else if (payloadCfg == NULL) // Memory has not yet been allocated - so use new { payloadCfg = new uint8_t[payloadSize]; packetCfg.payload = payloadCfg; @@ -466,51 +465,51 @@ bool SFE_UBLOX_GNSS::setPacketCfgPayloadSize(size_t payloadSize) packetCfgPayloadSize = payloadSize; } - else //Memory has already been allocated - so resize + else // Memory has already been allocated - so resize { uint8_t *newPayload = new uint8_t[payloadSize]; if (newPayload == NULL) // Check if the alloc was successful { - success = false; // Report failure. Don't change payloadCfg, packetCfg.payload or packetCfgPayloadSize + success = false; // Report failure. Don't change payloadCfg, packetCfg.payload or packetCfgPayloadSize if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging _debugSerial->println(F("setPacketCfgPayloadSize: RAM resize failed!")); } else { memcpy(newPayload, payloadCfg, payloadSize <= packetCfgPayloadSize ? payloadSize : packetCfgPayloadSize); // Copy as much existing data as we can - delete[] payloadCfg; // Free payloadCfg. Created with new[] - payloadCfg = newPayload; // Point to the newPayload - packetCfg.payload = payloadCfg; // Update the packet pointer - packetCfgPayloadSize = payloadSize; // Update the packet payload size + delete[] payloadCfg; // Free payloadCfg. Created with new[] + payloadCfg = newPayload; // Point to the newPayload + packetCfg.payload = payloadCfg; // Update the packet pointer + packetCfgPayloadSize = payloadSize; // Update the packet payload size } } return (success); } -//Initialize the I2C port +// Initialize the I2C port bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t maxWait, bool assumeSuccess) { commType = COMM_TYPE_I2C; - _i2cPort = &wirePort; //Grab which port the user wants us to use - _signsOfLife = false; //Clear the _signsOfLife flag. It will be set true if valid traffic is seen. + _i2cPort = &wirePort; // Grab which port the user wants us to use + _signsOfLife = false; // Clear the _signsOfLife flag. It will be set true if valid traffic is seen. - //We expect caller to begin their I2C port, with the speed of their choice external to the library - //But if they forget, we start the hardware here. + // We expect caller to begin their I2C port, with the speed of their choice external to the library + // But if they forget, we start the hardware here. - //We're moving away from the practice of starting Wire hardware in a library. This is to avoid cross platform issues. - //ie, there are some platforms that don't handle multiple starts to the wire hardware. Also, every time you start the wire - //hardware the clock speed reverts back to 100kHz regardless of previous Wire.setClocks(). + // We're moving away from the practice of starting Wire hardware in a library. This is to avoid cross platform issues. + // ie, there are some platforms that don't handle multiple starts to the wire hardware. Also, every time you start the wire + // hardware the clock speed reverts back to 100kHz regardless of previous Wire.setClocks(). //_i2cPort->begin(); - _gpsI2Caddress = deviceAddress; //Store the I2C address from user + _gpsI2Caddress = deviceAddress; // Store the I2C address from user - //New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already) + // New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already) if (packetCfgPayloadSize == 0) setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE); - //New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) + // New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) createFileBuffer(); // Call isConnected up to three times - tests on the NEO-M8U show the CFG RATE poll occasionally being ignored @@ -538,7 +537,7 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t ma connected = isConnected(maxWait); } - if ((!connected ) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + if ((!connected) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -552,26 +551,26 @@ bool SFE_UBLOX_GNSS::begin(TwoWire &wirePort, uint8_t deviceAddress, uint16_t ma return (connected); } -//Initialize the Serial port +// Initialize the Serial port bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool assumeSuccess) { commType = COMM_TYPE_SERIAL; - _serialPort = &serialPort; //Grab which port the user wants us to use - _signsOfLife = false; //Clear the _signsOfLife flag. It will be set true if valid traffic is seen. + _serialPort = &serialPort; // Grab which port the user wants us to use + _signsOfLife = false; // Clear the _signsOfLife flag. It will be set true if valid traffic is seen. - //New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already) + // New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already) if (packetCfgPayloadSize == 0) setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE); - //New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) + // New in v2.0: allocate memory for the file buffer - if required. (The user should have called setFileBufferSize already) createFileBuffer(); - //Get rid of any stale serial data already in the processor's RX buffer + // Get rid of any stale serial data already in the processor's RX buffer while (_serialPort->available()) _serialPort->read(); - //If assumeSuccess is true, the user must really want begin to succeed. So, let's empty the module's serial transmit buffer too! - //Keep discarding new serial data until we see a gap of 2ms - hopefully indicating that the module's TX buffer is empty. + // If assumeSuccess is true, the user must really want begin to succeed. So, let's empty the module's serial transmit buffer too! + // Keep discarding new serial data until we see a gap of 2ms - hopefully indicating that the module's TX buffer is empty. if (assumeSuccess) { unsigned long startTime = millis(); @@ -615,7 +614,7 @@ bool SFE_UBLOX_GNSS::begin(Stream &serialPort, uint16_t maxWait, bool assumeSucc connected = isConnected(maxWait); } - if ((!connected ) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + if ((!connected) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -636,26 +635,26 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, _spiPort = &spiPort; _csPin = csPin; _spiSpeed = spiSpeed; - _signsOfLife = false; //Clear the _signsOfLife flag. It will be set true if valid traffic is seen. + _signsOfLife = false; // Clear the _signsOfLife flag. It will be set true if valid traffic is seen. // Initialize the chip select pin pinMode(_csPin, OUTPUT); digitalWrite(_csPin, HIGH); - //New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already) + // New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already) if (packetCfgPayloadSize == 0) setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE); - + createFileBuffer(); - - //Create the SPI buffer - if (spiBuffer == NULL) //Memory has not yet been allocated - so use new + + // Create the SPI buffer + if (spiBuffer == NULL) // Memory has not yet been allocated - so use new { spiBuffer = new uint8_t[getSpiTransactionSize()]; } - + if (spiBuffer == NULL) - { + { if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { _debugSerial->print(F("begin (SPI): memory allocation failed for SPI Buffer!")); @@ -665,7 +664,7 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, else { // Initialize/clear the SPI buffer - fill it with 0xFF as this is what is received from the UBLOX module if there's no data to be processed - for (uint8_t i = 0; i < getSpiTransactionSize(); i++) + for (uint8_t i = 0; i < getSpiTransactionSize(); i++) { spiBuffer[i] = 0xFF; } @@ -696,7 +695,7 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, connected = isConnected(maxWait); } - if ((!connected ) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. + if ((!connected) && assumeSuccess && _signsOfLife) // Advanced users can assume success if required. Useful if the port is outputting messages at high navigation rate. { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -710,7 +709,6 @@ bool SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, return (connected); } - // Allow the user to change I2C polling wait (the minimum interval between I2C data requests - to avoid pounding the bus) // i2cPollingWait defaults to 100ms and is adjusted automatically when setNavigationFrequency() // or setHNRNavigationRate() are called. But if the user is using callbacks, it might be advantageous @@ -727,10 +725,10 @@ void SFE_UBLOX_GNSS::setSPIpollingWait(uint8_t newPollingWait_ms) spiPollingWait = newPollingWait_ms; } -//Sets the global size for I2C transactions -//Most platforms use 32 bytes (the default) but this allows users to increase the transaction -//size if the platform supports it -//Note: If the transaction size is set larger than the platforms buffer size, bad things will happen. +// Sets the global size for I2C transactions +// Most platforms use 32 bytes (the default) but this allows users to increase the transaction +// size if the platform supports it +// Note: If the transaction size is set larger than the platforms buffer size, bad things will happen. void SFE_UBLOX_GNSS::setI2CTransactionSize(uint8_t transactionSize) { if (transactionSize < 8) @@ -743,10 +741,10 @@ uint8_t SFE_UBLOX_GNSS::getI2CTransactionSize(void) return (i2cTransactionSize); } -//Sets the global size for the SPI buffer/transactions. -//Call this **before** begin()! -//Note: if the buffer size is too small, incoming characters may be lost if the message sent -//is larger than this buffer. If too big, you may run out of SRAM on constrained architectures! +// Sets the global size for the SPI buffer/transactions. +// Call this **before** begin()! +// Note: if the buffer size is too small, incoming characters may be lost if the message sent +// is larger than this buffer. If too big, you may run out of SRAM on constrained architectures! void SFE_UBLOX_GNSS::setSpiTransactionSize(uint8_t transactionSize) { if (spiBuffer == NULL) @@ -754,7 +752,7 @@ void SFE_UBLOX_GNSS::setSpiTransactionSize(uint8_t transactionSize) spiTransactionSize = transactionSize; } else - { + { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) { @@ -768,7 +766,7 @@ uint8_t SFE_UBLOX_GNSS::getSpiTransactionSize(void) return (spiTransactionSize); } -//Sets the size of maxNMEAByteCount +// Sets the size of maxNMEAByteCount void SFE_UBLOX_GNSS::setMaxNMEAByteCount(int8_t newMax) { maxNMEAByteCount = newMax; @@ -778,14 +776,14 @@ int8_t SFE_UBLOX_GNSS::getMaxNMEAByteCount(void) return (maxNMEAByteCount); } -//Returns true if I2C device ack's +// Returns true if I2C device ack's bool SFE_UBLOX_GNSS::isConnected(uint16_t maxWait) { if (commType == COMM_TYPE_I2C) { _i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); if (_i2cPort->endTransmission() != 0) - return false; //Sensor did not ack + return false; // Sensor did not ack } // Query port configuration to see whether we get a meaningful response @@ -794,31 +792,31 @@ bool SFE_UBLOX_GNSS::isConnected(uint16_t maxWait) return (getPortSettingsInternal(COM_PORT_I2C, maxWait)); else if (commType == COMM_TYPE_SERIAL) return (getPortSettingsInternal(COM_PORT_UART1, maxWait)); // Could be UART2 - but this is just a response check - else // if (commType == COMM_TYPE_SPI) + else // if (commType == COMM_TYPE_SPI) return (getPortSettingsInternal(COM_PORT_SPI, maxWait)); } -//Enable or disable the printing of sent/response HEX values. -//Use this in conjunction with 'Transport Logging' from the Universal Reader Assistant to see what they're doing that we're not +// Enable or disable the printing of sent/response HEX values. +// Use this in conjunction with 'Transport Logging' from the Universal Reader Assistant to see what they're doing that we're not void SFE_UBLOX_GNSS::enableDebugging(Stream &debugPort, bool printLimitedDebug) { - _debugSerial = &debugPort; //Grab which port the user wants us to use for debugging + _debugSerial = &debugPort; // Grab which port the user wants us to use for debugging if (printLimitedDebug == false) { - _printDebug = true; //Should we print the commands we send? Good for debugging + _printDebug = true; // Should we print the commands we send? Good for debugging } else { - _printLimitedDebug = true; //Should we print limited debug messages? Good for debugging high navigation rates + _printLimitedDebug = true; // Should we print limited debug messages? Good for debugging high navigation rates } } void SFE_UBLOX_GNSS::disableDebugging(void) { - _printDebug = false; //Turn off extra print statements + _printDebug = false; // Turn off extra print statements _printLimitedDebug = false; } -//Safely print messages +// Safely print messages void SFE_UBLOX_GNSS::debugPrint(char *message) { if (_printDebug == true) @@ -826,7 +824,7 @@ void SFE_UBLOX_GNSS::debugPrint(char *message) _debugSerial->print(message); } } -//Safely print messages +// Safely print messages void SFE_UBLOX_GNSS::debugPrintln(char *message) { if (_printDebug == true) @@ -890,19 +888,19 @@ const char *SFE_UBLOX_GNSS::statusString(sfe_ublox_status_e stat) // Check for the arrival of new I2C/Serial/SPI data -//Allow the user to disable the "7F" check (e.g.) when logging RAWX data +// Allow the user to disable the "7F" check (e.g.) when logging RAWX data void SFE_UBLOX_GNSS::disableUBX7Fcheck(bool disabled) { ubx7FcheckDisabled = disabled; } -//Called regularly to check for available bytes on the user' specified port +// Called regularly to check for available bytes on the user' specified port bool SFE_UBLOX_GNSS::checkUblox(uint8_t requestedClass, uint8_t requestedID) { return checkUbloxInternal(&packetCfg, requestedClass, requestedID); } -//PRIVATE: Called regularly to check for available bytes on the user' specified port +// PRIVATE: Called regularly to check for available bytes on the user' specified port bool SFE_UBLOX_GNSS::checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID) { if (commType == COMM_TYPE_I2C) @@ -914,17 +912,17 @@ bool SFE_UBLOX_GNSS::checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requeste return false; } -//Polls I2C for data, passing any new bytes to process() -//Returns true if new bytes are available +// Polls I2C for data, passing any new bytes to process() +// Returns true if new bytes are available bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID) { if (millis() - lastCheck >= i2cPollingWait) { - //Get the number of bytes available from the module + // Get the number of bytes available from the module uint16_t bytesAvailable = 0; _i2cPort->beginTransmission(_gpsI2Caddress); - _i2cPort->write(0xFD); //0xFD (MSB) and 0xFE (LSB) are the registers that contain number of bytes available - uint8_t i2cError = _i2cPort->endTransmission(false); //Always send a restart command. Do not release the bus. ESP32 supports this. + _i2cPort->write(0xFD); // 0xFD (MSB) and 0xFE (LSB) are the registers that contain number of bytes available + uint8_t i2cError = _i2cPort->endTransmission(false); // Always send a restart command. Do not release the bus. ESP32 supports this. if (i2cError != 0) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -934,10 +932,10 @@ bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClas _debugSerial->println(i2cError); } #endif - return (false); //Sensor did not ACK + return (false); // Sensor did not ACK } - //Forcing requestFrom to use a restart would be unwise. If bytesAvailable is zero, we want to surrender the bus. + // Forcing requestFrom to use a restart would be unwise. If bytesAvailable is zero, we want to surrender the bus. uint8_t bytesReturned = _i2cPort->requestFrom((uint8_t)_gpsI2Caddress, static_cast(2)); if (bytesReturned != 2) { @@ -948,9 +946,9 @@ bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClas _debugSerial->println(bytesReturned); } #endif - return (false); //Sensor did not return 2 bytes + return (false); // Sensor did not return 2 bytes } - else //if (_i2cPort->available()) + else // if (_i2cPort->available()) { uint8_t msb = _i2cPort->read(); uint8_t lsb = _i2cPort->read(); @@ -999,16 +997,16 @@ bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClas _debugSerial->println(F("checkUbloxI2C: OK, zero bytes available")); } #endif - lastCheck = millis(); //Put off checking to avoid I2C bus traffic + lastCheck = millis(); // Put off checking to avoid I2C bus traffic return (false); } - //Check for undocumented bit error. We found this doing logic scans. - //This error is rare but if we incorrectly interpret the first bit of the two 'data available' bytes as 1 - //then we have far too many bytes to check. May be related to I2C setup time violations: https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/40 + // Check for undocumented bit error. We found this doing logic scans. + // This error is rare but if we incorrectly interpret the first bit of the two 'data available' bytes as 1 + // then we have far too many bytes to check. May be related to I2C setup time violations: https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/40 if (bytesAvailable & ((uint16_t)1 << 15)) { - //Clear the MSbit + // Clear the MSbit bytesAvailable &= ~((uint16_t)1 << 15); // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -1058,56 +1056,56 @@ bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClas // pointing at 0xFF, so we do not need to write it here. The next four lines can be commented. //_i2cPort->beginTransmission(_gpsI2Caddress); //_i2cPort->write(0xFF); //0xFF is the register to read data from - //if (_i2cPort->endTransmission(false) != 0) //Send a restart command. Do not release bus. + // if (_i2cPort->endTransmission(false) != 0) //Send a restart command. Do not release bus. // return (false); //Sensor did not ACK - //Limit to 32 bytes or whatever the buffer limit is for given platform + // Limit to 32 bytes or whatever the buffer limit is for given platform uint16_t bytesToRead = bytesAvailable; // 16-bit - if (bytesToRead > i2cTransactionSize) // Limit for i2cTransactionSize is 8-bit + if (bytesToRead > i2cTransactionSize) // Limit for i2cTransactionSize is 8-bit bytesToRead = i2cTransactionSize; - //TRY_AGAIN: + // TRY_AGAIN: - //Here it would be desireable to use a restart where possible / supported, but only if there will be multiple reads. - //However, if an individual requestFrom fails, we could end up leaving the bus hanging. - //On balance, it is probably safest to not use restarts here. + // Here it would be desireable to use a restart where possible / supported, but only if there will be multiple reads. + // However, if an individual requestFrom fails, we could end up leaving the bus hanging. + // On balance, it is probably safest to not use restarts here. uint8_t bytesReturned = _i2cPort->requestFrom((uint8_t)_gpsI2Caddress, (uint8_t)bytesToRead); if ((uint16_t)bytesReturned == bytesToRead) { for (uint16_t x = 0; x < bytesToRead; x++) { - uint8_t incoming = _i2cPort->read(); //Grab the actual character + uint8_t incoming = _i2cPort->read(); // Grab the actual character - //Check to see if the first read is 0x7F. If it is, the module is not ready to respond. Stop, wait, and try again. - //Note: the integration manual says: + // Check to see if the first read is 0x7F. If it is, the module is not ready to respond. Stop, wait, and try again. + // Note: the integration manual says: //"If there is no data awaiting transmission from the receiver, then this register will deliver the value 0xFF, - // which cannot be the first byte of a valid message." - //But it can be the first byte waiting to be read from the buffer if we have already read part of the message. - //Therefore I think this check needs to be commented. - // if (x == 0) - // { - // if ((incoming == 0x7F) && (ubx7FcheckDisabled == false)) - // { - // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - // { - // _debugSerial->println(F("checkUbloxU2C: u-blox error, module not ready with data (7F error)")); - // } - // delay(5); //In logic analyzation, the module starting responding after 1.48ms - // if (debugPin >= 0) - // { - // digitalWrite((uint8_t)debugPin, LOW); - // delay(10); - // digitalWrite((uint8_t)debugPin, HIGH); - // } - // goto TRY_AGAIN; - // } - // } - - process(incoming, incomingUBX, requestedClass, requestedID); //Process this valid character + // which cannot be the first byte of a valid message." + // But it can be the first byte waiting to be read from the buffer if we have already read part of the message. + // Therefore I think this check needs to be commented. + // if (x == 0) + // { + // if ((incoming == 0x7F) && (ubx7FcheckDisabled == false)) + // { + // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + // { + // _debugSerial->println(F("checkUbloxU2C: u-blox error, module not ready with data (7F error)")); + // } + // delay(5); //In logic analyzation, the module starting responding after 1.48ms + // if (debugPin >= 0) + // { + // digitalWrite((uint8_t)debugPin, LOW); + // delay(10); + // digitalWrite((uint8_t)debugPin, HIGH); + // } + // goto TRY_AGAIN; + // } + // } + + process(incoming, incomingUBX, requestedClass, requestedID); // Process this valid character } } else - return (false); //Sensor did not respond + return (false); // Sensor did not respond bytesAvailable -= bytesToRead; } @@ -1115,9 +1113,9 @@ bool SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClas return (true); -} //end checkUbloxI2C() +} // end checkUbloxI2C() -//Checks Serial for data, passing any new bytes to process() +// Checks Serial for data, passing any new bytes to process() bool SFE_UBLOX_GNSS::checkUbloxSerial(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID) { while (_serialPort->available()) @@ -1126,15 +1124,15 @@ bool SFE_UBLOX_GNSS::checkUbloxSerial(ubxPacket *incomingUBX, uint8_t requestedC } return (true); -} //end checkUbloxSerial() - +} // end checkUbloxSerial() -//Checks SPI for data, passing any new bytes to process() +// Checks SPI for data, passing any new bytes to process() bool SFE_UBLOX_GNSS::checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID) { - // Process the contents of the SPI buffer if not empty! - for (uint8_t i = 0; i < spiBufferIndex; i++) { - process(spiBuffer[i], incomingUBX, requestedClass, requestedID); + // Process the contents of the SPI buffer if not empty! + for (uint8_t i = 0; i < spiBufferIndex; i++) + { + process(spiBuffer[i], incomingUBX, requestedClass, requestedID); } spiBufferIndex = 0; @@ -1146,7 +1144,7 @@ bool SFE_UBLOX_GNSS::checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClas // which could legitimately contain 0xFF within the data stream. But the currentSentence check will certainly help! // If we are not receiving a sentence (currentSentence == NONE) and the byteReturned is 0xFF, - // i.e. the module has no data for us, then delay for + // i.e. the module has no data for us, then delay for if ((byteReturned == 0xFF) && (currentSentence == NONE)) { digitalWrite(_csPin, HIGH); @@ -1156,7 +1154,7 @@ bool SFE_UBLOX_GNSS::checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClas } while ((byteReturned != 0xFF) || (currentSentence != NONE)) - { + { process(byteReturned, incomingUBX, requestedClass, requestedID); byteReturned = _spiPort->transfer(0xFF); } @@ -1164,341 +1162,373 @@ bool SFE_UBLOX_GNSS::checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClas _spiPort->endTransaction(); return (true); -} //end checkUbloxSpi() +} // end checkUbloxSpi() - -//PRIVATE: Check if we have storage allocated for an incoming "automatic" message +// PRIVATE: Check if we have storage allocated for an incoming "automatic" message bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) { bool result = false; switch (Class) { - case UBX_CLASS_NAV: + case UBX_CLASS_NAV: + { + switch (ID) { - switch (ID) - { - case UBX_NAV_POSECEF: - if (packetUBXNAVPOSECEF != NULL) result = true; - break; - case UBX_NAV_STATUS: - if (packetUBXNAVSTATUS != NULL) result = true; - break; - case UBX_NAV_DOP: - if (packetUBXNAVDOP != NULL) result = true; - break; - case UBX_NAV_ATT: - if (packetUBXNAVATT != NULL) result = true; - break; - case UBX_NAV_PVT: - if (packetUBXNAVPVT != NULL) result = true; - break; - case UBX_NAV_ODO: - if (packetUBXNAVODO != NULL) result = true; - break; - case UBX_NAV_VELECEF: - if (packetUBXNAVVELECEF != NULL) result = true; - break; - case UBX_NAV_VELNED: - if (packetUBXNAVVELNED != NULL) result = true; - break; - case UBX_NAV_HPPOSECEF: - if (packetUBXNAVHPPOSECEF != NULL) result = true; - break; - case UBX_NAV_HPPOSLLH: - if (packetUBXNAVHPPOSLLH != NULL) result = true; - break; - case UBX_NAV_PVAT: - if (packetUBXNAVPVAT != NULL) result = true; - break; - case UBX_NAV_CLOCK: - if (packetUBXNAVCLOCK != NULL) result = true; - break; - case UBX_NAV_TIMELS: - if (packetUBXNAVTIMELS != NULL) result = true; - break; - case UBX_NAV_SVIN: - if (packetUBXNAVSVIN != NULL) result = true; - break; - case UBX_NAV_SAT: - if (packetUBXNAVSAT != NULL) result = true; - break; - case UBX_NAV_RELPOSNED: - if (packetUBXNAVRELPOSNED != NULL) result = true; - break; - case UBX_NAV_AOPSTATUS: - if (packetUBXNAVAOPSTATUS != NULL) result = true; - break; - } + case UBX_NAV_POSECEF: + if (packetUBXNAVPOSECEF != NULL) + result = true; + break; + case UBX_NAV_STATUS: + if (packetUBXNAVSTATUS != NULL) + result = true; + break; + case UBX_NAV_DOP: + if (packetUBXNAVDOP != NULL) + result = true; + break; + case UBX_NAV_ATT: + if (packetUBXNAVATT != NULL) + result = true; + break; + case UBX_NAV_PVT: + if (packetUBXNAVPVT != NULL) + result = true; + break; + case UBX_NAV_ODO: + if (packetUBXNAVODO != NULL) + result = true; + break; + case UBX_NAV_VELECEF: + if (packetUBXNAVVELECEF != NULL) + result = true; + break; + case UBX_NAV_VELNED: + if (packetUBXNAVVELNED != NULL) + result = true; + break; + case UBX_NAV_HPPOSECEF: + if (packetUBXNAVHPPOSECEF != NULL) + result = true; + break; + case UBX_NAV_HPPOSLLH: + if (packetUBXNAVHPPOSLLH != NULL) + result = true; + break; + case UBX_NAV_PVAT: + if (packetUBXNAVPVAT != NULL) + result = true; + break; + case UBX_NAV_CLOCK: + if (packetUBXNAVCLOCK != NULL) + result = true; + break; + case UBX_NAV_TIMELS: + if (packetUBXNAVTIMELS != NULL) + result = true; + break; + case UBX_NAV_SVIN: + if (packetUBXNAVSVIN != NULL) + result = true; + break; + case UBX_NAV_SAT: + if (packetUBXNAVSAT != NULL) + result = true; + break; + case UBX_NAV_RELPOSNED: + if (packetUBXNAVRELPOSNED != NULL) + result = true; + break; + case UBX_NAV_AOPSTATUS: + if (packetUBXNAVAOPSTATUS != NULL) + result = true; + break; } - break; - case UBX_CLASS_RXM: + } + break; + case UBX_CLASS_RXM: + { + switch (ID) { - switch (ID) - { - case UBX_RXM_SFRBX: - if (packetUBXRXMSFRBX != NULL) result = true; - break; - case UBX_RXM_RAWX: - if (packetUBXRXMRAWX != NULL) result = true; - break; - case UBX_RXM_PMP: - if (packetUBXRXMPMP != NULL) result = true; - break; - } + case UBX_RXM_SFRBX: + if (packetUBXRXMSFRBX != NULL) + result = true; + break; + case UBX_RXM_RAWX: + if (packetUBXRXMRAWX != NULL) + result = true; + break; + case UBX_RXM_PMP: + if (packetUBXRXMPMP != NULL) + result = true; + break; } - break; - case UBX_CLASS_CFG: + } + break; + case UBX_CLASS_CFG: + { + switch (ID) { - switch (ID) - { - case UBX_CFG_PRT: - if (packetUBXCFGPRT != NULL) result = true; - break; - case UBX_CFG_RATE: - if (packetUBXCFGRATE != NULL) result = true; - break; - } + case UBX_CFG_PRT: + if (packetUBXCFGPRT != NULL) + result = true; + break; + case UBX_CFG_RATE: + if (packetUBXCFGRATE != NULL) + result = true; + break; } - break; - case UBX_CLASS_TIM: + } + break; + case UBX_CLASS_TIM: + { + switch (ID) { - switch (ID) - { - case UBX_TIM_TM2: - if (packetUBXTIMTM2 != NULL) result = true; - break; - } + case UBX_TIM_TM2: + if (packetUBXTIMTM2 != NULL) + result = true; + break; } - break; - case UBX_CLASS_ESF: + } + break; + case UBX_CLASS_ESF: + { + switch (ID) { - switch (ID) - { - case UBX_ESF_ALG: - if (packetUBXESFALG != NULL) result = true; - break; - case UBX_ESF_INS: - if (packetUBXESFINS != NULL) result = true; - break; - case UBX_ESF_MEAS: - if (packetUBXESFMEAS != NULL) result = true; - break; - case UBX_ESF_RAW: - if (packetUBXESFRAW != NULL) result = true; - break; - case UBX_ESF_STATUS: - if (packetUBXESFSTATUS != NULL) result = true; - break; - } + case UBX_ESF_ALG: + if (packetUBXESFALG != NULL) + result = true; + break; + case UBX_ESF_INS: + if (packetUBXESFINS != NULL) + result = true; + break; + case UBX_ESF_MEAS: + if (packetUBXESFMEAS != NULL) + result = true; + break; + case UBX_ESF_RAW: + if (packetUBXESFRAW != NULL) + result = true; + break; + case UBX_ESF_STATUS: + if (packetUBXESFSTATUS != NULL) + result = true; + break; } - break; - case UBX_CLASS_MGA: + } + break; + case UBX_CLASS_MGA: + { + switch (ID) { - switch (ID) - { - case UBX_MGA_ACK_DATA0: - if (packetUBXMGAACK != NULL) result = true; - break; - case UBX_MGA_DBD: - if (packetUBXMGADBD != NULL) result = true; - break; - } + case UBX_MGA_ACK_DATA0: + if (packetUBXMGAACK != NULL) + result = true; + break; + case UBX_MGA_DBD: + if (packetUBXMGADBD != NULL) + result = true; + break; } - break; - case UBX_CLASS_HNR: + } + break; + case UBX_CLASS_HNR: + { + switch (ID) { - switch (ID) - { - case UBX_HNR_PVT: - if (packetUBXHNRPVT != NULL) result = true; - break; - case UBX_HNR_ATT: - if (packetUBXHNRATT != NULL) result = true; - break; - case UBX_HNR_INS: - if (packetUBXHNRINS != NULL) result = true; - break; - } + case UBX_HNR_PVT: + if (packetUBXHNRPVT != NULL) + result = true; + break; + case UBX_HNR_ATT: + if (packetUBXHNRATT != NULL) + result = true; + break; + case UBX_HNR_INS: + if (packetUBXHNRINS != NULL) + result = true; + break; } - break; + } + break; } return (result); } -//PRIVATE: Calculate how much RAM is needed to store the payload for a given automatic message +// PRIVATE: Calculate how much RAM is needed to store the payload for a given automatic message uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) { uint16_t maxSize = 0; switch (Class) { - case UBX_CLASS_NAV: - { - switch (ID) - { - case UBX_NAV_POSECEF: - maxSize = UBX_NAV_POSECEF_LEN; - break; - case UBX_NAV_STATUS: - maxSize = UBX_NAV_STATUS_LEN; - break; - case UBX_NAV_DOP: - maxSize = UBX_NAV_DOP_LEN; - break; - case UBX_NAV_ATT: - maxSize = UBX_NAV_ATT_LEN; - break; - case UBX_NAV_PVT: - maxSize = UBX_NAV_PVT_LEN; - break; - case UBX_NAV_ODO: - maxSize = UBX_NAV_ODO_LEN; - break; - case UBX_NAV_VELECEF: - maxSize = UBX_NAV_VELECEF_LEN; - break; - case UBX_NAV_VELNED: - maxSize = UBX_NAV_VELNED_LEN; - break; - case UBX_NAV_HPPOSECEF: - maxSize = UBX_NAV_HPPOSECEF_LEN; - break; - case UBX_NAV_HPPOSLLH: - maxSize = UBX_NAV_HPPOSLLH_LEN; - break; - case UBX_NAV_PVAT: - maxSize = UBX_NAV_PVAT_LEN; - break; - case UBX_NAV_CLOCK: - maxSize = UBX_NAV_CLOCK_LEN; - break; - case UBX_NAV_TIMELS: - maxSize = UBX_NAV_TIMELS_LEN; - break; - case UBX_NAV_SVIN: - maxSize = UBX_NAV_SVIN_LEN; - break; - case UBX_NAV_SAT: - maxSize = UBX_NAV_SAT_MAX_LEN; - break; - case UBX_NAV_RELPOSNED: - maxSize = UBX_NAV_RELPOSNED_LEN_F9; - break; - case UBX_NAV_AOPSTATUS: - maxSize = UBX_NAV_AOPSTATUS_LEN; - break; - } - } - break; - case UBX_CLASS_RXM: - { - switch (ID) - { - case UBX_RXM_SFRBX: - maxSize = UBX_RXM_SFRBX_MAX_LEN; - break; - case UBX_RXM_RAWX: - maxSize = UBX_RXM_RAWX_MAX_LEN; - break; - case UBX_RXM_PMP: - maxSize = UBX_RXM_PMP_MAX_LEN; - break; - } - } - break; - case UBX_CLASS_CFG: + case UBX_CLASS_NAV: + { + switch (ID) + { + case UBX_NAV_POSECEF: + maxSize = UBX_NAV_POSECEF_LEN; + break; + case UBX_NAV_STATUS: + maxSize = UBX_NAV_STATUS_LEN; + break; + case UBX_NAV_DOP: + maxSize = UBX_NAV_DOP_LEN; + break; + case UBX_NAV_ATT: + maxSize = UBX_NAV_ATT_LEN; + break; + case UBX_NAV_PVT: + maxSize = UBX_NAV_PVT_LEN; + break; + case UBX_NAV_ODO: + maxSize = UBX_NAV_ODO_LEN; + break; + case UBX_NAV_VELECEF: + maxSize = UBX_NAV_VELECEF_LEN; + break; + case UBX_NAV_VELNED: + maxSize = UBX_NAV_VELNED_LEN; + break; + case UBX_NAV_HPPOSECEF: + maxSize = UBX_NAV_HPPOSECEF_LEN; + break; + case UBX_NAV_HPPOSLLH: + maxSize = UBX_NAV_HPPOSLLH_LEN; + break; + case UBX_NAV_PVAT: + maxSize = UBX_NAV_PVAT_LEN; + break; + case UBX_NAV_CLOCK: + maxSize = UBX_NAV_CLOCK_LEN; + break; + case UBX_NAV_TIMELS: + maxSize = UBX_NAV_TIMELS_LEN; + break; + case UBX_NAV_SVIN: + maxSize = UBX_NAV_SVIN_LEN; + break; + case UBX_NAV_SAT: + maxSize = UBX_NAV_SAT_MAX_LEN; + break; + case UBX_NAV_RELPOSNED: + maxSize = UBX_NAV_RELPOSNED_LEN_F9; + break; + case UBX_NAV_AOPSTATUS: + maxSize = UBX_NAV_AOPSTATUS_LEN; + break; + } + } + break; + case UBX_CLASS_RXM: + { + switch (ID) { - switch (ID) - { - case UBX_CFG_PRT: - maxSize = UBX_CFG_PRT_LEN; - break; - case UBX_CFG_RATE: - maxSize = UBX_CFG_RATE_LEN; - break; - } + case UBX_RXM_SFRBX: + maxSize = UBX_RXM_SFRBX_MAX_LEN; + break; + case UBX_RXM_RAWX: + maxSize = UBX_RXM_RAWX_MAX_LEN; + break; + case UBX_RXM_PMP: + maxSize = UBX_RXM_PMP_MAX_LEN; + break; } - break; - case UBX_CLASS_TIM: + } + break; + case UBX_CLASS_CFG: + { + switch (ID) { - switch (ID) - { - case UBX_TIM_TM2: - maxSize = UBX_TIM_TM2_LEN; - break; - } + case UBX_CFG_PRT: + maxSize = UBX_CFG_PRT_LEN; + break; + case UBX_CFG_RATE: + maxSize = UBX_CFG_RATE_LEN; + break; } - break; - case UBX_CLASS_ESF: + } + break; + case UBX_CLASS_TIM: + { + switch (ID) { - switch (ID) - { - case UBX_ESF_ALG: - maxSize = UBX_ESF_ALG_LEN; - break; - case UBX_ESF_INS: - maxSize = UBX_ESF_INS_LEN; - break; - case UBX_ESF_MEAS: - maxSize = UBX_ESF_MEAS_MAX_LEN; - break; - case UBX_ESF_RAW: - maxSize = UBX_ESF_RAW_MAX_LEN; - break; - case UBX_ESF_STATUS: - maxSize = UBX_ESF_STATUS_MAX_LEN; - break; - } + case UBX_TIM_TM2: + maxSize = UBX_TIM_TM2_LEN; + break; } - break; - case UBX_CLASS_MGA: + } + break; + case UBX_CLASS_ESF: + { + switch (ID) + { + case UBX_ESF_ALG: + maxSize = UBX_ESF_ALG_LEN; + break; + case UBX_ESF_INS: + maxSize = UBX_ESF_INS_LEN; + break; + case UBX_ESF_MEAS: + maxSize = UBX_ESF_MEAS_MAX_LEN; + break; + case UBX_ESF_RAW: + maxSize = UBX_ESF_RAW_MAX_LEN; + break; + case UBX_ESF_STATUS: + maxSize = UBX_ESF_STATUS_MAX_LEN; + break; + } + } + break; + case UBX_CLASS_MGA: + { + switch (ID) { - switch (ID) - { - case UBX_MGA_ACK_DATA0: - maxSize = UBX_MGA_ACK_DATA0_LEN; - break; - case UBX_MGA_DBD: - maxSize = UBX_MGA_DBD_LEN; // UBX_MGA_DBD_LEN is actually a maximum length. The packets could be shorter than this. - break; - } + case UBX_MGA_ACK_DATA0: + maxSize = UBX_MGA_ACK_DATA0_LEN; + break; + case UBX_MGA_DBD: + maxSize = UBX_MGA_DBD_LEN; // UBX_MGA_DBD_LEN is actually a maximum length. The packets could be shorter than this. + break; } - break; - case UBX_CLASS_HNR: + } + break; + case UBX_CLASS_HNR: + { + switch (ID) { - switch (ID) - { - case UBX_HNR_PVT: - maxSize = UBX_HNR_PVT_LEN; - break; - case UBX_HNR_ATT: - maxSize = UBX_HNR_ATT_LEN; - break; - case UBX_HNR_INS: - maxSize = UBX_HNR_INS_LEN; - break; - } + case UBX_HNR_PVT: + maxSize = UBX_HNR_PVT_LEN; + break; + case UBX_HNR_ATT: + maxSize = UBX_HNR_ATT_LEN; + break; + case UBX_HNR_INS: + maxSize = UBX_HNR_INS_LEN; + break; } - break; + } + break; } return (maxSize); } -//Processes NMEA and UBX binary sentences one byte at a time -//Take a given byte and file it into the proper array +// Processes NMEA and UBX binary sentences one byte at a time +// Take a given byte and file it into the proper array void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID) { if ((currentSentence == NONE) || (currentSentence == NMEA)) { - if (incoming == UBX_SYNCH_1) //UBX binary frames start with 0xB5, aka μ + if (incoming == UBX_SYNCH_1) // UBX binary frames start with 0xB5, aka μ { - //This is the start of a binary sentence. Reset flags. - //We still don't know the response class + // This is the start of a binary sentence. Reset flags. + // We still don't know the response class ubxFrameCounter = 0; currentSentence = UBX; - //Reset the packetBuf.counter even though we will need to reset it again when ubxFrameCounter == 2 + // Reset the packetBuf.counter even though we will need to reset it again when ubxFrameCounter == 2 packetBuf.counter = 0; - ignoreThisPayload = false; //We should not ignore this payload - yet - //Store data in packetBuf until we know if we have a requested class and ID match + ignoreThisPayload = false; // We should not ignore this payload - yet + // Store data in packetBuf until we know if we have a requested class and ID match activePacketBuffer = SFE_UBLOX_PACKET_PACKETBUF; } else if (incoming == '$') @@ -1506,64 +1536,64 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r nmeaByteCounter = 0; // Reset the NMEA byte counter currentSentence = NMEA; } - else if (incoming == 0xD3) //RTCM frames start with 0xD3 + else if (incoming == 0xD3) // RTCM frames start with 0xD3 { rtcmFrameCounter = 0; currentSentence = RTCM; } else { - //This character is unknown or we missed the previous start of a sentence + // This character is unknown or we missed the previous start of a sentence } } - //Depending on the sentence, pass the character to the individual processor + // Depending on the sentence, pass the character to the individual processor if (currentSentence == UBX) { - //Decide what type of response this is - if ((ubxFrameCounter == 0) && (incoming != UBX_SYNCH_1)) //ISO 'μ' - currentSentence = NONE; //Something went wrong. Reset. - else if ((ubxFrameCounter == 1) && (incoming != UBX_SYNCH_2)) //ASCII 'b' - currentSentence = NONE; //Something went wrong. Reset. + // Decide what type of response this is + if ((ubxFrameCounter == 0) && (incoming != UBX_SYNCH_1)) // ISO 'μ' + currentSentence = NONE; // Something went wrong. Reset. + else if ((ubxFrameCounter == 1) && (incoming != UBX_SYNCH_2)) // ASCII 'b' + currentSentence = NONE; // Something went wrong. Reset. // Note to future self: // There may be some duplication / redundancy in the next few lines as processUBX will also // load information into packetBuf, but we'll do it here too for clarity - else if (ubxFrameCounter == 2) //Class + else if (ubxFrameCounter == 2) // Class { // Record the class in packetBuf until we know what to do with it packetBuf.cls = incoming; // (Duplication) - rollingChecksumA = 0; //Reset our rolling checksums here (not when we receive the 0xB5) + rollingChecksumA = 0; // Reset our rolling checksums here (not when we receive the 0xB5) rollingChecksumB = 0; - packetBuf.counter = 0; //Reset the packetBuf.counter (again) + packetBuf.counter = 0; // Reset the packetBuf.counter (again) packetBuf.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; // Reset the packet validity (redundant?) - packetBuf.startingSpot = incomingUBX->startingSpot; //Copy the startingSpot + packetBuf.startingSpot = incomingUBX->startingSpot; // Copy the startingSpot } - else if (ubxFrameCounter == 3) //ID + else if (ubxFrameCounter == 3) // ID { // Record the ID in packetBuf until we know what to do with it packetBuf.id = incoming; // (Duplication) - //We can now identify the type of response - //If the packet we are receiving is not an ACK then check for a class and ID match + // We can now identify the type of response + // If the packet we are receiving is not an ACK then check for a class and ID match if (packetBuf.cls != UBX_CLASS_ACK) { - //This is not an ACK so check for a class and ID match + // This is not an ACK so check for a class and ID match if ((packetBuf.cls == requestedClass) && (packetBuf.id == requestedID)) { - //This is not an ACK and we have a class and ID match - //So start diverting data into incomingUBX (usually packetCfg) + // This is not an ACK and we have a class and ID match + // So start diverting data into incomingUBX (usually packetCfg) activePacketBuffer = SFE_UBLOX_PACKET_PACKETCFG; - incomingUBX->cls = packetBuf.cls; //Copy the class and ID into incomingUBX (usually packetCfg) + incomingUBX->cls = packetBuf.cls; // Copy the class and ID into incomingUBX (usually packetCfg) incomingUBX->id = packetBuf.id; - incomingUBX->counter = packetBuf.counter; //Copy over the .counter too + incomingUBX->counter = packetBuf.counter; // Copy over the .counter too } - //This is not an ACK and we do not have a complete class and ID match - //So let's check if this is an "automatic" message which has its own storage defined + // This is not an ACK and we do not have a complete class and ID match + // So let's check if this is an "automatic" message which has its own storage defined else if (checkAutomatic(packetBuf.cls, packetBuf.id)) { - //This is not the message we were expecting but it has its own storage and so we should process it anyway. - //We'll try to use packetAuto to buffer the message (so it can't overwrite anything in packetCfg). - //We need to allocate memory for the packetAuto payload (payloadAuto) - and delete it once - //reception is complete. + // This is not the message we were expecting but it has its own storage and so we should process it anyway. + // We'll try to use packetAuto to buffer the message (so it can't overwrite anything in packetCfg). + // We need to allocate memory for the packetAuto payload (payloadAuto) - and delete it once + // reception is complete. uint16_t maxPayload = getMaxPayloadSize(packetBuf.cls, packetBuf.id); // Calculate how much RAM we need if (maxPayload == 0) { @@ -1586,7 +1616,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r } #endif delete[] payloadAuto; // Created with new[] - payloadAuto = NULL; // Redundant? + payloadAuto = NULL; // Redundant? packetAuto.payload = payloadAuto; } payloadAuto = new uint8_t[maxPayload]; // Allocate RAM for payloadAuto @@ -1605,18 +1635,18 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r #endif // The RAM allocation failed so fall back to using incomingUBX (usually packetCfg) even though we risk overwriting data activePacketBuffer = SFE_UBLOX_PACKET_PACKETCFG; - incomingUBX->cls = packetBuf.cls; //Copy the class and ID into incomingUBX (usually packetCfg) + incomingUBX->cls = packetBuf.cls; // Copy the class and ID into incomingUBX (usually packetCfg) incomingUBX->id = packetBuf.id; - incomingUBX->counter = packetBuf.counter; //Copy over the .counter too + incomingUBX->counter = packetBuf.counter; // Copy over the .counter too } else { - //The RAM allocation was successful so we start diverting data into packetAuto and process it + // The RAM allocation was successful so we start diverting data into packetAuto and process it activePacketBuffer = SFE_UBLOX_PACKET_PACKETAUTO; - packetAuto.cls = packetBuf.cls; //Copy the class and ID into packetAuto + packetAuto.cls = packetBuf.cls; // Copy the class and ID into packetAuto packetAuto.id = packetBuf.id; - packetAuto.counter = packetBuf.counter; //Copy over the .counter too - packetAuto.startingSpot = packetBuf.startingSpot; //And the starting spot? (Probably redundant) + packetAuto.counter = packetBuf.counter; // Copy over the .counter too + packetAuto.startingSpot = packetBuf.startingSpot; // And the starting spot? (Probably redundant) #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) { @@ -1630,8 +1660,8 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r } else { - //This is not an ACK and we do not have a class and ID match - //so we should keep diverting data into packetBuf and ignore the payload + // This is not an ACK and we do not have a class and ID match + // so we should keep diverting data into packetBuf and ignore the payload ignoreThisPayload = true; } } @@ -1642,17 +1672,17 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r // So we should keep diverting data into packetBuf } } - else if (ubxFrameCounter == 4) //Length LSB + else if (ubxFrameCounter == 4) // Length LSB { - //We should save the length in packetBuf even if activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG + // We should save the length in packetBuf even if activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG packetBuf.len = incoming; // (Duplication) } - else if (ubxFrameCounter == 5) //Length MSB + else if (ubxFrameCounter == 5) // Length MSB { - //We should save the length in packetBuf even if activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG + // We should save the length in packetBuf even if activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG packetBuf.len |= incoming << 8; // (Duplication) } - else if (ubxFrameCounter == 6) //This should be the first byte of the payload unless .len is zero + else if (ubxFrameCounter == 6) // This should be the first byte of the payload unless .len is zero { if (packetBuf.len == 0) // Check if length is zero (hopefully this is impossible!) { @@ -1665,25 +1695,25 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r _debugSerial->println(packetBuf.id, HEX); } #endif - //If length is zero (!) this will be the first byte of the checksum so record it + // If length is zero (!) this will be the first byte of the checksum so record it packetBuf.checksumA = incoming; } else { - //The length is not zero so record this byte in the payload + // The length is not zero so record this byte in the payload packetBuf.payload[0] = incoming; } } - else if (ubxFrameCounter == 7) //This should be the second byte of the payload unless .len is zero or one + else if (ubxFrameCounter == 7) // This should be the second byte of the payload unless .len is zero or one { if (packetBuf.len == 0) // Check if length is zero (hopefully this is impossible!) { - //If length is zero (!) this will be the second byte of the checksum so record it + // If length is zero (!) this will be the second byte of the checksum so record it packetBuf.checksumB = incoming; } else if (packetBuf.len == 1) // Check if length is one { - //The length is one so this is the first byte of the checksum + // The length is one so this is the first byte of the checksum packetBuf.checksumA = incoming; } else // Length is >= 2 so this must be a payload byte @@ -1724,7 +1754,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r } } - //Divert incoming into the correct buffer + // Divert incoming into the correct buffer if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETACK) processUBX(incoming, &packetAck, requestedClass, requestedID); else if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG) @@ -1734,18 +1764,18 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r else // if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETAUTO) processUBX(incoming, &packetAuto, requestedClass, requestedID); - //Finally, increment the frame counter + // Finally, increment the frame counter ubxFrameCounter++; } else if (currentSentence == NMEA) // Process incoming NMEA mesages. Selectively log if desired. { if ((nmeaByteCounter == 0) && (incoming != '$')) { - currentSentence = NONE; //Something went wrong. Reset. (Almost certainly redundant!) + currentSentence = NONE; // Something went wrong. Reset. (Almost certainly redundant!) } else if ((nmeaByteCounter == 1) && (incoming != 'G')) { - currentSentence = NONE; //Something went wrong. Reset. + currentSentence = NONE; // Something went wrong. Reset. } else if ((nmeaByteCounter >= 0) && (nmeaByteCounter <= 5)) { @@ -1763,10 +1793,10 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r if (isThisNMEAauto()) { uint8_t *lengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length - uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data uint8_t nmeaMaxLength = getNMEAMaxLength(); - *lengthPtr = 6; // Set the working copy length - memset(nmeaPtr, 0, nmeaMaxLength); // Clear the working copy + *lengthPtr = 6; // Set the working copy length + memset(nmeaPtr, 0, nmeaMaxLength); // Clear the working copy memcpy(nmeaPtr, &nmeaAddressField[0], 6); // Copy the start character and address field into the working copy } else @@ -1785,7 +1815,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r // Check if it should be passed to processNMEA if (processThisNMEA()) { - processNMEA(nmeaAddressField[0]); //Process the start character and address field + processNMEA(nmeaAddressField[0]); // Process the start character and address field processNMEA(nmeaAddressField[1]); processNMEA(nmeaAddressField[2]); processNMEA(nmeaAddressField[3]); @@ -1799,12 +1829,12 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r if (isThisNMEAauto()) { uint8_t *lengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length - uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data uint8_t nmeaMaxLength = getNMEAMaxLength(); if (*lengthPtr < nmeaMaxLength) { *(nmeaPtr + *lengthPtr) = incoming; // Store the character - *lengthPtr = *lengthPtr + 1; // Increment the length + *lengthPtr = *lengthPtr + 1; // Increment the length if (*lengthPtr == nmeaMaxLength) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -1828,26 +1858,24 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r nmeaByteCounter++; // Increment the byte counter if (nmeaByteCounter == maxNMEAByteCount) // Check if we have processed too many bytes - currentSentence = NONE; //Something went wrong. Reset. + currentSentence = NONE; // Something went wrong. Reset. if (nmeaByteCounter == 0) // Check if we are done { if (isThisNMEAauto()) { uint8_t *workingLengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length - uint8_t *workingNMEAPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t *workingNMEAPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data uint8_t nmeaMaxLength = getNMEAMaxLength(); - + // Check the checksum: the checksum is the exclusive-OR of all characters between the $ and the * uint8_t nmeaChecksum = 0; uint8_t charsChecked = 1; // Start after the $ uint8_t thisChar = '\0'; - while ((charsChecked < (nmeaMaxLength - 1)) - && (charsChecked < ((*workingLengthPtr) - 4)) - && (thisChar != '*')) + while ((charsChecked < (nmeaMaxLength - 1)) && (charsChecked < ((*workingLengthPtr) - 4)) && (thisChar != '*')) { thisChar = *(workingNMEAPtr + charsChecked); // Get a char from the working copy - if (thisChar != '*') // Ex-or the char into the checksum - but not if it is the '*' + if (thisChar != '*') // Ex-or the char into the checksum - but not if it is the '*' nmeaChecksum ^= thisChar; charsChecked++; // Increment the counter } @@ -1859,31 +1887,30 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r uint8_t expectedChecksum2 = (nmeaChecksum & 0x0F) + '0'; if (expectedChecksum2 >= ':') // Handle Hex correctly expectedChecksum2 += 'A' - ':'; - if ((expectedChecksum1 == *(workingNMEAPtr + charsChecked)) - && (expectedChecksum2 == *(workingNMEAPtr + charsChecked + 1))) + if ((expectedChecksum1 == *(workingNMEAPtr + charsChecked)) && (expectedChecksum2 == *(workingNMEAPtr + charsChecked + 1))) { - uint8_t *completeLengthPtr = getNMEACompleteLengthPtr(); // Get a pointer to the complete copy length - uint8_t *completeNMEAPtr = getNMEACompleteNMEAPtr(); // Get a pointer to the complete copy NMEA data - memset(completeNMEAPtr, 0, nmeaMaxLength); // Clear the previous complete copy + uint8_t *completeLengthPtr = getNMEACompleteLengthPtr(); // Get a pointer to the complete copy length + uint8_t *completeNMEAPtr = getNMEACompleteNMEAPtr(); // Get a pointer to the complete copy NMEA data + memset(completeNMEAPtr, 0, nmeaMaxLength); // Clear the previous complete copy memcpy(completeNMEAPtr, workingNMEAPtr, *workingLengthPtr); // Copy the working copy into the complete copy - *completeLengthPtr = *workingLengthPtr; // Update the length - nmeaAutomaticFlags *flagsPtr = getNMEAFlagsPtr(); // Get a pointer to the flags + *completeLengthPtr = *workingLengthPtr; // Update the length + nmeaAutomaticFlags *flagsPtr = getNMEAFlagsPtr(); // Get a pointer to the flags nmeaAutomaticFlags flagsCopy = *flagsPtr; flagsCopy.flags.bits.completeCopyValid = 1; // Set the complete copy valid flag - flagsCopy.flags.bits.completeCopyRead = 0; // Clear the complete copy read flag - *flagsPtr = flagsCopy; // Update the flags + flagsCopy.flags.bits.completeCopyRead = 0; // Clear the complete copy read flag + *flagsPtr = flagsCopy; // Update the flags // Callback if (doesThisNMEAHaveCallback()) // Do we need to copy the data into the callback copy? { if (flagsCopy.flags.bits.callbackCopyValid == 0) // Has the callback copy valid flag been cleared (by checkCallbacks) { - uint8_t *callbackLengthPtr = getNMEACallbackLengthPtr(); // Get a pointer to the callback copy length - uint8_t *callbackNMEAPtr = getNMEACallbackNMEAPtr(); // Get a pointer to the callback copy NMEA data - memset(callbackNMEAPtr, 0, nmeaMaxLength); // Clear the previous callback copy + uint8_t *callbackLengthPtr = getNMEACallbackLengthPtr(); // Get a pointer to the callback copy length + uint8_t *callbackNMEAPtr = getNMEACallbackNMEAPtr(); // Get a pointer to the callback copy NMEA data + memset(callbackNMEAPtr, 0, nmeaMaxLength); // Clear the previous callback copy memcpy(callbackNMEAPtr, workingNMEAPtr, *workingLengthPtr); // Copy the working copy into the callback copy - *callbackLengthPtr = *workingLengthPtr; // Update the length - flagsCopy.flags.bits.callbackCopyValid = 1; // Set the callback copy valid flag - *flagsPtr = flagsCopy; // Update the flags + *callbackLengthPtr = *workingLengthPtr; // Update the length + flagsCopy.flags.bits.callbackCopyValid = 1; // Set the callback copy valid flag + *flagsPtr = flagsCopy; // Update the flags } } } @@ -1918,112 +1945,179 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r } else if (currentSentence == RTCM) { - processRTCMframe(incoming); //Deal with RTCM bytes + processRTCMframe(incoming); // Deal with RTCM bytes } } // PRIVATE: Return true if we should add this NMEA message to the file buffer for logging bool SFE_UBLOX_GNSS::logThisNMEA() { - if (_logNMEA.bits.all == 1) return (true); - if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M') && (_logNMEA.bits.UBX_NMEA_DTM == 1)) return (true); + if (_logNMEA.bits.all == 1) + return (true); + if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M') && (_logNMEA.bits.UBX_NMEA_DTM == 1)) + return (true); if (nmeaAddressField[3] == 'G') { - if ((nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GAQ == 1)) return (true); - if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GBQ == 1)) return (true); - if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GBS == 1)) return (true); - if ((nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_GGA == 1)) return (true); - if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L') && (_logNMEA.bits.UBX_NMEA_GLL == 1)) return (true); - if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GLQ == 1)) return (true); - if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GNQ == 1)) return (true); - if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GNS == 1)) return (true); - if ((nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GPQ == 1)) return (true); - if ((nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GQQ == 1)) return (true); - if ((nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GRS == 1)) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_GSA == 1)) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T') && (_logNMEA.bits.UBX_NMEA_GST == 1)) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V') && (_logNMEA.bits.UBX_NMEA_GSV == 1)) return (true); - } - if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M') && (_logNMEA.bits.UBX_NMEA_RLM == 1)) return (true); - if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C') && (_logNMEA.bits.UBX_NMEA_RMC == 1)) return (true); - if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T') && (_logNMEA.bits.UBX_NMEA_TXT == 1)) return (true); - if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W') && (_logNMEA.bits.UBX_NMEA_VLW == 1)) return (true); - if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G') && (_logNMEA.bits.UBX_NMEA_VTG == 1)) return (true); - if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_ZDA == 1)) return (true); + if ((nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GAQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GBQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GBS == 1)) + return (true); + if ((nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_GGA == 1)) + return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L') && (_logNMEA.bits.UBX_NMEA_GLL == 1)) + return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GLQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GNQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GNS == 1)) + return (true); + if ((nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GPQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GQQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GRS == 1)) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_GSA == 1)) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T') && (_logNMEA.bits.UBX_NMEA_GST == 1)) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V') && (_logNMEA.bits.UBX_NMEA_GSV == 1)) + return (true); + } + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M') && (_logNMEA.bits.UBX_NMEA_RLM == 1)) + return (true); + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C') && (_logNMEA.bits.UBX_NMEA_RMC == 1)) + return (true); + if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T') && (_logNMEA.bits.UBX_NMEA_TXT == 1)) + return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W') && (_logNMEA.bits.UBX_NMEA_VLW == 1)) + return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G') && (_logNMEA.bits.UBX_NMEA_VTG == 1)) + return (true); + if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_ZDA == 1)) + return (true); return (false); } // PRIVATE: Return true if the NMEA header is valid bool SFE_UBLOX_GNSS::isNMEAHeaderValid() { - if (nmeaAddressField[0] != '*') return (false); - if (nmeaAddressField[1] != 'G') return (false); - if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M')) return (true); + if (nmeaAddressField[0] != '*') + return (false); + if (nmeaAddressField[1] != 'G') + return (false); + if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M')) + return (true); if (nmeaAddressField[3] == 'G') { - if ((nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q')) return (true); - if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q')) return (true); - if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S')) return (true); - if ((nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A')) return (true); - if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L')) return (true); - if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q')) return (true); - if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q')) return (true); - if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S')) return (true); - if ((nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q')) return (true); - if ((nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q')) return (true); - if ((nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S')) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A')) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T')) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V')) return (true); - } - if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M')) return (true); - if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C')) return (true); - if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T')) return (true); - if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W')) return (true); - if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G')) return (true); - if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A')) return (true); + if ((nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q')) + return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q')) + return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S')) + return (true); + if ((nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A')) + return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L')) + return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q')) + return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q')) + return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S')) + return (true); + if ((nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q')) + return (true); + if ((nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q')) + return (true); + if ((nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S')) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A')) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T')) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V')) + return (true); + } + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M')) + return (true); + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C')) + return (true); + if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T')) + return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W')) + return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G')) + return (true); + if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A')) + return (true); return (false); } // PRIVATE: Return true if we should pass this NMEA message to processNMEA bool SFE_UBLOX_GNSS::processThisNMEA() { - if (_processNMEA.bits.all == 1) return (true); - if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M') && (_processNMEA.bits.UBX_NMEA_DTM == 1)) return (true); + if (_processNMEA.bits.all == 1) + return (true); + if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M') && (_processNMEA.bits.UBX_NMEA_DTM == 1)) + return (true); if (nmeaAddressField[3] == 'G') { - if ((nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GAQ == 1)) return (true); - if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GBQ == 1)) return (true); - if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S') && (_processNMEA.bits.UBX_NMEA_GBS == 1)) return (true); - if ((nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A') && (_processNMEA.bits.UBX_NMEA_GGA == 1)) return (true); - if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L') && (_processNMEA.bits.UBX_NMEA_GLL == 1)) return (true); - if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GLQ == 1)) return (true); - if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GNQ == 1)) return (true); - if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S') && (_processNMEA.bits.UBX_NMEA_GNS == 1)) return (true); - if ((nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GPQ == 1)) return (true); - if ((nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GQQ == 1)) return (true); - if ((nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S') && (_processNMEA.bits.UBX_NMEA_GRS == 1)) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A') && (_processNMEA.bits.UBX_NMEA_GSA == 1)) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T') && (_processNMEA.bits.UBX_NMEA_GST == 1)) return (true); - if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V') && (_processNMEA.bits.UBX_NMEA_GSV == 1)) return (true); - } - if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M') && (_processNMEA.bits.UBX_NMEA_RLM == 1)) return (true); - if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C') && (_processNMEA.bits.UBX_NMEA_RMC == 1)) return (true); - if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T') && (_processNMEA.bits.UBX_NMEA_TXT == 1)) return (true); - if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W') && (_processNMEA.bits.UBX_NMEA_VLW == 1)) return (true); - if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G') && (_processNMEA.bits.UBX_NMEA_VTG == 1)) return (true); - if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A') && (_processNMEA.bits.UBX_NMEA_ZDA == 1)) return (true); + if ((nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GAQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GBQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S') && (_processNMEA.bits.UBX_NMEA_GBS == 1)) + return (true); + if ((nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A') && (_processNMEA.bits.UBX_NMEA_GGA == 1)) + return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L') && (_processNMEA.bits.UBX_NMEA_GLL == 1)) + return (true); + if ((nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GLQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GNQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S') && (_processNMEA.bits.UBX_NMEA_GNS == 1)) + return (true); + if ((nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GPQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q') && (_processNMEA.bits.UBX_NMEA_GQQ == 1)) + return (true); + if ((nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S') && (_processNMEA.bits.UBX_NMEA_GRS == 1)) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A') && (_processNMEA.bits.UBX_NMEA_GSA == 1)) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T') && (_processNMEA.bits.UBX_NMEA_GST == 1)) + return (true); + if ((nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V') && (_processNMEA.bits.UBX_NMEA_GSV == 1)) + return (true); + } + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M') && (_processNMEA.bits.UBX_NMEA_RLM == 1)) + return (true); + if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C') && (_processNMEA.bits.UBX_NMEA_RMC == 1)) + return (true); + if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T') && (_processNMEA.bits.UBX_NMEA_TXT == 1)) + return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W') && (_processNMEA.bits.UBX_NMEA_VLW == 1)) + return (true); + if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G') && (_processNMEA.bits.UBX_NMEA_VTG == 1)) + return (true); + if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A') && (_processNMEA.bits.UBX_NMEA_ZDA == 1)) + return (true); return (false); } -//This is the default or generic NMEA processor. We're only going to pipe the data to serial port so we can see it. -//User could overwrite this function to pipe characters to nmea.process(c) of tinyGPS or MicroNMEA -//Or user could pipe each character to a buffer, radio, etc. +// This is the default or generic NMEA processor. We're only going to pipe the data to serial port so we can see it. +// User could overwrite this function to pipe characters to nmea.process(c) of tinyGPS or MicroNMEA +// Or user could pipe each character to a buffer, radio, etc. void SFE_UBLOX_GNSS::processNMEA(char incoming) { - //If user has assigned an output port then pipe the characters there + // If user has assigned an output port then pipe the characters there if (_nmeaOutputPort != NULL) - _nmeaOutputPort->write(incoming); //Echo this byte to the serial port + _nmeaOutputPort->write(incoming); // Echo this byte to the serial port } // Check if the NMEA message (in nmeaAddressField) is "auto" (i.e. has RAM allocated for it) @@ -2071,108 +2165,108 @@ bool SFE_UBLOX_GNSS::doesThisNMEAHaveCallback() } // Get a pointer to the working copy length -uint8_t * SFE_UBLOX_GNSS::getNMEAWorkingLengthPtr() +uint8_t *SFE_UBLOX_GNSS::getNMEAWorkingLengthPtr() { char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGPGGA->workingCopy.length; + return &storageNMEAGPGGA->workingCopy.length; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGNGGA->workingCopy.length; + return &storageNMEAGNGGA->workingCopy.length; } return NULL; } // Get a pointer to the working copy NMEA data -uint8_t * SFE_UBLOX_GNSS::getNMEAWorkingNMEAPtr() +uint8_t *SFE_UBLOX_GNSS::getNMEAWorkingNMEAPtr() { char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGPGGA->workingCopy.nmea[0]; + return &storageNMEAGPGGA->workingCopy.nmea[0]; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGNGGA->workingCopy.nmea[0]; + return &storageNMEAGNGGA->workingCopy.nmea[0]; } return NULL; } // Get a pointer to the complete copy length -uint8_t * SFE_UBLOX_GNSS::getNMEACompleteLengthPtr() +uint8_t *SFE_UBLOX_GNSS::getNMEACompleteLengthPtr() { char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGPGGA->completeCopy.length; + return &storageNMEAGPGGA->completeCopy.length; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGNGGA->completeCopy.length; + return &storageNMEAGNGGA->completeCopy.length; } return NULL; } // Get a pointer to the complete copy NMEA data -uint8_t * SFE_UBLOX_GNSS::getNMEACompleteNMEAPtr() +uint8_t *SFE_UBLOX_GNSS::getNMEACompleteNMEAPtr() { char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGPGGA->completeCopy.nmea[0]; + return &storageNMEAGPGGA->completeCopy.nmea[0]; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGNGGA->completeCopy.nmea[0]; + return &storageNMEAGNGGA->completeCopy.nmea[0]; } return NULL; } // Get a pointer to the callback copy length -uint8_t * SFE_UBLOX_GNSS::getNMEACallbackLengthPtr() +uint8_t *SFE_UBLOX_GNSS::getNMEACallbackLengthPtr() { char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGPGGA->callbackCopy->length; + return &storageNMEAGPGGA->callbackCopy->length; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGNGGA->callbackCopy->length; + return &storageNMEAGNGGA->callbackCopy->length; } return NULL; } // Get a pointer to the callback copy NMEA data -uint8_t * SFE_UBLOX_GNSS::getNMEACallbackNMEAPtr() +uint8_t *SFE_UBLOX_GNSS::getNMEACallbackNMEAPtr() { char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGPGGA->callbackCopy->nmea[0]; + return &storageNMEAGPGGA->callbackCopy->nmea[0]; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGNGGA->callbackCopy->nmea[0]; + return &storageNMEAGNGGA->callbackCopy->nmea[0]; } return NULL; @@ -2184,59 +2278,59 @@ uint8_t SFE_UBLOX_GNSS::getNMEAMaxLength() char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return NMEA_GGA_MAX_LENGTH; + return NMEA_GGA_MAX_LENGTH; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return NMEA_GGA_MAX_LENGTH; + return NMEA_GGA_MAX_LENGTH; } return 0; } // Get a pointer to the automatic NMEA flags -nmeaAutomaticFlags * SFE_UBLOX_GNSS::getNMEAFlagsPtr() +nmeaAutomaticFlags *SFE_UBLOX_GNSS::getNMEAFlagsPtr() { char thisNMEA[] = "GPGGA"; if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGPGGA->automaticFlags; + return &storageNMEAGPGGA->automaticFlags; } strcpy(thisNMEA, "GNGGA"); if (memcmp(thisNMEA, &nmeaAddressField[1], 5) == 0) { - return &storageNMEAGNGGA->automaticFlags; + return &storageNMEAGNGGA->automaticFlags; } return NULL; } -//We need to be able to identify an RTCM packet and then the length -//so that we know when the RTCM message is completely received and we then start -//listening for other sentences (like NMEA or UBX) -//RTCM packet structure is very odd. I never found RTCM STANDARD 10403.2 but -//http://d1.amobbs.com/bbs_upload782111/files_39/ourdev_635123CK0HJT.pdf is good -//https://dspace.cvut.cz/bitstream/handle/10467/65205/F3-BP-2016-Shkalikava-Anastasiya-Prenos%20polohove%20informace%20prostrednictvim%20datove%20site.pdf?sequence=-1 -//Lead me to: https://forum.u-blox.com/index.php/4348/how-to-read-rtcm-messages-from-neo-m8p -//RTCM 3.2 bytes look like this: -//Byte 0: Always 0xD3 -//Byte 1: 6-bits of zero -//Byte 2: 10-bits of length of this packet including the first two-ish header bytes, + 6. -//byte 3 + 4 bits: Msg type 12 bits -//Example: D3 00 7C 43 F0 ... / 0x7C = 124+6 = 130 bytes in this packet, 0x43F = Msg type 1087 +// We need to be able to identify an RTCM packet and then the length +// so that we know when the RTCM message is completely received and we then start +// listening for other sentences (like NMEA or UBX) +// RTCM packet structure is very odd. I never found RTCM STANDARD 10403.2 but +// http://d1.amobbs.com/bbs_upload782111/files_39/ourdev_635123CK0HJT.pdf is good +// https://dspace.cvut.cz/bitstream/handle/10467/65205/F3-BP-2016-Shkalikava-Anastasiya-Prenos%20polohove%20informace%20prostrednictvim%20datove%20site.pdf?sequence=-1 +// Lead me to: https://forum.u-blox.com/index.php/4348/how-to-read-rtcm-messages-from-neo-m8p +// RTCM 3.2 bytes look like this: +// Byte 0: Always 0xD3 +// Byte 1: 6-bits of zero +// Byte 2: 10-bits of length of this packet including the first two-ish header bytes, + 6. +// byte 3 + 4 bits: Msg type 12 bits +// Example: D3 00 7C 43 F0 ... / 0x7C = 124+6 = 130 bytes in this packet, 0x43F = Msg type 1087 void SFE_UBLOX_GNSS::processRTCMframe(uint8_t incoming) { if (rtcmFrameCounter == 1) { - rtcmLen = (incoming & 0x03) << 8; //Get the last two bits of this byte. Bits 8&9 of 10-bit length + rtcmLen = (incoming & 0x03) << 8; // Get the last two bits of this byte. Bits 8&9 of 10-bit length } else if (rtcmFrameCounter == 2) { - rtcmLen |= incoming; //Bits 0-7 of packet length - rtcmLen += 6; //There are 6 additional bytes of what we presume is header, msgType, CRC, and stuff + rtcmLen |= incoming; // Bits 0-7 of packet length + rtcmLen += 6; // There are 6 additional bytes of what we presume is header, msgType, CRC, and stuff } /*else if (rtcmFrameCounter == 3) { @@ -2249,42 +2343,43 @@ void SFE_UBLOX_GNSS::processRTCMframe(uint8_t incoming) rtcmFrameCounter++; - processRTCM(incoming); //Here is where we expose this byte to the user + processRTCM(incoming); // Here is where we expose this byte to the user if (rtcmFrameCounter == rtcmLen) { - //We're done! - currentSentence = NONE; //Reset and start looking for next sentence type + // We're done! + currentSentence = NONE; // Reset and start looking for next sentence type } } -//This function is called for each byte of an RTCM frame -//Ths user can overwrite this function and process the RTCM frame as they please -//Bytes can be piped to Serial or other interface. The consumer could be a radio or the internet (Ntrip broadcaster) +// This function is called for each byte of an RTCM frame +// Ths user can overwrite this function and process the RTCM frame as they please +// Bytes can be piped to Serial or other interface. The consumer could be a radio or the internet (Ntrip broadcaster) void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming) { - uint8_t ignoreMe = incoming; ignoreMe += 0; // Do something with incoming just to get rid of the pesky compiler warning! + uint8_t ignoreMe = incoming; + ignoreMe += 0; // Do something with incoming just to get rid of the pesky compiler warning! - //Radio.sendReliable((String)incoming); //An example of passing this byte to a radio + // Radio.sendReliable((String)incoming); //An example of passing this byte to a radio //_debugSerial->write(incoming); //An example of passing this byte out the serial port - //Debug printing - // _debugSerial->print(F(" ")); - // if(incoming < 0x10) _debugSerial->print(F("0")); - // _debugSerial->print(incoming, HEX); - // if(rtcmFrameCounter % 16 == 0) _debugSerial->println(); + // Debug printing + // _debugSerial->print(F(" ")); + // if(incoming < 0x10) _debugSerial->print(F("0")); + // _debugSerial->print(incoming, HEX); + // if(rtcmFrameCounter % 16 == 0) _debugSerial->println(); } -//Given a character, file it away into the uxb packet structure -//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 packetCfgPayloadSize bytes. -//startingSpot can be set so we only record a subset of bytes within a larger packet. +// Given a character, file it away into the uxb packet structure +// 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 packetCfgPayloadSize bytes. +// startingSpot can be set so we only record a subset of bytes within a larger packet. void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID) { - //If incomingUBX is a user-defined custom packet, then the payload size could be different to packetCfgPayloadSize. - //TO DO: update this to prevent an overrun when receiving an automatic message - // and the incomingUBX payload size is smaller than packetCfgPayloadSize. + // If incomingUBX is a user-defined custom packet, then the payload size could be different to packetCfgPayloadSize. + // TO DO: update this to prevent an overrun when receiving an automatic message + // and the incomingUBX payload size is smaller than packetCfgPayloadSize. uint16_t maximum_payload_size; if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG) maximum_payload_size = packetCfgPayloadSize; @@ -2293,23 +2388,23 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ // Calculate maximum payload size once Class and ID have been received // (This check is probably redundant as activePacketBuffer can only be SFE_UBLOX_PACKET_PACKETAUTO // when ubxFrameCounter >= 3) - //if (incomingUBX->counter >= 2) + // if (incomingUBX->counter >= 2) //{ - maximum_payload_size = getMaxPayloadSize(incomingUBX->cls, incomingUBX->id); - if (maximum_payload_size == 0) - { + maximum_payload_size = getMaxPayloadSize(incomingUBX->cls, incomingUBX->id); + if (maximum_payload_size == 0) + { #ifndef SFE_UBLOX_REDUCED_PROG_MEM - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->print(F("processUBX: getMaxPayloadSize returned ZERO!! Class: 0x")); - _debugSerial->print(incomingUBX->cls); - _debugSerial->print(F(" ID: 0x")); - _debugSerial->println(incomingUBX->id); - } -#endif + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("processUBX: getMaxPayloadSize returned ZERO!! Class: 0x")); + _debugSerial->print(incomingUBX->cls); + _debugSerial->print(F(" ID: 0x")); + _debugSerial->println(incomingUBX->id); } +#endif + } //} - //else + // else // maximum_payload_size = 2; } else @@ -2317,8 +2412,8 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ bool overrun = false; - //Add all incoming bytes to the rolling checksum - //Stop at len+4 as this is the checksum bytes to that should not be added to the rolling checksum + // Add all incoming bytes to the rolling checksum + // Stop at len+4 as this is the checksum bytes to that should not be added to the rolling checksum if (incomingUBX->counter < incomingUBX->len + 4) addToChecksum(incoming); @@ -2330,29 +2425,29 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ { incomingUBX->id = incoming; } - else if (incomingUBX->counter == 2) //Len LSB + else if (incomingUBX->counter == 2) // Len LSB { incomingUBX->len = incoming; } - else if (incomingUBX->counter == 3) //Len MSB + else if (incomingUBX->counter == 3) // Len MSB { incomingUBX->len |= incoming << 8; } - else if (incomingUBX->counter == incomingUBX->len + 4) //ChecksumA + else if (incomingUBX->counter == incomingUBX->len + 4) // ChecksumA { incomingUBX->checksumA = incoming; } - else if (incomingUBX->counter == incomingUBX->len + 5) //ChecksumB + else if (incomingUBX->counter == incomingUBX->len + 5) // ChecksumB { incomingUBX->checksumB = incoming; - currentSentence = NONE; //We're done! Reset the sentence to being looking for a new start char + currentSentence = NONE; // We're done! Reset the sentence to being looking for a new start char - //Validate this sentence + // Validate this sentence if ((incomingUBX->checksumA == rollingChecksumA) && (incomingUBX->checksumB == rollingChecksumB)) { incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_VALID; // Flag the packet as valid - _signsOfLife = true; //The checksum is valid, so set the _signsOfLife flag + _signsOfLife = true; // The checksum is valid, so set the _signsOfLife flag // Let's check if the class and ID match the requestedClass and requestedID // Remember - this could be a data packet or an ACK packet @@ -2382,8 +2477,8 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ #endif } - //This is not an ACK and we do not have a complete class and ID match - //So let's check for an "automatic" message arriving + // This is not an ACK and we do not have a complete class and ID match + // So let's check for an "automatic" message arriving else if (checkAutomatic(incomingUBX->cls, incomingUBX->id)) { // This isn't the message we are looking for... @@ -2426,7 +2521,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ } #endif - //We've got a valid packet, now do something with it but only if ignoreThisPayload is false + // We've got a valid packet, now do something with it but only if ignoreThisPayload is false if (ignoreThisPayload == false) { processUBXpacket(incomingUBX); @@ -2452,7 +2547,7 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - //Drive an external pin to allow for easier logic analyzation + // Drive an external pin to allow for easier logic analyzation if (debugPin >= 0) { digitalWrite((uint8_t)debugPin, LOW); @@ -2481,26 +2576,26 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETAUTO) { delete[] payloadAuto; // Created with new[] - payloadAuto = NULL; // Redundant? + payloadAuto = NULL; // Redundant? packetAuto.payload = payloadAuto; } } - else //Load this byte into the payload array + else // Load this byte into the payload array { - //If an automatic packet comes in asynchronously, we need to fudge the startingSpot + // If an automatic packet comes in asynchronously, we need to fudge the startingSpot uint16_t startingSpot = incomingUBX->startingSpot; if (checkAutomatic(incomingUBX->cls, incomingUBX->id)) startingSpot = 0; // Check if this is payload data which should be ignored if (ignoreThisPayload == false) { - //Begin recording if counter goes past startingSpot + // Begin recording if counter goes past startingSpot if ((incomingUBX->counter - 4) >= startingSpot) { - //Check to see if we have room for this byte - if (((incomingUBX->counter - 4) - startingSpot) < maximum_payload_size) //If counter = 208, starting spot = 200, we're good to record. + // Check to see if we have room for this byte + if (((incomingUBX->counter - 4) - startingSpot) < maximum_payload_size) // If counter = 208, starting spot = 200, we're good to record. { - incomingUBX->payload[(incomingUBX->counter - 4) - startingSpot] = incoming; //Store this byte into payload array + incomingUBX->payload[(incomingUBX->counter - 4) - startingSpot] = incoming; // Store this byte into payload array } else { @@ -2513,8 +2608,8 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ // incomingUBX->counter should never reach maximum_payload_size + class + id + len[2] + checksum[2] if (overrun || ((incomingUBX->counter == maximum_payload_size + 6) && (ignoreThisPayload == false))) { - //Something has gone very wrong - currentSentence = NONE; //Reset the sentence to being looking for a new start char + // Something has gone very wrong + currentSentence = NONE; // Reset the sentence to being looking for a new start char #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { @@ -2530,11 +2625,11 @@ void SFE_UBLOX_GNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_ #endif } - //Increment the counter + // Increment the counter incomingUBX->counter++; } -//Once a packet has been received and validated, identify this packet's class/id and update internal flags +// Once a packet has been received and validated, identify this packet's class/id and update internal flags void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) { switch (msg->cls) @@ -2542,7 +2637,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) case UBX_CLASS_NAV: if (msg->id == UBX_NAV_POSECEF && msg->len == UBX_NAV_POSECEF_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVPOSECEF != NULL) { packetUBXNAVPOSECEF->data.iTOW = extractLong(msg, 0); @@ -2551,18 +2646,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVPOSECEF->data.ecefZ = extractSignedLong(msg, 12); packetUBXNAVPOSECEF->data.pAcc = extractLong(msg, 16); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVPOSECEF->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVPOSECEF->callbackData->iTOW, &packetUBXNAVPOSECEF->data.iTOW, sizeof(UBX_NAV_POSECEF_data_t)); packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVPOSECEF->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2571,7 +2666,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_STATUS && msg->len == UBX_NAV_STATUS_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVSTATUS != NULL) { packetUBXNAVSTATUS->data.iTOW = extractLong(msg, 0); @@ -2582,18 +2677,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVSTATUS->data.ttff = extractLong(msg, 8); packetUBXNAVSTATUS->data.msss = extractLong(msg, 12); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVSTATUS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVSTATUS->callbackData->iTOW, &packetUBXNAVSTATUS->data.iTOW, sizeof(UBX_NAV_STATUS_data_t)); packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVSTATUS->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2602,7 +2697,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_DOP && msg->len == UBX_NAV_DOP_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVDOP != NULL) { packetUBXNAVDOP->data.iTOW = extractLong(msg, 0); @@ -2614,18 +2709,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVDOP->data.nDOP = extractInt(msg, 14); packetUBXNAVDOP->data.eDOP = extractInt(msg, 16); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVDOP->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVDOP->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVDOP->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVDOP->callbackData->iTOW, &packetUBXNAVDOP->data.iTOW, sizeof(UBX_NAV_DOP_data_t)); packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVDOP->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2634,7 +2729,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_ATT && msg->len == UBX_NAV_ATT_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVATT != NULL) { packetUBXNAVATT->data.iTOW = extractLong(msg, 0); @@ -2646,18 +2741,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVATT->data.accPitch = extractLong(msg, 24); packetUBXNAVATT->data.accHeading = extractLong(msg, 28); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVATT->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVATT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVATT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVATT->callbackData->iTOW, &packetUBXNAVATT->data.iTOW, sizeof(UBX_NAV_ATT_data_t)); packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVATT->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2666,7 +2761,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_PVT && msg->len == UBX_NAV_PVT_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVPVT != NULL) { packetUBXNAVPVT->data.iTOW = extractLong(msg, 0); @@ -2678,7 +2773,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVPVT->data.sec = extractByte(msg, 10); packetUBXNAVPVT->data.valid.all = extractByte(msg, 11); packetUBXNAVPVT->data.tAcc = extractLong(msg, 12); - packetUBXNAVPVT->data.nano = extractSignedLong(msg, 16); //Includes milliseconds + packetUBXNAVPVT->data.nano = extractSignedLong(msg, 16); // Includes milliseconds packetUBXNAVPVT->data.fixType = extractByte(msg, 20); packetUBXNAVPVT->data.flags.all = extractByte(msg, 21); packetUBXNAVPVT->data.flags2.all = extractByte(msg, 22); @@ -2702,19 +2797,19 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVPVT->data.magDec = extractSignedInt(msg, 88); packetUBXNAVPVT->data.magAcc = extractInt(msg, 90); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVPVT->moduleQueried.moduleQueried1.all = 0xFFFFFFFF; packetUBXNAVPVT->moduleQueried.moduleQueried2.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVPVT->callbackData->iTOW, &packetUBXNAVPVT->data.iTOW, sizeof(UBX_NAV_PVT_data_t)); packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVPVT->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2723,7 +2818,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_ODO && msg->len == UBX_NAV_ODO_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVODO != NULL) { packetUBXNAVODO->data.version = extractByte(msg, 0); @@ -2732,18 +2827,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVODO->data.totalDistance = extractLong(msg, 12); packetUBXNAVODO->data.distanceStd = extractLong(msg, 16); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVODO->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVODO->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVODO->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVODO->callbackData->version, &packetUBXNAVODO->data.version, sizeof(UBX_NAV_ODO_data_t)); packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVODO->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2752,7 +2847,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_VELECEF && msg->len == UBX_NAV_VELECEF_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVVELECEF != NULL) { packetUBXNAVVELECEF->data.iTOW = extractLong(msg, 0); @@ -2761,18 +2856,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVVELECEF->data.ecefVZ = extractSignedLong(msg, 12); packetUBXNAVVELECEF->data.sAcc = extractLong(msg, 16); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVVELECEF->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVVELECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVVELECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVVELECEF->callbackData->iTOW, &packetUBXNAVVELECEF->data.iTOW, sizeof(UBX_NAV_VELECEF_data_t)); packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVVELECEF->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2781,7 +2876,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_VELNED && msg->len == UBX_NAV_VELNED_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVVELNED != NULL) { packetUBXNAVVELNED->data.iTOW = extractLong(msg, 0); @@ -2794,18 +2889,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVVELNED->data.sAcc = extractLong(msg, 28); packetUBXNAVVELNED->data.cAcc = extractLong(msg, 32); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVVELNED->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVVELNED->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVVELNED->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVVELNED->callbackData->iTOW, &packetUBXNAVVELNED->data.iTOW, sizeof(UBX_NAV_VELNED_data_t)); packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVVELNED->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2814,7 +2909,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_HPPOSECEF && msg->len == UBX_NAV_HPPOSECEF_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVHPPOSECEF != NULL) { packetUBXNAVHPPOSECEF->data.version = extractByte(msg, 0); @@ -2828,18 +2923,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVHPPOSECEF->data.flags.all = extractByte(msg, 23); packetUBXNAVHPPOSECEF->data.pAcc = extractLong(msg, 24); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVHPPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVHPPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVHPPOSECEF->callbackData->version, &packetUBXNAVHPPOSECEF->data.version, sizeof(UBX_NAV_HPPOSECEF_data_t)); packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2848,7 +2943,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_HPPOSLLH && msg->len == UBX_NAV_HPPOSLLH_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVHPPOSLLH != NULL) { packetUBXNAVHPPOSLLH->data.version = extractByte(msg, 0); @@ -2865,18 +2960,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVHPPOSLLH->data.hAcc = extractLong(msg, 28); packetUBXNAVHPPOSLLH->data.vAcc = extractLong(msg, 32); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVHPPOSLLH->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVHPPOSLLH->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVHPPOSLLH->callbackData->version, &packetUBXNAVHPPOSLLH->data.version, sizeof(UBX_NAV_HPPOSLLH_data_t)); packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2885,7 +2980,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_PVAT && msg->len == UBX_NAV_PVAT_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVPVAT != NULL) { packetUBXNAVPVAT->data.iTOW = extractLong(msg, 0); @@ -2898,7 +2993,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVPVAT->data.min = extractByte(msg, 11); packetUBXNAVPVAT->data.sec = extractByte(msg, 12); packetUBXNAVPVAT->data.tAcc = extractLong(msg, 16); - packetUBXNAVPVAT->data.nano = extractSignedLong(msg, 20); //Includes milliseconds + packetUBXNAVPVAT->data.nano = extractSignedLong(msg, 20); // Includes milliseconds packetUBXNAVPVAT->data.fixType = extractByte(msg, 24); packetUBXNAVPVAT->data.flags.all = extractByte(msg, 25); packetUBXNAVPVAT->data.flags2.all = extractByte(msg, 26); @@ -2927,19 +3022,19 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVPVAT->data.errEllipseMajor = extractLong(msg, 100); packetUBXNAVPVAT->data.errEllipseMinor = extractLong(msg, 104); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0xFFFFFFFF; packetUBXNAVPVAT->moduleQueried.moduleQueried2.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVPVAT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVPVAT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVPVAT->callbackData->iTOW, &packetUBXNAVPVAT->data.iTOW, sizeof(UBX_NAV_PVAT_data_t)); packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVPVAT->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2948,7 +3043,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_CLOCK && msg->len == UBX_NAV_CLOCK_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVCLOCK != NULL) { packetUBXNAVCLOCK->data.iTOW = extractLong(msg, 0); @@ -2957,18 +3052,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVCLOCK->data.tAcc = extractLong(msg, 12); packetUBXNAVCLOCK->data.fAcc = extractLong(msg, 16); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVCLOCK->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVCLOCK->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVCLOCK->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVCLOCK->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVCLOCK->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVCLOCK->callbackData->iTOW, &packetUBXNAVCLOCK->data.iTOW, sizeof(UBX_NAV_CLOCK_data_t)); packetUBXNAVCLOCK->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVCLOCK->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -2977,7 +3072,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_TIMELS && msg->len == UBX_NAV_TIMELS_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVTIMELS != NULL) { packetUBXNAVTIMELS->data.iTOW = extractLong(msg, 0); @@ -2991,13 +3086,13 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVTIMELS->data.dateOfLsGpsDn = extractInt(msg, 18); packetUBXNAVTIMELS->data.valid.all = extractSignedChar(msg, 23); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVTIMELS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; } } else if (msg->id == UBX_NAV_SVIN && msg->len == UBX_NAV_SVIN_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVSVIN != NULL) { packetUBXNAVSVIN->data.version = extractByte(msg, 0); @@ -3014,13 +3109,13 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVSVIN->data.valid = extractSignedChar(msg, 36); packetUBXNAVSVIN->data.active = extractSignedChar(msg, 37); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVSVIN->moduleQueried.moduleQueried.all = 0xFFFFFFFF; } } else if (msg->id == UBX_NAV_SAT) // Note: length is variable { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVSAT != NULL) { packetUBXNAVSAT->data.header.iTOW = extractLong(msg, 0); @@ -3028,8 +3123,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVSAT->data.header.numSvs = extractByte(msg, 5); // The NAV SAT message could contain data for 255 SVs max. (numSvs is uint8_t. UBX_NAV_SAT_MAX_BLOCKS is 255) - for (uint16_t i = 0; (i < UBX_NAV_SAT_MAX_BLOCKS) && (i < ((uint16_t)packetUBXNAVSAT->data.header.numSvs)) - && ((i * 12) < (msg->len - 8)); i++) + for (uint16_t i = 0; (i < UBX_NAV_SAT_MAX_BLOCKS) && (i < ((uint16_t)packetUBXNAVSAT->data.header.numSvs)) && ((i * 12) < (msg->len - 8)); i++) { uint16_t offset = (i * 12) + 8; packetUBXNAVSAT->data.blocks[i].gnssId = extractByte(msg, offset + 0); @@ -3041,18 +3135,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVSAT->data.blocks[i].flags.all = extractLong(msg, offset + 8); } - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVSAT->moduleQueried = true; - //Check if we need to copy the data for the callback - if ((packetUBXNAVSAT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVSAT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVSAT->callbackData->header.iTOW, &packetUBXNAVSAT->data.header.iTOW, sizeof(UBX_NAV_SAT_data_t)); packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVSAT->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3061,12 +3155,12 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_RELPOSNED && ((msg->len == UBX_NAV_RELPOSNED_LEN) || (msg->len == UBX_NAV_RELPOSNED_LEN_F9))) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVRELPOSNED != NULL) { - //Note: - // RELPOSNED on the M8 is only 40 bytes long - // RELPOSNED on the F9 is 64 bytes long and contains much more information + // Note: + // RELPOSNED on the M8 is only 40 bytes long + // RELPOSNED on the F9 is 64 bytes long and contains much more information packetUBXNAVRELPOSNED->data.version = extractByte(msg, 0); packetUBXNAVRELPOSNED->data.refStationId = extractInt(msg, 2); @@ -3108,18 +3202,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVRELPOSNED->data.flags.all = extractLong(msg, 60); } - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVRELPOSNED->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVRELPOSNED->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVRELPOSNED->callbackData->version, &packetUBXNAVRELPOSNED->data.version, sizeof(UBX_NAV_RELPOSNED_data_t)); packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3128,25 +3222,25 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_NAV_AOPSTATUS && msg->len == UBX_NAV_AOPSTATUS_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXNAVAOPSTATUS != NULL) { packetUBXNAVAOPSTATUS->data.iTOW = extractLong(msg, 0); packetUBXNAVAOPSTATUS->data.aopCfg.all = extractByte(msg, 4); packetUBXNAVAOPSTATUS->data.status = extractByte(msg, 5); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXNAVAOPSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXNAVAOPSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXNAVAOPSTATUS->callbackData->iTOW, &packetUBXNAVAOPSTATUS->data.iTOW, sizeof(UBX_NAV_AOPSTATUS_data_t)); packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3159,7 +3253,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // Note: length is variable with version 0x01 // Note: the field positions depend on the version { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXRXMPMP != NULL) { packetUBXRXMPMP->data.version = extractByte(msg, 0); @@ -3189,12 +3283,12 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMPMP->data.userData[i] = extractByte(msg, i + userDataStart); } - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXRXMPMP->moduleQueried = true; - //Check if we need to copy the data for the callbacks - if ((packetUBXRXMPMP->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callbacks + if ((packetUBXRXMPMP->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXRXMPMP->callbackData->version, &packetUBXRXMPMP->data.version, sizeof(UBX_RXM_PMP_data_t)); packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = true; @@ -3206,7 +3300,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // Note: on protocol version 17: numWords is (0..16) // on protocol version 18+: numWords is (0..10) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXRXMSFRBX != NULL) { packetUBXRXMSFRBX->data.gnssId = extractByte(msg, 0); @@ -3216,24 +3310,23 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMSFRBX->data.chn = extractByte(msg, 5); packetUBXRXMSFRBX->data.version = extractByte(msg, 6); - for (uint8_t i = 0; (i < UBX_RXM_SFRBX_MAX_WORDS) && (i < packetUBXRXMSFRBX->data.numWords) - && ((i * 4) < (msg->len - 8)); i++) + for (uint8_t i = 0; (i < UBX_RXM_SFRBX_MAX_WORDS) && (i < packetUBXRXMSFRBX->data.numWords) && ((i * 4) < (msg->len - 8)); i++) { packetUBXRXMSFRBX->data.dwrd[i] = extractLong(msg, 8 + (i * 4)); } - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXRXMSFRBX->moduleQueried = true; - //Check if we need to copy the data for the callback - if ((packetUBXRXMSFRBX->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXRXMSFRBX->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXRXMSFRBX->callbackData->gnssId, &packetUBXRXMSFRBX->data.gnssId, sizeof(UBX_RXM_SFRBX_data_t)); packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXRXMSFRBX->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3243,7 +3336,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) else if (msg->id == UBX_RXM_RAWX) // Note: length is variable { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXRXMRAWX != NULL) { for (uint8_t i = 0; i < 8; i++) @@ -3256,8 +3349,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMRAWX->data.header.recStat.all = extractByte(msg, 12); packetUBXRXMRAWX->data.header.version = extractByte(msg, 13); - for (uint8_t i = 0; (i < UBX_RXM_RAWX_MAX_BLOCKS) && (i < packetUBXRXMRAWX->data.header.numMeas) - && ((((uint16_t)i) * 32) < (msg->len - 16)); i++) + for (uint8_t i = 0; (i < UBX_RXM_RAWX_MAX_BLOCKS) && (i < packetUBXRXMRAWX->data.header.numMeas) && ((((uint16_t)i) * 32) < (msg->len - 16)); i++) { uint16_t offset = (((uint16_t)i) * 32) + 16; for (uint8_t j = 0; j < 8; j++) @@ -3279,18 +3371,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMRAWX->data.blocks[i].trkStat.all = extractByte(msg, offset + 30); } - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXRXMRAWX->moduleQueried = true; - //Check if we need to copy the data for the callback - if ((packetUBXRXMRAWX->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXRXMRAWX->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXRXMRAWX->callbackData->header.rcvTow[0], &packetUBXRXMRAWX->data.header.rcvTow[0], sizeof(UBX_RXM_RAWX_data_t)); packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXRXMRAWX->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3301,7 +3393,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) case UBX_CLASS_CFG: if (msg->id == UBX_CFG_PRT && msg->len == UBX_CFG_PRT_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXCFGPRT != NULL) { packetUBXCFGPRT->data.portID = extractByte(msg, 0); @@ -3312,21 +3404,21 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXCFGPRT->data.outProtoMask.all = extractInt(msg, 14); packetUBXCFGPRT->data.flags = extractInt(msg, 16); - //Mark data as valid + // Mark data as valid packetUBXCFGPRT->dataValid = true; } } break; if (msg->id == UBX_CFG_RATE && msg->len == UBX_CFG_RATE_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXCFGRATE != NULL) { packetUBXCFGRATE->data.measRate = extractInt(msg, 0); packetUBXCFGRATE->data.navRate = extractInt(msg, 2); packetUBXCFGRATE->data.timeRef = extractInt(msg, 4); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXCFGRATE->moduleQueried.moduleQueried.all = 0xFFFFFFFF; } } @@ -3334,7 +3426,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) case UBX_CLASS_TIM: if (msg->id == UBX_TIM_TM2 && msg->len == UBX_TIM_TM2_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXTIMTM2 != NULL) { packetUBXTIMTM2->data.ch = extractByte(msg, 0); @@ -3348,18 +3440,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXTIMTM2->data.towSubMsF = extractLong(msg, 20); packetUBXTIMTM2->data.accEst = extractLong(msg, 24); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXTIMTM2->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXTIMTM2->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXTIMTM2->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXTIMTM2->callbackData->ch, &packetUBXTIMTM2->data.ch, sizeof(UBX_TIM_TM2_data_t)); packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXTIMTM2->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3370,7 +3462,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) case UBX_CLASS_ESF: if (msg->id == UBX_ESF_ALG && msg->len == UBX_ESF_ALG_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXESFALG != NULL) { packetUBXESFALG->data.iTOW = extractLong(msg, 0); @@ -3381,18 +3473,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXESFALG->data.pitch = extractSignedInt(msg, 12); packetUBXESFALG->data.roll = extractSignedInt(msg, 14); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXESFALG->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXESFALG->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXESFALG->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXESFALG->callbackData->iTOW, &packetUBXESFALG->data.iTOW, sizeof(UBX_ESF_ALG_data_t)); packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXESFALG->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3401,7 +3493,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_ESF_INS && msg->len == UBX_ESF_INS_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXESFINS != NULL) { packetUBXESFINS->data.bitfield0.all = extractLong(msg, 0); @@ -3413,18 +3505,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXESFINS->data.yAccel = extractSignedLong(msg, 28); packetUBXESFINS->data.zAccel = extractSignedLong(msg, 32); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXESFINS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXESFINS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXESFINS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXESFINS->callbackData->bitfield0.all, &packetUBXESFINS->data.bitfield0.all, sizeof(UBX_ESF_INS_data_t)); packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXESFINS->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3433,32 +3525,31 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_ESF_MEAS) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXESFMEAS != NULL) { packetUBXESFMEAS->data.timeTag = extractLong(msg, 0); packetUBXESFMEAS->data.flags.all = extractInt(msg, 4); packetUBXESFMEAS->data.id = extractInt(msg, 6); - for (uint16_t i = 0; (i < DEF_NUM_SENS) && (i < packetUBXESFMEAS->data.flags.bits.numMeas) - && ((i * 4) < (msg->len - 8)); i++) + for (uint16_t i = 0; (i < DEF_NUM_SENS) && (i < packetUBXESFMEAS->data.flags.bits.numMeas) && ((i * 4) < (msg->len - 8)); i++) { packetUBXESFMEAS->data.data[i].data.all = extractLong(msg, 8 + (i * 4)); } if ((uint16_t)msg->len > (uint16_t)(8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4))) packetUBXESFMEAS->data.calibTtag = extractLong(msg, 8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4)); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXESFMEAS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXESFMEAS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXESFMEAS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXESFMEAS->callbackData->timeTag, &packetUBXESFMEAS->data.timeTag, sizeof(UBX_ESF_MEAS_data_t)); packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXESFMEAS->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3467,7 +3558,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_ESF_RAW) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXESFRAW != NULL) { for (uint16_t i = 0; (i < DEF_NUM_SENS) && ((i * 8) < (msg->len - 4)); i++) @@ -3476,18 +3567,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXESFRAW->data.data[i].sTag = extractLong(msg, 8 + (i * 8)); } - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXESFRAW->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXESFRAW->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXESFRAW->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXESFRAW->callbackData->data[0].data.all, &packetUBXESFRAW->data.data[0].data.all, sizeof(UBX_ESF_RAW_data_t)); packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXESFRAW->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3496,15 +3587,14 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_ESF_STATUS) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXESFSTATUS != NULL) { packetUBXESFSTATUS->data.iTOW = extractLong(msg, 0); packetUBXESFSTATUS->data.version = extractByte(msg, 4); packetUBXESFSTATUS->data.fusionMode = extractByte(msg, 12); packetUBXESFSTATUS->data.numSens = extractByte(msg, 15); - for (uint16_t i = 0; (i < DEF_NUM_SENS) && (i < packetUBXESFSTATUS->data.numSens) - && ((i * 4) < (msg->len - 16)); i++) + for (uint16_t i = 0; (i < DEF_NUM_SENS) && (i < packetUBXESFSTATUS->data.numSens) && ((i * 4) < (msg->len - 16)); i++) { packetUBXESFSTATUS->data.status[i].sensStatus1.all = extractByte(msg, 16 + (i * 4) + 0); packetUBXESFSTATUS->data.status[i].sensStatus2.all = extractByte(msg, 16 + (i * 4) + 1); @@ -3512,18 +3602,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXESFSTATUS->data.status[i].faults.all = extractByte(msg, 16 + (i * 4) + 3); } - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXESFSTATUS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXESFSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXESFSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXESFSTATUS->callbackData->iTOW, &packetUBXESFSTATUS->data.iTOW, sizeof(UBX_ESF_STATUS_data_t)); packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXESFSTATUS->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3534,7 +3624,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) case UBX_CLASS_MGA: if (msg->id == UBX_MGA_ACK_DATA0 && msg->len == UBX_MGA_ACK_DATA0_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXMGAACK != NULL) { // Calculate how many ACKs are already stored in the ring buffer @@ -3571,7 +3661,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->println(F("processUBXpacket: packetUBXMGAACK is full. ACK will be lost!")); + _debugSerial->println(F("processUBXpacket: packetUBXMGAACK is full. ACK will be lost!")); } #endif } @@ -3579,7 +3669,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_MGA_DBD && msg->len <= UBX_MGA_DBD_LEN) // Message length may be less than UBX_MGA_DBD_LEN. UBX_MGA_DBD_LEN is the maximum it will be. { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXMGADBD != NULL) { // Calculate how many DBDs are already stored in the ring buffer @@ -3599,7 +3689,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) { // Yes, we have, so store it // We need to save the entire message - header, payload and checksum - packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryHeader1 = UBX_SYNCH_1; + packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryHeader1 = UBX_SYNCH_1; packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryHeader2 = UBX_SYNCH_2; packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryClass = UBX_CLASS_MGA; packetUBXMGADBD->data[packetUBXMGADBD->head].dbdEntryID = UBX_MGA_DBD; @@ -3621,7 +3711,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->println(F("processUBXpacket: packetUBXMGADBD is full. DBD data will be lost!")); + _debugSerial->println(F("processUBXpacket: packetUBXMGADBD is full. DBD data will be lost!")); } #endif } @@ -3631,7 +3721,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) case UBX_CLASS_HNR: if (msg->id == UBX_HNR_PVT && msg->len == UBX_HNR_PVT_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXHNRPVT != NULL) { packetUBXHNRPVT->data.iTOW = extractLong(msg, 0); @@ -3658,18 +3748,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXHNRPVT->data.sAcc = extractLong(msg, 60); packetUBXHNRPVT->data.headAcc = extractLong(msg, 64); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXHNRPVT->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXHNRPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXHNRPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXHNRPVT->callbackData->iTOW, &packetUBXHNRPVT->data.iTOW, sizeof(UBX_HNR_PVT_data_t)); packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXHNRPVT->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3678,7 +3768,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_HNR_ATT && msg->len == UBX_HNR_ATT_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXHNRATT != NULL) { packetUBXHNRATT->data.iTOW = extractLong(msg, 0); @@ -3690,18 +3780,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXHNRATT->data.accPitch = extractLong(msg, 24); packetUBXHNRATT->data.accHeading = extractLong(msg, 28); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXHNRATT->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXHNRATT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXHNRATT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXHNRATT->callbackData->iTOW, &packetUBXHNRATT->data.iTOW, sizeof(UBX_HNR_ATT_data_t)); packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXHNRATT->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3710,7 +3800,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } else if (msg->id == UBX_HNR_INS && msg->len == UBX_HNR_INS_LEN) { - //Parse various byte fields into storage - but only if we have memory allocated for it + // Parse various byte fields into storage - but only if we have memory allocated for it if (packetUBXHNRINS != NULL) { packetUBXHNRINS->data.bitfield0.all = extractLong(msg, 0); @@ -3722,18 +3812,18 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXHNRINS->data.yAccel = extractSignedLong(msg, 28); packetUBXHNRINS->data.zAccel = extractSignedLong(msg, 32); - //Mark all datums as fresh (not read before) + // Mark all datums as fresh (not read before) packetUBXHNRINS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; - //Check if we need to copy the data for the callback - if ((packetUBXHNRINS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + // Check if we need to copy the data for the callback + if ((packetUBXHNRINS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale { memcpy(&packetUBXHNRINS->callbackData->bitfield0.all, &packetUBXHNRINS->data.bitfield0.all, sizeof(UBX_HNR_INS_data_t)); packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid = true; } - //Check if we need to copy the data into the file buffer + // Check if we need to copy the data into the file buffer if (packetUBXHNRINS->automaticFlags.flags.bits.addToFileBuffer) { storePacket(msg); @@ -3744,8 +3834,8 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) } } -//Given a message, calc and store the two byte "8-Bit Fletcher" checksum over the entirety of the message -//This is called before we send a command message +// Given a message, calc and store the two byte "8-Bit Fletcher" checksum over the entirety of the message +// This is called before we send a command message void SFE_UBLOX_GNSS::calcChecksum(ubxPacket *msg) { msg->checksumA = 0; @@ -3770,20 +3860,20 @@ void SFE_UBLOX_GNSS::calcChecksum(ubxPacket *msg) } } -//Given a message and a byte, add to rolling "8-Bit Fletcher" checksum -//This is used when receiving messages from module +// Given a message and a byte, add to rolling "8-Bit Fletcher" checksum +// This is used when receiving messages from module void SFE_UBLOX_GNSS::addToChecksum(uint8_t incoming) { rollingChecksumA += incoming; rollingChecksumB += rollingChecksumA; } -//Given a packet and payload, send everything including CRC bytes via I2C port +// Given a packet and payload, send everything including CRC bytes via I2C port sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t maxWait, bool expectACKonly) { sfe_ublox_status_e retVal = SFE_UBLOX_STATUS_SUCCESS; - calcChecksum(outgoingUBX); //Sets checksum A and B bytes of the packet + calcChecksum(outgoingUBX); // Sets checksum A and B bytes of the packet #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) @@ -3818,7 +3908,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t if (maxWait > 0) { - //Depending on what we just sent, either we need to look for an ACK or not + // Depending on what we just sent, either we need to look for an ACK or not if ((outgoingUBX->cls == UBX_CLASS_CFG) || (expectACKonly == true)) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -3827,7 +3917,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t _debugSerial->println(F("sendCommand: Waiting for ACK response")); } #endif - retVal = waitForACKResponse(outgoingUBX, outgoingUBX->cls, outgoingUBX->id, maxWait); //Wait for Ack response + retVal = waitForACKResponse(outgoingUBX, outgoingUBX->cls, outgoingUBX->id, maxWait); // Wait for Ack response } else { @@ -3837,17 +3927,18 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t _debugSerial->println(F("sendCommand: Waiting for No ACK response")); } #endif - retVal = waitForNoACKResponse(outgoingUBX, outgoingUBX->cls, outgoingUBX->id, maxWait); //Wait for Ack response + retVal = waitForNoACKResponse(outgoingUBX, outgoingUBX->cls, outgoingUBX->id, maxWait); // Wait for Ack response } } return retVal; } -//Returns false if sensor fails to respond to I2C traffic +// Returns false if sensor fails to respond to I2C traffic sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait) { - uint16_t ignoreMe = maxWait; ignoreMe += 0; // Do something with maxWait just to avoid the pesky compiler warnings! - + uint16_t ignoreMe = maxWait; + ignoreMe += 0; // Do something with maxWait just to avoid the pesky compiler warnings! + // From the integration guide: // "The receiver does not provide any write access except for writing UBX and NMEA messages to the // receiver, such as configuration or aiding data. Therefore, the register set mentioned in section Read @@ -3870,7 +3961,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 // The next four lines can be commented. We do not need to point at the 0xFF data register //_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); //There is no register to write to, we just begin writing data bytes //_i2cPort->write(0xFF); - //if (_i2cPort->endTransmission(false) != 0) //Don't release bus + // if (_i2cPort->endTransmission(false) != 0) //Don't release bus // return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); //Sensor did not ACK // The total number of bytes to be written is: payload len + 8 @@ -3887,14 +3978,14 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 // i2cTransactionSize will be at least 8. We don't need to check for smaller values than that. uint16_t bytesToSend = outgoingUBX->len + 8; // How many bytes need to be sent - uint16_t bytesSent = 0; // How many bytes have been sent - uint16_t bytesLeftToSend = bytesToSend; // How many bytes remain to be sent - uint16_t startSpot = 0; // Payload pointer + uint16_t bytesSent = 0; // How many bytes have been sent + uint16_t bytesLeftToSend = bytesToSend; // How many bytes remain to be sent + uint16_t startSpot = 0; // Payload pointer while (bytesLeftToSend > 0) { uint16_t len = bytesLeftToSend; // How many bytes should we actually write? - if (len > i2cTransactionSize) // Limit len to i2cTransactionSize + if (len > i2cTransactionSize) // Limit len to i2cTransactionSize len = i2cTransactionSize; bytesLeftToSend -= len; // Calculate how many bytes will be left after we do this write @@ -3904,7 +3995,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 // But if bytesLeftToSend is 1, we need to adjust len to make sure we write at least 2 bytes in the final write if (bytesLeftToSend == 1) { - len -= 1; // Decrement len by 1 + len -= 1; // Decrement len by 1 bytesLeftToSend += 1; // Increment bytesLeftToSend by 1 } @@ -3912,19 +4003,19 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 if (bytesSent == 0) // Is this the first write? If it is, write the header bytes { - _i2cPort->write(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on. - _i2cPort->write(UBX_SYNCH_2); //b + _i2cPort->write(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on. + _i2cPort->write(UBX_SYNCH_2); // b _i2cPort->write(outgoingUBX->cls); _i2cPort->write(outgoingUBX->id); - _i2cPort->write(outgoingUBX->len & 0xFF); //LSB - _i2cPort->write(outgoingUBX->len >> 8); //MSB + _i2cPort->write(outgoingUBX->len & 0xFF); // LSB + _i2cPort->write(outgoingUBX->len >> 8); // MSB bytesSent += 6; uint16_t x = 0; - //Write a portion of the payload to the bus. - //Keep going until we reach the end of the payload (x == outgoingUBX->len) - //or we've sent as many bytes as we can in this transmission (bytesSent == len). + // Write a portion of the payload to the bus. + // Keep going until we reach the end of the payload (x == outgoingUBX->len) + // or we've sent as many bytes as we can in this transmission (bytesSent == len). for (; (x < outgoingUBX->len) && (bytesSent < len); x++) { _i2cPort->write(outgoingUBX->payload[startSpot + x]); @@ -3932,12 +4023,12 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 } startSpot += x; - //Can we write both checksum bytes? - //We can send both bytes now if we have exactly 2 bytes left - //to be sent in this transmission (bytesSent == (len - 2)). + // Can we write both checksum bytes? + // We can send both bytes now if we have exactly 2 bytes left + // to be sent in this transmission (bytesSent == (len - 2)). if (bytesSent == (len - 2)) { - //Write checksum + // Write checksum _i2cPort->write(outgoingUBX->checksumA); _i2cPort->write(outgoingUBX->checksumB); bytesSent += 2; @@ -3946,9 +4037,9 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 else // Keep writing payload bytes. Write the checksum at the right time. { uint16_t x = 0; - //Write a portion of the payload to the bus. - //Keep going until we've sent as many bytes as we can in this transmission (x == len) - //or until we reach the end of the payload ((startSpot + x) == (outgoingUBX->len)) + // Write a portion of the payload to the bus. + // Keep going until we've sent as many bytes as we can in this transmission (x == len) + // or until we reach the end of the payload ((startSpot + x) == (outgoingUBX->len)) for (; (x < len) && ((startSpot + x) < (outgoingUBX->len)); x++) { _i2cPort->write(outgoingUBX->payload[startSpot + x]); @@ -3956,12 +4047,12 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 } startSpot += x; - //Can we write both checksum bytes? - //We can send both bytes if we have exactly 2 bytes left to be sent (bytesSent == (bytesToSend - 2)) - //and if there is room for 2 bytes in this transmission + // Can we write both checksum bytes? + // We can send both bytes if we have exactly 2 bytes left to be sent (bytesSent == (bytesToSend - 2)) + // and if there is room for 2 bytes in this transmission if ((bytesSent == (bytesToSend - 2)) && (x == (len - 2))) { - //Write checksum + // Write checksum _i2cPort->write(outgoingUBX->checksumA); _i2cPort->write(outgoingUBX->checksumB); bytesSent += 2; @@ -3970,44 +4061,43 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 if (bytesSent < bytesToSend) // Do we need to go round the loop again? { - if (_i2cPort->endTransmission(_i2cStopRestart) != 0) //Don't release bus unless we have to - return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); //Sensor did not ACK + if (_i2cPort->endTransmission(_i2cStopRestart) != 0) // Don't release bus unless we have to + return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); // Sensor did not ACK } } - //All done transmitting bytes. Release bus. + // All done transmitting bytes. Release bus. if (_i2cPort->endTransmission() != 0) - return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); //Sensor did not ACK + return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); // Sensor did not ACK return (SFE_UBLOX_STATUS_SUCCESS); } -//Given a packet and payload, send everything including CRC bytesA via Serial port +// Given a packet and payload, send everything including CRC bytesA via Serial port void SFE_UBLOX_GNSS::sendSerialCommand(ubxPacket *outgoingUBX) { - //Write header bytes + // Write header bytes _serialPort->write(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on. - _serialPort->write(UBX_SYNCH_2); //b + _serialPort->write(UBX_SYNCH_2); // b _serialPort->write(outgoingUBX->cls); _serialPort->write(outgoingUBX->id); - _serialPort->write(outgoingUBX->len & 0xFF); //LSB - _serialPort->write(outgoingUBX->len >> 8); //MSB + _serialPort->write(outgoingUBX->len & 0xFF); // LSB + _serialPort->write(outgoingUBX->len >> 8); // MSB - //Write payload. + // Write payload. for (uint16_t i = 0; i < outgoingUBX->len; i++) { _serialPort->write(outgoingUBX->payload[i]); } - //Write checksum + // Write checksum _serialPort->write(outgoingUBX->checksumA); _serialPort->write(outgoingUBX->checksumB); } - // Transfer a byte to SPI. Also capture any bytes received from the UBLOX device during sending and capture them in a small buffer so that // they can be processed later with process -void SFE_UBLOX_GNSS::spiTransfer(uint8_t byteToTransfer) +void SFE_UBLOX_GNSS::spiTransfer(uint8_t byteToTransfer) { uint8_t returnedByte = _spiPort->transfer(byteToTransfer); if ((spiBufferIndex < getSpiTransactionSize()) && (returnedByte != 0xFF || currentSentence != NONE)) @@ -4021,28 +4111,28 @@ void SFE_UBLOX_GNSS::spiTransfer(uint8_t byteToTransfer) void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX) { if (spiBuffer == NULL) - { + { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->print(F("sendSpiCommand: no memory allocation for SPI Buffer!")); + _debugSerial->print(F("sendSpiCommand: no memory allocation for SPI Buffer!")); } #endif return; } - + // Start at the beginning of the SPI buffer spiBufferIndex = 0; _spiPort->beginTransaction(SPISettings(_spiSpeed, MSBFIRST, SPI_MODE0)); digitalWrite(_csPin, LOW); - //Write header bytes + // Write header bytes spiTransfer(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on. - spiTransfer(UBX_SYNCH_2); //b + spiTransfer(UBX_SYNCH_2); // b spiTransfer(outgoingUBX->cls); spiTransfer(outgoingUBX->id); - spiTransfer(outgoingUBX->len & 0xFF); //LSB + spiTransfer(outgoingUBX->len & 0xFF); // LSB spiTransfer(outgoingUBX->len >> 8); #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -4063,7 +4153,7 @@ void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX) } #endif - //Write payload. + // Write payload. for (uint16_t i = 0; i < outgoingUBX->len; i++) { spiTransfer(outgoingUBX->payload[i]); @@ -4076,7 +4166,7 @@ void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX) #endif } - //Write checksum + // Write checksum spiTransfer(outgoingUBX->checksumA); spiTransfer(outgoingUBX->checksumB); digitalWrite(_csPin, HIGH); @@ -4093,7 +4183,7 @@ void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX) #endif } -//Pretty prints the current ubxPacket +// Pretty prints the current ubxPacket void SFE_UBLOX_GNSS::printPacket(ubxPacket *packet, bool alwaysPrintPayload) { // Only print the payload is ignoreThisPayload is false otherwise @@ -4106,13 +4196,13 @@ void SFE_UBLOX_GNSS::printPacket(ubxPacket *packet, bool alwaysPrintPayload) if (_printDebug == true) { _debugSerial->print(F("CLS:")); - if (packet->cls == UBX_CLASS_NAV) //1 + if (packet->cls == UBX_CLASS_NAV) // 1 _debugSerial->print(F("NAV")); - else if (packet->cls == UBX_CLASS_ACK) //5 + else if (packet->cls == UBX_CLASS_ACK) // 5 _debugSerial->print(F("ACK")); - else if (packet->cls == UBX_CLASS_CFG) //6 + else if (packet->cls == UBX_CLASS_CFG) // 6 _debugSerial->print(F("CFG")); - else if (packet->cls == UBX_CLASS_MON) //0x0A + else if (packet->cls == UBX_CLASS_MON) // 0x0A _debugSerial->print(F("MON")); else { @@ -4161,40 +4251,40 @@ void SFE_UBLOX_GNSS::printPacket(ubxPacket *packet, bool alwaysPrintPayload) #endif } -//When messages from the class CFG are sent to the receiver, the receiver will send an "acknowledge"(UBX - ACK - ACK) or a +// 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. +// Some messages from other classes also use the same acknowledgement mechanism. -//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 +// 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 +// 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 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_. +// 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) -//We need to think carefully about how interleaved PVT packets affect things. -//It is entirely possible that our packetCfg and packetAck were received successfully -//but while we are still in the "if (checkUblox() == true)" loop a PVT packet is processed -//or _starts_ to arrive (remember that Serial data can arrive very slowly). - -//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 something very bad happens (e.g. a double checksum failure) -//Returns SFE_UBLOX_STATUS_COMMAND_NACK if the packet was not-acknowledged (NACK) -//Returns SFE_UBLOX_STATUS_CRC_FAIL if we had a checksum failure -//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out -//Returns SFE_UBLOX_STATUS_DATA_OVERWRITTEN if we got an ACK and a valid packetCfg but that the packetCfg has been -// or is currently being overwritten (remember that Serial data can arrive very slowly) +// We need to think carefully about how interleaved PVT packets affect things. +// It is entirely possible that our packetCfg and packetAck were received successfully +// but while we are still in the "if (checkUblox() == true)" loop a PVT packet is processed +// or _starts_ to arrive (remember that Serial data can arrive very slowly). + +// 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 something very bad happens (e.g. a double checksum failure) +// Returns SFE_UBLOX_STATUS_COMMAND_NACK if the packet was not-acknowledged (NACK) +// Returns SFE_UBLOX_STATUS_CRC_FAIL if we had a checksum failure +// Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out +// Returns SFE_UBLOX_STATUS_DATA_OVERWRITTEN if we got an ACK and a valid packetCfg but that the packetCfg has been +// or is currently being overwritten (remember that Serial data can arrive very slowly) sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime) { - outgoingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent + outgoingUBX->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; packetBuf.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; packetAuto.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; @@ -4206,7 +4296,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui unsigned long startTime = millis(); while (millis() < (startTime + (unsigned long)maxTime)) { - if (checkUbloxInternal(outgoingUBX, requestedClass, requestedID) == true) //See if new data is available. Process bytes as they come in. + if (checkUbloxInternal(outgoingUBX, requestedClass, requestedID) == true) // See if new data is available. Process bytes as they come in. { // If both the outgoingUBX->classAndIDmatch and packetAck.classAndIDmatch are VALID // and outgoingUBX->valid is _still_ VALID and the class and ID _still_ match @@ -4221,7 +4311,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data and a correct ACK! + return (SFE_UBLOX_STATUS_DATA_RECEIVED); // We received valid data and a correct ACK! } // We can be confident that the data packet (if we are going to get one) will always arrive @@ -4239,7 +4329,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_DATA_SENT); //We got an ACK but no data... + return (SFE_UBLOX_STATUS_DATA_SENT); // We got an ACK but no data... } // If both the outgoingUBX->classAndIDmatch and packetAck.classAndIDmatch are VALID @@ -4274,7 +4364,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_CRC_FAIL); //Checksum fail + return (SFE_UBLOX_STATUS_CRC_FAIL); // Checksum fail } // If our packet was not-acknowledged (NACK) we do not receive a data packet - we only get the NACK. @@ -4294,7 +4384,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_COMMAND_NACK); //We received a NACK! + return (SFE_UBLOX_STATUS_COMMAND_NACK); // We received a NACK! } // If the outgoingUBX->classAndIDmatch is VALID but the packetAck.classAndIDmatch is NOT_VALID @@ -4310,7 +4400,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data and an invalid ACK! + return (SFE_UBLOX_STATUS_DATA_RECEIVED); // We received valid data and an invalid ACK! } // If the outgoingUBX->classAndIDmatch is NOT_VALID and the packetAck.classAndIDmatch is NOT_VALID @@ -4325,7 +4415,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_FAIL); //We received invalid data and an invalid ACK! + return (SFE_UBLOX_STATUS_FAIL); // We received invalid data and an invalid ACK! } // If the outgoingUBX->classAndIDmatch is VALID and the packetAck.classAndIDmatch is NOT_DEFINED @@ -4340,10 +4430,10 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui // } } - } //checkUbloxInternal == true + } // checkUbloxInternal == true delay(1); // Allow an RTOS to get an elbow in (#11) - } //while (millis() < (startTime + (unsigned long)maxTime)) + } // while (millis() < (startTime + (unsigned long)maxTime)) // We have timed out... // If the outgoingUBX->classAndIDmatch is VALID then we can take a gamble and return DATA_RECEIVED @@ -4358,7 +4448,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui _debugSerial->println(F(" msec. ")); } #endif - return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data... But no ACK! + return (SFE_UBLOX_STATUS_DATA_RECEIVED); // We received valid data... But no ACK! } #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -4373,15 +4463,15 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui return (SFE_UBLOX_STATUS_TIMEOUT); } -//For non-CFG queries no ACK is sent so we use this function -//Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a config packet full of response data that has CLS/ID match to our query packet -//Returns SFE_UBLOX_STATUS_CRC_FAIL if we got a corrupt config packet that has CLS/ID match to our query packet -//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out -//Returns SFE_UBLOX_STATUS_DATA_OVERWRITTEN if we got an a valid packetCfg but that the packetCfg has been -// or is currently being overwritten (remember that Serial data can arrive very slowly) +// For non-CFG queries no ACK is sent so we use this function +// Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a config packet full of response data that has CLS/ID match to our query packet +// Returns SFE_UBLOX_STATUS_CRC_FAIL if we got a corrupt config packet that has CLS/ID match to our query packet +// Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out +// Returns SFE_UBLOX_STATUS_DATA_OVERWRITTEN if we got an a valid packetCfg but that the packetCfg has been +// or is currently being overwritten (remember that Serial data can arrive very slowly) sfe_ublox_status_e SFE_UBLOX_GNSS::waitForNoACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime) { - outgoingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent + outgoingUBX->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; packetBuf.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; packetAuto.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; @@ -4393,7 +4483,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForNoACKResponse(ubxPacket *outgoingUBX, unsigned long startTime = millis(); while (millis() - startTime < maxTime) { - if (checkUbloxInternal(outgoingUBX, requestedClass, requestedID) == true) //See if new data is available. Process bytes as they come in. + if (checkUbloxInternal(outgoingUBX, requestedClass, requestedID) == true) // See if new data is available. Process bytes as they come in. { // If outgoingUBX->classAndIDmatch is VALID @@ -4409,7 +4499,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForNoACKResponse(ubxPacket *outgoingUBX, _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data! + return (SFE_UBLOX_STATUS_DATA_RECEIVED); // We received valid data! } // If the outgoingUBX->classAndIDmatch is VALID @@ -4458,7 +4548,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForNoACKResponse(ubxPacket *outgoingUBX, _debugSerial->println(F(" msec")); } #endif - return (SFE_UBLOX_STATUS_CRC_FAIL); //We received invalid data + return (SFE_UBLOX_STATUS_CRC_FAIL); // We received invalid data } } @@ -4485,9 +4575,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) checkCallbacksReentrant = true; - if ((packetUBXNAVPOSECEF != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVPOSECEF != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVPOSECEF->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4504,9 +4594,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVPOSECEF->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVSTATUS != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVSTATUS != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4523,9 +4613,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVSTATUS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVDOP != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVDOP->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVDOP != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVDOP->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVDOP->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4542,9 +4632,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVDOP->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVATT != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVATT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVATT != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVATT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVATT->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4561,9 +4651,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVATT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVPVT != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVPVT != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVPVT->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4580,9 +4670,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVODO != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVODO->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVODO != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVODO->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVODO->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4599,9 +4689,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVODO->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVVELECEF != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVVELECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVVELECEF != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVVELECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVVELECEF->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4618,9 +4708,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVVELECEF->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVVELNED != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVVELNED->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVVELNED != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVVELNED->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVVELNED->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4637,9 +4727,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVVELNED->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVHPPOSECEF != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVHPPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVHPPOSECEF != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVHPPOSECEF->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVHPPOSECEF->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4656,9 +4746,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVHPPOSLLH != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVHPPOSLLH->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVHPPOSLLH != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVHPPOSLLH->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVHPPOSLLH->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4675,9 +4765,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVPVAT != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVPVAT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVPVAT != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVPVAT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVPVAT->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4694,9 +4784,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVPVAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVCLOCK != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVCLOCK->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVCLOCK->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVCLOCK != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVCLOCK->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVCLOCK->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVCLOCK->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4713,9 +4803,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVCLOCK->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 + 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 { if (packetUBXNAVSAT->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4732,9 +4822,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVRELPOSNED != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVRELPOSNED->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVRELPOSNED != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVRELPOSNED->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVRELPOSNED->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4751,9 +4841,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVRELPOSNED->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXNAVAOPSTATUS != NULL) // If RAM has been allocated for message storage - && (packetUBXNAVAOPSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXNAVAOPSTATUS != NULL) // If RAM has been allocated for message storage + && (packetUBXNAVAOPSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXNAVAOPSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4770,9 +4860,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - 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->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + 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->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined { @@ -4783,9 +4873,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXRXMSFRBX != NULL) // If RAM has been allocated for message storage - && (packetUBXRXMSFRBX->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXRXMSFRBX != NULL) // If RAM has been allocated for message storage + && (packetUBXRXMSFRBX->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXRXMSFRBX->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4802,9 +4892,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXRXMRAWX != NULL) // If RAM has been allocated for message storage - && (packetUBXRXMRAWX->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXRXMRAWX != NULL) // If RAM has been allocated for message storage + && (packetUBXRXMRAWX->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXRXMRAWX->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4821,9 +4911,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXRXMRAWX->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXTIMTM2 != NULL) // If RAM has been allocated for message storage - && (packetUBXTIMTM2->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXTIMTM2 != NULL) // If RAM has been allocated for message storage + && (packetUBXTIMTM2->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXTIMTM2->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4840,9 +4930,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXESFALG != NULL) // If RAM has been allocated for message storage - && (packetUBXESFALG->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXESFALG != NULL) // If RAM has been allocated for message storage + && (packetUBXESFALG->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXESFALG->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4859,9 +4949,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXESFALG->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXESFINS != NULL) // If RAM has been allocated for message storage - && (packetUBXESFINS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXESFINS != NULL) // If RAM has been allocated for message storage + && (packetUBXESFINS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXESFINS->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4878,9 +4968,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXESFINS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXESFMEAS != NULL) // If RAM has been allocated for message storage - && (packetUBXESFMEAS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXESFMEAS != NULL) // If RAM has been allocated for message storage + && (packetUBXESFMEAS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXESFMEAS->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4897,9 +4987,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXESFRAW != NULL) // If RAM has been allocated for message storage - && (packetUBXESFRAW->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXESFRAW != NULL) // If RAM has been allocated for message storage + && (packetUBXESFRAW->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXESFRAW->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4916,9 +5006,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXESFSTATUS != NULL) // If RAM has been allocated for message storage - && (packetUBXESFSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXESFSTATUS != NULL) // If RAM has been allocated for message storage + && (packetUBXESFSTATUS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXESFSTATUS->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4935,9 +5025,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXESFSTATUS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXHNRATT != NULL) // If RAM has been allocated for message storage - && (packetUBXHNRATT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXHNRATT != NULL) // If RAM has been allocated for message storage + && (packetUBXHNRATT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXHNRATT->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4954,9 +5044,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXHNRATT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXHNRINS != NULL) // If RAM has been allocated for message storage - && (packetUBXHNRINS->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXHNRINS != NULL) // If RAM has been allocated for message storage + && (packetUBXHNRINS->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXHNRINS->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4973,9 +5063,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXHNRINS->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXHNRPVT != NULL) // If RAM has been allocated for message storage - && (packetUBXHNRPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXHNRPVT != NULL) // If RAM has been allocated for message storage + && (packetUBXHNRPVT->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { if (packetUBXHNRPVT->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -4992,9 +5082,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXHNRPVT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((storageNMEAGPGGA != NULL) // If RAM has been allocated for message storage - && (storageNMEAGPGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data - && (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid + if ((storageNMEAGPGGA != NULL) // If RAM has been allocated for message storage + && (storageNMEAGPGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data + && (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid { if (storageNMEAGPGGA->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -5011,9 +5101,9 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale } - if ((storageNMEAGNGGA != NULL) // If RAM has been allocated for message storage - && (storageNMEAGNGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data - && (storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid + if ((storageNMEAGNGGA != NULL) // If RAM has been allocated for message storage + && (storageNMEAGNGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data + && (storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid { if (storageNMEAGNGGA->callbackPointer != NULL) // If the pointer to the callback has been defined { @@ -5087,7 +5177,7 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s else bytesToWrite = bytesLeftToWrite; - //If there would be one byte left to be written next time, send one byte less now + // If there would be one byte left to be written next time, send one byte less now if ((bytesLeftToWrite - bytesToWrite) == 1) bytesToWrite--; @@ -5095,18 +5185,18 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s size_t bytesWritten = 0; - //If _pushSingleByte is true, push it now + // If _pushSingleByte is true, push it now if (_pushSingleByte == true) { - bytesWritten += _i2cPort->write(_pushThisSingleByte); // Write the single byte + bytesWritten += _i2cPort->write(_pushThisSingleByte); // Write the single byte bytesWritten += _i2cPort->write(dataBytes, bytesToWrite - 1); // Write the bytes - but send one byte less - dataBytes += bytesToWrite - 1; // Point to fresh data - _pushSingleByte = false; // Clear the flag + dataBytes += bytesToWrite - 1; // Point to fresh data + _pushSingleByte = false; // Clear the flag } else { bytesWritten += _i2cPort->write(dataBytes, bytesToWrite); // Write the bytes - dataBytes += bytesToWrite; // Point to fresh data + dataBytes += bytesToWrite; // Point to fresh data } bytesWrittenTotal += bytesWritten; // Update the totals @@ -5114,17 +5204,17 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s if (bytesLeftToWrite > 0) { - if (_i2cPort->endTransmission(stop) != 0) //Send a restart or stop command - return (false); //Sensor did not ACK + if (_i2cPort->endTransmission(stop) != 0) // Send a restart or stop command + return (false); // Sensor did not ACK } else { - if (_i2cPort->endTransmission() != 0) //We're done. Release bus. Always use a stop here - return (false); //Sensor did not ACK + if (_i2cPort->endTransmission() != 0) // We're done. Release bus. Always use a stop here + return (false); // Sensor did not ACK } } - return (bytesWrittenTotal == numDataBytes); //Return true if the correct number of bytes were written + return (bytesWrittenTotal == numDataBytes); // Return true if the correct number of bytes were written } else // SPI { @@ -5170,9 +5260,9 @@ size_t SFE_UBLOX_GNSS::pushAssistNowData(size_t offset, bool skipTime, const uin } size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - size_t dataPtr = offset; // Pointer into dataBytes + size_t dataPtr = offset; // Pointer into dataBytes size_t packetsProcessed = 0; // Keep count of how many packets have been processed - size_t bytesPushed = 0; // Keep count + size_t bytesPushed = 0; // Keep count bool checkForAcks = (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_YES); // If mgaAck is YES, always check for Acks @@ -5195,21 +5285,22 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c // If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages if (checkForAcks) { - if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data - if (packetUBXMGAACK == NULL) //Bail if the RAM allocation failed + if (packetUBXMGAACK == NULL) + initPacketUBXMGAACK(); // Check that RAM has been allocated for the MGA_ACK data + if (packetUBXMGAACK == NULL) // Bail if the RAM allocation failed return (0); } - + while (dataPtr < (offset + numDataBytes)) // Keep going until we have processed all the bytes { // Start by checking the validity of the packet being pointed to bool dataIsOK = true; - dataIsOK &= (*(dataBytes + dataPtr + 0) == UBX_SYNCH_1); // Check for 0xB5 - dataIsOK &= (*(dataBytes + dataPtr + 1) == UBX_SYNCH_2); // Check for 0x62 + dataIsOK &= (*(dataBytes + dataPtr + 0) == UBX_SYNCH_1); // Check for 0xB5 + dataIsOK &= (*(dataBytes + dataPtr + 1) == UBX_SYNCH_2); // Check for 0x62 dataIsOK &= (*(dataBytes + dataPtr + 2) == UBX_CLASS_MGA); // Check for class UBX-MGA - - size_t packetLength = ((size_t)*(dataBytes + dataPtr + 4)) | (((size_t)*(dataBytes + dataPtr + 5)) << 8); // Extract the length + + size_t packetLength = ((size_t) * (dataBytes + dataPtr + 4)) | (((size_t) * (dataBytes + dataPtr + 5)) << 8); // Extract the length uint8_t checksumA = 0; uint8_t checksumB = 0; @@ -5269,8 +5360,8 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c checkUblox(); if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's? { - bool dataAckd = true; // Check if we've received the correct ACK - dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == *(dataBytes + dataPtr + 3)); // Check if the message ID matches + bool dataAckd = true; // Check if we've received the correct ACK + dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == *(dataBytes + dataPtr + 3)); // Check if the message ID matches dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == *(dataBytes + dataPtr + 6)); // Check if the first four data bytes match dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == *(dataBytes + dataPtr + 7)); dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == *(dataBytes + dataPtr + 8)); @@ -5334,7 +5425,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c } else { - + #ifndef SFE_UBLOX_REDUCED_PROG_MEM // The data was invalid. Send a debug message and then try to find the next 0xB5 if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -5343,7 +5434,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c _debugSerial->println(dataPtr); } #endif - + while ((dataPtr < (offset + numDataBytes)) && (*(dataBytes + ++dataPtr) != UBX_SYNCH_1)) { ; // Increment dataPtr until we are pointing at the next 0xB5 - or we reach the end of the data @@ -5365,7 +5456,7 @@ size_t SFE_UBLOX_GNSS::pushAssistNowDataInternal(size_t offset, bool skipTime, c // PRIVATE: Allocate RAM for packetUBXMGAACK and initialize it bool SFE_UBLOX_GNSS::initPacketUBXMGAACK() { - packetUBXMGAACK = new UBX_MGA_ACK_DATA0_t; //Allocate RAM for the main struct + packetUBXMGAACK = new UBX_MGA_ACK_DATA0_t; // Allocate RAM for the main struct if (packetUBXMGAACK == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -5385,32 +5476,32 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - uint8_t iniTimeUTC[32]; // Create the UBX-MGA-INI-TIME_UTC message by hand + uint8_t iniTimeUTC[32]; // Create the UBX-MGA-INI-TIME_UTC message by hand memset(iniTimeUTC, 0x00, 32); // Set all unused / reserved bytes and the checksum to zero - iniTimeUTC[0] = UBX_SYNCH_1; // Sync char 1 - iniTimeUTC[1] = UBX_SYNCH_2; // Sync char 2 - iniTimeUTC[2] = UBX_CLASS_MGA; // Class - iniTimeUTC[3] = UBX_MGA_INI_TIME_UTC; // ID - iniTimeUTC[4] = 24; // Length LSB - iniTimeUTC[5] = 0x00; // Length MSB - iniTimeUTC[6] = 0x10; // type - iniTimeUTC[7] = 0x00; // version - iniTimeUTC[8] = source; // ref (source) - iniTimeUTC[9] = 0x80; // leapSecs. Set to 0x80 = unknown - iniTimeUTC[10] = (uint8_t)(year & 0xFF); // year LSB - iniTimeUTC[11] = (uint8_t)(year >> 8); // year MSB - iniTimeUTC[12] = month; // month starting at 1 - iniTimeUTC[13] = day; // day starting at 1 - iniTimeUTC[14] = hour; // hour 0:23 - iniTimeUTC[15] = minute; // minute 0:59 - iniTimeUTC[16] = second; // seconds 0:59 + iniTimeUTC[0] = UBX_SYNCH_1; // Sync char 1 + iniTimeUTC[1] = UBX_SYNCH_2; // Sync char 2 + iniTimeUTC[2] = UBX_CLASS_MGA; // Class + iniTimeUTC[3] = UBX_MGA_INI_TIME_UTC; // ID + iniTimeUTC[4] = 24; // Length LSB + iniTimeUTC[5] = 0x00; // Length MSB + iniTimeUTC[6] = 0x10; // type + iniTimeUTC[7] = 0x00; // version + iniTimeUTC[8] = source; // ref (source) + iniTimeUTC[9] = 0x80; // leapSecs. Set to 0x80 = unknown + iniTimeUTC[10] = (uint8_t)(year & 0xFF); // year LSB + iniTimeUTC[11] = (uint8_t)(year >> 8); // year MSB + iniTimeUTC[12] = month; // month starting at 1 + iniTimeUTC[13] = day; // day starting at 1 + iniTimeUTC[14] = hour; // hour 0:23 + iniTimeUTC[15] = minute; // minute 0:59 + iniTimeUTC[16] = second; // seconds 0:59 iniTimeUTC[18] = (uint8_t)(nanos & 0xFF); // nanoseconds LSB iniTimeUTC[19] = (uint8_t)((nanos >> 8) & 0xFF); iniTimeUTC[20] = (uint8_t)((nanos >> 16) & 0xFF); - iniTimeUTC[21] = (uint8_t)(nanos >> 24); // nanoseconds MSB - iniTimeUTC[22] = (uint8_t)(tAccS & 0xFF); // seconds part of the accuracy LSB - iniTimeUTC[23] = (uint8_t)(tAccS >> 8); // seconds part of the accuracy MSB + iniTimeUTC[21] = (uint8_t)(nanos >> 24); // nanoseconds MSB + iniTimeUTC[22] = (uint8_t)(tAccS & 0xFF); // seconds part of the accuracy LSB + iniTimeUTC[23] = (uint8_t)(tAccS >> 8); // seconds part of the accuracy MSB iniTimeUTC[26] = (uint8_t)(tAccNs & 0xFF); // nanoseconds part of the accuracy LSB iniTimeUTC[27] = (uint8_t)((tAccNs >> 8) & 0xFF); iniTimeUTC[28] = (uint8_t)((tAccNs >> 16) & 0xFF); @@ -5430,22 +5521,22 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t // The units for ecefX/Y/Z and posAcc (stddev) are cm. bool SFE_UBLOX_GNSS::setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - uint8_t iniPosXYZ[28]; // Create the UBX-MGA-INI-POS_XYZ message by hand + uint8_t iniPosXYZ[28]; // Create the UBX-MGA-INI-POS_XYZ message by hand memset(iniPosXYZ, 0x00, 28); // Set all unused / reserved bytes and the checksum to zero - iniPosXYZ[0] = UBX_SYNCH_1; // Sync char 1 - iniPosXYZ[1] = UBX_SYNCH_2; // Sync char 2 - iniPosXYZ[2] = UBX_CLASS_MGA; // Class + iniPosXYZ[0] = UBX_SYNCH_1; // Sync char 1 + iniPosXYZ[1] = UBX_SYNCH_2; // Sync char 2 + iniPosXYZ[2] = UBX_CLASS_MGA; // Class iniPosXYZ[3] = UBX_MGA_INI_POS_XYZ; // ID - iniPosXYZ[4] = 20; // Length LSB - iniPosXYZ[5] = 0x00; // Length MSB - iniPosXYZ[6] = 0x00; // type - iniPosXYZ[7] = 0x00; // version - + iniPosXYZ[4] = 20; // Length LSB + iniPosXYZ[5] = 0x00; // Length MSB + iniPosXYZ[6] = 0x00; // type + iniPosXYZ[7] = 0x00; // version + union // Use a union to convert from int32_t to uint32_t { - int32_t signedLong; - uint32_t unsignedLong; + int32_t signedLong; + uint32_t unsignedLong; } signedUnsigned; signedUnsigned.signedLong = ecefX; @@ -5485,22 +5576,22 @@ bool SFE_UBLOX_GNSS::setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int3 // The units for alt (WGS84) and posAcc (stddev) are cm. bool SFE_UBLOX_GNSS::setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) { - uint8_t iniPosLLH[28]; // Create the UBX-MGA-INI-POS_LLH message by hand + uint8_t iniPosLLH[28]; // Create the UBX-MGA-INI-POS_LLH message by hand memset(iniPosLLH, 0x00, 28); // Set all unused / reserved bytes and the checksum to zero - iniPosLLH[0] = UBX_SYNCH_1; // Sync char 1 - iniPosLLH[1] = UBX_SYNCH_2; // Sync char 2 - iniPosLLH[2] = UBX_CLASS_MGA; // Class + iniPosLLH[0] = UBX_SYNCH_1; // Sync char 1 + iniPosLLH[1] = UBX_SYNCH_2; // Sync char 2 + iniPosLLH[2] = UBX_CLASS_MGA; // Class iniPosLLH[3] = UBX_MGA_INI_POS_LLH; // ID - iniPosLLH[4] = 20; // Length LSB - iniPosLLH[5] = 0x00; // Length MSB - iniPosLLH[6] = 0x01; // type - iniPosLLH[7] = 0x00; // version - + iniPosLLH[4] = 20; // Length LSB + iniPosLLH[5] = 0x00; // Length MSB + iniPosLLH[6] = 0x01; // type + iniPosLLH[7] = 0x00; // version + union // Use a union to convert from int32_t to uint32_t { - int32_t signedLong; - uint32_t unsignedLong; + int32_t signedLong; + uint32_t unsignedLong; } signedUnsigned; signedUnsigned.signedLong = lat; @@ -5550,7 +5641,7 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDate(const uint8_t *dataBytes, size_t numDat } size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture) { - size_t dataPtr = 0; // Pointer into dataBytes + size_t dataPtr = 0; // Pointer into dataBytes bool dateFound = false; // Flag to indicate when the date has been found // Calculate matchDay, matchMonth and matchYear @@ -5566,46 +5657,46 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_ daysIntoFutureCopy--; switch (matchMonth) { - case 1: - case 3: - case 5: - case 7: - case 8: - case 10: - case 12: - if (matchDay == 32) - { - matchDay = 1; - matchMonth++; - if (matchMonth == 13) - { - matchMonth = 1; - matchYear++; - } - } - break; - case 4: - case 6: - case 9: - case 11: - if (matchDay == 31) - { - matchDay = 1; - matchMonth++; - } - break; - default: // February - if (((matchYear % 4) == 0) && (matchDay == 30)) - { - matchDay = 1; - matchMonth++; - } - else if (((matchYear % 4) > 0) && (matchDay == 29)) + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: + if (matchDay == 32) + { + matchDay = 1; + matchMonth++; + if (matchMonth == 13) { - matchDay = 1; - matchMonth++; + matchMonth = 1; + matchYear++; } - break; + } + break; + case 4: + case 6: + case 9: + case 11: + if (matchDay == 31) + { + matchDay = 1; + matchMonth++; + } + break; + default: // February + if (((matchYear % 4) == 0) && (matchDay == 30)) + { + matchDay = 1; + matchMonth++; + } + else if (((matchYear % 4) > 0) && (matchDay == 29)) + { + matchDay = 1; + matchMonth++; + } + break; } } @@ -5614,11 +5705,11 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_ // Start by checking the validity of the packet being pointed to bool dataIsOK = true; - dataIsOK &= (*(dataBytes + dataPtr + 0) == UBX_SYNCH_1); // Check for 0xB5 - dataIsOK &= (*(dataBytes + dataPtr + 1) == UBX_SYNCH_2); // Check for 0x62 + dataIsOK &= (*(dataBytes + dataPtr + 0) == UBX_SYNCH_1); // Check for 0xB5 + dataIsOK &= (*(dataBytes + dataPtr + 1) == UBX_SYNCH_2); // Check for 0x62 dataIsOK &= (*(dataBytes + dataPtr + 2) == UBX_CLASS_MGA); // Check for class UBX-MGA - - size_t packetLength = ((size_t)*(dataBytes + dataPtr + 4)) | (((size_t)*(dataBytes + dataPtr + 5)) << 8); // Extract the length + + size_t packetLength = ((size_t) * (dataBytes + dataPtr + 4)) | (((size_t) * (dataBytes + dataPtr + 5)) << 8); // Extract the length uint8_t checksumA = 0; uint8_t checksumB = 0; @@ -5639,10 +5730,7 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_ // If the data is valid, check for a date match if (dataIsOK) { - if ((*(dataBytes + dataPtr + 3) == UBX_MGA_ANO) - && (*(dataBytes + dataPtr + 10) == matchYear) - && (*(dataBytes + dataPtr + 11) == matchMonth) - && (*(dataBytes + dataPtr + 12) == matchDay)) + if ((*(dataBytes + dataPtr + 3) == UBX_MGA_ANO) && (*(dataBytes + dataPtr + 10) == matchYear) && (*(dataBytes + dataPtr + 11) == matchMonth) && (*(dataBytes + dataPtr + 12) == matchDay)) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -5661,7 +5749,7 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_ } else { - + #ifndef SFE_UBLOX_REDUCED_PROG_MEM // The data was invalid. Send a debug message and then try to find the next 0xB5 if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -5670,7 +5758,7 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_ _debugSerial->println(dataPtr); } #endif - + while ((dataPtr < numDataBytes) && (*(dataBytes + ++dataPtr) != UBX_SYNCH_1)) { ; // Increment dataPtr until we are pointing at the next 0xB5 - or we reach the end of the data @@ -5690,8 +5778,9 @@ size_t SFE_UBLOX_GNSS::findMGAANOForDateInternal(const uint8_t *dataBytes, size_ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumDataBytes, uint16_t maxWait) { // Allocate RAM to store the MGA ACK message - if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data - if (packetUBXMGAACK == NULL) //Bail if the RAM allocation failed + if (packetUBXMGAACK == NULL) + initPacketUBXMGAACK(); // Check that RAM has been allocated for the MGA_ACK data + if (packetUBXMGAACK == NULL) // Bail if the RAM allocation failed { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) @@ -5713,8 +5802,9 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD } // Allocate RAM to store the MGA DBD messages - if (packetUBXMGADBD == NULL) initPacketUBXMGADBD(); //Check that RAM has been allocated for the MGA_DBD data - if (packetUBXMGADBD == NULL) //Bail if the RAM allocation failed + if (packetUBXMGADBD == NULL) + initPacketUBXMGADBD(); // Check that RAM has been allocated for the MGA_DBD data + if (packetUBXMGADBD == NULL) // Bail if the RAM allocation failed { #ifndef SFE_UBLOX_REDUCED_PROG_MEM if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging @@ -5748,15 +5838,15 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD i2cPollingWait = 1; // Construct the poll message: - uint8_t pollNaviDatabase[8]; // Create the UBX-MGA-DBD message by hand + uint8_t pollNaviDatabase[8]; // Create the UBX-MGA-DBD message by hand memset(pollNaviDatabase, 0x00, 8); // Set all unused / reserved bytes and the checksum to zero - pollNaviDatabase[0] = UBX_SYNCH_1; // Sync char 1 - pollNaviDatabase[1] = UBX_SYNCH_2; // Sync char 2 + pollNaviDatabase[0] = UBX_SYNCH_1; // Sync char 1 + pollNaviDatabase[1] = UBX_SYNCH_2; // Sync char 2 pollNaviDatabase[2] = UBX_CLASS_MGA; // Class - pollNaviDatabase[3] = UBX_MGA_DBD; // ID - pollNaviDatabase[4] = 0x00; // Length LSB - pollNaviDatabase[5] = 0x00; // Length MSB + pollNaviDatabase[3] = UBX_MGA_DBD; // ID + pollNaviDatabase[4] = 0x00; // Length LSB + pollNaviDatabase[5] = 0x00; // Length MSB for (uint8_t i = 2; i < 6; i++) // Calculate the checksum { @@ -5778,7 +5868,7 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD } #endif i2cPollingWait = currentI2cPollingWait; // Restore i2cPollingWait - setAckAiding(currentAckAiding); // Restore Ack Aiding + setAckAiding(currentAckAiding); // Restore Ack Aiding return ((size_t)0); } @@ -5786,7 +5876,7 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD bool keepGoing = true; unsigned long startTime = millis(); uint32_t databaseEntriesRX = 0; // Keep track of how many database entries are received - size_t numBytesReceived = 0; // Keep track of how many bytes are received + size_t numBytesReceived = 0; // Keep track of how many bytes are received while (keepGoing && (millis() < (startTime + maxWait))) { @@ -5892,7 +5982,7 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD } i2cPollingWait = currentI2cPollingWait; // Restore i2cPollingWait - setAckAiding(currentAckAiding); // Restore Ack Aiding + setAckAiding(currentAckAiding); // Restore Ack Aiding return (numBytesReceived); } @@ -5900,7 +5990,7 @@ size_t SFE_UBLOX_GNSS::readNavigationDatabase(uint8_t *dataBytes, size_t maxNumD // PRIVATE: Allocate RAM for packetUBXMGADBD and initialize it bool SFE_UBLOX_GNSS::initPacketUBXMGADBD() { - packetUBXMGADBD = new UBX_MGA_DBD_t; //Allocate RAM for the main struct + packetUBXMGADBD = new UBX_MGA_DBD_t; // Allocate RAM for the main struct if (packetUBXMGADBD == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -5916,13 +6006,13 @@ bool SFE_UBLOX_GNSS::initPacketUBXMGADBD() // Support for data logging -//Set the file buffer size. This must be called _before_ .begin +// Set the file buffer size. This must be called _before_ .begin void SFE_UBLOX_GNSS::setFileBufferSize(uint16_t bufferSize) { fileBufferSize = bufferSize; } -//Return the file buffer size +// Return the file buffer size uint16_t SFE_UBLOX_GNSS::getFileBufferSize(void) { return (fileBufferSize); @@ -5940,7 +6030,7 @@ uint16_t SFE_UBLOX_GNSS::extractFileBufferData(uint8_t *destination, uint16_t nu // Start copying at fileBufferTail. Wrap-around if required. uint16_t bytesBeforeWrapAround = fileBufferSize - fileBufferTail; // How much space is available 'above' Tail? - if (bytesBeforeWrapAround > numBytes) // Will we need to wrap-around? + if (bytesBeforeWrapAround > numBytes) // Will we need to wrap-around? { bytesBeforeWrapAround = numBytes; // We need to wrap-around } @@ -5948,10 +6038,10 @@ uint16_t SFE_UBLOX_GNSS::extractFileBufferData(uint8_t *destination, uint16_t nu // Is there any data leftover which we need to copy from the 'bottom' of the buffer? uint16_t bytesLeftToCopy = numBytes - bytesBeforeWrapAround; // Calculate if there are any bytes left to copy - if (bytesLeftToCopy > 0) // If there are bytes left to copy + if (bytesLeftToCopy > 0) // If there are bytes left to copy { memcpy(&destination[bytesBeforeWrapAround], &ubxFileBuffer[0], bytesLeftToCopy); // Copy the remaining data out of the buffer - fileBufferTail = bytesLeftToCopy; // Update Tail. The next byte to be read will be read from here. + fileBufferTail = bytesLeftToCopy; // Update Tail. The next byte to be read will be read from here. } else { @@ -5999,18 +6089,18 @@ bool SFE_UBLOX_GNSS::createFileBuffer(void) _debugSerial->println(F("createFileBuffer: Warning. fileBufferSize is zero. Data logging is not possible.")); } #endif - return(false); + return (false); } - if (ubxFileBuffer != NULL) // Bail if RAM has already been allocated for the file buffer - { // This will happen if you call .begin more than once - without calling .end first + if (ubxFileBuffer != NULL) // Bail if RAM has already been allocated for the file buffer + { // This will happen if you call .begin more than once - without calling .end first #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) { _debugSerial->println(F("createFileBuffer: Warning. File buffer already exists. Skipping...")); } #endif - return(false); + return (false); } ubxFileBuffer = new uint8_t[fileBufferSize]; // Allocate RAM for the buffer @@ -6021,7 +6111,7 @@ bool SFE_UBLOX_GNSS::createFileBuffer(void) { _debugSerial->println(F("createFileBuffer: RAM alloc failed!")); } - return(false); + return (false); } #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -6071,7 +6161,7 @@ bool SFE_UBLOX_GNSS::storePacket(ubxPacket *msg) _debugSerial->println(F("storePacket: file buffer not available!")); } #endif - return(false); + return (false); } // Now, check if there is enough space in the buffer for all of the data @@ -6084,27 +6174,27 @@ bool SFE_UBLOX_GNSS::storePacket(ubxPacket *msg) _debugSerial->println(F("storePacket: insufficient space available! Data will be lost!")); } #endif - return(false); + return (false); } - //Store the two sync chars + // Store the two sync chars uint8_t sync_chars[] = {UBX_SYNCH_1, UBX_SYNCH_2}; writeToFileBuffer(sync_chars, 2); - //Store the Class & ID + // Store the Class & ID writeToFileBuffer(&msg->cls, 1); writeToFileBuffer(&msg->id, 1); - //Store the length. Ensure length is little-endian + // Store the length. Ensure length is little-endian uint8_t msg_length[2]; msg_length[0] = msg->len & 0xFF; msg_length[1] = msg->len >> 8; writeToFileBuffer(msg_length, 2); - //Store the payload + // Store the payload writeToFileBuffer(msg->payload, msg->len); - //Store the checksum + // Store the checksum writeToFileBuffer(&msg->checksumA, 1); writeToFileBuffer(&msg->checksumB, 1); @@ -6123,7 +6213,7 @@ bool SFE_UBLOX_GNSS::storeFileBytes(uint8_t *theBytes, uint16_t numBytes) _debugSerial->println(F("storeFileBytes: file buffer not available!")); } #endif - return(false); + return (false); } // Now, check if there is enough space in the buffer for all of the data @@ -6135,7 +6225,7 @@ bool SFE_UBLOX_GNSS::storeFileBytes(uint8_t *theBytes, uint16_t numBytes) _debugSerial->println(F("storeFileBytes: insufficient space available! Data will be lost!")); } #endif - return(false); + return (false); } // There is room for all the data in the buffer so copy the data into the buffer @@ -6149,7 +6239,7 @@ void SFE_UBLOX_GNSS::writeToFileBuffer(uint8_t *theBytes, uint16_t numBytes) { // Start writing at fileBufferHead. Wrap-around if required. uint16_t bytesBeforeWrapAround = fileBufferSize - fileBufferHead; // How much space is available 'above' Head? - if (bytesBeforeWrapAround > numBytes) // Is there enough room for all the data? + if (bytesBeforeWrapAround > numBytes) // Is there enough room for all the data? { bytesBeforeWrapAround = numBytes; // There is enough room for all the data } @@ -6157,17 +6247,17 @@ void SFE_UBLOX_GNSS::writeToFileBuffer(uint8_t *theBytes, uint16_t numBytes) // Is there any data leftover which we need to copy to the 'bottom' of the buffer? uint16_t bytesLeftToCopy = numBytes - bytesBeforeWrapAround; // Calculate if there are any bytes left to copy - if (bytesLeftToCopy > 0) // If there are bytes left to copy + if (bytesLeftToCopy > 0) // If there are bytes left to copy { memcpy(&ubxFileBuffer[0], &theBytes[bytesBeforeWrapAround], bytesLeftToCopy); // Copy the remaining data into the buffer - fileBufferHead = bytesLeftToCopy; // Update Head. The next byte written will be written here. + fileBufferHead = bytesLeftToCopy; // Update Head. The next byte written will be written here. } else { fileBufferHead += numBytes; // Only update Head. The next byte written will be written here. } - //Update fileBufferMaxAvail if required + // Update fileBufferMaxAvail if required uint16_t bytesInBuffer = fileBufferSpaceUsed(); if (bytesInBuffer > fileBufferMaxAvail) fileBufferMaxAvail = bytesInBuffer; @@ -6176,7 +6266,7 @@ void SFE_UBLOX_GNSS::writeToFileBuffer(uint8_t *theBytes, uint16_t numBytes) //=-=-=-=-=-=-=-= Specific commands =-=-=-=-=-=-=-==-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -//Loads the payloadCfg array with the current protocol bits located the UBX-CFG-PRT register for a given port +// Loads the payloadCfg array with the current protocol bits located the UBX-CFG-PRT register for a given port bool SFE_UBLOX_GNSS::getPortSettings(uint8_t portID, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -6189,81 +6279,81 @@ bool SFE_UBLOX_GNSS::getPortSettings(uint8_t portID, uint16_t maxWait) return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_RECEIVED); // We are expecting data and an ACK } -//Configure a given port to output UBX, NMEA, RTCM3 or a combination thereof -//Port 0=I2c, 1=UART1, 2=UART2, 3=USB, 4=SPI -//Bit:0 = UBX, :1=NMEA, :5=RTCM3 +// Configure a given port to output UBX, NMEA, RTCM3 or a combination thereof +// Port 0=I2c, 1=UART1, 2=UART2, 3=USB, 4=SPI +// Bit:0 = UBX, :1=NMEA, :5=RTCM3 bool SFE_UBLOX_GNSS::setPortOutput(uint8_t portID, uint8_t outStreamSettings, uint16_t maxWait) { - //Get the current config values for this port ID + // Get the current config values for this port ID if (getPortSettings(portID, maxWait) == false) - return (false); //Something went wrong. Bail. + return (false); // Something went wrong. Bail. packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_PRT; packetCfg.len = 20; packetCfg.startingSpot = 0; - //payloadCfg is now loaded with current bytes. Change only the ones we need to - payloadCfg[14] = outStreamSettings; //OutProtocolMask LSB - Set outStream bits + // 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)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof -//Port 0=I2c, 1=UART1, 2=UART2, 3=USB, 4=SPI -//Bit:0 = UBX, :1=NMEA, :5=RTCM3 +// Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof +// Port 0=I2c, 1=UART1, 2=UART2, 3=USB, 4=SPI +// Bit:0 = UBX, :1=NMEA, :5=RTCM3 bool SFE_UBLOX_GNSS::setPortInput(uint8_t portID, uint8_t inStreamSettings, uint16_t maxWait) { - //Get the current config values for this port ID - //This will load the payloadCfg array with current port settings + // Get the current config values for this port ID + // This will load the payloadCfg array with current port settings if (getPortSettings(portID, maxWait) == false) - return (false); //Something went wrong. Bail. + return (false); // Something went wrong. Bail. packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_PRT; packetCfg.len = 20; packetCfg.startingSpot = 0; - //payloadCfg is now loaded with current bytes. Change only the ones we need to - payloadCfg[12] = inStreamSettings; //InProtocolMask LSB - Set inStream bits + // 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)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Changes the I2C address that the u-blox module responds to -//0x42 is the default but can be changed with this command +// Changes the I2C address that the u-blox module responds to +// 0x42 is the default but can be changed with this command bool SFE_UBLOX_GNSS::setI2CAddress(uint8_t deviceAddress, uint16_t maxWait) { - //Get the current config values for the I2C port - //This will load the payloadCfg array with current port settings + // Get the current config values for the I2C port + // This will load the payloadCfg array with current port settings if (getPortSettings(COM_PORT_I2C, maxWait) == false) - return (false); //Something went wrong. Bail. + return (false); // Something went wrong. Bail. packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_PRT; packetCfg.len = 20; packetCfg.startingSpot = 0; - //payloadCfg is now loaded with current bytes. Change only the ones we need to - payloadCfg[4] = deviceAddress << 1; //DDC mode LSB + // 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) == SFE_UBLOX_STATUS_DATA_SENT) // We are only expecting an ACK { - //Success! Now change our internal global. - _gpsI2Caddress = deviceAddress; //Store the I2C address from user + // Success! Now change our internal global. + _gpsI2Caddress = deviceAddress; // Store the I2C address from user return (true); } return (false); } -//Changes the serial baud rate of the u-blox module, can't return success/fail 'cause ACK from modem -//is lost due to baud rate change +// Changes the serial baud rate of the u-blox module, can't return success/fail 'cause ACK from modem +// is lost due to baud rate change void SFE_UBLOX_GNSS::setSerialRate(uint32_t baudrate, uint8_t uartPort, uint16_t maxWait) { - //Get the current config values for the UART port - //This will load the payloadCfg array with current port settings + // Get the current config values for the UART port + // This will load the payloadCfg array with current port settings if (getPortSettings(uartPort, maxWait) == false) - return; //Something went wrong. Bail. + return; // Something went wrong. Bail. #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) @@ -6278,7 +6368,7 @@ void SFE_UBLOX_GNSS::setSerialRate(uint32_t baudrate, uint8_t uartPort, uint16_t packetCfg.len = 20; packetCfg.startingSpot = 0; - //payloadCfg is now loaded with current bytes. Change only the ones we need to + // payloadCfg is now loaded with current bytes. Change only the ones we need to payloadCfg[8] = baudrate; payloadCfg[9] = baudrate >> 8; payloadCfg[10] = baudrate >> 16; @@ -6305,7 +6395,7 @@ void SFE_UBLOX_GNSS::setSerialRate(uint32_t baudrate, uint8_t uartPort, uint16_t #endif } -//Configure a port to output UBX, NMEA, RTCM3 or a combination thereof +// Configure a port to output UBX, NMEA, RTCM3 or a combination thereof bool SFE_UBLOX_GNSS::setI2COutput(uint8_t comSettings, uint16_t maxWait) { return (setPortOutput(COM_PORT_I2C, comSettings, maxWait)); @@ -6327,10 +6417,10 @@ bool SFE_UBLOX_GNSS::setSPIOutput(uint8_t comSettings, uint16_t maxWait) return (setPortOutput(COM_PORT_SPI, comSettings, maxWait)); } -//Want to see the NMEA messages on the Serial port? Here's how +// Want to see the NMEA messages on the Serial port? Here's how void SFE_UBLOX_GNSS::setNMEAOutputPort(Stream &nmeaOutputPort) { - _nmeaOutputPort = &nmeaOutputPort; //Store the port from user + _nmeaOutputPort = &nmeaOutputPort; // Store the port from user } // Reset to defaults @@ -6382,8 +6472,8 @@ void SFE_UBLOX_GNSS::softwareResetGNSSOnly() sendCommand(&packetCfg, 0); // don't expect ACK } -//Reset module to factory defaults -//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods +// Reset module to factory defaults +// This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods bool SFE_UBLOX_GNSS::factoryDefault(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -6391,21 +6481,21 @@ bool SFE_UBLOX_GNSS::factoryDefault(uint16_t maxWait) packetCfg.len = 12; packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - packetCfg.payload[0] = 0xFF; //Set any bit in the clearMask field to clear saved config + packetCfg.payload[0] = 0xFF; // Set any bit in the clearMask field to clear saved config packetCfg.payload[1] = 0xFF; - packetCfg.payload[8] = 0xFF; //Set any bit in the loadMask field to discard current config and rebuild from lower non-volatile memory layers + packetCfg.payload[8] = 0xFF; // Set any bit in the loadMask field to discard current config and rebuild from lower non-volatile memory layers packetCfg.payload[9] = 0xFF; return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Save configuration to BBR / Flash +// Save configuration to BBR / Flash -//Save current configuration to flash and BBR (battery backed RAM) -//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods +// Save current configuration to flash and BBR (battery backed RAM) +// This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods bool SFE_UBLOX_GNSS::saveConfiguration(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -6413,17 +6503,17 @@ bool SFE_UBLOX_GNSS::saveConfiguration(uint16_t maxWait) packetCfg.len = 12; packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - packetCfg.payload[4] = 0xFF; //Set any bit in the saveMask field to save current config to Flash and BBR + packetCfg.payload[4] = 0xFF; // Set any bit in the saveMask field to save current config to Flash and BBR packetCfg.payload[5] = 0xFF; return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Save the selected configuration sub-sections to flash and BBR (battery backed RAM) -//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods +// Save the selected configuration sub-sections to flash and BBR (battery backed RAM) +// This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods bool SFE_UBLOX_GNSS::saveConfigSelective(uint32_t configMask, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -6431,10 +6521,10 @@ bool SFE_UBLOX_GNSS::saveConfigSelective(uint32_t configMask, uint16_t maxWait) packetCfg.len = 12; packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - packetCfg.payload[4] = configMask & 0xFF; //Set the appropriate bits in the saveMask field to save current config to Flash and BBR + packetCfg.payload[4] = configMask & 0xFF; // Set the appropriate bits in the saveMask field to save current config to Flash and BBR packetCfg.payload[5] = (configMask >> 8) & 0xFF; packetCfg.payload[6] = (configMask >> 16) & 0xFF; packetCfg.payload[7] = (configMask >> 24) & 0xFF; @@ -6442,10 +6532,10 @@ bool SFE_UBLOX_GNSS::saveConfigSelective(uint32_t configMask, uint16_t maxWait) return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Configure a given message type for a given port (UART1, I2C, SPI, etc) +// Configure a given message type for a given port (UART1, I2C, SPI, etc) bool SFE_UBLOX_GNSS::configureMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate, uint16_t maxWait) { - //Poll for the current settings for a given message + // Poll for the current settings for a given message packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; packetCfg.len = 2; @@ -6454,25 +6544,25 @@ bool SFE_UBLOX_GNSS::configureMessage(uint8_t msgClass, uint8_t msgID, uint8_t p payloadCfg[0] = msgClass; payloadCfg[1] = msgID; - //This will load the payloadCfg array with current settings of the given register + // This will load the payloadCfg array with current settings of the given register if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK - return (false); //If command send fails then bail + return (false); // If command send fails then bail - //Now send it back with new mods + // Now send it back with new mods packetCfg.len = 8; - //payloadCfg is now loaded with current bytes. Change only the ones we need to - payloadCfg[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. + // payloadCfg is now loaded with current bytes. Change only the ones we need to + payloadCfg[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)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Enable a given message type, default of 1 per update rate (usually 1 per second) +// Enable a given message type, default of 1 per update rate (usually 1 per second) bool SFE_UBLOX_GNSS::enableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t rate, uint16_t maxWait) { return (configureMessage(msgClass, msgID, portID, rate, maxWait)); } -//Disable a given message type on a given port +// Disable a given message type on a given port bool SFE_UBLOX_GNSS::disableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint16_t maxWait) { return (configureMessage(msgClass, msgID, portID, 0, maxWait)); @@ -6487,35 +6577,35 @@ bool SFE_UBLOX_GNSS::disableNMEAMessage(uint8_t msgID, uint8_t portID, uint16_t return (enableNMEAMessage(msgID, portID, 0, maxWait)); } -//Given a message number turns on a message ID for output over a given portID (UART, I2C, SPI, USB, etc) -//To disable a message, set secondsBetween messages to 0 -//Note: This function will return false if the message is already enabled -//For base station RTK output we need to enable various sentences +// Given a message number turns on a message ID for output over a given portID (UART, I2C, SPI, USB, etc) +// To disable a message, set secondsBetween messages to 0 +// Note: This function will return false if the message is already enabled +// For base station RTK output we need to enable various sentences -//NEO-M8P has four: -//1005 = 0xF5 0x05 - Stationary RTK reference ARP -//1077 = 0xF5 0x4D - GPS MSM7 -//1087 = 0xF5 0x57 - GLONASS MSM7 -//1230 = 0xF5 0xE6 - GLONASS code-phase biases, set to once every 10 seconds +// NEO-M8P has four: +// 1005 = 0xF5 0x05 - Stationary RTK reference ARP +// 1077 = 0xF5 0x4D - GPS MSM7 +// 1087 = 0xF5 0x57 - GLONASS MSM7 +// 1230 = 0xF5 0xE6 - GLONASS code-phase biases, set to once every 10 seconds -//ZED-F9P has six: -//1005, 1074, 1084, 1094, 1124, 1230 +// ZED-F9P has six: +// 1005, 1074, 1084, 1094, 1124, 1230 -//Much of this configuration is not documented and instead discerned from u-center binary console +// Much of this configuration is not documented and instead discerned from u-center binary console bool SFE_UBLOX_GNSS::enableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint8_t sendRate, uint16_t maxWait) { return (configureMessage(UBX_RTCM_MSB, messageNumber, portID, sendRate, maxWait)); } -//Disable a given message on a given port by setting secondsBetweenMessages to zero +// Disable a given message on a given port by setting secondsBetweenMessages to zero bool SFE_UBLOX_GNSS::disableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint16_t maxWait) { return (enableRTCMmessage(messageNumber, portID, 0, maxWait)); } -//Functions used for RTK and base station setup +// Functions used for RTK and base station setup -//Get the current TimeMode3 settings - these contain survey in statuses +// Get the current TimeMode3 settings - these contain survey in statuses bool SFE_UBLOX_GNSS::getSurveyMode(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -6526,10 +6616,10 @@ bool SFE_UBLOX_GNSS::getSurveyMode(uint16_t maxWait) return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_RECEIVED); // We are expecting data and an ACK } -//Control Survey-In for NEO-M8P +// Control Survey-In for NEO-M8P bool SFE_UBLOX_GNSS::setSurveyMode(uint8_t mode, uint16_t observationTime, float requiredAccuracy, uint16_t maxWait) { - if (getSurveyMode(maxWait) == false) //Ask module for the current TimeMode3 settings. Loads into payloadCfg. + if (getSurveyMode(maxWait) == false) // Ask module for the current TimeMode3 settings. Loads into payloadCfg. return (false); packetCfg.cls = UBX_CLASS_CFG; @@ -6537,18 +6627,18 @@ bool SFE_UBLOX_GNSS::setSurveyMode(uint8_t mode, uint16_t observationTime, float packetCfg.len = 40; packetCfg.startingSpot = 0; - //payloadCfg should be loaded with poll response. Now modify only the bits we care about - payloadCfg[2] = mode; //Set mode. Survey-In and Disabled are most common. Use ECEF (not LAT/LON/ALT). + // payloadCfg should be loaded with poll response. Now modify only the bits we care about + payloadCfg[2] = mode; // Set mode. Survey-In and Disabled are most common. Use ECEF (not LAT/LON/ALT). - //svinMinDur is U4 (uint32_t) but we'll only use a uint16_t (waiting more than 65535 seconds seems excessive!) - payloadCfg[24] = observationTime & 0xFF; //svinMinDur in seconds - payloadCfg[25] = observationTime >> 8; //svinMinDur in seconds - payloadCfg[26] = 0; //Truncate to 16 bits - payloadCfg[27] = 0; //Truncate to 16 bits + // svinMinDur is U4 (uint32_t) but we'll only use a uint16_t (waiting more than 65535 seconds seems excessive!) + payloadCfg[24] = observationTime & 0xFF; // svinMinDur in seconds + payloadCfg[25] = observationTime >> 8; // svinMinDur in seconds + payloadCfg[26] = 0; // Truncate to 16 bits + payloadCfg[27] = 0; // Truncate to 16 bits - //svinAccLimit is U4 (uint32_t) in 0.1mm. - uint32_t svinAccLimit = (uint32_t)(requiredAccuracy * 10000.0); //Convert m to 0.1mm - payloadCfg[28] = svinAccLimit & 0xFF; //svinAccLimit in 0.1mm increments + // svinAccLimit is U4 (uint32_t) in 0.1mm. + uint32_t svinAccLimit = (uint32_t)(requiredAccuracy * 10000.0); // Convert m to 0.1mm + payloadCfg[28] = svinAccLimit & 0xFF; // svinAccLimit in 0.1mm increments payloadCfg[29] = svinAccLimit >> 8; payloadCfg[30] = svinAccLimit >> 16; payloadCfg[31] = svinAccLimit >> 24; @@ -6556,23 +6646,23 @@ bool SFE_UBLOX_GNSS::setSurveyMode(uint8_t mode, uint16_t observationTime, float return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Begin Survey-In for NEO-M8P +// Begin Survey-In for NEO-M8P bool SFE_UBLOX_GNSS::enableSurveyMode(uint16_t observationTime, float requiredAccuracy, uint16_t maxWait) { return (setSurveyMode(SVIN_MODE_ENABLE, observationTime, requiredAccuracy, maxWait)); } -//Stop Survey-In for NEO-M8P +// Stop Survey-In for NEO-M8P bool SFE_UBLOX_GNSS::disableSurveyMode(uint16_t maxWait) { return (setSurveyMode(SVIN_MODE_DISABLE, 0, 0, maxWait)); } -//Set the ECEF or Lat/Long coordinates of a receiver -//This imediately puts the receiver in TIME mode (fixed) and will begin outputting RTCM sentences if enabled -//This is helpful once an antenna's position has been established. See this tutorial: https://learn.sparkfun.com/tutorials/how-to-build-a-diy-gnss-reference-station#gather-raw-gnss-data -// For ECEF the units are: cm, 0.1mm, cm, 0.1mm, cm, 0.1mm -// For Lat/Lon/Alt the units are: degrees^-7, degrees^-9, degrees^-7, degrees^-9, cm, 0.1mm +// Set the ECEF or Lat/Long coordinates of a receiver +// This imediately puts the receiver in TIME mode (fixed) and will begin outputting RTCM sentences if enabled +// This is helpful once an antenna's position has been established. See this tutorial: https://learn.sparkfun.com/tutorials/how-to-build-a-diy-gnss-reference-station#gather-raw-gnss-data +// For ECEF the units are: cm, 0.1mm, cm, 0.1mm, cm, 0.1mm +// For Lat/Lon/Alt the units are: degrees^-7, degrees^-9, degrees^-7, degrees^-9, cm, 0.1mm bool SFE_UBLOX_GNSS::setStaticPosition(int32_t ecefXOrLat, int8_t ecefXOrLatHP, int32_t ecefYOrLon, int8_t ecefYOrLonHP, int32_t ecefZOrAlt, int8_t ecefZOrAltHP, bool latLong, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -6580,37 +6670,37 @@ bool SFE_UBLOX_GNSS::setStaticPosition(int32_t ecefXOrLat, int8_t ecefXOrLatHP, packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current TimeMode3 settings. Loads into payloadCfg. + // Ask module for the current TimeMode3 settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); packetCfg.len = 40; - //customCfg should be loaded with poll response. Now modify only the bits we care about - payloadCfg[2] = 2; //Set mode to fixed. Use ECEF (not LAT/LON/ALT). + // customCfg should be loaded with poll response. Now modify only the bits we care about + payloadCfg[2] = 2; // Set mode to fixed. Use ECEF (not LAT/LON/ALT). if (latLong == true) - payloadCfg[3] = (uint8_t)(1 << 0); //Set mode to fixed. Use LAT/LON/ALT. + payloadCfg[3] = (uint8_t)(1 << 0); // Set mode to fixed. Use LAT/LON/ALT. - //Set ECEF X or Lat - payloadCfg[4] = (ecefXOrLat >> 8 * 0) & 0xFF; //LSB + // Set ECEF X or Lat + payloadCfg[4] = (ecefXOrLat >> 8 * 0) & 0xFF; // LSB payloadCfg[5] = (ecefXOrLat >> 8 * 1) & 0xFF; payloadCfg[6] = (ecefXOrLat >> 8 * 2) & 0xFF; - payloadCfg[7] = (ecefXOrLat >> 8 * 3) & 0xFF; //MSB + payloadCfg[7] = (ecefXOrLat >> 8 * 3) & 0xFF; // MSB - //Set ECEF Y or Long - payloadCfg[8] = (ecefYOrLon >> 8 * 0) & 0xFF; //LSB + // Set ECEF Y or Long + payloadCfg[8] = (ecefYOrLon >> 8 * 0) & 0xFF; // LSB payloadCfg[9] = (ecefYOrLon >> 8 * 1) & 0xFF; payloadCfg[10] = (ecefYOrLon >> 8 * 2) & 0xFF; - payloadCfg[11] = (ecefYOrLon >> 8 * 3) & 0xFF; //MSB + payloadCfg[11] = (ecefYOrLon >> 8 * 3) & 0xFF; // MSB - //Set ECEF Z or Altitude - payloadCfg[12] = (ecefZOrAlt >> 8 * 0) & 0xFF; //LSB + // Set ECEF Z or Altitude + payloadCfg[12] = (ecefZOrAlt >> 8 * 0) & 0xFF; // LSB payloadCfg[13] = (ecefZOrAlt >> 8 * 1) & 0xFF; payloadCfg[14] = (ecefZOrAlt >> 8 * 2) & 0xFF; - payloadCfg[15] = (ecefZOrAlt >> 8 * 3) & 0xFF; //MSB + payloadCfg[15] = (ecefZOrAlt >> 8 * 3) & 0xFF; // MSB - //Set high precision parts + // Set high precision parts payloadCfg[16] = ecefXOrLatHP; payloadCfg[17] = ecefYOrLonHP; payloadCfg[18] = ecefZOrAltHP; @@ -6639,15 +6729,15 @@ bool SFE_UBLOX_GNSS::setDGNSSConfiguration(sfe_ublox_dgnss_mode_e dgnssMode, uin return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } - // Module Protocol Version -//Get the current protocol version of the u-blox module we're communicating with -//This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) +// Get the current protocol version of the u-blox module we're communicating with +// This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) uint8_t SFE_UBLOX_GNSS::getProtocolVersionHigh(uint16_t maxWait) { - if (moduleSWVersion == NULL) initModuleSWVersion(); //Check that RAM has been allocated for the SW version - if (moduleSWVersion == NULL) //Bail if the RAM allocation failed + if (moduleSWVersion == NULL) + initModuleSWVersion(); // Check that RAM has been allocated for the SW version + if (moduleSWVersion == NULL) // Bail if the RAM allocation failed return (false); if (moduleSWVersion->moduleQueried == false) @@ -6655,12 +6745,13 @@ uint8_t SFE_UBLOX_GNSS::getProtocolVersionHigh(uint16_t maxWait) return (moduleSWVersion->versionHigh); } -//Get the current protocol version of the u-blox module we're communicating with -//This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) +// Get the current protocol version of the u-blox module we're communicating with +// This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) uint8_t SFE_UBLOX_GNSS::getProtocolVersionLow(uint16_t maxWait) { - if (moduleSWVersion == NULL) initModuleSWVersion(); //Check that RAM has been allocated for the SW version - if (moduleSWVersion == NULL) //Bail if the RAM allocation failed + if (moduleSWVersion == NULL) + initModuleSWVersion(); // Check that RAM has been allocated for the SW version + if (moduleSWVersion == NULL) // Bail if the RAM allocation failed return (false); if (moduleSWVersion->moduleQueried == false) @@ -6668,25 +6759,26 @@ uint8_t SFE_UBLOX_GNSS::getProtocolVersionLow(uint16_t maxWait) return (moduleSWVersion->versionLow); } -//Get the current protocol version of the u-blox module we're communicating with -//This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) +// Get the current protocol version of the u-blox module we're communicating with +// This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) bool SFE_UBLOX_GNSS::getProtocolVersion(uint16_t maxWait) { - if (moduleSWVersion == NULL) initModuleSWVersion(); //Check that RAM has been allocated for the SW version - if (moduleSWVersion == NULL) //Bail if the RAM allocation failed + if (moduleSWVersion == NULL) + initModuleSWVersion(); // Check that RAM has been allocated for the SW version + if (moduleSWVersion == NULL) // Bail if the RAM allocation failed return (false); - //Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID. + // Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID. packetCfg.cls = UBX_CLASS_MON; packetCfg.id = UBX_MON_VER; packetCfg.len = 0; - packetCfg.startingSpot = 40; //Start at first "extended software information" string + packetCfg.startingSpot = 40; // Start at first "extended software information" string if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are only expecting data (no ACK) - return (false); //If command send fails then bail + return (false); // If command send fails then bail - //Payload should now contain ~220 characters (depends on module type) + // Payload should now contain ~220 characters (depends on module type) // if (_printDebug == true) // { @@ -6700,15 +6792,15 @@ bool SFE_UBLOX_GNSS::getProtocolVersion(uint16_t maxWait) // _debugSerial->println(); // } - //We will step through the payload looking at each extension field of 30 bytes + // We will step through the payload looking at each extension field of 30 bytes for (uint8_t extensionNumber = 0; extensionNumber < 10; extensionNumber++) { - //Now we need to find "PROTVER=18.00" in the incoming byte stream + // Now we need to find "PROTVER=18.00" in the incoming byte stream if ((payloadCfg[(30 * extensionNumber) + 0] == 'P') && (payloadCfg[(30 * extensionNumber) + 6] == 'R')) { - moduleSWVersion->versionHigh = (payloadCfg[(30 * extensionNumber) + 8] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 9] - '0'); //Convert '18' to 18 - moduleSWVersion->versionLow = (payloadCfg[(30 * extensionNumber) + 11] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 12] - '0'); //Convert '00' to 00 - moduleSWVersion->moduleQueried = true; // Mark this data as new + moduleSWVersion->versionHigh = (payloadCfg[(30 * extensionNumber) + 8] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 9] - '0'); // Convert '18' to 18 + moduleSWVersion->versionLow = (payloadCfg[(30 * extensionNumber) + 11] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 12] - '0'); // Convert '00' to 00 + moduleSWVersion->moduleQueried = true; // Mark this data as new #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) @@ -6719,17 +6811,17 @@ bool SFE_UBLOX_GNSS::getProtocolVersion(uint16_t maxWait) _debugSerial->println(moduleSWVersion->versionLow); } #endif - return (true); //Success! + return (true); // Success! } } - return (false); //We failed + return (false); // We failed } // PRIVATE: Allocate RAM for moduleSWVersion and initialize it bool SFE_UBLOX_GNSS::initModuleSWVersion() { - moduleSWVersion = new moduleSWVersion_t; //Allocate RAM for the main struct + moduleSWVersion = new moduleSWVersion_t; // Allocate RAM for the main struct if (moduleSWVersion == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -6746,10 +6838,11 @@ bool SFE_UBLOX_GNSS::initModuleSWVersion() // Geofences -//Add a new geofence using UBX-CFG-GEOFENCE +// Add a new geofence using UBX-CFG-GEOFENCE bool SFE_UBLOX_GNSS::addGeofence(int32_t latitude, int32_t longitude, uint32_t radius, byte confidence, byte pinPolarity, byte pin, uint16_t maxWait) { - if (currentGeofenceParams == NULL) initGeofenceParams(); // Check if RAM has been allocated for currentGeofenceParams + if (currentGeofenceParams == NULL) + initGeofenceParams(); // Check if RAM has been allocated for currentGeofenceParams if (currentGeofenceParams == NULL) // Abort if the RAM allocation failed return (false); @@ -6767,10 +6860,10 @@ bool SFE_UBLOX_GNSS::addGeofence(int32_t latitude, int32_t longitude, uint32_t r packetCfg.len = (currentGeofenceParams->numFences * 12) + 8; packetCfg.startingSpot = 0; - payloadCfg[0] = 0; // Message version = 0x00 + payloadCfg[0] = 0; // Message version = 0x00 payloadCfg[1] = currentGeofenceParams->numFences; // numFences - payloadCfg[2] = confidence; // confLvl = Confidence level 0-4 (none, 68%, 95%, 99.7%, 99.99%) - payloadCfg[3] = 0; // reserved1 + payloadCfg[2] = confidence; // confLvl = Confidence level 0-4 (none, 68%, 95%, 99.7%, 99.99%) + payloadCfg[3] = 0; // reserved1 if (pin > 0) { payloadCfg[4] = 1; // enable PIO combined fence state @@ -6781,7 +6874,7 @@ bool SFE_UBLOX_GNSS::addGeofence(int32_t latitude, int32_t longitude, uint32_t r } payloadCfg[5] = pinPolarity; // PIO pin polarity (0 = low means inside, 1 = low means outside (or unknown)) payloadCfg[6] = pin; // PIO pin - payloadCfg[7] = 0; //reserved2 + payloadCfg[7] = 0; // reserved2 payloadCfg[8] = currentGeofenceParams->lats[0] & 0xFF; payloadCfg[9] = currentGeofenceParams->lats[0] >> 8; payloadCfg[10] = currentGeofenceParams->lats[0] >> 16; @@ -6842,10 +6935,11 @@ bool SFE_UBLOX_GNSS::addGeofence(int32_t latitude, int32_t longitude, uint32_t r return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Clear all geofences using UBX-CFG-GEOFENCE +// Clear all geofences using UBX-CFG-GEOFENCE bool SFE_UBLOX_GNSS::clearGeofences(uint16_t maxWait) { - if (currentGeofenceParams == NULL) initGeofenceParams(); // Check if RAM has been allocated for currentGeofenceParams + if (currentGeofenceParams == NULL) + initGeofenceParams(); // Check if RAM has been allocated for currentGeofenceParams if (currentGeofenceParams == NULL) // Abort if the RAM allocation failed return (false); @@ -6861,16 +6955,16 @@ bool SFE_UBLOX_GNSS::clearGeofences(uint16_t maxWait) payloadCfg[4] = 0; // disable PIO combined fence state payloadCfg[5] = 0; // PIO pin polarity (0 = low means inside, 1 = low means outside (or unknown)) payloadCfg[6] = 0; // PIO pin - payloadCfg[7] = 0; //reserved2 + payloadCfg[7] = 0; // reserved2 currentGeofenceParams->numFences = 0; // Zero the number of geofences currently in use return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Clear the antenna control settings using UBX-CFG-ANT -//This function is hopefully redundant but may be needed to release -//any PIO pins pre-allocated for antenna functions +// Clear the antenna control settings using UBX-CFG-ANT +// This function is hopefully redundant but may be needed to release +// any PIO pins pre-allocated for antenna functions bool SFE_UBLOX_GNSS::clearAntPIO(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -6886,7 +6980,7 @@ bool SFE_UBLOX_GNSS::clearAntPIO(uint16_t maxWait) return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Returns the combined geofence state using UBX-NAV-GEOFENCE +// Returns the combined geofence state using UBX-NAV-GEOFENCE bool SFE_UBLOX_GNSS::getGeofenceState(geofenceState ¤tGeofenceState, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_NAV; @@ -6894,7 +6988,7 @@ bool SFE_UBLOX_GNSS::getGeofenceState(geofenceState ¤tGeofenceState, uint1 packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the geofence status. Loads into payloadCfg. + // Ask module for the geofence status. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK return (false); @@ -6916,7 +7010,7 @@ bool SFE_UBLOX_GNSS::getGeofenceState(geofenceState ¤tGeofenceState, uint1 // PRIVATE: Allocate RAM for currentGeofenceParams and initialize it bool SFE_UBLOX_GNSS::initGeofenceParams() { - currentGeofenceParams = new geofenceParams_t; //Allocate RAM for the main struct + currentGeofenceParams = new geofenceParams_t; // Allocate RAM for the main struct if (currentGeofenceParams == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -6929,8 +7023,8 @@ bool SFE_UBLOX_GNSS::initGeofenceParams() return (true); } -//Power Save Mode -//Enables/Disables Low Power Mode using UBX-CFG-RXM +// Power Save Mode +// Enables/Disables Low Power Mode using UBX-CFG-RXM bool SFE_UBLOX_GNSS::powerSaveMode(bool power_save, uint16_t maxWait) { // Let's begin by checking the Protocol Version as UBX_CFG_RXM is not supported on the ZED (protocol >= 27) @@ -6957,7 +7051,7 @@ bool SFE_UBLOX_GNSS::powerSaveMode(bool power_save, uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current power management settings. Loads into payloadCfg. + // Ask module for the current power management settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK return (false); @@ -7005,7 +7099,7 @@ uint8_t SFE_UBLOX_GNSS::getPowerSaveMode(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current power management settings. Loads into payloadCfg. + // Ask module for the current power management settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK return (255); @@ -7041,10 +7135,10 @@ bool SFE_UBLOX_GNSS::powerOff(uint32_t durationInMs, uint16_t maxWait) payloadCfg[2] = (durationInMs >> (8 * 2)) & 0xff; payloadCfg[3] = (durationInMs >> (8 * 3)) & 0xff; - payloadCfg[4] = 0x02; //Flags : set the backup bit - payloadCfg[5] = 0x00; //Flags - payloadCfg[6] = 0x00; //Flags - payloadCfg[7] = 0x00; //Flags + payloadCfg[4] = 0x02; // Flags : set the backup bit + payloadCfg[5] = 0x00; // Flags + payloadCfg[6] = 0x00; // Flags + payloadCfg[7] = 0x00; // Flags if (maxWait != 0) { @@ -7139,14 +7233,14 @@ bool SFE_UBLOX_GNSS::powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeu } } -//Dynamic Platform Model +// Dynamic Platform Model -//Change the dynamic platform model using UBX-CFG-NAV5 -//Possible values are: -//PORTABLE,STATIONARY,PEDESTRIAN,AUTOMOTIVE,SEA, -//AIRBORNE1g,AIRBORNE2g,AIRBORNE4g,WRIST,BIKE -//WRIST is not supported in protocol versions less than 18 -//BIKE is supported in protocol versions 19.2 +// Change the dynamic platform model using UBX-CFG-NAV5 +// Possible values are: +// PORTABLE,STATIONARY,PEDESTRIAN,AUTOMOTIVE,SEA, +// AIRBORNE1g,AIRBORNE2g,AIRBORNE4g,WRIST,BIKE +// WRIST is not supported in protocol versions less than 18 +// BIKE is supported in protocol versions 19.2 bool SFE_UBLOX_GNSS::setDynamicModel(dynModel newDynamicModel, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -7154,7 +7248,7 @@ bool SFE_UBLOX_GNSS::setDynamicModel(dynModel newDynamicModel, uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current navigation model settings. Loads into payloadCfg. + // Ask module for the current navigation model settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK return (false); @@ -7168,8 +7262,8 @@ bool SFE_UBLOX_GNSS::setDynamicModel(dynModel newDynamicModel, uint16_t maxWait) return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Get the dynamic platform model using UBX-CFG-NAV5 -//Returns DYN_MODEL_UNKNOWN (255) if the sendCommand fails +// Get the dynamic platform model using UBX-CFG-NAV5 +// Returns DYN_MODEL_UNKNOWN (255) if the sendCommand fails uint8_t SFE_UBLOX_GNSS::getDynamicModel(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -7177,14 +7271,14 @@ uint8_t SFE_UBLOX_GNSS::getDynamicModel(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current navigation model settings. Loads into payloadCfg. + // Ask module for the current navigation model settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK return (DYN_MODEL_UNKNOWN); return (payloadCfg[2]); // Return the dynamic model } -//Reset the odometer +// Reset the odometer bool SFE_UBLOX_GNSS::resetOdometer(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_NAV; @@ -7196,7 +7290,7 @@ bool SFE_UBLOX_GNSS::resetOdometer(uint16_t maxWait) return (sendCommand(&packetCfg, maxWait, true) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Enable/Disable individual GNSS systems using UBX-CFG-GNSS +// Enable/Disable individual GNSS systems using UBX-CFG-GNSS bool SFE_UBLOX_GNSS::enableGNSS(bool enable, sfe_ublox_gnss_ids_e id, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -7224,7 +7318,7 @@ bool SFE_UBLOX_GNSS::enableGNSS(bool enable, sfe_ublox_gnss_ids_e id, uint16_t m return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Check if an individual GNSS system is enabled +// Check if an individual GNSS system is enabled bool SFE_UBLOX_GNSS::isGNSSenabled(sfe_ublox_gnss_ids_e id, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -7252,7 +7346,7 @@ bool SFE_UBLOX_GNSS::isGNSSenabled(sfe_ublox_gnss_ids_e id, uint16_t maxWait) return (retVal); } -//Reset ESF automatic IMU-mount alignment +// Reset ESF automatic IMU-mount alignment bool SFE_UBLOX_GNSS::resetIMUalignment(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_ESF; @@ -7264,8 +7358,8 @@ bool SFE_UBLOX_GNSS::resetIMUalignment(uint16_t maxWait) return (sendCommand(&packetCfg, maxWait, true) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//UBX-CFG-ESFALG is not documented. This was found using u-center. -//Returns the state of the UBX-CFG-ESFALG 'Automatic IMU-mount Alignment' flag +// UBX-CFG-ESFALG is not documented. This was found using u-center. +// Returns the state of the UBX-CFG-ESFALG 'Automatic IMU-mount Alignment' flag bool SFE_UBLOX_GNSS::getESFAutoAlignment(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -7275,20 +7369,20 @@ bool SFE_UBLOX_GNSS::getESFAutoAlignment(uint16_t maxWait) if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) { - #ifndef SFE_UBLOX_REDUCED_PROG_MEM +#ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) { _debugSerial->println(F("getESFAutoAlignment failed")); } - #endif +#endif - return (false); //If command send fails then bail + return (false); // If command send fails then bail } - return (payloadCfg[1] & 0b1); //Return Bit 0 + return (payloadCfg[1] & 0b1); // Return Bit 0 } -//Set the state of the UBX-CFG-ESFALG 'Automatic IMU-mount Alignment' flag +// Set the state of the UBX-CFG-ESFALG 'Automatic IMU-mount Alignment' flag bool SFE_UBLOX_GNSS::setESFAutoAlignment(bool enable, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -7298,17 +7392,17 @@ bool SFE_UBLOX_GNSS::setESFAutoAlignment(bool enable, uint16_t maxWait) if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) { - #ifndef SFE_UBLOX_REDUCED_PROG_MEM - if (_printDebug == true) - { - _debugSerial->println(F("getESFAutoAlignment failed")); - } - #endif +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + { + _debugSerial->println(F("getESFAutoAlignment failed")); + } +#endif - return (false); //If command send fails then bail + return (false); // If command send fails then bail } - //payloadCfg is now filled + // payloadCfg is now filled if (enable) payloadCfg[1] |= 0b1; @@ -7317,20 +7411,19 @@ bool SFE_UBLOX_GNSS::setESFAutoAlignment(bool enable, uint16_t maxWait) if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) // This time we are only expecting an ACK { - #ifndef SFE_UBLOX_REDUCED_PROG_MEM - if (_printDebug == true) - { - _debugSerial->println(F("setESFAutoAlignment failed")); - } - #endif +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + { + _debugSerial->println(F("setESFAutoAlignment failed")); + } +#endif return (false); } return (true); } - -//Get the time pulse parameters using UBX_CFG_TP5 +// Get the time pulse parameters using UBX_CFG_TP5 bool SFE_UBLOX_GNSS::getTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t maxWait) { if (data == NULL) // Check if the user forgot to include the data pointer @@ -7356,10 +7449,10 @@ bool SFE_UBLOX_GNSS::getTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t m data->userConfigDelay = extractSignedLong(&packetCfg, 24); data->flags.all = extractLong(&packetCfg, 28); - return(true); + return (true); } -//Set the time pulse parameters using UBX_CFG_TP5 +// Set the time pulse parameters using UBX_CFG_TP5 bool SFE_UBLOX_GNSS::setTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t maxWait) { if (data == NULL) // Check if the user forgot to include the data pointer @@ -7405,7 +7498,7 @@ bool SFE_UBLOX_GNSS::setTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t m return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data +// UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data uint8_t SFE_UBLOX_GNSS::getAckAiding(uint16_t maxWait) // Get the ackAiding byte - returns 255 if the sendCommand fails { packetCfg.cls = UBX_CLASS_CFG; @@ -7443,8 +7536,8 @@ bool SFE_UBLOX_GNSS::setAckAiding(uint8_t ackAiding, uint16_t maxWait) // Set th return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//AssistNow Autonomous support -//UBX-CFG-NAVX5 - get the AssistNow Autonomous configuration (aopCfg) - returns 255 if the sendCommand fails +// AssistNow Autonomous support +// UBX-CFG-NAVX5 - get the AssistNow Autonomous configuration (aopCfg) - returns 255 if the sendCommand fails uint8_t SFE_UBLOX_GNSS::getAopCfg(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; @@ -7474,7 +7567,7 @@ bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t m // There are three versions of UBX-CFG-NAVX5 but aopCfg is always in byte 27 and aopOrbMaxErr is always in bytes 30 & 31 payloadCfg[27] = aopCfg; payloadCfg[30] = (uint8_t)(aopOrbMaxErr & 0xFF); // aopOrbMaxErr LSB - payloadCfg[31] = (uint8_t)(aopOrbMaxErr >> 8); // aopOrbMaxErr MSB + payloadCfg[31] = (uint8_t)(aopOrbMaxErr >> 8); // aopOrbMaxErr MSB // There are three versions of UBX-CFG-NAVX5 but the aop flag is always in bit 14 of mask1 payloadCfg[2] = 0x00; // Clear the LS byte of mask1 @@ -7485,17 +7578,17 @@ bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t m return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//SPARTN dynamic keys +// SPARTN dynamic keys //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. //"Every time the 'current' key is expired, 'next' takes its place." //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. -//The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. +// The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait) { // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F bool isASCIIHex = true; uint16_t i = 0; - while((i < (uint16_t)keyLengthBytes) && (isASCIIHex == true)) + while ((i < (uint16_t)keyLengthBytes) && (isASCIIHex == true)) { if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) i++; // Keep checking if data is all ASCII Hex @@ -7504,7 +7597,7 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validF } if (isASCIIHex) // Check the second half of the ASCII Hex key { - while((i < ((uint16_t)keyLengthBytes * 2) && (isASCIIHex == true))) + while ((i < ((uint16_t)keyLengthBytes * 2) && (isASCIIHex == true))) { if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) i++; // Keep checking if data is all ASCII Hex @@ -7519,7 +7612,7 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validF { if (!setPacketCfgPayloadSize(payloadLength)) // Check if the resize was successful { - return (false); + return (false); } } @@ -7544,7 +7637,7 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validF if (isASCIIHex) // Convert ASCII Hex key to binary { - for(i = 0; i < ((uint16_t)keyLengthBytes * 2); i += 2) + for (i = 0; i < ((uint16_t)keyLengthBytes * 2); i += 2) { if ((key[i] >= '0') && (key[i] <= '9')) { @@ -7589,7 +7682,7 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t vali // CONFIGURATION INTERFACE (protocol v27 and above) -//Form 32-bit key from group/id/size +// Form 32-bit key from group/id/size uint32_t SFE_UBLOX_GNSS::createKey(uint16_t group, uint16_t id, uint8_t size) { uint32_t key = 0; @@ -7599,36 +7692,36 @@ uint32_t SFE_UBLOX_GNSS::createKey(uint16_t group, uint16_t id, uint8_t size) return (key); } -//Given a key, load the payload with data that can then be extracted to 8, 16, or 32 bits -//This function takes a full 32-bit key -//Default layer is RAM -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a key, load the payload with data that can then be extracted to 8, 16, or 32 bits +// This function takes a full 32-bit key +// Default layer is RAM +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P sfe_ublox_status_e SFE_UBLOX_GNSS::getVal(uint32_t key, uint8_t layer, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALGET; - packetCfg.len = 4 + 4 * 1; //While multiple keys are allowed, we will send only one key at a time + packetCfg.len = 4 + 4 * 1; // While multiple keys are allowed, we will send only one key at a time packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - //VALGET uses different memory layer definitions to VALSET - //because it can only return the value for one layer. - //So we need to fiddle the layer here. - //And just to complicate things further, the ZED-F9P only responds - //correctly to layer 0 (RAM) and layer 7 (Default)! + // VALGET uses different memory layer definitions to VALSET + // because it can only return the value for one layer. + // So we need to fiddle the layer here. + // And just to complicate things further, the ZED-F9P only responds + // correctly to layer 0 (RAM) and layer 7 (Default)! uint8_t getLayer = 7; // 7 is the "Default Layer" if ((layer & VAL_LAYER_RAM) == VAL_LAYER_RAM) // Did the user request the RAM layer? { getLayer = 0; // Layer 0 is RAM } - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = getLayer; //Layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = getLayer; // Layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; @@ -7642,7 +7735,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::getVal(uint32_t key, uint8_t layer, uint16_t } #endif - //Send VALGET command with this key + // Send VALGET command with this key sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait); #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -7653,18 +7746,18 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::getVal(uint32_t key, uint8_t layer, uint16_t } #endif - //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?) - //Response is 8 bytes plus cfg data - //if(packet->len > 8+1) + // 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?) + // Response is 8 bytes plus cfg data + // if(packet->len > 8+1) - //The response is now sitting in payload, ready for extraction + // The response is now sitting in payload, ready for extraction return (retVal); } -//Given a key, return its value -//This function takes a full 32-bit key -//Default layer is RAM -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a key, return its value +// This function takes a full 32-bit key +// Default layer is RAM +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::getVal8(uint32_t key, uint8_t layer, uint16_t maxWait) { if (getVal(key, layer, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) @@ -7694,9 +7787,9 @@ uint64_t SFE_UBLOX_GNSS::getVal64(uint32_t key, uint8_t layer, uint16_t maxWait) return (extractLongLong(&packetCfg, 8)); } -//Given a group, ID and size, return the value of this config spot -//The 32-bit key is put together from group/ID/size. See other getVal to send key directly. -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a group, ID and size, return the value of this config spot +// The 32-bit key is put together from group/ID/size. See other getVal to send key directly. +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::getVal8(uint16_t group, uint16_t id, uint8_t size, uint8_t layer, uint16_t maxWait) { uint32_t key = createKey(group, id, size); @@ -7718,134 +7811,134 @@ uint64_t SFE_UBLOX_GNSS::getVal64(uint16_t group, uint16_t id, uint8_t size, uin return getVal64(key, layer, maxWait); } -//Given a key, set a 16-bit value -//This function takes a full 32-bit key -//Default layer is all: RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a key, set a 16-bit value +// This function takes a full 32-bit key +// Default layer is all: RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::setVal(uint32_t key, uint16_t value, uint8_t layer, uint16_t maxWait) { return setVal16(key, value, layer, maxWait); } -//Given a key, set a 16-bit value -//This function takes a full 32-bit key -//Default layer is all: RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a key, set a 16-bit value +// This function takes a full 32-bit key +// Default layer is all: RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::setVal16(uint32_t key, uint16_t value, uint8_t layer, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 2; //4 byte header, 4 byte key ID, 2 bytes of value + packetCfg.len = 4 + 4 + 2; // 4 byte header, 4 byte key ID, 2 bytes of value packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[8] = value >> 8 * 0; // Value LSB payloadCfg[9] = value >> 8 * 1; - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Given a key, set an 8-bit value -//This function takes a full 32-bit key -//Default layer is all: RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a key, set an 8-bit value +// This function takes a full 32-bit key +// Default layer is all: RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::setVal8(uint32_t key, uint8_t value, uint8_t layer, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 1; //4 byte header, 4 byte key ID, 1 byte value + packetCfg.len = 4 + 4 + 1; // 4 byte header, 4 byte key ID, 1 byte value packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value; //Value + // Load user's value + payloadCfg[8] = value; // Value - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Given a key, set a 32-bit value -//This function takes a full 32-bit key -//Default layer is all: RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a key, set a 32-bit value +// This function takes a full 32-bit key +// Default layer is all: RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::setVal32(uint32_t key, uint32_t value, uint8_t layer, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 4; //4 byte header, 4 byte key ID, 4 bytes of value + packetCfg.len = 4 + 4 + 4; // 4 byte header, 4 byte key ID, 4 bytes of value packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[8] = value >> 8 * 0; // Value LSB payloadCfg[9] = value >> 8 * 1; payloadCfg[10] = value >> 8 * 2; payloadCfg[11] = value >> 8 * 3; - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Given a key, set a 64-bit value -//This function takes a full 32-bit key -//Default layer is all: RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Given a key, set a 64-bit value +// This function takes a full 32-bit key +// Default layer is all: RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::setVal64(uint32_t key, uint64_t value, uint8_t layer, uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 8; //4 byte header, 4 byte key ID, 8 bytes of value + packetCfg.len = 4 + 4 + 8; // 4 byte header, 4 byte key ID, 8 bytes of value packetCfg.startingSpot = 0; - //Clear packet payload + // Clear packet payload memset(payloadCfg, 0, packetCfg.len); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[8] = value >> 8 * 0; // Value LSB payloadCfg[9] = value >> 8 * 1; payloadCfg[10] = value >> 8 * 2; payloadCfg[11] = value >> 8 * 3; @@ -7854,35 +7947,35 @@ uint8_t SFE_UBLOX_GNSS::setVal64(uint32_t key, uint64_t value, uint8_t layer, ui payloadCfg[14] = value >> 8 * 6; payloadCfg[15] = value >> 8 * 7; - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Start defining a new UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 64-bit value -//Default layer is RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Start defining a new UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 64-bit value +// Default layer is RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::newCfgValset64(uint32_t key, uint64_t value, uint8_t layer) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 8; //4 byte header, 4 byte key ID, 8 bytes of value + packetCfg.len = 4 + 4 + 8; // 4 byte header, 4 byte key ID, 8 bytes of value packetCfg.startingSpot = 0; - //Clear all of packet payload + // Clear all of packet payload memset(payloadCfg, 0, packetCfgPayloadSize); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[8] = value >> 8 * 0; // Value LSB payloadCfg[9] = value >> 8 * 1; payloadCfg[10] = value >> 8 * 2; payloadCfg[11] = value >> 8 * 3; @@ -7891,116 +7984,116 @@ uint8_t SFE_UBLOX_GNSS::newCfgValset64(uint32_t key, uint64_t value, uint8_t lay payloadCfg[14] = value >> 8 * 6; payloadCfg[15] = value >> 8 * 7; - //All done + // All done return (true); } -//Start defining a new UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 32-bit value -//Default layer is RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Start defining a new UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 32-bit value +// Default layer is RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::newCfgValset32(uint32_t key, uint32_t value, uint8_t layer) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 4; //4 byte header, 4 byte key ID, 4 bytes of value + packetCfg.len = 4 + 4 + 4; // 4 byte header, 4 byte key ID, 4 bytes of value packetCfg.startingSpot = 0; - //Clear all of packet payload + // Clear all of packet payload memset(payloadCfg, 0, packetCfgPayloadSize); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[8] = value >> 8 * 0; // Value LSB payloadCfg[9] = value >> 8 * 1; payloadCfg[10] = value >> 8 * 2; payloadCfg[11] = value >> 8 * 3; - //All done + // All done return (true); } -//Start defining a new UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 16-bit value -//Default layer is RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Start defining a new UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 16-bit value +// Default layer is RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::newCfgValset16(uint32_t key, uint16_t value, uint8_t layer) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 2; //4 byte header, 4 byte key ID, 2 bytes of value + packetCfg.len = 4 + 4 + 2; // 4 byte header, 4 byte key ID, 2 bytes of value packetCfg.startingSpot = 0; - //Clear all of packet payload + // Clear all of packet payload memset(payloadCfg, 0, packetCfgPayloadSize); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[8] = value >> 8 * 0; // Value LSB payloadCfg[9] = value >> 8 * 1; - //All done + // All done return (true); } -//Start defining a new UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 8-bit value -//Default layer is RAM+BBR+Flash -//Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P +// Start defining a new UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 8-bit value +// Default layer is RAM+BBR+Flash +// Configuration of modern u-blox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P uint8_t SFE_UBLOX_GNSS::newCfgValset8(uint32_t key, uint8_t value, uint8_t layer) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_VALSET; - packetCfg.len = 4 + 4 + 1; //4 byte header, 4 byte key ID, 1 byte value + packetCfg.len = 4 + 4 + 1; // 4 byte header, 4 byte key ID, 1 byte value packetCfg.startingSpot = 0; - //Clear all of packet payload + // Clear all of packet payload memset(payloadCfg, 0, packetCfgPayloadSize); - payloadCfg[0] = 0; //Message Version - set to 0 - payloadCfg[1] = layer; //By default we ask for the BBR layer + payloadCfg[0] = 0; // Message Version - set to 0 + payloadCfg[1] = layer; // By default we ask for the BBR layer - //Load key into outgoing payload - payloadCfg[4] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[4] = key >> 8 * 0; // Key LSB payloadCfg[5] = key >> 8 * 1; payloadCfg[6] = key >> 8 * 2; payloadCfg[7] = key >> 8 * 3; - //Load user's value - payloadCfg[8] = value; //Value + // Load user's value + payloadCfg[8] = value; // Value - //All done + // All done return (true); } -//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 64-bit value +// Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 64-bit value uint8_t SFE_UBLOX_GNSS::addCfgValset64(uint32_t key, uint64_t value) { - //Load key into outgoing payload - payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[packetCfg.len + 0] = key >> 8 * 0; // Key LSB payloadCfg[packetCfg.len + 1] = key >> 8 * 1; payloadCfg[packetCfg.len + 2] = key >> 8 * 2; payloadCfg[packetCfg.len + 3] = key >> 8 * 3; - //Load user's value - payloadCfg[packetCfg.len + 4] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[packetCfg.len + 4] = value >> 8 * 0; // Value LSB payloadCfg[packetCfg.len + 5] = value >> 8 * 1; payloadCfg[packetCfg.len + 6] = value >> 8 * 2; payloadCfg[packetCfg.len + 7] = value >> 8 * 3; @@ -8009,153 +8102,153 @@ uint8_t SFE_UBLOX_GNSS::addCfgValset64(uint32_t key, uint64_t value) payloadCfg[packetCfg.len + 10] = value >> 8 * 6; payloadCfg[packetCfg.len + 11] = value >> 8 * 7; - //Update packet length: 4 byte key ID, 8 bytes of value + // Update packet length: 4 byte key ID, 8 bytes of value packetCfg.len = packetCfg.len + 4 + 8; - //All done + // All done return (true); } -//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 32-bit value +// Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 32-bit value uint8_t SFE_UBLOX_GNSS::addCfgValset32(uint32_t key, uint32_t value) { - //Load key into outgoing payload - payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[packetCfg.len + 0] = key >> 8 * 0; // Key LSB payloadCfg[packetCfg.len + 1] = key >> 8 * 1; payloadCfg[packetCfg.len + 2] = key >> 8 * 2; payloadCfg[packetCfg.len + 3] = key >> 8 * 3; - //Load user's value - payloadCfg[packetCfg.len + 4] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[packetCfg.len + 4] = value >> 8 * 0; // Value LSB payloadCfg[packetCfg.len + 5] = value >> 8 * 1; payloadCfg[packetCfg.len + 6] = value >> 8 * 2; payloadCfg[packetCfg.len + 7] = value >> 8 * 3; - //Update packet length: 4 byte key ID, 4 bytes of value + // Update packet length: 4 byte key ID, 4 bytes of value packetCfg.len = packetCfg.len + 4 + 4; - //All done + // All done return (true); } -//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 16-bit value +// Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 16-bit value uint8_t SFE_UBLOX_GNSS::addCfgValset16(uint32_t key, uint16_t value) { - //Load key into outgoing payload - payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[packetCfg.len + 0] = key >> 8 * 0; // Key LSB payloadCfg[packetCfg.len + 1] = key >> 8 * 1; payloadCfg[packetCfg.len + 2] = key >> 8 * 2; payloadCfg[packetCfg.len + 3] = key >> 8 * 3; - //Load user's value - payloadCfg[packetCfg.len + 4] = value >> 8 * 0; //Value LSB + // Load user's value + payloadCfg[packetCfg.len + 4] = value >> 8 * 0; // Value LSB payloadCfg[packetCfg.len + 5] = value >> 8 * 1; - //Update packet length: 4 byte key ID, 2 bytes of value + // Update packet length: 4 byte key ID, 2 bytes of value packetCfg.len = packetCfg.len + 4 + 2; - //All done + // All done return (true); } -//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket -//This function takes a full 32-bit key and 8-bit value +// Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket +// This function takes a full 32-bit key and 8-bit value uint8_t SFE_UBLOX_GNSS::addCfgValset8(uint32_t key, uint8_t value) { - //Load key into outgoing payload - payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB + // Load key into outgoing payload + payloadCfg[packetCfg.len + 0] = key >> 8 * 0; // Key LSB payloadCfg[packetCfg.len + 1] = key >> 8 * 1; payloadCfg[packetCfg.len + 2] = key >> 8 * 2; payloadCfg[packetCfg.len + 3] = key >> 8 * 3; - //Load user's value - payloadCfg[packetCfg.len + 4] = value; //Value + // Load user's value + payloadCfg[packetCfg.len + 4] = value; // Value - //Update packet length: 4 byte key ID, 1 byte value + // Update packet length: 4 byte key ID, 1 byte value packetCfg.len = packetCfg.len + 4 + 1; - //All done + // All done return (true); } -//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it -//This function takes a full 32-bit key and 64-bit value +// Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it +// This function takes a full 32-bit key and 64-bit value uint8_t SFE_UBLOX_GNSS::sendCfgValset64(uint32_t key, uint64_t value, uint16_t maxWait) { - //Load keyID and value into outgoing payload + // Load keyID and value into outgoing payload addCfgValset64(key, value); - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it -//This function takes a full 32-bit key and 32-bit value +// Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it +// This function takes a full 32-bit key and 32-bit value uint8_t SFE_UBLOX_GNSS::sendCfgValset32(uint32_t key, uint32_t value, uint16_t maxWait) { - //Load keyID and value into outgoing payload + // Load keyID and value into outgoing payload addCfgValset32(key, value); - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it -//This function takes a full 32-bit key and 16-bit value +// Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it +// This function takes a full 32-bit key and 16-bit value uint8_t SFE_UBLOX_GNSS::sendCfgValset16(uint32_t key, uint16_t value, uint16_t maxWait) { - //Load keyID and value into outgoing payload + // Load keyID and value into outgoing payload addCfgValset16(key, value); - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } -//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it -//This function takes a full 32-bit key and 8-bit value +// Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it +// This function takes a full 32-bit key and 8-bit value uint8_t SFE_UBLOX_GNSS::sendCfgValset8(uint32_t key, uint8_t value, uint16_t maxWait) { - //Load keyID and value into outgoing payload + // Load keyID and value into outgoing payload addCfgValset8(key, value); - //Send VALSET command with this key and value + // Send VALSET command with this key and value return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } //=-=-=-=-=-=-=-= "Automatic" Messages =-=-=-=-=-=-=-==-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - // ***** NAV POSECEF automatic support bool SFE_UBLOX_GNSS::getNAVPOSECEF(uint16_t maxWait) { - if (packetUBXNAVPOSECEF == NULL) initPacketUBXNAVPOSECEF(); //Check that RAM has been allocated for the POSECEF data - if (packetUBXNAVPOSECEF == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPOSECEF == NULL) + initPacketUBXNAVPOSECEF(); // Check that RAM has been allocated for the POSECEF data + if (packetUBXNAVPOSECEF == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPOSECEF->automaticFlags.flags.bits.automatic && packetUBXNAVPOSECEF->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_POSECEF); return packetUBXNAVPOSECEF->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVPOSECEF->automaticFlags.flags.bits.automatic && !packetUBXNAVPOSECEF->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_POSECEF; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -8170,29 +8263,31 @@ bool SFE_UBLOX_GNSS::getNAVPOSECEF(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPOSECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPOSECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVPOSECEF(bool enable, uint16_t maxWait) { return setAutoNAVPOSECEFrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPOSECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPOSECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVPOSECEF(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVPOSECEFrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPOSECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPOSECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVPOSECEF == NULL) initPacketUBXNAVPOSECEF(); //Check that RAM has been allocated for the data - if (packetUBXNAVPOSECEF == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVPOSECEF == NULL) + initPacketUBXNAVPOSECEF(); // Check that RAM has been allocated for the data + if (packetUBXNAVPOSECEF == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -8212,7 +8307,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFrate(uint8_t rate, bool implicitUpdate, ui return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFcallback(void (*callbackPointer)(UBX_NAV_POSECEF_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -8220,9 +8315,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFcallback(void (*callbackPointer)(UBX_NAV_P if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVPOSECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVPOSECEF->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVPOSECEF->callbackData = new UBX_NAV_POSECEF_data_t; //Allocate RAM for the main struct + packetUBXNAVPOSECEF->callbackData = new UBX_NAV_POSECEF_data_t; // Allocate RAM for the main struct } if (packetUBXNAVPOSECEF->callbackData == NULL) @@ -8245,9 +8340,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVPOSECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVPOSECEF->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVPOSECEF->callbackData = new UBX_NAV_POSECEF_data_t; //Allocate RAM for the main struct + packetUBXNAVPOSECEF->callbackData = new UBX_NAV_POSECEF_data_t; // Allocate RAM for the main struct } if (packetUBXNAVPOSECEF->callbackData == NULL) @@ -8263,12 +8358,13 @@ bool SFE_UBLOX_GNSS::setAutoNAVPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX return (true); } -//In case no config access to the GNSS is possible and POSECEF is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and POSECEF is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVPOSECEF(bool enabled, bool implicitUpdate) { - if (packetUBXNAVPOSECEF == NULL) initPacketUBXNAVPOSECEF(); //Check that RAM has been allocated for the data - if (packetUBXNAVPOSECEF == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVPOSECEF == NULL) + initPacketUBXNAVPOSECEF(); // Check that RAM has been allocated for the data + if (packetUBXNAVPOSECEF == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVPOSECEF->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVPOSECEF->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -8283,7 +8379,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVPOSECEF(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVPOSECEF and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVPOSECEF() { - packetUBXNAVPOSECEF = new UBX_NAV_POSECEF_t; //Allocate RAM for the main struct + packetUBXNAVPOSECEF = new UBX_NAV_POSECEF_t; // Allocate RAM for the main struct if (packetUBXNAVPOSECEF == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -8300,18 +8396,20 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPOSECEF() return (true); } -//Mark all the data as read/stale. This is handy to get data alignment after CRC failure -//or if there are no helper functions and the user wants to request fresh data +// Mark all the data as read/stale. This is handy to get data alignment after CRC failure +// or if there are no helper functions and the user wants to request fresh data void SFE_UBLOX_GNSS::flushNAVPOSECEF() { - if (packetUBXNAVPOSECEF == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVPOSECEF->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVPOSECEF == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVPOSECEF->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVPOSECEF(bool enabled) { - if (packetUBXNAVPOSECEF == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVPOSECEF == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVPOSECEF->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -8319,30 +8417,31 @@ void SFE_UBLOX_GNSS::logNAVPOSECEF(bool enabled) bool SFE_UBLOX_GNSS::getNAVSTATUS(uint16_t maxWait) { - if (packetUBXNAVSTATUS == NULL) initPacketUBXNAVSTATUS(); //Check that RAM has been allocated for the STATUS data - if (packetUBXNAVSTATUS == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVSTATUS == NULL) + initPacketUBXNAVSTATUS(); // Check that RAM has been allocated for the STATUS data + if (packetUBXNAVSTATUS == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVSTATUS->automaticFlags.flags.bits.automatic && packetUBXNAVSTATUS->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_STATUS); return packetUBXNAVSTATUS->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVSTATUS->automaticFlags.flags.bits.automatic && !packetUBXNAVSTATUS->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_STATUS; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -8357,29 +8456,31 @@ bool SFE_UBLOX_GNSS::getNAVSTATUS(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getNAVSTATUS -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getNAVSTATUS +// works. bool SFE_UBLOX_GNSS::setAutoNAVSTATUS(bool enable, uint16_t maxWait) { return setAutoNAVSTATUSrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getNAVSTATUS -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getNAVSTATUS +// works. bool SFE_UBLOX_GNSS::setAutoNAVSTATUS(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVSTATUSrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getNAVSTATUS -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getNAVSTATUS +// works. bool SFE_UBLOX_GNSS::setAutoNAVSTATUSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVSTATUS == NULL) initPacketUBXNAVSTATUS(); //Check that RAM has been allocated for the data - if (packetUBXNAVSTATUS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVSTATUS == NULL) + initPacketUBXNAVSTATUS(); // Check that RAM has been allocated for the data + if (packetUBXNAVSTATUS == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -8399,7 +8500,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVSTATUSrate(uint8_t rate, bool implicitUpdate, uin return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVSTATUScallback(void (*callbackPointer)(UBX_NAV_STATUS_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -8407,9 +8508,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVSTATUScallback(void (*callbackPointer)(UBX_NAV_ST if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVSTATUS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVSTATUS->callbackData = new UBX_NAV_STATUS_data_t; //Allocate RAM for the main struct + packetUBXNAVSTATUS->callbackData = new UBX_NAV_STATUS_data_t; // Allocate RAM for the main struct } if (packetUBXNAVSTATUS->callbackData == NULL) @@ -8432,9 +8533,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVSTATUS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVSTATUS->callbackData = new UBX_NAV_STATUS_data_t; //Allocate RAM for the main struct + packetUBXNAVSTATUS->callbackData = new UBX_NAV_STATUS_data_t; // Allocate RAM for the main struct } if (packetUBXNAVSTATUS->callbackData == NULL) @@ -8450,12 +8551,13 @@ bool SFE_UBLOX_GNSS::setAutoNAVSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ return (true); } -//In case no config access to the GNSS is possible and STATUS is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and STATUS is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVSTATUS(bool enabled, bool implicitUpdate) { - if (packetUBXNAVSTATUS == NULL) initPacketUBXNAVSTATUS(); //Check that RAM has been allocated for the data - if (packetUBXNAVSTATUS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVSTATUS == NULL) + initPacketUBXNAVSTATUS(); // Check that RAM has been allocated for the data + if (packetUBXNAVSTATUS == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVSTATUS->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVSTATUS->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -8470,7 +8572,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVSTATUS(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVSTATUS and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVSTATUS() { - packetUBXNAVSTATUS = new UBX_NAV_STATUS_t; //Allocate RAM for the main struct + packetUBXNAVSTATUS = new UBX_NAV_STATUS_t; // Allocate RAM for the main struct if (packetUBXNAVSTATUS == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -8487,18 +8589,20 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSTATUS() return (true); } -//Mark all the data as read/stale. This is handy to get data alignment after CRC failure -//or if there are no helper functions and the user wants to request fresh data +// Mark all the data as read/stale. This is handy to get data alignment after CRC failure +// or if there are no helper functions and the user wants to request fresh data void SFE_UBLOX_GNSS::flushNAVSTATUS() { - if (packetUBXNAVSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVSTATUS->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVSTATUS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSTATUS->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVSTATUS(bool enabled) { - if (packetUBXNAVSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVSTATUS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVSTATUS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -8506,27 +8610,28 @@ void SFE_UBLOX_GNSS::logNAVSTATUS(bool enabled) bool SFE_UBLOX_GNSS::getDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVDOP->automaticFlags.flags.bits.automatic && packetUBXNAVDOP->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getDOP: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getDOP: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_DOP); return packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVDOP->automaticFlags.flags.bits.automatic && !packetUBXNAVDOP->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getDOP: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getDOP: Exit immediately")); + // } return (false); } else @@ -8536,13 +8641,13 @@ bool SFE_UBLOX_GNSS::getDOP(uint16_t maxWait) // _debugSerial->println(F("getDOP: Polling")); // } - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_DOP; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -8566,26 +8671,27 @@ bool SFE_UBLOX_GNSS::getDOP(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getDOP -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getDOP +// works. bool SFE_UBLOX_GNSS::setAutoDOP(bool enable, uint16_t maxWait) { return setAutoDOPrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getDOP -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getDOP +// works. bool SFE_UBLOX_GNSS::setAutoDOP(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoDOPrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getDOP -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getDOP +// works. bool SFE_UBLOX_GNSS::setAutoDOPrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the data - if (packetUBXNAVDOP == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the data + if (packetUBXNAVDOP == NULL) // Only attempt this if RAM allocation was successful return false; packetCfg.cls = UBX_CLASS_CFG; @@ -8606,7 +8712,7 @@ bool SFE_UBLOX_GNSS::setAutoDOPrate(uint8_t rate, bool implicitUpdate, uint16_t return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoDOPcallback(void (*callbackPointer)(UBX_NAV_DOP_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -8614,9 +8720,9 @@ bool SFE_UBLOX_GNSS::setAutoDOPcallback(void (*callbackPointer)(UBX_NAV_DOP_data if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVDOP->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVDOP->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVDOP->callbackData = new UBX_NAV_DOP_data_t; //Allocate RAM for the main struct + packetUBXNAVDOP->callbackData = new UBX_NAV_DOP_data_t; // Allocate RAM for the main struct } if (packetUBXNAVDOP->callbackData == NULL) @@ -8639,9 +8745,9 @@ bool SFE_UBLOX_GNSS::setAutoDOPcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_DO if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVDOP->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVDOP->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVDOP->callbackData = new UBX_NAV_DOP_data_t; //Allocate RAM for the main struct + packetUBXNAVDOP->callbackData = new UBX_NAV_DOP_data_t; // Allocate RAM for the main struct } if (packetUBXNAVDOP->callbackData == NULL) @@ -8657,12 +8763,13 @@ bool SFE_UBLOX_GNSS::setAutoDOPcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_DO return (true); } -//In case no config access to the GNSS is possible and DOP is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and DOP is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoDOP(bool enabled, bool implicitUpdate) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the data - if (packetUBXNAVDOP == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the data + if (packetUBXNAVDOP == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVDOP->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVDOP->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -8677,7 +8784,7 @@ bool SFE_UBLOX_GNSS::assumeAutoDOP(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVDOP and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVDOP() { - packetUBXNAVDOP = new UBX_NAV_DOP_t; //Allocate RAM for the main struct + packetUBXNAVDOP = new UBX_NAV_DOP_t; // Allocate RAM for the main struct if (packetUBXNAVDOP == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -8693,17 +8800,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVDOP() return (true); } -//Mark all the DOP data as read/stale. This is handy to get data alignment after CRC failure +// Mark all the DOP data as read/stale. This is handy to get data alignment after CRC failure void SFE_UBLOX_GNSS::flushDOP() { - if (packetUBXNAVDOP == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVDOP->moduleQueried.moduleQueried.all = 0; //Mark all DOPs as stale (read before) + if (packetUBXNAVDOP == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVDOP->moduleQueried.moduleQueried.all = 0; // Mark all DOPs as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVDOP(bool enabled) { - if (packetUBXNAVDOP == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVDOP == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVDOP->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -8716,30 +8825,31 @@ bool SFE_UBLOX_GNSS::getVehAtt(uint16_t maxWait) bool SFE_UBLOX_GNSS::getNAVATT(uint16_t maxWait) { - if (packetUBXNAVATT == NULL) initPacketUBXNAVATT(); //Check that RAM has been allocated for the ESF RAW data - if (packetUBXNAVATT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVATT == NULL) + initPacketUBXNAVATT(); // Check that RAM has been allocated for the ESF RAW data + if (packetUBXNAVATT == NULL) // Only attempt this if RAM allocation was successful return false; if (packetUBXNAVATT->automaticFlags.flags.bits.automatic && packetUBXNAVATT->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_ATT); return packetUBXNAVATT->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVATT->automaticFlags.flags.bits.automatic && !packetUBXNAVATT->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting HNR PVT so we have to poll explicitly + // The GPS is not automatically reporting HNR PVT so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_ATT; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -8756,29 +8866,31 @@ bool SFE_UBLOX_GNSS::getNAVATT(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic NAV ATT message generation by the GNSS. This changes the way getVehAtt -//works. +// Enable or disable automatic NAV ATT message generation by the GNSS. This changes the way getVehAtt +// works. bool SFE_UBLOX_GNSS::setAutoNAVATT(bool enable, uint16_t maxWait) { return setAutoNAVATTrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic NAV ATT message generation by the GNSS. This changes the way getVehAtt -//works. +// Enable or disable automatic NAV ATT message generation by the GNSS. This changes the way getVehAtt +// works. bool SFE_UBLOX_GNSS::setAutoNAVATT(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVATTrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic NAV ATT attitude message generation by the GNSS. This changes the way getVehAtt -//works. +// Enable or disable automatic NAV ATT attitude message generation by the GNSS. This changes the way getVehAtt +// works. bool SFE_UBLOX_GNSS::setAutoNAVATTrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVATT == NULL) initPacketUBXNAVATT(); //Check that RAM has been allocated for the data - if (packetUBXNAVATT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVATT == NULL) + initPacketUBXNAVATT(); // Check that RAM has been allocated for the data + if (packetUBXNAVATT == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -8798,7 +8910,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVATTrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVATTcallback(void (*callbackPointer)(UBX_NAV_ATT_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -8806,9 +8918,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVATTcallback(void (*callbackPointer)(UBX_NAV_ATT_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVATT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVATT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVATT->callbackData = new UBX_NAV_ATT_data_t; //Allocate RAM for the main struct + packetUBXNAVATT->callbackData = new UBX_NAV_ATT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVATT->callbackData == NULL) @@ -8831,9 +8943,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVATTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVATT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVATT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVATT->callbackData = new UBX_NAV_ATT_data_t; //Allocate RAM for the main struct + packetUBXNAVATT->callbackData = new UBX_NAV_ATT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVATT->callbackData == NULL) @@ -8849,12 +8961,13 @@ bool SFE_UBLOX_GNSS::setAutoNAVATTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV return (true); } -//In case no config access to the GNSS is possible and NAV ATT attitude is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and NAV ATT attitude is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVATT(bool enabled, bool implicitUpdate) { - if (packetUBXNAVATT == NULL) initPacketUBXNAVATT(); //Check that RAM has been allocated for the ESF RAW data - if (packetUBXNAVATT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVATT == NULL) + initPacketUBXNAVATT(); // Check that RAM has been allocated for the ESF RAW data + if (packetUBXNAVATT == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVATT->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVATT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -8869,7 +8982,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVATT(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVATT and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVATT() { - packetUBXNAVATT = new UBX_NAV_ATT_t; //Allocate RAM for the main struct + packetUBXNAVATT = new UBX_NAV_ATT_t; // Allocate RAM for the main struct if (packetUBXNAVATT == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -8886,46 +8999,49 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVATT() return (true); } -//Mark all the ATT data as read/stale. This is handy to get data alignment after CRC failure +// Mark all the ATT data as read/stale. This is handy to get data alignment after CRC failure void SFE_UBLOX_GNSS::flushNAVATT() { - if (packetUBXNAVATT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVATT->moduleQueried.moduleQueried.all = 0; //Mark all ATT data as stale (read before) + if (packetUBXNAVATT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVATT->moduleQueried.moduleQueried.all = 0; // Mark all ATT data as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVATT(bool enabled) { - if (packetUBXNAVATT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVATT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVATT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } // ***** PVT automatic support -//Get the latest Position/Velocity/Time solution and fill all global variables +// Get the latest Position/Velocity/Time solution and fill all global variables bool SFE_UBLOX_GNSS::getPVT(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVT->automaticFlags.flags.bits.automatic && packetUBXNAVPVT->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getPVT: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getPVT: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_PVT); return packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all; } else if (packetUBXNAVPVT->automaticFlags.flags.bits.automatic && !packetUBXNAVPVT->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getPVT: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getPVT: Exit immediately")); + // } return (false); } else @@ -8935,14 +9051,14 @@ bool SFE_UBLOX_GNSS::getPVT(uint16_t maxWait) // _debugSerial->println(F("getPVT: Polling")); // } - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // 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 = 0; - //packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+packetCfgPayloadSize = 84 bytes Note:now hard-coded in processUBX + // packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+packetCfgPayloadSize = 84 bytes Note:now hard-coded in processUBX - //The data is parsed as part of processing the response + // 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) @@ -8966,29 +9082,31 @@ bool SFE_UBLOX_GNSS::getPVT(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT +// works. bool SFE_UBLOX_GNSS::setAutoPVT(bool enable, uint16_t maxWait) { return setAutoPVTrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT +// works. bool SFE_UBLOX_GNSS::setAutoPVT(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoPVTrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT +// works. bool SFE_UBLOX_GNSS::setAutoPVTrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -9008,7 +9126,7 @@ bool SFE_UBLOX_GNSS::setAutoPVTrate(uint8_t rate, bool implicitUpdate, uint16_t return ok; } -//Enable automatic navigation message generation by the GNSS. This changes the way getPVT works. +// Enable automatic navigation message generation by the GNSS. This changes the way getPVT works. bool SFE_UBLOX_GNSS::setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -9016,9 +9134,9 @@ bool SFE_UBLOX_GNSS::setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data if (!result) return (result); // Bail if setAutoPVT failed - if (packetUBXNAVPVT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVPVT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVPVT->callbackData = new UBX_NAV_PVT_data_t; //Allocate RAM for the main struct + packetUBXNAVPVT->callbackData = new UBX_NAV_PVT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVPVT->callbackData == NULL) @@ -9042,9 +9160,9 @@ bool SFE_UBLOX_GNSS::setAutoPVTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PV if (!result) return (result); // Bail if setAutoPVT failed - if (packetUBXNAVPVT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVPVT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVPVT->callbackData = new UBX_NAV_PVT_data_t; //Allocate RAM for the main struct + packetUBXNAVPVT->callbackData = new UBX_NAV_PVT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVPVT->callbackData == NULL) @@ -9061,19 +9179,20 @@ bool SFE_UBLOX_GNSS::setAutoPVTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PV return (true); } -//In case no config access to the GNSS is possible and PVT is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and PVT is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoPVT(bool enabled, bool implicitUpdate) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVPVT->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVPVT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; if (changes) { - packetUBXNAVPVT->automaticFlags.flags.bits.automatic = enabled; - packetUBXNAVPVT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + packetUBXNAVPVT->automaticFlags.flags.bits.automatic = enabled; + packetUBXNAVPVT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; } return changes; } @@ -9081,7 +9200,7 @@ bool SFE_UBLOX_GNSS::assumeAutoPVT(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVPVT and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVPVT() { - packetUBXNAVPVT = new UBX_NAV_PVT_t; //Allocate RAM for the main struct + packetUBXNAVPVT = new UBX_NAV_PVT_t; // Allocate RAM for the main struct if (packetUBXNAVPVT == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -9099,18 +9218,20 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPVT() return (true); } -//Mark all the PVT data as read/stale. This is handy to get data alignment after CRC failure +// Mark all the PVT data as read/stale. This is handy to get data alignment after CRC failure void SFE_UBLOX_GNSS::flushPVT() { - if (packetUBXNAVPVT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVPVT->moduleQueried.moduleQueried1.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVPVT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVPVT->moduleQueried.moduleQueried1.all = 0; // Mark all datums as stale (read before) packetUBXNAVPVT->moduleQueried.moduleQueried2.all = 0; } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVPVT(bool enabled) { - if (packetUBXNAVPVT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVPVT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVPVT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -9118,30 +9239,31 @@ void SFE_UBLOX_GNSS::logNAVPVT(bool enabled) bool SFE_UBLOX_GNSS::getNAVODO(uint16_t maxWait) { - if (packetUBXNAVODO == NULL) initPacketUBXNAVODO(); //Check that RAM has been allocated for the ODO data - if (packetUBXNAVODO == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVODO == NULL) + initPacketUBXNAVODO(); // Check that RAM has been allocated for the ODO data + if (packetUBXNAVODO == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVODO->automaticFlags.flags.bits.automatic && packetUBXNAVODO->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_ODO); return packetUBXNAVODO->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVODO->automaticFlags.flags.bits.automatic && !packetUBXNAVODO->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_ODO; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -9156,29 +9278,31 @@ bool SFE_UBLOX_GNSS::getNAVODO(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getODO -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getODO +// works. bool SFE_UBLOX_GNSS::setAutoNAVODO(bool enable, uint16_t maxWait) { return setAutoNAVODOrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getODO -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getODO +// works. bool SFE_UBLOX_GNSS::setAutoNAVODO(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVODOrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getODO -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getODO +// works. bool SFE_UBLOX_GNSS::setAutoNAVODOrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVODO == NULL) initPacketUBXNAVODO(); //Check that RAM has been allocated for the data - if (packetUBXNAVODO == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVODO == NULL) + initPacketUBXNAVODO(); // Check that RAM has been allocated for the data + if (packetUBXNAVODO == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -9198,7 +9322,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVODOrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -9206,9 +9330,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVODO->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVODO->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVODO->callbackData = new UBX_NAV_ODO_data_t; //Allocate RAM for the main struct + packetUBXNAVODO->callbackData = new UBX_NAV_ODO_data_t; // Allocate RAM for the main struct } if (packetUBXNAVODO->callbackData == NULL) @@ -9231,9 +9355,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVODOcallbackPtr(void (*callbackPointerPtr)(UBX_NAV if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVODO->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVODO->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVODO->callbackData = new UBX_NAV_ODO_data_t; //Allocate RAM for the main struct + packetUBXNAVODO->callbackData = new UBX_NAV_ODO_data_t; // Allocate RAM for the main struct } if (packetUBXNAVODO->callbackData == NULL) @@ -9249,12 +9373,13 @@ bool SFE_UBLOX_GNSS::setAutoNAVODOcallbackPtr(void (*callbackPointerPtr)(UBX_NAV return (true); } -//In case no config access to the GNSS is possible and ODO is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and ODO is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVODO(bool enabled, bool implicitUpdate) { - if (packetUBXNAVODO == NULL) initPacketUBXNAVODO(); //Check that RAM has been allocated for the data - if (packetUBXNAVODO == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVODO == NULL) + initPacketUBXNAVODO(); // Check that RAM has been allocated for the data + if (packetUBXNAVODO == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVODO->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVODO->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -9269,7 +9394,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVODO(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVODO and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVODO() { - packetUBXNAVODO = new UBX_NAV_ODO_t; //Allocate RAM for the main struct + packetUBXNAVODO = new UBX_NAV_ODO_t; // Allocate RAM for the main struct if (packetUBXNAVODO == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -9286,17 +9411,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVODO() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushNAVODO() { - if (packetUBXNAVODO == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVODO->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVODO == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVODO->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVODO(bool enabled) { - if (packetUBXNAVODO == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVODO == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVODO->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -9304,30 +9431,31 @@ void SFE_UBLOX_GNSS::logNAVODO(bool enabled) bool SFE_UBLOX_GNSS::getNAVVELECEF(uint16_t maxWait) { - if (packetUBXNAVVELECEF == NULL) initPacketUBXNAVVELECEF(); //Check that RAM has been allocated for the VELECEF data - if (packetUBXNAVVELECEF == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVVELECEF == NULL) + initPacketUBXNAVVELECEF(); // Check that RAM has been allocated for the VELECEF data + if (packetUBXNAVVELECEF == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVVELECEF->automaticFlags.flags.bits.automatic && packetUBXNAVVELECEF->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_VELECEF); return packetUBXNAVVELECEF->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVVELECEF->automaticFlags.flags.bits.automatic && !packetUBXNAVVELECEF->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_VELECEF; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -9342,29 +9470,31 @@ bool SFE_UBLOX_GNSS::getNAVVELECEF(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVVELECEF(bool enable, uint16_t maxWait) { return setAutoNAVVELECEFrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVVELECEF(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVVELECEFrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVVELECEFrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVVELECEF == NULL) initPacketUBXNAVVELECEF(); //Check that RAM has been allocated for the data - if (packetUBXNAVVELECEF == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVVELECEF == NULL) + initPacketUBXNAVVELECEF(); // Check that RAM has been allocated for the data + if (packetUBXNAVVELECEF == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -9384,7 +9514,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELECEFrate(uint8_t rate, bool implicitUpdate, ui return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVVELECEFcallback(void (*callbackPointer)(UBX_NAV_VELECEF_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -9392,9 +9522,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELECEFcallback(void (*callbackPointer)(UBX_NAV_V if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVVELECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVVELECEF->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVVELECEF->callbackData = new UBX_NAV_VELECEF_data_t; //Allocate RAM for the main struct + packetUBXNAVVELECEF->callbackData = new UBX_NAV_VELECEF_data_t; // Allocate RAM for the main struct } if (packetUBXNAVVELECEF->callbackData == NULL) @@ -9417,9 +9547,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELECEFcallbackPtr(void (*callbackPointerPtr)(UBX if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVVELECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVVELECEF->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVVELECEF->callbackData = new UBX_NAV_VELECEF_data_t; //Allocate RAM for the main struct + packetUBXNAVVELECEF->callbackData = new UBX_NAV_VELECEF_data_t; // Allocate RAM for the main struct } if (packetUBXNAVVELECEF->callbackData == NULL) @@ -9435,12 +9565,13 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELECEFcallbackPtr(void (*callbackPointerPtr)(UBX return (true); } -//In case no config access to the GNSS is possible and VELECEF is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and VELECEF is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVVELECEF(bool enabled, bool implicitUpdate) { - if (packetUBXNAVVELECEF == NULL) initPacketUBXNAVVELECEF(); //Check that RAM has been allocated for the data - if (packetUBXNAVVELECEF == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVVELECEF == NULL) + initPacketUBXNAVVELECEF(); // Check that RAM has been allocated for the data + if (packetUBXNAVVELECEF == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVVELECEF->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVVELECEF->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -9455,7 +9586,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVVELECEF(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVVELECEF and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVVELECEF() { - packetUBXNAVVELECEF = new UBX_NAV_VELECEF_t; //Allocate RAM for the main struct + packetUBXNAVVELECEF = new UBX_NAV_VELECEF_t; // Allocate RAM for the main struct if (packetUBXNAVVELECEF == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -9472,17 +9603,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVVELECEF() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushNAVVELECEF() { - if (packetUBXNAVVELECEF == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVVELECEF->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVVELECEF == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVVELECEF->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVVELECEF(bool enabled) { - if (packetUBXNAVVELECEF == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVVELECEF == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVVELECEF->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -9490,30 +9623,31 @@ void SFE_UBLOX_GNSS::logNAVVELECEF(bool enabled) bool SFE_UBLOX_GNSS::getNAVVELNED(uint16_t maxWait) { - if (packetUBXNAVVELNED == NULL) initPacketUBXNAVVELNED(); //Check that RAM has been allocated for the VELNED data - if (packetUBXNAVVELNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVVELNED == NULL) + initPacketUBXNAVVELNED(); // Check that RAM has been allocated for the VELNED data + if (packetUBXNAVVELNED == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVVELNED->automaticFlags.flags.bits.automatic && packetUBXNAVVELNED->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_VELNED); return packetUBXNAVVELNED->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVVELNED->automaticFlags.flags.bits.automatic && !packetUBXNAVVELNED->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_VELNED; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -9528,26 +9662,27 @@ bool SFE_UBLOX_GNSS::getNAVVELNED(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED +// works. bool SFE_UBLOX_GNSS::setAutoNAVVELNED(bool enable, uint16_t maxWait) { return setAutoNAVVELNEDrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED +// works. bool SFE_UBLOX_GNSS::setAutoNAVVELNED(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVVELNEDrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED +// works. bool SFE_UBLOX_GNSS::setAutoNAVVELNEDrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVVELNED == NULL) initPacketUBXNAVVELNED(); //Check that RAM has been allocated for the data - if (packetUBXNAVVELNED == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVVELNED == NULL) + initPacketUBXNAVVELNED(); // Check that RAM has been allocated for the data + if (packetUBXNAVVELNED == NULL) // Only attempt this if RAM allocation was successful return false; packetCfg.cls = UBX_CLASS_CFG; @@ -9568,7 +9703,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELNEDrate(uint8_t rate, bool implicitUpdate, uin return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VELNED_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -9576,9 +9711,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VE if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVVELNED->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVVELNED->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVVELNED->callbackData = new UBX_NAV_VELNED_data_t; //Allocate RAM for the main struct + packetUBXNAVVELNED->callbackData = new UBX_NAV_VELNED_data_t; // Allocate RAM for the main struct } if (packetUBXNAVVELNED->callbackData == NULL) @@ -9601,9 +9736,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELNEDcallbackPtr(void (*callbackPointerPtr)(UBX_ if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVVELNED->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVVELNED->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVVELNED->callbackData = new UBX_NAV_VELNED_data_t; //Allocate RAM for the main struct + packetUBXNAVVELNED->callbackData = new UBX_NAV_VELNED_data_t; // Allocate RAM for the main struct } if (packetUBXNAVVELNED->callbackData == NULL) @@ -9619,12 +9754,13 @@ bool SFE_UBLOX_GNSS::setAutoNAVVELNEDcallbackPtr(void (*callbackPointerPtr)(UBX_ return (true); } -//In case no config access to the GNSS is possible and VELNED is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and VELNED is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVVELNED(bool enabled, bool implicitUpdate) { - if (packetUBXNAVVELNED == NULL) initPacketUBXNAVVELNED(); //Check that RAM has been allocated for the data - if (packetUBXNAVVELNED == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVVELNED == NULL) + initPacketUBXNAVVELNED(); // Check that RAM has been allocated for the data + if (packetUBXNAVVELNED == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVVELNED->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVVELNED->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -9639,7 +9775,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVVELNED(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVVELNED and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVVELNED() { - packetUBXNAVVELNED = new UBX_NAV_VELNED_t; //Allocate RAM for the main struct + packetUBXNAVVELNED = new UBX_NAV_VELNED_t; // Allocate RAM for the main struct if (packetUBXNAVVELNED == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -9656,17 +9792,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVVELNED() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushNAVVELNED() { - if (packetUBXNAVVELNED == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere! - packetUBXNAVVELNED->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVVELNED == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere! + packetUBXNAVVELNED->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVVELNED(bool enabled) { - if (packetUBXNAVVELNED == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVVELNED == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVVELNED->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -9674,30 +9812,31 @@ void SFE_UBLOX_GNSS::logNAVVELNED(bool enabled) bool SFE_UBLOX_GNSS::getNAVHPPOSECEF(uint16_t maxWait) { - if (packetUBXNAVHPPOSECEF == NULL) initPacketUBXNAVHPPOSECEF(); //Check that RAM has been allocated for the HPPOSECEF data - if (packetUBXNAVHPPOSECEF == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSECEF == NULL) + initPacketUBXNAVHPPOSECEF(); // Check that RAM has been allocated for the HPPOSECEF data + if (packetUBXNAVHPPOSECEF == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.automatic && packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_HPPOSECEF); return packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.automatic && !packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_HPPOSECEF; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -9712,29 +9851,31 @@ bool SFE_UBLOX_GNSS::getNAVHPPOSECEF(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEF(bool enable, uint16_t maxWait) { return setAutoNAVHPPOSECEFrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEF(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVHPPOSECEFrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSECEF -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSECEF +// works. bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVHPPOSECEF == NULL) initPacketUBXNAVHPPOSECEF(); //Check that RAM has been allocated for the data - if (packetUBXNAVHPPOSECEF == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVHPPOSECEF == NULL) + initPacketUBXNAVHPPOSECEF(); // Check that RAM has been allocated for the data + if (packetUBXNAVHPPOSECEF == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -9754,7 +9895,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFrate(uint8_t rate, bool implicitUpdate, return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFcallback(void (*callbackPointer)(UBX_NAV_HPPOSECEF_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -9762,9 +9903,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFcallback(void (*callbackPointer)(UBX_NAV if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVHPPOSECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVHPPOSECEF->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVHPPOSECEF->callbackData = new UBX_NAV_HPPOSECEF_data_t; //Allocate RAM for the main struct + packetUBXNAVHPPOSECEF->callbackData = new UBX_NAV_HPPOSECEF_data_t; // Allocate RAM for the main struct } if (packetUBXNAVHPPOSECEF->callbackData == NULL) @@ -9787,9 +9928,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFcallbackPtr(void (*callbackPointerPtr)(U if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVHPPOSECEF->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVHPPOSECEF->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVHPPOSECEF->callbackData = new UBX_NAV_HPPOSECEF_data_t; //Allocate RAM for the main struct + packetUBXNAVHPPOSECEF->callbackData = new UBX_NAV_HPPOSECEF_data_t; // Allocate RAM for the main struct } if (packetUBXNAVHPPOSECEF->callbackData == NULL) @@ -9805,12 +9946,13 @@ bool SFE_UBLOX_GNSS::setAutoNAVHPPOSECEFcallbackPtr(void (*callbackPointerPtr)(U return (true); } -//In case no config access to the GNSS is possible and HPPOSECEF is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and HPPOSECEF is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate) { - if (packetUBXNAVHPPOSECEF == NULL) initPacketUBXNAVHPPOSECEF(); //Check that RAM has been allocated for the data - if (packetUBXNAVHPPOSECEF == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVHPPOSECEF == NULL) + initPacketUBXNAVHPPOSECEF(); // Check that RAM has been allocated for the data + if (packetUBXNAVHPPOSECEF == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -9825,7 +9967,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVHPPOSECEF and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSECEF() { - packetUBXNAVHPPOSECEF = new UBX_NAV_HPPOSECEF_t; //Allocate RAM for the main struct + packetUBXNAVHPPOSECEF = new UBX_NAV_HPPOSECEF_t; // Allocate RAM for the main struct if (packetUBXNAVHPPOSECEF == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -9842,17 +9984,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSECEF() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushNAVHPPOSECEF() { - if (packetUBXNAVHPPOSECEF == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVHPPOSECEF == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVHPPOSECEF(bool enabled) { - if (packetUBXNAVHPPOSECEF == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVHPPOSECEF == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVHPPOSECEF->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -9860,27 +10004,28 @@ void SFE_UBLOX_GNSS::logNAVHPPOSECEF(bool enabled) bool SFE_UBLOX_GNSS::getHPPOSLLH(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.automatic && packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHPPOSLLH: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHPPOSLLH: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_HPPOSLLH); return packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.automatic && !packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHPPOSLLH: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHPPOSLLH: Exit immediately")); + // } return (false); } else @@ -9890,13 +10035,13 @@ bool SFE_UBLOX_GNSS::getHPPOSLLH(uint16_t maxWait) // _debugSerial->println(F("getHPPOSLLH: Polling")); // } - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_HPPOSLLH; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -9920,29 +10065,31 @@ bool SFE_UBLOX_GNSS::getHPPOSLLH(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSLLH -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSLLH +// works. bool SFE_UBLOX_GNSS::setAutoHPPOSLLH(bool enable, uint16_t maxWait) { return setAutoHPPOSLLHrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSLLH -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSLLH +// works. bool SFE_UBLOX_GNSS::setAutoHPPOSLLH(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoHPPOSLLHrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSLLH -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getHPPOSLLH +// works. bool SFE_UBLOX_GNSS::setAutoHPPOSLLHrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the data - if (packetUBXNAVHPPOSLLH == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the data + if (packetUBXNAVHPPOSLLH == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -9962,7 +10109,7 @@ bool SFE_UBLOX_GNSS::setAutoHPPOSLLHrate(uint8_t rate, bool implicitUpdate, uint return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoHPPOSLLHcallback(void (*callbackPointer)(UBX_NAV_HPPOSLLH_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -9970,9 +10117,9 @@ bool SFE_UBLOX_GNSS::setAutoHPPOSLLHcallback(void (*callbackPointer)(UBX_NAV_HPP if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVHPPOSLLH->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVHPPOSLLH->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVHPPOSLLH->callbackData = new UBX_NAV_HPPOSLLH_data_t; //Allocate RAM for the main struct + packetUBXNAVHPPOSLLH->callbackData = new UBX_NAV_HPPOSLLH_data_t; // Allocate RAM for the main struct } if (packetUBXNAVHPPOSLLH->callbackData == NULL) @@ -9995,9 +10142,9 @@ bool SFE_UBLOX_GNSS::setAutoHPPOSLLHcallbackPtr(void (*callbackPointerPtr)(UBX_N if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVHPPOSLLH->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVHPPOSLLH->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVHPPOSLLH->callbackData = new UBX_NAV_HPPOSLLH_data_t; //Allocate RAM for the main struct + packetUBXNAVHPPOSLLH->callbackData = new UBX_NAV_HPPOSLLH_data_t; // Allocate RAM for the main struct } if (packetUBXNAVHPPOSLLH->callbackData == NULL) @@ -10013,12 +10160,13 @@ bool SFE_UBLOX_GNSS::setAutoHPPOSLLHcallbackPtr(void (*callbackPointerPtr)(UBX_N return (true); } -//In case no config access to the GNSS is possible and HPPOSLLH is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and HPPOSLLH is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHPPOSLLH(bool enabled, bool implicitUpdate) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the data - if (packetUBXNAVHPPOSLLH == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the data + if (packetUBXNAVHPPOSLLH == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -10033,7 +10181,7 @@ bool SFE_UBLOX_GNSS::assumeAutoHPPOSLLH(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVHPPOSLLH and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSLLH() { - packetUBXNAVHPPOSLLH = new UBX_NAV_HPPOSLLH_t; //Allocate RAM for the main struct + packetUBXNAVHPPOSLLH = new UBX_NAV_HPPOSLLH_t; // Allocate RAM for the main struct if (packetUBXNAVHPPOSLLH == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -10050,27 +10198,30 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVHPPOSLLH() return (true); } -//Mark all the HPPOSLLH data as read/stale. This is handy to get data alignment after CRC failure +// Mark all the HPPOSLLH data as read/stale. This is handy to get data alignment after CRC failure void SFE_UBLOX_GNSS::flushHPPOSLLH() { - if (packetUBXNAVHPPOSLLH == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere! - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVHPPOSLLH == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere! + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVHPPOSLLH(bool enabled) { - if (packetUBXNAVHPPOSLLH == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVHPPOSLLH == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVHPPOSLLH->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } // ***** PVAT automatic support -//Get the latest Position/Velocity/Time solution and fill all global variables +// Get the latest Position/Velocity/Time solution and fill all global variables bool SFE_UBLOX_GNSS::getNAVPVAT(uint16_t maxWait) { - if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data - if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVAT == NULL) + initPacketUBXNAVPVAT(); // Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVAT->automaticFlags.flags.bits.automatic && packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate) @@ -10080,18 +10231,18 @@ bool SFE_UBLOX_GNSS::getNAVPVAT(uint16_t maxWait) } else if (packetUBXNAVPVAT->automaticFlags.flags.bits.automatic && !packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_PVAT; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -10106,29 +10257,31 @@ bool SFE_UBLOX_GNSS::getNAVPVAT(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT +// works. bool SFE_UBLOX_GNSS::setAutoNAVPVAT(bool enable, uint16_t maxWait) { return setAutoNAVPVATrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT +// works. bool SFE_UBLOX_GNSS::setAutoNAVPVAT(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVPVATrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVAT +// works. bool SFE_UBLOX_GNSS::setAutoNAVPVATrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data - if (packetUBXNAVPVAT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVPVAT == NULL) + initPacketUBXNAVPVAT(); // Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -10148,7 +10301,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVPVATrate(uint8_t rate, bool implicitUpdate, uint1 return ok; } -//Enable automatic navigation message generation by the GNSS. This changes the way getPVAT works. +// Enable automatic navigation message generation by the GNSS. This changes the way getPVAT works. bool SFE_UBLOX_GNSS::setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -10156,9 +10309,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT if (!result) return (result); // Bail if setAutoPVAT failed - if (packetUBXNAVPVAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVPVAT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVPVAT->callbackData = new UBX_NAV_PVAT_data_t; //Allocate RAM for the main struct + packetUBXNAVPVAT->callbackData = new UBX_NAV_PVAT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVPVAT->callbackData == NULL) @@ -10182,9 +10335,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVPVATcallbackPtr(void (*callbackPointerPtr)(UBX_NA if (!result) return (result); // Bail if setAutoPVAT failed - if (packetUBXNAVPVAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVPVAT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVPVAT->callbackData = new UBX_NAV_PVAT_data_t; //Allocate RAM for the main struct + packetUBXNAVPVAT->callbackData = new UBX_NAV_PVAT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVPVAT->callbackData == NULL) @@ -10201,19 +10354,20 @@ bool SFE_UBLOX_GNSS::setAutoNAVPVATcallbackPtr(void (*callbackPointerPtr)(UBX_NA return (true); } -//In case no config access to the GNSS is possible and PVAT is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and PVAT is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVPVAT(bool enabled, bool implicitUpdate) { - if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data - if (packetUBXNAVPVAT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVPVAT == NULL) + initPacketUBXNAVPVAT(); // Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVPVAT->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; if (changes) { - packetUBXNAVPVAT->automaticFlags.flags.bits.automatic = enabled; - packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + packetUBXNAVPVAT->automaticFlags.flags.bits.automatic = enabled; + packetUBXNAVPVAT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; } return changes; } @@ -10221,7 +10375,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVPVAT(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVPVAT and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVPVAT() { - packetUBXNAVPVAT = new UBX_NAV_PVAT_t; //Allocate RAM for the main struct + packetUBXNAVPVAT = new UBX_NAV_PVAT_t; // Allocate RAM for the main struct if (packetUBXNAVPVAT == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -10239,18 +10393,20 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVPVAT() return (true); } -//Mark all the PVAT data as read/stale. This is handy to get data alignment after CRC failure +// Mark all the PVAT data as read/stale. This is handy to get data alignment after CRC failure void SFE_UBLOX_GNSS::flushNAVPVAT() { - if (packetUBXNAVPVAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVPVAT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVPVAT->moduleQueried.moduleQueried1.all = 0; // Mark all datums as stale (read before) packetUBXNAVPVAT->moduleQueried.moduleQueried2.all = 0; } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVPVAT(bool enabled) { - if (packetUBXNAVPVAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVPVAT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVPVAT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -10258,30 +10414,31 @@ void SFE_UBLOX_GNSS::logNAVPVAT(bool enabled) bool SFE_UBLOX_GNSS::getNAVCLOCK(uint16_t maxWait) { - if (packetUBXNAVCLOCK == NULL) initPacketUBXNAVCLOCK(); //Check that RAM has been allocated for the CLOCK data - if (packetUBXNAVCLOCK == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVCLOCK == NULL) + initPacketUBXNAVCLOCK(); // Check that RAM has been allocated for the CLOCK data + if (packetUBXNAVCLOCK == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVCLOCK->automaticFlags.flags.bits.automatic && packetUBXNAVCLOCK->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_CLOCK); return packetUBXNAVCLOCK->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVCLOCK->automaticFlags.flags.bits.automatic && !packetUBXNAVCLOCK->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting CLOCK so we have to poll explicitly + // The GPS is not automatically reporting CLOCK so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_CLOCK; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -10296,29 +10453,31 @@ bool SFE_UBLOX_GNSS::getNAVCLOCK(uint16_t maxWait) } } -//Enable or disable automatic CLOCK message generation by the GNSS. This changes the way getNAVCLOCK -//works. +// Enable or disable automatic CLOCK message generation by the GNSS. This changes the way getNAVCLOCK +// works. bool SFE_UBLOX_GNSS::setAutoNAVCLOCK(bool enable, uint16_t maxWait) { return setAutoNAVCLOCKrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic CLOCK message generation by the GNSS. This changes the way getNAVCLOCK -//works. +// Enable or disable automatic CLOCK message generation by the GNSS. This changes the way getNAVCLOCK +// works. bool SFE_UBLOX_GNSS::setAutoNAVCLOCK(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVCLOCKrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic CLOCK attitude message generation by the GNSS. This changes the way getNAVCLOCK -//works. +// Enable or disable automatic CLOCK attitude message generation by the GNSS. This changes the way getNAVCLOCK +// works. bool SFE_UBLOX_GNSS::setAutoNAVCLOCKrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVCLOCK == NULL) initPacketUBXNAVCLOCK(); //Check that RAM has been allocated for the data - if (packetUBXNAVCLOCK == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVCLOCK == NULL) + initPacketUBXNAVCLOCK(); // Check that RAM has been allocated for the data + if (packetUBXNAVCLOCK == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -10338,7 +10497,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVCLOCKrate(uint8_t rate, bool implicitUpdate, uint return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVCLOCKcallback(void (*callbackPointer)(UBX_NAV_CLOCK_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -10346,9 +10505,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVCLOCKcallback(void (*callbackPointer)(UBX_NAV_CLO if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVCLOCK->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVCLOCK->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVCLOCK->callbackData = new UBX_NAV_CLOCK_data_t; //Allocate RAM for the main struct + packetUBXNAVCLOCK->callbackData = new UBX_NAV_CLOCK_data_t; // Allocate RAM for the main struct } if (packetUBXNAVCLOCK->callbackData == NULL) @@ -10371,9 +10530,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVCLOCKcallbackPtr(void (*callbackPointerPtr)(UBX_N if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVCLOCK->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVCLOCK->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVCLOCK->callbackData = new UBX_NAV_CLOCK_data_t; //Allocate RAM for the main struct + packetUBXNAVCLOCK->callbackData = new UBX_NAV_CLOCK_data_t; // Allocate RAM for the main struct } if (packetUBXNAVCLOCK->callbackData == NULL) @@ -10389,12 +10548,13 @@ 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 -//set config to suitable parameters +// In case no config access to the GNSS is possible and HNR attitude is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate) { - if (packetUBXNAVCLOCK == NULL) initPacketUBXNAVCLOCK(); //Check that RAM has been allocated for the CLOCK data - if (packetUBXNAVCLOCK == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVCLOCK == NULL) + initPacketUBXNAVCLOCK(); // Check that RAM has been allocated for the CLOCK data + if (packetUBXNAVCLOCK == NULL) // Bail if the RAM allocation failed return (false); bool changes = packetUBXNAVCLOCK->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVCLOCK->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -10409,7 +10569,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVCLOCK and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVCLOCK() { - packetUBXNAVCLOCK = new UBX_NAV_CLOCK_t ; //Allocate RAM for the main struct + packetUBXNAVCLOCK = new UBX_NAV_CLOCK_t; // Allocate RAM for the main struct if (packetUBXNAVCLOCK == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -10426,28 +10586,31 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVCLOCK() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushNAVCLOCK() { - if (packetUBXNAVCLOCK == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVCLOCK->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVCLOCK == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVCLOCK->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVCLOCK(bool enabled) { - if (packetUBXNAVCLOCK == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVCLOCK == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVCLOCK->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } // ***** NAV TIMELS automatic support -//Reads leap second event information and sets the global variables -//for future leap second change and number of leap seconds since GPS epoch -//Returns true if commands was successful +// Reads leap second event information and sets the global variables +// for future leap second change and number of leap seconds since GPS epoch +// Returns true if commands was successful bool SFE_UBLOX_GNSS::getLeapSecondEvent(uint16_t maxWait) { - if (packetUBXNAVTIMELS == NULL) initPacketUBXNAVTIMELS(); //Check that RAM has been allocated for the TIMELS data + if (packetUBXNAVTIMELS == NULL) + initPacketUBXNAVTIMELS(); // Check that RAM has been allocated for the TIMELS data if (packetUBXNAVTIMELS == NULL) // Abort if the RAM allocation failed return (false); @@ -10456,7 +10619,7 @@ bool SFE_UBLOX_GNSS::getLeapSecondEvent(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -10473,7 +10636,7 @@ bool SFE_UBLOX_GNSS::getLeapSecondEvent(uint16_t maxWait) // PRIVATE: Allocate RAM for packetUBXNAVTIMELS and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVTIMELS() { - packetUBXNAVTIMELS = new UBX_NAV_TIMELS_t; //Allocate RAM for the main struct + packetUBXNAVTIMELS = new UBX_NAV_TIMELS_t; // Allocate RAM for the main struct if (packetUBXNAVTIMELS == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -10492,12 +10655,13 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVTIMELS() // ***** NAV SVIN automatic support -//Reads survey in status and sets the global variables -//for status, position valid, observation time, and mean 3D StdDev -//Returns true if commands was successful +// Reads survey in status and sets the global variables +// for status, position valid, observation time, and mean 3D StdDev +// Returns true if commands was successful bool SFE_UBLOX_GNSS::getSurveyStatus(uint16_t maxWait) { - if (packetUBXNAVSVIN == NULL) initPacketUBXNAVSVIN(); //Check that RAM has been allocated for the SVIN data + if (packetUBXNAVSVIN == NULL) + initPacketUBXNAVSVIN(); // Check that RAM has been allocated for the SVIN data if (packetUBXNAVSVIN == NULL) // Abort if the RAM allocation failed return (false); @@ -10506,7 +10670,7 @@ bool SFE_UBLOX_GNSS::getSurveyStatus(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -10523,7 +10687,7 @@ bool SFE_UBLOX_GNSS::getSurveyStatus(uint16_t maxWait) // PRIVATE: Allocate RAM for packetUBXNAVSVIN and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVSVIN() { - packetUBXNAVSVIN = new UBX_NAV_SVIN_t; //Allocate RAM for the main struct + packetUBXNAVSVIN = new UBX_NAV_SVIN_t; // Allocate RAM for the main struct if (packetUBXNAVSVIN == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -10542,34 +10706,35 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSVIN() // ***** NAV SAT automatic support -//Signal information -//Returns true if commands was successful +// Signal information +// Returns true if commands was successful bool SFE_UBLOX_GNSS::getNAVSAT(uint16_t maxWait) { - if (packetUBXNAVSAT == NULL) initPacketUBXNAVSAT(); //Check that RAM has been allocated for the NAVSAT data - if (packetUBXNAVSAT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVSAT == NULL) + initPacketUBXNAVSAT(); // Check that RAM has been allocated for the NAVSAT data + if (packetUBXNAVSAT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVSAT->automaticFlags.flags.bits.automatic && packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_SAT); return packetUBXNAVSAT->moduleQueried; } else if (packetUBXNAVSAT->automaticFlags.flags.bits.automatic && !packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting NAVSAT so we have to poll explicitly + // The GPS is not automatically reporting NAVSAT so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_SAT; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -10584,29 +10749,31 @@ bool SFE_UBLOX_GNSS::getNAVSAT(uint16_t maxWait) } } -//Enable or disable automatic NAVSAT message generation by the GNSS. This changes the way getNAVSAT -//works. +// Enable or disable automatic NAVSAT message generation by the GNSS. This changes the way getNAVSAT +// works. bool SFE_UBLOX_GNSS::setAutoNAVSAT(bool enable, uint16_t maxWait) { return setAutoNAVSATrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic NAVSAT message generation by the GNSS. This changes the way getNAVSAT -//works. +// Enable or disable automatic NAVSAT message generation by the GNSS. This changes the way getNAVSAT +// works. bool SFE_UBLOX_GNSS::setAutoNAVSAT(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoNAVSATrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getNAVSAT -//works. +// Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getNAVSAT +// works. bool SFE_UBLOX_GNSS::setAutoNAVSATrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVSAT == NULL) initPacketUBXNAVSAT(); //Check that RAM has been allocated for the data - if (packetUBXNAVSAT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVSAT == NULL) + initPacketUBXNAVSAT(); // Check that RAM has been allocated for the data + if (packetUBXNAVSAT == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -10626,7 +10793,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVSATrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -10634,9 +10801,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVSAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVSAT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVSAT->callbackData = new UBX_NAV_SAT_data_t; //Allocate RAM for the main struct + packetUBXNAVSAT->callbackData = new UBX_NAV_SAT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVSAT->callbackData == NULL) @@ -10659,9 +10826,9 @@ bool SFE_UBLOX_GNSS::setAutoNAVSATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVSAT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVSAT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVSAT->callbackData = new UBX_NAV_SAT_data_t; //Allocate RAM for the main struct + packetUBXNAVSAT->callbackData = new UBX_NAV_SAT_data_t; // Allocate RAM for the main struct } if (packetUBXNAVSAT->callbackData == NULL) @@ -10677,12 +10844,13 @@ 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 -//set config to suitable parameters +// In case no config access to the GNSS is possible and HNR attitude is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoNAVSAT(bool enabled, bool implicitUpdate) { - if (packetUBXNAVSAT == NULL) initPacketUBXNAVSAT(); //Check that RAM has been allocated for the NAVSAT data - if (packetUBXNAVSAT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVSAT == NULL) + initPacketUBXNAVSAT(); // Check that RAM has been allocated for the NAVSAT data + if (packetUBXNAVSAT == NULL) // Bail if the RAM allocation failed return (false); bool changes = packetUBXNAVSAT->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVSAT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -10697,7 +10865,7 @@ bool SFE_UBLOX_GNSS::assumeAutoNAVSAT(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVSAT and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVSAT() { - packetUBXNAVSAT = new UBX_NAV_SAT_t ; //Allocate RAM for the main struct + packetUBXNAVSAT = new UBX_NAV_SAT_t; // Allocate RAM for the main struct if (packetUBXNAVSAT == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -10714,53 +10882,56 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVSAT() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushNAVSAT() { - if (packetUBXNAVSAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVSAT->moduleQueried = false; //Mark all datums as stale (read before) + if (packetUBXNAVSAT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSAT->moduleQueried = false; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVSAT(bool enabled) { - if (packetUBXNAVSAT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVSAT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVSAT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } // ***** NAV RELPOSNED automatic support -//Relative Positioning Information in NED frame -//Returns true if commands was successful -//Note: -// RELPOSNED on the M8 is only 40 bytes long -// RELPOSNED on the F9 is 64 bytes long and contains much more information +// Relative Positioning Information in NED frame +// Returns true if commands was successful +// Note: +// RELPOSNED on the M8 is only 40 bytes long +// RELPOSNED on the F9 is 64 bytes long and contains much more information bool SFE_UBLOX_GNSS::getRELPOSNED(uint16_t maxWait) { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.automatic && packetUBXNAVRELPOSNED->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_RELPOSNED); return packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVRELPOSNED->automaticFlags.flags.bits.automatic && !packetUBXNAVRELPOSNED->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting RELPOSNED so we have to poll explicitly + // The GPS is not automatically reporting RELPOSNED so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_RELPOSNED; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -10775,29 +10946,31 @@ bool SFE_UBLOX_GNSS::getRELPOSNED(uint16_t maxWait) } } -//Enable or disable automatic RELPOSNED message generation by the GNSS. This changes the way getRELPOSNED -//works. +// Enable or disable automatic RELPOSNED message generation by the GNSS. This changes the way getRELPOSNED +// works. bool SFE_UBLOX_GNSS::setAutoRELPOSNED(bool enable, uint16_t maxWait) { return setAutoRELPOSNEDrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic RELPOSNED message generation by the GNSS. This changes the way getRELPOSNED -//works. +// Enable or disable automatic RELPOSNED message generation by the GNSS. This changes the way getRELPOSNED +// works. bool SFE_UBLOX_GNSS::setAutoRELPOSNED(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoRELPOSNEDrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getRELPOSNED -//works. +// Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getRELPOSNED +// works. bool SFE_UBLOX_GNSS::setAutoRELPOSNEDrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the data - if (packetUBXNAVRELPOSNED == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the data + if (packetUBXNAVRELPOSNED == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -10817,7 +10990,7 @@ bool SFE_UBLOX_GNSS::setAutoRELPOSNEDrate(uint8_t rate, bool implicitUpdate, uin return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoRELPOSNEDcallback(void (*callbackPointer)(UBX_NAV_RELPOSNED_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -10825,9 +10998,9 @@ bool SFE_UBLOX_GNSS::setAutoRELPOSNEDcallback(void (*callbackPointer)(UBX_NAV_RE if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVRELPOSNED->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVRELPOSNED->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVRELPOSNED->callbackData = new UBX_NAV_RELPOSNED_data_t; //Allocate RAM for the main struct + packetUBXNAVRELPOSNED->callbackData = new UBX_NAV_RELPOSNED_data_t; // Allocate RAM for the main struct } if (packetUBXNAVRELPOSNED->callbackData == NULL) @@ -10850,9 +11023,9 @@ bool SFE_UBLOX_GNSS::setAutoRELPOSNEDcallbackPtr(void (*callbackPointerPtr)(UBX_ if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVRELPOSNED->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVRELPOSNED->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVRELPOSNED->callbackData = new UBX_NAV_RELPOSNED_data_t; //Allocate RAM for the main struct + packetUBXNAVRELPOSNED->callbackData = new UBX_NAV_RELPOSNED_data_t; // Allocate RAM for the main struct } if (packetUBXNAVRELPOSNED->callbackData == NULL) @@ -10868,12 +11041,13 @@ 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 -//set config to suitable parameters +// In case no config access to the GNSS is possible and HNR attitude is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoRELPOSNED(bool enabled, bool implicitUpdate) { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return (false); bool changes = packetUBXNAVRELPOSNED->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVRELPOSNED->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -10888,7 +11062,7 @@ bool SFE_UBLOX_GNSS::assumeAutoRELPOSNED(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVRELPOSNED and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVRELPOSNED() { - packetUBXNAVRELPOSNED = new UBX_NAV_RELPOSNED_t ; //Allocate RAM for the main struct + packetUBXNAVRELPOSNED = new UBX_NAV_RELPOSNED_t; // Allocate RAM for the main struct if (packetUBXNAVRELPOSNED == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -10905,17 +11079,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVRELPOSNED() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushNAVRELPOSNED() { - if (packetUBXNAVRELPOSNED == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXNAVRELPOSNED == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logNAVRELPOSNED(bool enabled) { - if (packetUBXNAVRELPOSNED == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVRELPOSNED == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVRELPOSNED->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -10923,27 +11099,28 @@ void SFE_UBLOX_GNSS::logNAVRELPOSNED(bool enabled) bool SFE_UBLOX_GNSS::getAOPSTATUS(uint16_t maxWait) { - if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the AOPSTATUS data - if (packetUBXNAVAOPSTATUS == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVAOPSTATUS == NULL) + initPacketUBXNAVAOPSTATUS(); // Check that RAM has been allocated for the AOPSTATUS data + if (packetUBXNAVAOPSTATUS == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic && packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getAOPSTATUS: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getAOPSTATUS: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_AOPSTATUS); return packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.all; } else if (packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic && !packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getAOPSTATUS: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getAOPSTATUS: Exit immediately")); + // } return (false); } else @@ -10953,13 +11130,13 @@ bool SFE_UBLOX_GNSS::getAOPSTATUS(uint16_t maxWait) // _debugSerial->println(F("getAOPSTATUS: Polling")); // } - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_NAV; packetCfg.id = UBX_NAV_AOPSTATUS; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -10983,26 +11160,27 @@ bool SFE_UBLOX_GNSS::getAOPSTATUS(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS +// works. bool SFE_UBLOX_GNSS::setAutoAOPSTATUS(bool enable, uint16_t maxWait) { return setAutoAOPSTATUSrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS +// works. bool SFE_UBLOX_GNSS::setAutoAOPSTATUS(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoAOPSTATUSrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getAOPSTATUS +// works. bool SFE_UBLOX_GNSS::setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the data - if (packetUBXNAVAOPSTATUS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVAOPSTATUS == NULL) + initPacketUBXNAVAOPSTATUS(); // Check that RAM has been allocated for the data + if (packetUBXNAVAOPSTATUS == NULL) // Only attempt this if RAM allocation was successful return false; packetCfg.cls = UBX_CLASS_CFG; @@ -11023,7 +11201,7 @@ bool SFE_UBLOX_GNSS::setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate, uin return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -11031,9 +11209,9 @@ bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AO if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVAOPSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVAOPSTATUS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVAOPSTATUS->callbackData = new UBX_NAV_AOPSTATUS_data_t; //Allocate RAM for the main struct + packetUBXNAVAOPSTATUS->callbackData = new UBX_NAV_AOPSTATUS_data_t; // Allocate RAM for the main struct } if (packetUBXNAVAOPSTATUS->callbackData == NULL) @@ -11056,9 +11234,9 @@ bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ if (!result) return (result); // Bail if setAuto failed - if (packetUBXNAVAOPSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXNAVAOPSTATUS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXNAVAOPSTATUS->callbackData = new UBX_NAV_AOPSTATUS_data_t; //Allocate RAM for the main struct + packetUBXNAVAOPSTATUS->callbackData = new UBX_NAV_AOPSTATUS_data_t; // Allocate RAM for the main struct } if (packetUBXNAVAOPSTATUS->callbackData == NULL) @@ -11074,12 +11252,13 @@ bool SFE_UBLOX_GNSS::setAutoAOPSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ return (true); } -//In case no config access to the GNSS is possible and AOPSTATUS is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and AOPSTATUS is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate) { - if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the data - if (packetUBXNAVAOPSTATUS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXNAVAOPSTATUS == NULL) + initPacketUBXNAVAOPSTATUS(); // Check that RAM has been allocated for the data + if (packetUBXNAVAOPSTATUS == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -11094,7 +11273,7 @@ bool SFE_UBLOX_GNSS::assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXNAVAOPSTATUS and initialize it bool SFE_UBLOX_GNSS::initPacketUBXNAVAOPSTATUS() { - packetUBXNAVAOPSTATUS = new UBX_NAV_AOPSTATUS_t; //Allocate RAM for the main struct + packetUBXNAVAOPSTATUS = new UBX_NAV_AOPSTATUS_t; // Allocate RAM for the main struct if (packetUBXNAVAOPSTATUS == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -11111,17 +11290,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXNAVAOPSTATUS() return (true); } -//Mark all the AOPSTATUS data as read/stale. This is handy to get data alignment after CRC failure +// Mark all the AOPSTATUS data as read/stale. This is handy to get data alignment after CRC failure void SFE_UBLOX_GNSS::flushAOPSTATUS() { - if (packetUBXNAVAOPSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.all = 0; //Mark all AOPSTATUSs as stale (read before) + if (packetUBXNAVAOPSTATUS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.all = 0; // Mark all AOPSTATUSs as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logAOPSTATUS(bool enabled) { - if (packetUBXNAVAOPSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXNAVAOPSTATUS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVAOPSTATUS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -11130,13 +11311,14 @@ void SFE_UBLOX_GNSS::logAOPSTATUS(bool enabled) // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! bool SFE_UBLOX_GNSS::setAutoRXMPMPcallbackPtr(void (*callbackPointer)(UBX_RXM_PMP_data_t *)) { - if (packetUBXRXMPMP == NULL) initPacketUBXRXMPMP(); //Check that RAM has been allocated for the data - if (packetUBXRXMPMP == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXRXMPMP == NULL) + initPacketUBXRXMPMP(); // Check that RAM has been allocated for the data + if (packetUBXRXMPMP == NULL) // Only attempt this if RAM allocation was successful return false; - if (packetUBXRXMPMP->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXRXMPMP->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXRXMPMP->callbackData = new UBX_RXM_PMP_data_t; //Allocate RAM for the main struct + packetUBXRXMPMP->callbackData = new UBX_RXM_PMP_data_t; // Allocate RAM for the main struct } if (packetUBXRXMPMP->callbackData == NULL) @@ -11155,7 +11337,7 @@ bool SFE_UBLOX_GNSS::setAutoRXMPMPcallbackPtr(void (*callbackPointer)(UBX_RXM_PM // PRIVATE: Allocate RAM for packetUBXRXMPMP and initialize it bool SFE_UBLOX_GNSS::initPacketUBXRXMPMP() { - packetUBXRXMPMP = new UBX_RXM_PMP_t; //Allocate RAM for the main struct + packetUBXRXMPMP = new UBX_RXM_PMP_t; // Allocate RAM for the main struct if (packetUBXRXMPMP == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -11175,30 +11357,31 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMPMP() bool SFE_UBLOX_GNSS::getRXMSFRBX(uint16_t maxWait) { - if (packetUBXRXMSFRBX == NULL) initPacketUBXRXMSFRBX(); //Check that RAM has been allocated for the TM2 data - if (packetUBXRXMSFRBX == NULL) //Bail if the RAM allocation failed + if (packetUBXRXMSFRBX == NULL) + initPacketUBXRXMSFRBX(); // Check that RAM has been allocated for the TM2 data + if (packetUBXRXMSFRBX == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXRXMSFRBX->automaticFlags.flags.bits.automatic && packetUBXRXMSFRBX->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_TIM, UBX_TIM_TM2); return packetUBXRXMSFRBX->moduleQueried; } else if (packetUBXRXMSFRBX->automaticFlags.flags.bits.automatic && !packetUBXRXMSFRBX->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_RXM; packetCfg.id = UBX_RXM_SFRBX; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -11213,29 +11396,31 @@ bool SFE_UBLOX_GNSS::getRXMSFRBX(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMSFRBX -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMSFRBX +// works. bool SFE_UBLOX_GNSS::setAutoRXMSFRBX(bool enable, uint16_t maxWait) { return setAutoRXMSFRBXrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMSFRBX -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMSFRBX +// works. bool SFE_UBLOX_GNSS::setAutoRXMSFRBX(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoRXMSFRBXrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMSFRBX -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMSFRBX +// works. bool SFE_UBLOX_GNSS::setAutoRXMSFRBXrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXRXMSFRBX == NULL) initPacketUBXRXMSFRBX(); //Check that RAM has been allocated for the data - if (packetUBXRXMSFRBX == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXRXMSFRBX == NULL) + initPacketUBXRXMSFRBX(); // Check that RAM has been allocated for the data + if (packetUBXRXMSFRBX == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -11255,7 +11440,7 @@ bool SFE_UBLOX_GNSS::setAutoRXMSFRBXrate(uint8_t rate, bool implicitUpdate, uint return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoRXMSFRBXcallback(void (*callbackPointer)(UBX_RXM_SFRBX_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -11263,9 +11448,9 @@ bool SFE_UBLOX_GNSS::setAutoRXMSFRBXcallback(void (*callbackPointer)(UBX_RXM_SFR if (!result) return (result); // Bail if setAuto failed - if (packetUBXRXMSFRBX->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXRXMSFRBX->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXRXMSFRBX->callbackData = new UBX_RXM_SFRBX_data_t; //Allocate RAM for the main struct + packetUBXRXMSFRBX->callbackData = new UBX_RXM_SFRBX_data_t; // Allocate RAM for the main struct } if (packetUBXRXMSFRBX->callbackData == NULL) @@ -11288,9 +11473,9 @@ bool SFE_UBLOX_GNSS::setAutoRXMSFRBXcallbackPtr(void (*callbackPointerPtr)(UBX_R if (!result) return (result); // Bail if setAuto failed - if (packetUBXRXMSFRBX->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXRXMSFRBX->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXRXMSFRBX->callbackData = new UBX_RXM_SFRBX_data_t; //Allocate RAM for the main struct + packetUBXRXMSFRBX->callbackData = new UBX_RXM_SFRBX_data_t; // Allocate RAM for the main struct } if (packetUBXRXMSFRBX->callbackData == NULL) @@ -11306,12 +11491,13 @@ bool SFE_UBLOX_GNSS::setAutoRXMSFRBXcallbackPtr(void (*callbackPointerPtr)(UBX_R return (true); } -//In case no config access to the GNSS is possible and SFRBX is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and SFRBX is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoRXMSFRBX(bool enabled, bool implicitUpdate) { - if (packetUBXRXMSFRBX == NULL) initPacketUBXRXMSFRBX(); //Check that RAM has been allocated for the data - if (packetUBXRXMSFRBX == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXRXMSFRBX == NULL) + initPacketUBXRXMSFRBX(); // Check that RAM has been allocated for the data + if (packetUBXRXMSFRBX == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXRXMSFRBX->automaticFlags.flags.bits.automatic != enabled || packetUBXRXMSFRBX->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -11326,7 +11512,7 @@ bool SFE_UBLOX_GNSS::assumeAutoRXMSFRBX(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXRXMSFRBX and initialize it bool SFE_UBLOX_GNSS::initPacketUBXRXMSFRBX() { - packetUBXRXMSFRBX = new UBX_RXM_SFRBX_t; //Allocate RAM for the main struct + packetUBXRXMSFRBX = new UBX_RXM_SFRBX_t; // Allocate RAM for the main struct if (packetUBXRXMSFRBX == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -11343,17 +11529,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMSFRBX() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushRXMSFRBX() { - if (packetUBXRXMSFRBX == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXRXMSFRBX->moduleQueried = false; //Mark all datums as stale (read before) + if (packetUBXRXMSFRBX == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXRXMSFRBX->moduleQueried = false; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logRXMSFRBX(bool enabled) { - if (packetUBXRXMSFRBX == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXRXMSFRBX == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXRXMSFRBX->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -11361,30 +11549,31 @@ void SFE_UBLOX_GNSS::logRXMSFRBX(bool enabled) bool SFE_UBLOX_GNSS::getRXMRAWX(uint16_t maxWait) { - if (packetUBXRXMRAWX == NULL) initPacketUBXRXMRAWX(); //Check that RAM has been allocated for the TM2 data - if (packetUBXRXMRAWX == NULL) //Bail if the RAM allocation failed + if (packetUBXRXMRAWX == NULL) + initPacketUBXRXMRAWX(); // Check that RAM has been allocated for the TM2 data + if (packetUBXRXMRAWX == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXRXMRAWX->automaticFlags.flags.bits.automatic && packetUBXRXMRAWX->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_TIM, UBX_TIM_TM2); return packetUBXRXMRAWX->moduleQueried; } else if (packetUBXRXMRAWX->automaticFlags.flags.bits.automatic && !packetUBXRXMRAWX->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_RXM; packetCfg.id = UBX_RXM_RAWX; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -11399,29 +11588,31 @@ bool SFE_UBLOX_GNSS::getRXMRAWX(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMRAWX -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMRAWX +// works. bool SFE_UBLOX_GNSS::setAutoRXMRAWX(bool enable, uint16_t maxWait) { return setAutoRXMRAWXrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMRAWX -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMRAWX +// works. bool SFE_UBLOX_GNSS::setAutoRXMRAWX(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoRXMRAWXrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMRAWX -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getRXMRAWX +// works. bool SFE_UBLOX_GNSS::setAutoRXMRAWXrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXRXMRAWX == NULL) initPacketUBXRXMRAWX(); //Check that RAM has been allocated for the data - if (packetUBXRXMRAWX == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXRXMRAWX == NULL) + initPacketUBXRXMRAWX(); // Check that RAM has been allocated for the data + if (packetUBXRXMRAWX == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -11441,7 +11632,7 @@ bool SFE_UBLOX_GNSS::setAutoRXMRAWXrate(uint8_t rate, bool implicitUpdate, uint1 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoRXMRAWXcallback(void (*callbackPointer)(UBX_RXM_RAWX_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -11449,9 +11640,9 @@ bool SFE_UBLOX_GNSS::setAutoRXMRAWXcallback(void (*callbackPointer)(UBX_RXM_RAWX if (!result) return (result); // Bail if setAuto failed - if (packetUBXRXMRAWX->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXRXMRAWX->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXRXMRAWX->callbackData = new UBX_RXM_RAWX_data_t; //Allocate RAM for the main struct + packetUBXRXMRAWX->callbackData = new UBX_RXM_RAWX_data_t; // Allocate RAM for the main struct } if (packetUBXRXMRAWX->callbackData == NULL) @@ -11474,9 +11665,9 @@ bool SFE_UBLOX_GNSS::setAutoRXMRAWXcallbackPtr(void (*callbackPointerPtr)(UBX_RX if (!result) return (result); // Bail if setAuto failed - if (packetUBXRXMRAWX->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXRXMRAWX->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXRXMRAWX->callbackData = new UBX_RXM_RAWX_data_t; //Allocate RAM for the main struct + packetUBXRXMRAWX->callbackData = new UBX_RXM_RAWX_data_t; // Allocate RAM for the main struct } if (packetUBXRXMRAWX->callbackData == NULL) @@ -11492,12 +11683,13 @@ bool SFE_UBLOX_GNSS::setAutoRXMRAWXcallbackPtr(void (*callbackPointerPtr)(UBX_RX return (true); } -//In case no config access to the GNSS is possible and VELNED is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and VELNED is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoRXMRAWX(bool enabled, bool implicitUpdate) { - if (packetUBXRXMRAWX == NULL) initPacketUBXRXMRAWX(); //Check that RAM has been allocated for the data - if (packetUBXRXMRAWX == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXRXMRAWX == NULL) + initPacketUBXRXMRAWX(); // Check that RAM has been allocated for the data + if (packetUBXRXMRAWX == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXRXMRAWX->automaticFlags.flags.bits.automatic != enabled || packetUBXRXMRAWX->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -11512,7 +11704,7 @@ bool SFE_UBLOX_GNSS::assumeAutoRXMRAWX(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXRXMRAWX and initialize it bool SFE_UBLOX_GNSS::initPacketUBXRXMRAWX() { - packetUBXRXMRAWX = new UBX_RXM_RAWX_t; //Allocate RAM for the main struct + packetUBXRXMRAWX = new UBX_RXM_RAWX_t; // Allocate RAM for the main struct if (packetUBXRXMRAWX == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -11529,33 +11721,36 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMRAWX() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushRXMRAWX() { - if (packetUBXRXMRAWX == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXRXMRAWX->moduleQueried = false; //Mark all datums as stale (read before) + if (packetUBXRXMRAWX == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXRXMRAWX->moduleQueried = false; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logRXMRAWX(bool enabled) { - if (packetUBXRXMRAWX == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXRXMRAWX == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXRXMRAWX->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } // ***** CFG automatic support -//Get the latest CFG PRT - as used by isConnected -// Here's the dilemma: -// The NEO-D9S doesn't support NAV-RATE so, if we want to include the D9 without creating a special class for it, -// we need to use something else as the 'isConnected' test. The D9 does support CFG-PRT so we'll use that. -// BUT many users could already be using getPortSettings and expecting the settings to be returned in packetCfg. -// So, for isConnected ONLY, we need to enable auto support for CFG-PRT and then disable it afterwards so the settings -// go back to being returned in packetCfg... What a tangled web we weave...! +// Get the latest CFG PRT - as used by isConnected +// Here's the dilemma: +// The NEO-D9S doesn't support NAV-RATE so, if we want to include the D9 without creating a special class for it, +// we need to use something else as the 'isConnected' test. The D9 does support CFG-PRT so we'll use that. +// BUT many users could already be using getPortSettings and expecting the settings to be returned in packetCfg. +// So, for isConnected ONLY, we need to enable auto support for CFG-PRT and then disable it afterwards so the settings +// go back to being returned in packetCfg... What a tangled web we weave...! bool SFE_UBLOX_GNSS::getPortSettingsInternal(uint8_t portID, uint16_t maxWait) { - if (packetUBXCFGPRT == NULL) initPacketUBXCFGPRT(); //Check that RAM has been allocated for the data - if (packetUBXCFGPRT == NULL) //Bail if the RAM allocation failed + if (packetUBXCFGPRT == NULL) + initPacketUBXCFGPRT(); // Check that RAM has been allocated for the data + if (packetUBXCFGPRT == NULL) // Bail if the RAM allocation failed return (false); // The CFG PRT message will never be produced automatically - that would be pointless. @@ -11564,10 +11759,10 @@ bool SFE_UBLOX_GNSS::getPortSettingsInternal(uint8_t portID, uint16_t maxWait) packetCfg.id = UBX_CFG_PRT; packetCfg.len = 1; packetCfg.startingSpot = 0; - + payloadCfg[0] = portID; - //The data is parsed as part of processing the response + // The data is parsed as part of processing the response sfe_ublox_status_e result = sendCommand(&packetCfg, maxWait); bool retVal = false; @@ -11577,7 +11772,7 @@ bool SFE_UBLOX_GNSS::getPortSettingsInternal(uint8_t portID, uint16_t maxWait) if (result == SFE_UBLOX_STATUS_DATA_OVERWRITTEN) retVal = true; - //Now disable automatic support for CFG-RATE (see above) + // Now disable automatic support for CFG-RATE (see above) delete packetUBXCFGPRT; packetUBXCFGPRT = NULL; @@ -11587,7 +11782,7 @@ bool SFE_UBLOX_GNSS::getPortSettingsInternal(uint8_t portID, uint16_t maxWait) // PRIVATE: Allocate RAM for packetUBXCFGPRT and initialize it bool SFE_UBLOX_GNSS::initPacketUBXCFGPRT() { - packetUBXCFGPRT = new UBX_CFG_PRT_t; //Allocate RAM for the main struct + packetUBXCFGPRT = new UBX_CFG_PRT_t; // Allocate RAM for the main struct if (packetUBXCFGPRT == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -11600,11 +11795,12 @@ bool SFE_UBLOX_GNSS::initPacketUBXCFGPRT() return (true); } -//Get the latest CFG RATE +// Get the latest CFG RATE bool SFE_UBLOX_GNSS::getNavigationFrequencyInternal(uint16_t maxWait) { - if (packetUBXCFGRATE == NULL) initPacketUBXCFGRATE(); //Check that RAM has been allocated for the data - if (packetUBXCFGRATE == NULL) //Bail if the RAM allocation failed + if (packetUBXCFGRATE == NULL) + initPacketUBXCFGRATE(); // Check that RAM has been allocated for the data + if (packetUBXCFGRATE == NULL) // Bail if the RAM allocation failed return (false); // The CFG RATE message will never be produced automatically - that would be pointless. @@ -11614,7 +11810,7 @@ bool SFE_UBLOX_GNSS::getNavigationFrequencyInternal(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -11629,7 +11825,7 @@ bool SFE_UBLOX_GNSS::getNavigationFrequencyInternal(uint16_t maxWait) // PRIVATE: Allocate RAM for packetUBXCFGRATE and initialize it bool SFE_UBLOX_GNSS::initPacketUBXCFGRATE() { - packetUBXCFGRATE = new UBX_CFG_RATE_t; //Allocate RAM for the main struct + packetUBXCFGRATE = new UBX_CFG_RATE_t; // Allocate RAM for the main struct if (packetUBXCFGRATE == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -11638,7 +11834,7 @@ bool SFE_UBLOX_GNSS::initPacketUBXCFGRATE() #endif return (false); } - packetUBXCFGRATE->automaticFlags.flags.all = 0; // Redundant + packetUBXCFGRATE->automaticFlags.flags.all = 0; // Redundant packetUBXCFGRATE->moduleQueried.moduleQueried.all = 0; // Mark all data as stale/read return (true); } @@ -11647,30 +11843,31 @@ bool SFE_UBLOX_GNSS::initPacketUBXCFGRATE() bool SFE_UBLOX_GNSS::getTIMTM2(uint16_t maxWait) { - if (packetUBXTIMTM2 == NULL) initPacketUBXTIMTM2(); //Check that RAM has been allocated for the TM2 data - if (packetUBXTIMTM2 == NULL) //Bail if the RAM allocation failed + if (packetUBXTIMTM2 == NULL) + initPacketUBXTIMTM2(); // Check that RAM has been allocated for the TM2 data + if (packetUBXTIMTM2 == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXTIMTM2->automaticFlags.flags.bits.automatic && packetUBXTIMTM2->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data + // The GPS is automatically reporting, we just check whether we got unread data checkUbloxInternal(&packetCfg, UBX_CLASS_TIM, UBX_TIM_TM2); return packetUBXTIMTM2->moduleQueried.moduleQueried.bits.all; } else if (packetUBXTIMTM2->automaticFlags.flags.bits.automatic && !packetUBXTIMTM2->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... + // Someone else has to call checkUblox for us... return (false); } else { - //The GPS is not automatically reporting navigation position so we have to poll explicitly + // The GPS is not automatically reporting navigation position so we have to poll explicitly packetCfg.cls = UBX_CLASS_TIM; packetCfg.id = UBX_TIM_TM2; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -11685,29 +11882,31 @@ bool SFE_UBLOX_GNSS::getTIMTM2(uint16_t maxWait) } } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getTIMTM2 -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getTIMTM2 +// works. bool SFE_UBLOX_GNSS::setAutoTIMTM2(bool enable, uint16_t maxWait) { return setAutoTIMTM2rate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getTIMTM2 -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getTIMTM2 +// works. bool SFE_UBLOX_GNSS::setAutoTIMTM2(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoTIMTM2rate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic navigation message generation by the GNSS. This changes the way getTIMTM2 -//works. +// Enable or disable automatic navigation message generation by the GNSS. This changes the way getTIMTM2 +// works. bool SFE_UBLOX_GNSS::setAutoTIMTM2rate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXTIMTM2 == NULL) initPacketUBXTIMTM2(); //Check that RAM has been allocated for the data - if (packetUBXTIMTM2 == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXTIMTM2 == NULL) + initPacketUBXTIMTM2(); // Check that RAM has been allocated for the data + if (packetUBXTIMTM2 == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -11727,7 +11926,7 @@ bool SFE_UBLOX_GNSS::setAutoTIMTM2rate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoTIMTM2callback(void (*callbackPointer)(UBX_TIM_TM2_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -11735,9 +11934,9 @@ bool SFE_UBLOX_GNSS::setAutoTIMTM2callback(void (*callbackPointer)(UBX_TIM_TM2_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXTIMTM2->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXTIMTM2->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXTIMTM2->callbackData = new UBX_TIM_TM2_data_t; //Allocate RAM for the main struct + packetUBXTIMTM2->callbackData = new UBX_TIM_TM2_data_t; // Allocate RAM for the main struct } if (packetUBXTIMTM2->callbackData == NULL) @@ -11760,9 +11959,9 @@ bool SFE_UBLOX_GNSS::setAutoTIMTM2callbackPtr(void (*callbackPointerPtr)(UBX_TIM if (!result) return (result); // Bail if setAuto failed - if (packetUBXTIMTM2->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXTIMTM2->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXTIMTM2->callbackData = new UBX_TIM_TM2_data_t; //Allocate RAM for the main struct + packetUBXTIMTM2->callbackData = new UBX_TIM_TM2_data_t; // Allocate RAM for the main struct } if (packetUBXTIMTM2->callbackData == NULL) @@ -11778,12 +11977,13 @@ bool SFE_UBLOX_GNSS::setAutoTIMTM2callbackPtr(void (*callbackPointerPtr)(UBX_TIM return (true); } -//In case no config access to the GNSS is possible and VELNED is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and VELNED is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoTIMTM2(bool enabled, bool implicitUpdate) { - if (packetUBXTIMTM2 == NULL) initPacketUBXTIMTM2(); //Check that RAM has been allocated for the data - if (packetUBXTIMTM2 == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXTIMTM2 == NULL) + initPacketUBXTIMTM2(); // Check that RAM has been allocated for the data + if (packetUBXTIMTM2 == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXTIMTM2->automaticFlags.flags.bits.automatic != enabled || packetUBXTIMTM2->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -11798,7 +11998,7 @@ bool SFE_UBLOX_GNSS::assumeAutoTIMTM2(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXTIMTM2 and initialize it bool SFE_UBLOX_GNSS::initPacketUBXTIMTM2() { - packetUBXTIMTM2 = new UBX_TIM_TM2_t; //Allocate RAM for the main struct + packetUBXTIMTM2 = new UBX_TIM_TM2_t; // Allocate RAM for the main struct if (packetUBXTIMTM2 == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -11815,17 +12015,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXTIMTM2() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushTIMTM2() { - if (packetUBXTIMTM2 == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXTIMTM2->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXTIMTM2 == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXTIMTM2->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logTIMTM2(bool enabled) { - if (packetUBXTIMTM2 == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXTIMTM2 == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXTIMTM2->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -11838,27 +12040,28 @@ bool SFE_UBLOX_GNSS::getEsfAlignment(uint16_t maxWait) bool SFE_UBLOX_GNSS::getESFALG(uint16_t maxWait) { - if (packetUBXESFALG == NULL) initPacketUBXESFALG(); //Check that RAM has been allocated for the ESF alignment data - if (packetUBXESFALG == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFALG == NULL) + initPacketUBXESFALG(); // Check that RAM has been allocated for the ESF alignment data + if (packetUBXESFALG == NULL) // Only attempt this if RAM allocation was successful return false; if (packetUBXESFALG->automaticFlags.flags.bits.automatic && packetUBXESFALG->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfAlignment: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfAlignment: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_ESF, UBX_ESF_ALG); return packetUBXESFALG->moduleQueried.moduleQueried.bits.all; } else if (packetUBXESFALG->automaticFlags.flags.bits.automatic && !packetUBXESFALG->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfAlignment: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfAlignment: Exit immediately")); + // } return (false); } else @@ -11868,13 +12071,13 @@ bool SFE_UBLOX_GNSS::getESFALG(uint16_t maxWait) // _debugSerial->println(F("getEsfAlignment: Polling")); // } - //The GPS is not automatically reporting HNR PVT so we have to poll explicitly + // The GPS is not automatically reporting HNR PVT so we have to poll explicitly packetCfg.cls = UBX_CLASS_ESF; packetCfg.id = UBX_ESF_ALG; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -11900,29 +12103,31 @@ bool SFE_UBLOX_GNSS::getESFALG(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic ESF ALG message generation by the GNSS. This changes the way getEsfAlignment -//works. +// Enable or disable automatic ESF ALG message generation by the GNSS. This changes the way getEsfAlignment +// works. bool SFE_UBLOX_GNSS::setAutoESFALG(bool enable, uint16_t maxWait) { return setAutoESFALGrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic ESF ALG message generation by the GNSS. This changes the way getEsfAlignment -//works. +// Enable or disable automatic ESF ALG message generation by the GNSS. This changes the way getEsfAlignment +// works. bool SFE_UBLOX_GNSS::setAutoESFALG(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoESFALGrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic ESF ALG message generation by the GNSS. This changes the way getEsfAlignment -//works. +// Enable or disable automatic ESF ALG message generation by the GNSS. This changes the way getEsfAlignment +// works. bool SFE_UBLOX_GNSS::setAutoESFALGrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXESFALG == NULL) initPacketUBXESFALG(); //Check that RAM has been allocated for the data - if (packetUBXESFALG == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFALG == NULL) + initPacketUBXESFALG(); // Check that RAM has been allocated for the data + if (packetUBXESFALG == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -11942,7 +12147,7 @@ bool SFE_UBLOX_GNSS::setAutoESFALGrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoESFALGcallback(void (*callbackPointer)(UBX_ESF_ALG_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -11950,9 +12155,9 @@ bool SFE_UBLOX_GNSS::setAutoESFALGcallback(void (*callbackPointer)(UBX_ESF_ALG_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFALG->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFALG->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFALG->callbackData = new UBX_ESF_ALG_data_t; //Allocate RAM for the main struct + packetUBXESFALG->callbackData = new UBX_ESF_ALG_data_t; // Allocate RAM for the main struct } if (packetUBXESFALG->callbackData == NULL) @@ -11975,9 +12180,9 @@ bool SFE_UBLOX_GNSS::setAutoESFALGcallbackPtr(void (*callbackPointerPtr)(UBX_ESF if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFALG->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFALG->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFALG->callbackData = new UBX_ESF_ALG_data_t; //Allocate RAM for the main struct + packetUBXESFALG->callbackData = new UBX_ESF_ALG_data_t; // Allocate RAM for the main struct } if (packetUBXESFALG->callbackData == NULL) @@ -11993,12 +12198,13 @@ bool SFE_UBLOX_GNSS::setAutoESFALGcallbackPtr(void (*callbackPointerPtr)(UBX_ESF return (true); } -//In case no config access to the GNSS is possible and ESF ALG is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and ESF ALG is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFALG(bool enabled, bool implicitUpdate) { - if (packetUBXESFALG == NULL) initPacketUBXESFALG(); //Check that RAM has been allocated for the ESF alignment data - if (packetUBXESFALG == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFALG == NULL) + initPacketUBXESFALG(); // Check that RAM has been allocated for the ESF alignment data + if (packetUBXESFALG == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXESFALG->automaticFlags.flags.bits.automatic != enabled || packetUBXESFALG->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -12013,7 +12219,7 @@ bool SFE_UBLOX_GNSS::assumeAutoESFALG(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXESFALG and initialize it bool SFE_UBLOX_GNSS::initPacketUBXESFALG() { - packetUBXESFALG = new UBX_ESF_ALG_t; //Allocate RAM for the main struct + packetUBXESFALG = new UBX_ESF_ALG_t; // Allocate RAM for the main struct if (packetUBXESFALG == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -12030,17 +12236,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFALG() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushESFALG() { - if (packetUBXESFALG == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXESFALG->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXESFALG == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXESFALG->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logESFALG(bool enabled) { - if (packetUBXESFALG == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXESFALG == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXESFALG->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -12053,27 +12261,28 @@ bool SFE_UBLOX_GNSS::getEsfInfo(uint16_t maxWait) bool SFE_UBLOX_GNSS::getESFSTATUS(uint16_t maxWait) { - if (packetUBXESFSTATUS == NULL) initPacketUBXESFSTATUS(); //Check that RAM has been allocated for the ESF status data - if (packetUBXESFSTATUS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFSTATUS == NULL) + initPacketUBXESFSTATUS(); // Check that RAM has been allocated for the ESF status data + if (packetUBXESFSTATUS == NULL) // Only attempt this if RAM allocation was successful return false; if (packetUBXESFSTATUS->automaticFlags.flags.bits.automatic && packetUBXESFSTATUS->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfInfo: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfInfo: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_ESF, UBX_ESF_STATUS); return packetUBXESFSTATUS->moduleQueried.moduleQueried.bits.all; } else if (packetUBXESFSTATUS->automaticFlags.flags.bits.automatic && !packetUBXESFSTATUS->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfInfo: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfInfo: Exit immediately")); + // } return (false); } else @@ -12083,13 +12292,13 @@ bool SFE_UBLOX_GNSS::getESFSTATUS(uint16_t maxWait) // _debugSerial->println(F("getEsfInfo: Polling")); // } - //The GPS is not automatically reporting HNR PVT so we have to poll explicitly + // The GPS is not automatically reporting HNR PVT so we have to poll explicitly packetCfg.cls = UBX_CLASS_ESF; packetCfg.id = UBX_ESF_STATUS; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -12115,29 +12324,31 @@ bool SFE_UBLOX_GNSS::getESFSTATUS(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic ESF STATUS message generation by the GNSS. This changes the way getESFInfo -//works. +// Enable or disable automatic ESF STATUS message generation by the GNSS. This changes the way getESFInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFSTATUS(bool enable, uint16_t maxWait) { return setAutoESFSTATUSrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic ESF STATUS message generation by the GNSS. This changes the way getESFInfo -//works. +// Enable or disable automatic ESF STATUS message generation by the GNSS. This changes the way getESFInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFSTATUS(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoESFSTATUSrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic ESF STATUS message generation by the GNSS. This changes the way getESFInfo -//works. +// Enable or disable automatic ESF STATUS message generation by the GNSS. This changes the way getESFInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFSTATUSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXESFSTATUS == NULL) initPacketUBXESFSTATUS(); //Check that RAM has been allocated for the data - if (packetUBXESFSTATUS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFSTATUS == NULL) + initPacketUBXESFSTATUS(); // Check that RAM has been allocated for the data + if (packetUBXESFSTATUS == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -12157,7 +12368,7 @@ bool SFE_UBLOX_GNSS::setAutoESFSTATUSrate(uint8_t rate, bool implicitUpdate, uin return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoESFSTATUScallback(void (*callbackPointer)(UBX_ESF_STATUS_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -12165,9 +12376,9 @@ bool SFE_UBLOX_GNSS::setAutoESFSTATUScallback(void (*callbackPointer)(UBX_ESF_ST if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFSTATUS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFSTATUS->callbackData = new UBX_ESF_STATUS_data_t; //Allocate RAM for the main struct + packetUBXESFSTATUS->callbackData = new UBX_ESF_STATUS_data_t; // Allocate RAM for the main struct } if (packetUBXESFSTATUS->callbackData == NULL) @@ -12190,9 +12401,9 @@ bool SFE_UBLOX_GNSS::setAutoESFSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFSTATUS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFSTATUS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFSTATUS->callbackData = new UBX_ESF_STATUS_data_t; //Allocate RAM for the main struct + packetUBXESFSTATUS->callbackData = new UBX_ESF_STATUS_data_t; // Allocate RAM for the main struct } if (packetUBXESFSTATUS->callbackData == NULL) @@ -12208,12 +12419,13 @@ bool SFE_UBLOX_GNSS::setAutoESFSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ return (true); } -//In case no config access to the GNSS is possible and ESF STATUS is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and ESF STATUS is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFSTATUS(bool enabled, bool implicitUpdate) { - if (packetUBXESFSTATUS == NULL) initPacketUBXESFSTATUS(); //Check that RAM has been allocated for the ESF status data - if (packetUBXESFSTATUS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFSTATUS == NULL) + initPacketUBXESFSTATUS(); // Check that RAM has been allocated for the ESF status data + if (packetUBXESFSTATUS == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXESFSTATUS->automaticFlags.flags.bits.automatic != enabled || packetUBXESFSTATUS->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -12228,7 +12440,7 @@ bool SFE_UBLOX_GNSS::assumeAutoESFSTATUS(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXESFSTATUS and initialize it bool SFE_UBLOX_GNSS::initPacketUBXESFSTATUS() { - packetUBXESFSTATUS = new UBX_ESF_STATUS_t; //Allocate RAM for the main struct + packetUBXESFSTATUS = new UBX_ESF_STATUS_t; // Allocate RAM for the main struct if (packetUBXESFSTATUS == NULL) { @@ -12246,17 +12458,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFSTATUS() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushESFSTATUS() { - if (packetUBXESFSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXESFSTATUS->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXESFSTATUS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXESFSTATUS->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logESFSTATUS(bool enabled) { - if (packetUBXESFSTATUS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXESFSTATUS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXESFSTATUS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -12269,27 +12483,28 @@ bool SFE_UBLOX_GNSS::getEsfIns(uint16_t maxWait) bool SFE_UBLOX_GNSS::getESFINS(uint16_t maxWait) { - if (packetUBXESFINS == NULL) initPacketUBXESFINS(); //Check that RAM has been allocated for the ESF INS data - if (packetUBXESFINS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFINS == NULL) + initPacketUBXESFINS(); // Check that RAM has been allocated for the ESF INS data + if (packetUBXESFINS == NULL) // Only attempt this if RAM allocation was successful return false; if (packetUBXESFINS->automaticFlags.flags.bits.automatic && packetUBXESFINS->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfIns: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfIns: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_ESF, UBX_ESF_INS); return packetUBXESFINS->moduleQueried.moduleQueried.bits.all; } else if (packetUBXESFINS->automaticFlags.flags.bits.automatic && !packetUBXESFINS->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfIns: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfIns: Exit immediately")); + // } return (false); } else @@ -12299,13 +12514,13 @@ bool SFE_UBLOX_GNSS::getESFINS(uint16_t maxWait) // _debugSerial->println(F("getEsfIns: Polling")); // } - //The GPS is not automatically reporting HNR PVT so we have to poll explicitly + // The GPS is not automatically reporting HNR PVT so we have to poll explicitly packetCfg.cls = UBX_CLASS_ESF; packetCfg.id = UBX_ESF_INS; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -12331,29 +12546,31 @@ bool SFE_UBLOX_GNSS::getESFINS(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic ESF INS message generation by the GNSS. This changes the way getESFIns -//works. +// Enable or disable automatic ESF INS message generation by the GNSS. This changes the way getESFIns +// works. bool SFE_UBLOX_GNSS::setAutoESFINS(bool enable, uint16_t maxWait) { return setAutoESFINSrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic ESF INS message generation by the GNSS. This changes the way getESFIns -//works. +// Enable or disable automatic ESF INS message generation by the GNSS. This changes the way getESFIns +// works. bool SFE_UBLOX_GNSS::setAutoESFINS(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoESFINSrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic ESF INS message generation by the GNSS. This changes the way getESFIns -//works. +// Enable or disable automatic ESF INS message generation by the GNSS. This changes the way getESFIns +// works. bool SFE_UBLOX_GNSS::setAutoESFINSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXESFINS == NULL) initPacketUBXESFINS(); //Check that RAM has been allocated for the data - if (packetUBXESFINS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFINS == NULL) + initPacketUBXESFINS(); // Check that RAM has been allocated for the data + if (packetUBXESFINS == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -12373,7 +12590,7 @@ bool SFE_UBLOX_GNSS::setAutoESFINSrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoESFINScallback(void (*callbackPointer)(UBX_ESF_INS_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -12381,9 +12598,9 @@ bool SFE_UBLOX_GNSS::setAutoESFINScallback(void (*callbackPointer)(UBX_ESF_INS_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFINS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFINS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFINS->callbackData = new UBX_ESF_INS_data_t; //Allocate RAM for the main struct + packetUBXESFINS->callbackData = new UBX_ESF_INS_data_t; // Allocate RAM for the main struct } if (packetUBXESFINS->callbackData == NULL) @@ -12406,9 +12623,9 @@ bool SFE_UBLOX_GNSS::setAutoESFINScallbackPtr(void (*callbackPointerPtr)(UBX_ESF if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFINS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFINS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFINS->callbackData = new UBX_ESF_INS_data_t; //Allocate RAM for the main struct + packetUBXESFINS->callbackData = new UBX_ESF_INS_data_t; // Allocate RAM for the main struct } if (packetUBXESFINS->callbackData == NULL) @@ -12424,12 +12641,13 @@ bool SFE_UBLOX_GNSS::setAutoESFINScallbackPtr(void (*callbackPointerPtr)(UBX_ESF return (true); } -//In case no config access to the GNSS is possible and ESF INS is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and ESF INS is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFINS(bool enabled, bool implicitUpdate) { - if (packetUBXESFINS == NULL) initPacketUBXESFINS(); //Check that RAM has been allocated for the ESF INS data - if (packetUBXESFINS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFINS == NULL) + initPacketUBXESFINS(); // Check that RAM has been allocated for the ESF INS data + if (packetUBXESFINS == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXESFINS->automaticFlags.flags.bits.automatic != enabled || packetUBXESFINS->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -12444,7 +12662,7 @@ bool SFE_UBLOX_GNSS::assumeAutoESFINS(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXESFINS and initialize it bool SFE_UBLOX_GNSS::initPacketUBXESFINS() { - packetUBXESFINS = new UBX_ESF_INS_t; //Allocate RAM for the main struct + packetUBXESFINS = new UBX_ESF_INS_t; // Allocate RAM for the main struct if (packetUBXESFINS == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -12461,17 +12679,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFINS() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushESFINS() { - if (packetUBXESFINS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXESFINS->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXESFINS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXESFINS->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logESFINS(bool enabled) { - if (packetUBXESFINS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXESFINS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXESFINS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -12484,27 +12704,28 @@ bool SFE_UBLOX_GNSS::getEsfDataInfo(uint16_t maxWait) bool SFE_UBLOX_GNSS::getESFMEAS(uint16_t maxWait) { - if (packetUBXESFMEAS == NULL) initPacketUBXESFMEAS(); //Check that RAM has been allocated for the ESF MEAS data - if (packetUBXESFMEAS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFMEAS == NULL) + initPacketUBXESFMEAS(); // Check that RAM has been allocated for the ESF MEAS data + if (packetUBXESFMEAS == NULL) // Only attempt this if RAM allocation was successful return false; if (packetUBXESFMEAS->automaticFlags.flags.bits.automatic && packetUBXESFMEAS->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfDataInfo: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfDataInfo: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_ESF, UBX_ESF_MEAS); return packetUBXESFMEAS->moduleQueried.moduleQueried.bits.all; } else if (packetUBXESFMEAS->automaticFlags.flags.bits.automatic && !packetUBXESFMEAS->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfDataInfo: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfDataInfo: Exit immediately")); + // } return (false); } else @@ -12514,13 +12735,13 @@ bool SFE_UBLOX_GNSS::getESFMEAS(uint16_t maxWait) // _debugSerial->println(F("getEsfDataInfo: Polling")); // } - //The GPS is not automatically reporting HNR PVT so we have to poll explicitly + // The GPS is not automatically reporting HNR PVT so we have to poll explicitly packetCfg.cls = UBX_CLASS_ESF; packetCfg.id = UBX_ESF_MEAS; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -12546,29 +12767,31 @@ bool SFE_UBLOX_GNSS::getESFMEAS(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo -//works. +// Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFMEAS(bool enable, uint16_t maxWait) { return setAutoESFMEASrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo -//works. +// Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFMEAS(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoESFMEASrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo -//works. +// Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFMEASrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXESFMEAS == NULL) initPacketUBXESFMEAS(); //Check that RAM has been allocated for the data - if (packetUBXESFMEAS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFMEAS == NULL) + initPacketUBXESFMEAS(); // Check that RAM has been allocated for the data + if (packetUBXESFMEAS == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -12588,7 +12811,7 @@ bool SFE_UBLOX_GNSS::setAutoESFMEASrate(uint8_t rate, bool implicitUpdate, uint1 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -12596,9 +12819,9 @@ bool SFE_UBLOX_GNSS::setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFMEAS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFMEAS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFMEAS->callbackData = new UBX_ESF_MEAS_data_t; //Allocate RAM for the main struct + packetUBXESFMEAS->callbackData = new UBX_ESF_MEAS_data_t; // Allocate RAM for the main struct } if (packetUBXESFMEAS->callbackData == NULL) @@ -12621,9 +12844,9 @@ bool SFE_UBLOX_GNSS::setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ES if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFMEAS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFMEAS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFMEAS->callbackData = new UBX_ESF_MEAS_data_t; //Allocate RAM for the main struct + packetUBXESFMEAS->callbackData = new UBX_ESF_MEAS_data_t; // Allocate RAM for the main struct } if (packetUBXESFMEAS->callbackData == NULL) @@ -12639,12 +12862,13 @@ bool SFE_UBLOX_GNSS::setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ES return (true); } -//In case no config access to the GNSS is possible and ESF MEAS is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and ESF MEAS is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFMEAS(bool enabled, bool implicitUpdate) { - if (packetUBXESFMEAS == NULL) initPacketUBXESFMEAS(); //Check that RAM has been allocated for the ESF MEAS data - if (packetUBXESFMEAS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFMEAS == NULL) + initPacketUBXESFMEAS(); // Check that RAM has been allocated for the ESF MEAS data + if (packetUBXESFMEAS == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXESFMEAS->automaticFlags.flags.bits.automatic != enabled || packetUBXESFMEAS->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -12659,7 +12883,7 @@ bool SFE_UBLOX_GNSS::assumeAutoESFMEAS(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXESFMEAS and initialize it bool SFE_UBLOX_GNSS::initPacketUBXESFMEAS() { - packetUBXESFMEAS = new UBX_ESF_MEAS_t; //Allocate RAM for the main struct + packetUBXESFMEAS = new UBX_ESF_MEAS_t; // Allocate RAM for the main struct if (packetUBXESFMEAS == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -12676,17 +12900,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFMEAS() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushESFMEAS() { - if (packetUBXESFMEAS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXESFMEAS->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXESFMEAS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXESFMEAS->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logESFMEAS(bool enabled) { - if (packetUBXESFMEAS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXESFMEAS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXESFMEAS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -12699,27 +12925,28 @@ bool SFE_UBLOX_GNSS::getEsfRawDataInfo(uint16_t maxWait) bool SFE_UBLOX_GNSS::getESFRAW(uint16_t maxWait) { - if (packetUBXESFRAW == NULL) initPacketUBXESFRAW(); //Check that RAM has been allocated for the ESF RAW data - if (packetUBXESFRAW == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFRAW == NULL) + initPacketUBXESFRAW(); // Check that RAM has been allocated for the ESF RAW data + if (packetUBXESFRAW == NULL) // Only attempt this if RAM allocation was successful return false; if (packetUBXESFRAW->automaticFlags.flags.bits.automatic && packetUBXESFRAW->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfRawDataInfo: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfRawDataInfo: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_ESF, UBX_ESF_RAW); return packetUBXESFRAW->moduleQueried.moduleQueried.bits.all; } else if (packetUBXESFRAW->automaticFlags.flags.bits.automatic && !packetUBXESFRAW->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getEsfRawDataInfo: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getEsfRawDataInfo: Exit immediately")); + // } return (false); } else @@ -12729,13 +12956,13 @@ bool SFE_UBLOX_GNSS::getESFRAW(uint16_t maxWait) // _debugSerial->println(F("getEsfRawDataInfo: Polling")); // } - //The GPS is not automatically reporting HNR PVT so we have to poll explicitly + // The GPS is not automatically reporting HNR PVT so we have to poll explicitly packetCfg.cls = UBX_CLASS_ESF; packetCfg.id = UBX_ESF_RAW; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -12761,29 +12988,31 @@ bool SFE_UBLOX_GNSS::getESFRAW(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo -//works. +// Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFRAW(bool enable, uint16_t maxWait) { return setAutoESFRAWrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo -//works. +// Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFRAW(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoESFRAWrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo -//works. +// Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo +// works. bool SFE_UBLOX_GNSS::setAutoESFRAWrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXESFRAW == NULL) initPacketUBXESFRAW(); //Check that RAM has been allocated for the data - if (packetUBXESFRAW == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFRAW == NULL) + initPacketUBXESFRAW(); // Check that RAM has been allocated for the data + if (packetUBXESFRAW == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -12803,7 +13032,7 @@ bool SFE_UBLOX_GNSS::setAutoESFRAWrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -12811,9 +13040,9 @@ bool SFE_UBLOX_GNSS::setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFRAW->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFRAW->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFRAW->callbackData = new UBX_ESF_RAW_data_t; //Allocate RAM for the main struct + packetUBXESFRAW->callbackData = new UBX_ESF_RAW_data_t; // Allocate RAM for the main struct } if (packetUBXESFRAW->callbackData == NULL) @@ -12836,9 +13065,9 @@ bool SFE_UBLOX_GNSS::setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF if (!result) return (result); // Bail if setAuto failed - if (packetUBXESFRAW->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXESFRAW->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXESFRAW->callbackData = new UBX_ESF_RAW_data_t; //Allocate RAM for the main struct + packetUBXESFRAW->callbackData = new UBX_ESF_RAW_data_t; // Allocate RAM for the main struct } if (packetUBXESFRAW->callbackData == NULL) @@ -12854,12 +13083,13 @@ bool SFE_UBLOX_GNSS::setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF return (true); } -//In case no config access to the GNSS is possible and ESF RAW is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and ESF RAW is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoESFRAW(bool enabled, bool implicitUpdate) { - if (packetUBXESFRAW == NULL) initPacketUBXESFRAW(); //Check that RAM has been allocated for the ESF RAW data - if (packetUBXESFRAW == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXESFRAW == NULL) + initPacketUBXESFRAW(); // Check that RAM has been allocated for the ESF RAW data + if (packetUBXESFRAW == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXESFRAW->automaticFlags.flags.bits.automatic != enabled || packetUBXESFRAW->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -12874,7 +13104,7 @@ bool SFE_UBLOX_GNSS::assumeAutoESFRAW(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXESFRAW and initialize it bool SFE_UBLOX_GNSS::initPacketUBXESFRAW() { - packetUBXESFRAW = new UBX_ESF_RAW_t; //Allocate RAM for the main struct + packetUBXESFRAW = new UBX_ESF_RAW_t; // Allocate RAM for the main struct if (packetUBXESFRAW == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -12891,17 +13121,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFRAW() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushESFRAW() { - if (packetUBXESFRAW == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXESFRAW->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXESFRAW == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXESFRAW->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logESFRAW(bool enabled) { - if (packetUBXESFRAW == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXESFRAW == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXESFRAW->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -12912,34 +13144,35 @@ bool SFE_UBLOX_GNSS::getHNRAtt(uint16_t maxWait) return (getHNRATT(maxWait)); } -//Get the HNR Attitude data -// Returns true if the get HNR attitude is successful. Data is returned in hnrAtt -// Note: if hnrAttQueried is true, it gets set to false by this function since we assume -// that the user will read hnrAtt immediately after this. I.e. this function will -// only return true _once_ after each auto HNR Att is processed +// Get the HNR Attitude data +// Returns true if the get HNR attitude is successful. Data is returned in hnrAtt +// Note: if hnrAttQueried is true, it gets set to false by this function since we assume +// that the user will read hnrAtt immediately after this. I.e. this function will +// only return true _once_ after each auto HNR Att is processed bool SFE_UBLOX_GNSS::getHNRATT(uint16_t maxWait) { - if (packetUBXHNRATT == NULL) initPacketUBXHNRATT(); //Check that RAM has been allocated for the data - if (packetUBXHNRATT == NULL) //Bail if the RAM allocation failed + if (packetUBXHNRATT == NULL) + initPacketUBXHNRATT(); // Check that RAM has been allocated for the data + if (packetUBXHNRATT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXHNRATT->automaticFlags.flags.bits.automatic && packetUBXHNRATT->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHNRAtt: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHNRAtt: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_HNR, UBX_HNR_ATT); return packetUBXHNRATT->moduleQueried.moduleQueried.bits.all; } else if (packetUBXHNRATT->automaticFlags.flags.bits.automatic && !packetUBXHNRATT->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHNRAtt: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHNRAtt: Exit immediately")); + // } return (false); } else @@ -12949,13 +13182,13 @@ bool SFE_UBLOX_GNSS::getHNRATT(uint16_t maxWait) // _debugSerial->println(F("getHNRAtt: Polling")); // } - //The GPS is not automatically reporting HNR attitude so we have to poll explicitly + // The GPS is not automatically reporting HNR attitude so we have to poll explicitly packetCfg.cls = UBX_CLASS_HNR; packetCfg.id = UBX_HNR_ATT; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -12981,29 +13214,31 @@ bool SFE_UBLOX_GNSS::getHNRATT(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getHNRAtt -//works. +// Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getHNRAtt +// works. bool SFE_UBLOX_GNSS::setAutoHNRATT(bool enable, uint16_t maxWait) { return setAutoHNRATTrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getHNRAtt -//works. +// Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getHNRAtt +// works. bool SFE_UBLOX_GNSS::setAutoHNRATT(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoHNRATTrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getHNRAtt -//works. +// Enable or disable automatic HNR attitude message generation by the GNSS. This changes the way getHNRAtt +// works. bool SFE_UBLOX_GNSS::setAutoHNRATTrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXHNRATT == NULL) initPacketUBXHNRATT(); //Check that RAM has been allocated for the data - if (packetUBXHNRATT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXHNRATT == NULL) + initPacketUBXHNRATT(); // Check that RAM has been allocated for the data + if (packetUBXHNRATT == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -13023,7 +13258,7 @@ bool SFE_UBLOX_GNSS::setAutoHNRATTrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoHNRATTcallback(void (*callbackPointer)(UBX_HNR_ATT_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -13031,9 +13266,9 @@ bool SFE_UBLOX_GNSS::setAutoHNRATTcallback(void (*callbackPointer)(UBX_HNR_ATT_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXHNRATT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXHNRATT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXHNRATT->callbackData = new UBX_HNR_ATT_data_t; //Allocate RAM for the main struct + packetUBXHNRATT->callbackData = new UBX_HNR_ATT_data_t; // Allocate RAM for the main struct } if (packetUBXHNRATT->callbackData == NULL) @@ -13056,9 +13291,9 @@ bool SFE_UBLOX_GNSS::setAutoHNRATTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR if (!result) return (result); // Bail if setAuto failed - if (packetUBXHNRATT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXHNRATT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXHNRATT->callbackData = new UBX_HNR_ATT_data_t; //Allocate RAM for the main struct + packetUBXHNRATT->callbackData = new UBX_HNR_ATT_data_t; // Allocate RAM for the main struct } if (packetUBXHNRATT->callbackData == NULL) @@ -13074,12 +13309,13 @@ bool SFE_UBLOX_GNSS::setAutoHNRATTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR return (true); } -//In case no config access to the GNSS is possible and HNR attitude is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and HNR attitude is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHNRATT(bool enabled, bool implicitUpdate) { - if (packetUBXHNRATT == NULL) initPacketUBXHNRATT(); //Check that RAM has been allocated for the data - if (packetUBXHNRATT == NULL) //Bail if the RAM allocation failed + if (packetUBXHNRATT == NULL) + initPacketUBXHNRATT(); // Check that RAM has been allocated for the data + if (packetUBXHNRATT == NULL) // Bail if the RAM allocation failed return (false); bool changes = packetUBXHNRATT->automaticFlags.flags.bits.automatic != enabled || packetUBXHNRATT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -13094,7 +13330,7 @@ bool SFE_UBLOX_GNSS::assumeAutoHNRATT(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXHNRATT and initialize it bool SFE_UBLOX_GNSS::initPacketUBXHNRATT() { - packetUBXHNRATT = new UBX_HNR_ATT_t; //Allocate RAM for the main struct + packetUBXHNRATT = new UBX_HNR_ATT_t; // Allocate RAM for the main struct if (packetUBXHNRATT == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -13111,18 +13347,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRATT() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushHNRATT() { - if (packetUBXHNRATT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXHNRATT->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXHNRATT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXHNRATT->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } - -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logHNRATT(bool enabled) { - if (packetUBXHNRATT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXHNRATT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXHNRATT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -13133,34 +13370,35 @@ bool SFE_UBLOX_GNSS::getHNRDyn(uint16_t maxWait) return (getHNRINS(maxWait)); } -//Get the HNR vehicle dynamics data -// Returns true if the get HNR vehicle dynamics is successful. Data is returned in hnrVehDyn -// Note: if hnrDynQueried is true, it gets set to false by this function since we assume -// that the user will read hnrVehDyn immediately after this. I.e. this function will -// only return true _once_ after each auto HNR Dyn is processed +// Get the HNR vehicle dynamics data +// Returns true if the get HNR vehicle dynamics is successful. Data is returned in hnrVehDyn +// Note: if hnrDynQueried is true, it gets set to false by this function since we assume +// that the user will read hnrVehDyn immediately after this. I.e. this function will +// only return true _once_ after each auto HNR Dyn is processed bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) { - if (packetUBXHNRINS == NULL) initPacketUBXHNRINS(); //Check that RAM has been allocated for the data - if (packetUBXHNRINS == NULL) //Bail if the RAM allocation failed + if (packetUBXHNRINS == NULL) + initPacketUBXHNRINS(); // Check that RAM has been allocated for the data + if (packetUBXHNRINS == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXHNRINS->automaticFlags.flags.bits.automatic && packetUBXHNRINS->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHNRINS: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHNRINS: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_HNR, UBX_HNR_INS); return packetUBXHNRINS->moduleQueried.moduleQueried.bits.all; } else if (packetUBXHNRINS->automaticFlags.flags.bits.automatic && !packetUBXHNRINS->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHNRINS: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHNRINS: Exit immediately")); + // } return (false); } else @@ -13170,13 +13408,13 @@ bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) // _debugSerial->println(F("getHNRINS: Polling")); // } - //The GPS is not automatically reporting HNR vehicle dynamics so we have to poll explicitly + // The GPS is not automatically reporting HNR vehicle dynamics so we have to poll explicitly packetCfg.cls = UBX_CLASS_HNR; packetCfg.id = UBX_HNR_INS; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -13202,29 +13440,31 @@ bool SFE_UBLOX_GNSS::getHNRINS(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS -//works. +// Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS +// works. bool SFE_UBLOX_GNSS::setAutoHNRINS(bool enable, uint16_t maxWait) { return setAutoHNRINSrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS -//works. +// Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS +// works. bool SFE_UBLOX_GNSS::setAutoHNRINS(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoHNRINSrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS -//works. +// Enable or disable automatic HNR vehicle dynamics message generation by the GNSS. This changes the way getHNRINS +// works. bool SFE_UBLOX_GNSS::setAutoHNRINSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXHNRINS == NULL) initPacketUBXHNRINS(); //Check that RAM has been allocated for the data - if (packetUBXHNRINS == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXHNRINS == NULL) + initPacketUBXHNRINS(); // Check that RAM has been allocated for the data + if (packetUBXHNRINS == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -13244,7 +13484,7 @@ bool SFE_UBLOX_GNSS::setAutoHNRINSrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -13252,9 +13492,9 @@ bool SFE_UBLOX_GNSS::setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXHNRINS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXHNRINS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXHNRINS->callbackData = new UBX_HNR_INS_data_t; //Allocate RAM for the main struct + packetUBXHNRINS->callbackData = new UBX_HNR_INS_data_t; // Allocate RAM for the main struct } if (packetUBXHNRINS->callbackData == NULL) @@ -13277,9 +13517,9 @@ bool SFE_UBLOX_GNSS::setAutoHNRINScallbackPtr(void (*callbackPointerPtr)(UBX_HNR if (!result) return (result); // Bail if setAuto failed - if (packetUBXHNRINS->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXHNRINS->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXHNRINS->callbackData = new UBX_HNR_INS_data_t; //Allocate RAM for the main struct + packetUBXHNRINS->callbackData = new UBX_HNR_INS_data_t; // Allocate RAM for the main struct } if (packetUBXHNRINS->callbackData == NULL) @@ -13295,12 +13535,13 @@ bool SFE_UBLOX_GNSS::setAutoHNRINScallbackPtr(void (*callbackPointerPtr)(UBX_HNR return (true); } -//In case no config access to the GNSS is possible and HNR vehicle dynamics is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and HNR vehicle dynamics is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHNRINS(bool enabled, bool implicitUpdate) { - if (packetUBXHNRINS == NULL) initPacketUBXHNRINS(); //Check that RAM has been allocated for the data - if (packetUBXHNRINS == NULL) //Bail if the RAM allocation failed + if (packetUBXHNRINS == NULL) + initPacketUBXHNRINS(); // Check that RAM has been allocated for the data + if (packetUBXHNRINS == NULL) // Bail if the RAM allocation failed return (false); bool changes = packetUBXHNRINS->automaticFlags.flags.bits.automatic != enabled || packetUBXHNRINS->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -13315,7 +13556,7 @@ bool SFE_UBLOX_GNSS::assumeAutoHNRINS(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXHNRINS and initialize it bool SFE_UBLOX_GNSS::initPacketUBXHNRINS() { - packetUBXHNRINS = new UBX_HNR_INS_t; //Allocate RAM for the main struct + packetUBXHNRINS = new UBX_HNR_INS_t; // Allocate RAM for the main struct if (packetUBXHNRINS == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -13332,50 +13573,53 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRINS() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushHNRINS() { - if (packetUBXHNRINS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXHNRINS->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXHNRINS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXHNRINS->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logHNRINS(bool enabled) { - if (packetUBXHNRINS == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXHNRINS == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXHNRINS->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } // ***** HNR PVT automatic support -//Get the HNR PVT data -// Returns true if the get HNR PVT is successful. Data is returned in hnrPVT -// Note: if hnrPVTQueried is true, it gets set to false by this function since we assume -// that the user will read hnrPVT immediately after this. I.e. this function will -// only return true _once_ after each auto HNR PVT is processed +// Get the HNR PVT data +// Returns true if the get HNR PVT is successful. Data is returned in hnrPVT +// Note: if hnrPVTQueried is true, it gets set to false by this function since we assume +// that the user will read hnrPVT immediately after this. I.e. this function will +// only return true _once_ after each auto HNR PVT is processed bool SFE_UBLOX_GNSS::getHNRPVT(uint16_t maxWait) { - if (packetUBXHNRPVT == NULL) initPacketUBXHNRPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXHNRPVT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXHNRPVT == NULL) + initPacketUBXHNRPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXHNRPVT == NULL) // Only attempt this if RAM allocation was successful return false; if (packetUBXHNRPVT->automaticFlags.flags.bits.automatic && packetUBXHNRPVT->automaticFlags.flags.bits.implicitUpdate) { - //The GPS is automatically reporting, we just check whether we got unread data - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHNRPVT: Autoreporting")); - // } + // The GPS is automatically reporting, we just check whether we got unread data + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHNRPVT: Autoreporting")); + // } checkUbloxInternal(&packetCfg, UBX_CLASS_HNR, UBX_HNR_PVT); return packetUBXHNRPVT->moduleQueried.moduleQueried.bits.all; } else if (packetUBXHNRPVT->automaticFlags.flags.bits.automatic && !packetUBXHNRPVT->automaticFlags.flags.bits.implicitUpdate) { - //Someone else has to call checkUblox for us... - // if (_printDebug == true) - // { - // _debugSerial->println(F("getHNRPVT: Exit immediately")); - // } + // Someone else has to call checkUblox for us... + // if (_printDebug == true) + // { + // _debugSerial->println(F("getHNRPVT: Exit immediately")); + // } return (false); } else @@ -13385,13 +13629,13 @@ bool SFE_UBLOX_GNSS::getHNRPVT(uint16_t maxWait) // _debugSerial->println(F("getHNRPVT: Polling")); // } - //The GPS is not automatically reporting HNR PVT so we have to poll explicitly + // The GPS is not automatically reporting HNR PVT so we have to poll explicitly packetCfg.cls = UBX_CLASS_HNR; packetCfg.id = UBX_HNR_PVT; packetCfg.len = 0; packetCfg.startingSpot = 0; - //The data is parsed as part of processing the response + // 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) @@ -13417,29 +13661,31 @@ bool SFE_UBLOX_GNSS::getHNRPVT(uint16_t maxWait) return (false); // Trap. We should never get here... } -//Enable or disable automatic HNR PVT message generation by the GNSS. This changes the way getHNRPVT -//works. +// Enable or disable automatic HNR PVT message generation by the GNSS. This changes the way getHNRPVT +// works. bool SFE_UBLOX_GNSS::setAutoHNRPVT(bool enable, uint16_t maxWait) { return setAutoHNRPVTrate(enable ? 1 : 0, true, maxWait); } -//Enable or disable automatic HNR PVT message generation by the GNSS. This changes the way getHNRPVT -//works. +// Enable or disable automatic HNR PVT message generation by the GNSS. This changes the way getHNRPVT +// works. bool SFE_UBLOX_GNSS::setAutoHNRPVT(bool enable, bool implicitUpdate, uint16_t maxWait) { return setAutoHNRPVTrate(enable ? 1 : 0, implicitUpdate, maxWait); } -//Enable or disable automatic HNR PVT message generation by the GNSS. This changes the way getHNRPVT -//works. +// Enable or disable automatic HNR PVT message generation by the GNSS. This changes the way getHNRPVT +// works. bool SFE_UBLOX_GNSS::setAutoHNRPVTrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait) { - if (packetUBXHNRPVT == NULL) initPacketUBXHNRPVT(); //Check that RAM has been allocated for the data - if (packetUBXHNRPVT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXHNRPVT == NULL) + initPacketUBXHNRPVT(); // Check that RAM has been allocated for the data + if (packetUBXHNRPVT == NULL) // Only attempt this if RAM allocation was successful return false; - if (rate > 127) rate = 127; + if (rate > 127) + rate = 127; packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_MSG; @@ -13459,7 +13705,7 @@ bool SFE_UBLOX_GNSS::setAutoHNRPVTrate(uint8_t rate, bool implicitUpdate, uint16 return ok; } -//Enable automatic navigation message generation by the GNSS. +// Enable automatic navigation message generation by the GNSS. bool SFE_UBLOX_GNSS::setAutoHNRPVTcallback(void (*callbackPointer)(UBX_HNR_PVT_data_t), uint16_t maxWait) { // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. @@ -13467,9 +13713,9 @@ bool SFE_UBLOX_GNSS::setAutoHNRPVTcallback(void (*callbackPointer)(UBX_HNR_PVT_d if (!result) return (result); // Bail if setAuto failed - if (packetUBXHNRPVT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXHNRPVT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXHNRPVT->callbackData = new UBX_HNR_PVT_data_t; //Allocate RAM for the main struct + packetUBXHNRPVT->callbackData = new UBX_HNR_PVT_data_t; // Allocate RAM for the main struct } if (packetUBXHNRPVT->callbackData == NULL) @@ -13492,9 +13738,9 @@ bool SFE_UBLOX_GNSS::setAutoHNRPVTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR if (!result) return (result); // Bail if setAuto failed - if (packetUBXHNRPVT->callbackData == NULL) //Check if RAM has been allocated for the callback copy + if (packetUBXHNRPVT->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXHNRPVT->callbackData = new UBX_HNR_PVT_data_t; //Allocate RAM for the main struct + packetUBXHNRPVT->callbackData = new UBX_HNR_PVT_data_t; // Allocate RAM for the main struct } if (packetUBXHNRPVT->callbackData == NULL) @@ -13510,12 +13756,13 @@ bool SFE_UBLOX_GNSS::setAutoHNRPVTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR return (true); } -//In case no config access to the GNSS is possible and HNR PVT is send cyclically already -//set config to suitable parameters +// In case no config access to the GNSS is possible and HNR PVT is send cyclically already +// set config to suitable parameters bool SFE_UBLOX_GNSS::assumeAutoHNRPVT(bool enabled, bool implicitUpdate) { - if (packetUBXHNRPVT == NULL) initPacketUBXHNRPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXHNRPVT == NULL) //Only attempt this if RAM allocation was successful + if (packetUBXHNRPVT == NULL) + initPacketUBXHNRPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXHNRPVT == NULL) // Only attempt this if RAM allocation was successful return false; bool changes = packetUBXHNRPVT->automaticFlags.flags.bits.automatic != enabled || packetUBXHNRPVT->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; @@ -13530,7 +13777,7 @@ bool SFE_UBLOX_GNSS::assumeAutoHNRPVT(bool enabled, bool implicitUpdate) // PRIVATE: Allocate RAM for packetUBXHNRPVT and initialize it bool SFE_UBLOX_GNSS::initPacketUBXHNRPVT() { - packetUBXHNRPVT = new UBX_HNR_PVT_t; //Allocate RAM for the main struct + packetUBXHNRPVT = new UBX_HNR_PVT_t; // Allocate RAM for the main struct if (packetUBXHNRPVT == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -13547,17 +13794,19 @@ bool SFE_UBLOX_GNSS::initPacketUBXHNRPVT() return (true); } -//Mark all the data as read/stale +// Mark all the data as read/stale void SFE_UBLOX_GNSS::flushHNRPVT() { - if (packetUBXHNRPVT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXHNRPVT->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXHNRPVT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXHNRPVT->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } -//Log this data in file buffer +// Log this data in file buffer void SFE_UBLOX_GNSS::logHNRPVT(bool enabled) { - if (packetUBXHNRPVT == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + if (packetUBXHNRPVT == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXHNRPVT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } @@ -13566,13 +13815,13 @@ void SFE_UBLOX_GNSS::logHNRPVT(bool enabled) // Set the mainTalkerId used by NMEA messages - allows all NMEA messages except GSV to be prefixed with GP instead of GN bool SFE_UBLOX_GNSS::setMainTalkerID(sfe_ublox_talker_ids_e id, uint16_t maxWait) { - //Get the current extended NMEA protocol configuration (V1) + // Get the current extended NMEA protocol configuration (V1) packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_NMEA; packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current settings. Loads into payloadCfg. + // Ask module for the current settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK return (false); @@ -13587,19 +13836,19 @@ bool SFE_UBLOX_GNSS::setMainTalkerID(sfe_ublox_talker_ids_e id, uint16_t maxWait // Enable/Disable NMEA High Precision Mode - include extra decimal places in the Lat and Lon bool SFE_UBLOX_GNSS::setHighPrecisionMode(bool enable, uint16_t maxWait) { - //Get the current extended NMEA protocol configuration (V1) + // Get the current extended NMEA protocol configuration (V1) packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_NMEA; packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current settings. Loads into payloadCfg. + // Ask module for the current settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK return (false); if (enable) { - payloadCfg[3] |= (1 << 3); // Set the highPrec flag + payloadCfg[3] |= (1 << 3); // Set the highPrec flag payloadCfg[3] &= ~((1 << 0) | (1 << 2)); // Clear the compat and limit82 flags } else @@ -13640,8 +13889,9 @@ uint32_t SFE_UBLOX_GNSS::getProcessNMEAMask() // Return 2 if the data is valid and is fresh/unread uint8_t SFE_UBLOX_GNSS::getLatestNMEAGPGGA(NMEA_GGA_data_t *data) { - if (storageNMEAGPGGA == NULL) initStorageNMEAGPGGA(); //Check that RAM has been allocated for the message - if (storageNMEAGPGGA == NULL) //Bail if the RAM allocation failed + if (storageNMEAGPGGA == NULL) + initStorageNMEAGPGGA(); // Check that RAM has been allocated for the message + if (storageNMEAGPGGA == NULL) // Bail if the RAM allocation failed return (false); checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Use a fake UBX class and ID. @@ -13662,11 +13912,12 @@ uint8_t SFE_UBLOX_GNSS::getLatestNMEAGPGGA(NMEA_GGA_data_t *data) return (result); } -//Enable a callback on the arrival of a GPGGA message +// Enable a callback on the arrival of a GPGGA message bool SFE_UBLOX_GNSS::setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)) { - if (storageNMEAGPGGA == NULL) initStorageNMEAGPGGA(); //Check that RAM has been allocated for the message - if (storageNMEAGPGGA == NULL) //Bail if the RAM allocation failed + if (storageNMEAGPGGA == NULL) + initStorageNMEAGPGGA(); // Check that RAM has been allocated for the message + if (storageNMEAGPGGA == NULL) // Bail if the RAM allocation failed return (false); if (storageNMEAGPGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy @@ -13689,8 +13940,9 @@ bool SFE_UBLOX_GNSS::setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_ bool SFE_UBLOX_GNSS::setNMEAGPGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)) { - if (storageNMEAGPGGA == NULL) initStorageNMEAGPGGA(); //Check that RAM has been allocated for the message - if (storageNMEAGPGGA == NULL) //Bail if the RAM allocation failed + if (storageNMEAGPGGA == NULL) + initStorageNMEAGPGGA(); // Check that RAM has been allocated for the message + if (storageNMEAGPGGA == NULL) // Bail if the RAM allocation failed return (false); if (storageNMEAGPGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy @@ -13714,7 +13966,7 @@ bool SFE_UBLOX_GNSS::setNMEAGPGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA // Private: allocate RAM for incoming NMEA GPGGA messages and initialize it bool SFE_UBLOX_GNSS::initStorageNMEAGPGGA() { - storageNMEAGPGGA = new NMEA_GPGGA_t; //Allocate RAM for the main struct + storageNMEAGPGGA = new NMEA_GPGGA_t; // Allocate RAM for the main struct if (storageNMEAGPGGA == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -13724,12 +13976,12 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGPGGA() return (false); } - storageNMEAGPGGA->workingCopy.length = 0; // Clear the data length - memset(storageNMEAGPGGA->workingCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage - storageNMEAGPGGA->completeCopy.length = 0; // Clear the data length + storageNMEAGPGGA->workingCopy.length = 0; // Clear the data length + memset(storageNMEAGPGGA->workingCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage + storageNMEAGPGGA->completeCopy.length = 0; // Clear the data length memset(storageNMEAGPGGA->completeCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage - storageNMEAGPGGA->callbackPointer = NULL; // Clear the callback pointers + storageNMEAGPGGA->callbackPointer = NULL; // Clear the callback pointers storageNMEAGPGGA->callbackPointerPtr = NULL; // Clear the callback pointers storageNMEAGPGGA->callbackCopy = NULL; @@ -13740,8 +13992,9 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGPGGA() uint8_t SFE_UBLOX_GNSS::getLatestNMEAGNGGA(NMEA_GGA_data_t *data) { - if (storageNMEAGNGGA == NULL) initStorageNMEAGNGGA(); //Check that RAM has been allocated for the message - if (storageNMEAGNGGA == NULL) //Bail if the RAM allocation failed + if (storageNMEAGNGGA == NULL) + initStorageNMEAGNGGA(); // Check that RAM has been allocated for the message + if (storageNMEAGNGGA == NULL) // Bail if the RAM allocation failed return (false); checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Use a fake UBX class and ID. @@ -13764,8 +14017,9 @@ uint8_t SFE_UBLOX_GNSS::getLatestNMEAGNGGA(NMEA_GGA_data_t *data) bool SFE_UBLOX_GNSS::setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)) { - if (storageNMEAGNGGA == NULL) initStorageNMEAGNGGA(); //Check that RAM has been allocated for the message - if (storageNMEAGNGGA == NULL) //Bail if the RAM allocation failed + if (storageNMEAGNGGA == NULL) + initStorageNMEAGNGGA(); // Check that RAM has been allocated for the message + if (storageNMEAGNGGA == NULL) // Bail if the RAM allocation failed return (false); if (storageNMEAGNGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy @@ -13788,8 +14042,9 @@ bool SFE_UBLOX_GNSS::setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_ bool SFE_UBLOX_GNSS::setNMEAGNGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)) { - if (storageNMEAGNGGA == NULL) initStorageNMEAGNGGA(); //Check that RAM has been allocated for the message - if (storageNMEAGNGGA == NULL) //Bail if the RAM allocation failed + if (storageNMEAGNGGA == NULL) + initStorageNMEAGNGGA(); // Check that RAM has been allocated for the message + if (storageNMEAGNGGA == NULL) // Bail if the RAM allocation failed return (false); if (storageNMEAGNGGA->callbackCopy == NULL) // Check if RAM has been allocated for the callback copy @@ -13813,7 +14068,7 @@ bool SFE_UBLOX_GNSS::setNMEAGNGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA // Private: allocate RAM for incoming NMEA GNGGA messages and initialize it bool SFE_UBLOX_GNSS::initStorageNMEAGNGGA() { - storageNMEAGNGGA = new NMEA_GNGGA_t; //Allocate RAM for the main struct + storageNMEAGNGGA = new NMEA_GNGGA_t; // Allocate RAM for the main struct if (storageNMEAGNGGA == NULL) { #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -13823,12 +14078,12 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGNGGA() return (false); } - storageNMEAGNGGA->workingCopy.length = 0; // Clear the data length - memset(storageNMEAGNGGA->workingCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage - storageNMEAGNGGA->completeCopy.length = 0; // Clear the data length + storageNMEAGNGGA->workingCopy.length = 0; // Clear the data length + memset(storageNMEAGNGGA->workingCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage + storageNMEAGNGGA->completeCopy.length = 0; // Clear the data length memset(storageNMEAGNGGA->completeCopy.nmea, 0, NMEA_GGA_MAX_LENGTH); // Clear the nmea storage - storageNMEAGNGGA->callbackPointer = NULL; // Clear the callback pointers + storageNMEAGNGGA->callbackPointer = NULL; // Clear the callback pointers storageNMEAGNGGA->callbackPointerPtr = NULL; // Clear the callback pointers storageNMEAGNGGA->callbackCopy = NULL; @@ -13839,9 +14094,9 @@ bool SFE_UBLOX_GNSS::initStorageNMEAGNGGA() // ***** CFG RATE Helper Functions -//Set the rate at which the module will give us an updated navigation solution -//Expects a number that is the updates per second. For example 1 = 1Hz, 2 = 2Hz, etc. -//Max is 40Hz(?!) +// Set the rate at which the module will give us an updated navigation solution +// Expects a number that is the updates per second. For example 1 = 1Hz, 2 = 2Hz, etc. +// Max is 40Hz(?!) bool SFE_UBLOX_GNSS::setNavigationFrequency(uint8_t navFreq, uint16_t maxWait) { if (navFreq == 0) // Return now if navFreq is zero @@ -13850,26 +14105,26 @@ bool SFE_UBLOX_GNSS::setNavigationFrequency(uint8_t navFreq, uint16_t maxWait) if (navFreq > 40) navFreq = 40; // Limit navFreq to 40Hz so i2cPollingWait is set correctly - //Adjust the I2C polling timeout based on update rate - //Do this even if the sendCommand fails - i2cPollingWaitNAV = 1000 / (((int)navFreq) * 4); //This is the number of ms to wait between checks for new I2C data. Max is 250. Min is 6. + // Adjust the I2C polling timeout based on update rate + // Do this even if the sendCommand fails + i2cPollingWaitNAV = 1000 / (((int)navFreq) * 4); // This is the number of ms to wait between checks for new I2C data. Max is 250. Min is 6. i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR - //Query the module + // Query the module packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_RATE; packetCfg.len = 0; packetCfg.startingSpot = 0; - //This will load the payloadCfg array with current settings of the given register + // This will load the payloadCfg array with current settings of the given register if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK - return (false); //If command send fails then bail + return (false); // If command send fails then bail uint16_t measurementRate = 1000 / navFreq; - //payloadCfg is now loaded with current bytes. Change only the ones we need to - payloadCfg[0] = measurementRate & 0xFF; //measRate LSB - payloadCfg[1] = measurementRate >> 8; //measRate MSB + // payloadCfg is now loaded with current bytes. Change only the ones we need to + payloadCfg[0] = measurementRate & 0xFF; // measRate LSB + payloadCfg[1] = measurementRate >> 8; // measRate MSB bool result = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK @@ -13878,50 +14133,51 @@ bool SFE_UBLOX_GNSS::setNavigationFrequency(uint8_t navFreq, uint16_t maxWait) return (result); } -//Get the rate at which the module is outputting nav solutions +// Get the rate at which the module is outputting nav solutions uint8_t SFE_UBLOX_GNSS::getNavigationFrequency(uint16_t maxWait) { - if (packetUBXCFGRATE == NULL) initPacketUBXCFGRATE(); //Check that RAM has been allocated for the RATE data - if (packetUBXCFGRATE == NULL) //Bail if the RAM allocation failed + if (packetUBXCFGRATE == NULL) + initPacketUBXCFGRATE(); // Check that RAM has been allocated for the RATE data + if (packetUBXCFGRATE == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXCFGRATE->moduleQueried.moduleQueried.bits.measRate == false) getNavigationFrequencyInternal(maxWait); - packetUBXCFGRATE->moduleQueried.moduleQueried.bits.measRate = false; //Since we are about to give this to user, mark this data as stale + packetUBXCFGRATE->moduleQueried.moduleQueried.bits.measRate = false; // Since we are about to give this to user, mark this data as stale packetUBXCFGRATE->moduleQueried.moduleQueried.bits.all = false; uint16_t measurementRate = packetUBXCFGRATE->data.measRate; - measurementRate = 1000 / measurementRate; //This may return an int when it's a float, but I'd rather not return 4 bytes + measurementRate = 1000 / measurementRate; // This may return an int when it's a float, but I'd rather not return 4 bytes return (measurementRate); } -//Set the elapsed time between GNSS measurements in milliseconds, which defines the rate +// Set the elapsed time between GNSS measurements in milliseconds, which defines the rate bool SFE_UBLOX_GNSS::setMeasurementRate(uint16_t rate, uint16_t maxWait) { if (rate < 25) // "Measurement rate should be greater than or equal to 25 ms." rate = 25; - //Adjust the I2C polling timeout based on update rate + // Adjust the I2C polling timeout based on update rate if (rate >= 1000) i2cPollingWaitNAV = 250; else - i2cPollingWaitNAV = rate / 4; //This is the number of ms to wait between checks for new I2C data + i2cPollingWaitNAV = rate / 4; // This is the number of ms to wait between checks for new I2C data i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR - //Query the module + // Query the module packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_RATE; packetCfg.len = 0; packetCfg.startingSpot = 0; - //This will load the payloadCfg array with current settings of the given register + // This will load the payloadCfg array with current settings of the given register if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK - return (false); //If command send fails then bail + return (false); // If command send fails then bail - //payloadCfg is now loaded with current bytes. Change only the ones we need to - payloadCfg[0] = rate & 0xFF; //measRate LSB - payloadCfg[1] = rate >> 8; //measRate MSB + // payloadCfg is now loaded with current bytes. Change only the ones we need to + payloadCfg[0] = rate & 0xFF; // measRate LSB + payloadCfg[1] = rate >> 8; // measRate MSB bool result = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK @@ -13930,37 +14186,38 @@ bool SFE_UBLOX_GNSS::setMeasurementRate(uint16_t rate, uint16_t maxWait) return (result); } -//Return the elapsed time between GNSS measurements in milliseconds, which defines the rate +// Return the elapsed time between GNSS measurements in milliseconds, which defines the rate uint16_t SFE_UBLOX_GNSS::getMeasurementRate(uint16_t maxWait) { - if (packetUBXCFGRATE == NULL) initPacketUBXCFGRATE(); //Check that RAM has been allocated for the RATE data - if (packetUBXCFGRATE == NULL) //Bail if the RAM allocation failed + if (packetUBXCFGRATE == NULL) + initPacketUBXCFGRATE(); // Check that RAM has been allocated for the RATE data + if (packetUBXCFGRATE == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXCFGRATE->moduleQueried.moduleQueried.bits.measRate == false) getNavigationFrequencyInternal(maxWait); - packetUBXCFGRATE->moduleQueried.moduleQueried.bits.measRate = false; //Since we are about to give this to user, mark this data as stale + packetUBXCFGRATE->moduleQueried.moduleQueried.bits.measRate = false; // Since we are about to give this to user, mark this data as stale packetUBXCFGRATE->moduleQueried.moduleQueried.bits.all = false; return (packetUBXCFGRATE->data.measRate); } -//Set the ratio between the number of measurements and the number of navigation solutions. Unit is cycles. Max is 127. +// Set the ratio between the number of measurements and the number of navigation solutions. Unit is cycles. Max is 127. bool SFE_UBLOX_GNSS::setNavigationRate(uint16_t rate, uint16_t maxWait) { - //Query the module + // Query the module packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_RATE; packetCfg.len = 0; packetCfg.startingSpot = 0; - //This will load the payloadCfg array with current settings of the given register + // This will load the payloadCfg array with current settings of the given register if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK - return (false); //If command send fails then bail + return (false); // If command send fails then bail - //payloadCfg is now loaded with current bytes. Change only the ones we need to - payloadCfg[2] = rate & 0xFF; //navRate LSB - payloadCfg[3] = rate >> 8; //navRate MSB + // payloadCfg is now loaded with current bytes. Change only the ones we need to + payloadCfg[2] = rate & 0xFF; // navRate LSB + payloadCfg[3] = rate >> 8; // navRate MSB bool result = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK @@ -13969,117 +14226,126 @@ bool SFE_UBLOX_GNSS::setNavigationRate(uint16_t rate, uint16_t maxWait) return (result); } -//Return the ratio between the number of measurements and the number of navigation solutions. Unit is cycles +// Return the ratio between the number of measurements and the number of navigation solutions. Unit is cycles uint16_t SFE_UBLOX_GNSS::getNavigationRate(uint16_t maxWait) { - if (packetUBXCFGRATE == NULL) initPacketUBXCFGRATE(); //Check that RAM has been allocated for the RATE data - if (packetUBXCFGRATE == NULL) //Bail if the RAM allocation failed + if (packetUBXCFGRATE == NULL) + initPacketUBXCFGRATE(); // Check that RAM has been allocated for the RATE data + if (packetUBXCFGRATE == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXCFGRATE->moduleQueried.moduleQueried.bits.navRate == false) getNavigationFrequencyInternal(maxWait); - packetUBXCFGRATE->moduleQueried.moduleQueried.bits.navRate = false; //Since we are about to give this to user, mark this data as stale + packetUBXCFGRATE->moduleQueried.moduleQueried.bits.navRate = false; // Since we are about to give this to user, mark this data as stale packetUBXCFGRATE->moduleQueried.moduleQueried.bits.all = false; return (packetUBXCFGRATE->data.navRate); } -//Mark the CFG RATE data as read/stale +// Mark the CFG RATE data as read/stale void SFE_UBLOX_GNSS::flushCFGRATE() { - if (packetUBXCFGRATE == NULL) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) - packetUBXCFGRATE->moduleQueried.moduleQueried.all = 0; //Mark all datums as stale (read before) + if (packetUBXCFGRATE == NULL) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXCFGRATE->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before) } // ***** DOP Helper Functions uint16_t SFE_UBLOX_GNSS::getGeometricDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVDOP->moduleQueried.moduleQueried.bits.gDOP == false) getDOP(maxWait); - packetUBXNAVDOP->moduleQueried.moduleQueried.bits.gDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVDOP->moduleQueried.moduleQueried.bits.gDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVDOP->data.gDOP); } uint16_t SFE_UBLOX_GNSS::getPositionDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVDOP->moduleQueried.moduleQueried.bits.pDOP == false) getDOP(maxWait); - packetUBXNAVDOP->moduleQueried.moduleQueried.bits.pDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVDOP->moduleQueried.moduleQueried.bits.pDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVDOP->data.pDOP); } uint16_t SFE_UBLOX_GNSS::getTimeDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVDOP->moduleQueried.moduleQueried.bits.tDOP == false) getDOP(maxWait); - packetUBXNAVDOP->moduleQueried.moduleQueried.bits.tDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVDOP->moduleQueried.moduleQueried.bits.tDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVDOP->data.tDOP); } uint16_t SFE_UBLOX_GNSS::getVerticalDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVDOP->moduleQueried.moduleQueried.bits.vDOP == false) getDOP(maxWait); - packetUBXNAVDOP->moduleQueried.moduleQueried.bits.vDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVDOP->moduleQueried.moduleQueried.bits.vDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVDOP->data.vDOP); } uint16_t SFE_UBLOX_GNSS::getHorizontalDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVDOP->moduleQueried.moduleQueried.bits.hDOP == false) getDOP(maxWait); - packetUBXNAVDOP->moduleQueried.moduleQueried.bits.hDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVDOP->moduleQueried.moduleQueried.bits.hDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVDOP->data.hDOP); } uint16_t SFE_UBLOX_GNSS::getNorthingDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVDOP->moduleQueried.moduleQueried.bits.nDOP == false) getDOP(maxWait); - packetUBXNAVDOP->moduleQueried.moduleQueried.bits.nDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVDOP->moduleQueried.moduleQueried.bits.nDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVDOP->data.nDOP); } uint16_t SFE_UBLOX_GNSS::getEastingDOP(uint16_t maxWait) { - if (packetUBXNAVDOP == NULL) initPacketUBXNAVDOP(); //Check that RAM has been allocated for the DOP data - if (packetUBXNAVDOP == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVDOP == NULL) + initPacketUBXNAVDOP(); // Check that RAM has been allocated for the DOP data + if (packetUBXNAVDOP == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVDOP->moduleQueried.moduleQueried.bits.eDOP == false) getDOP(maxWait); - packetUBXNAVDOP->moduleQueried.moduleQueried.bits.eDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVDOP->moduleQueried.moduleQueried.bits.eDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVDOP->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVDOP->data.eDOP); } @@ -14088,39 +14354,42 @@ uint16_t SFE_UBLOX_GNSS::getEastingDOP(uint16_t maxWait) float SFE_UBLOX_GNSS::getATTroll(uint16_t maxWait) // Returned as degrees { - if (packetUBXNAVATT == NULL) initPacketUBXNAVATT(); //Check that RAM has been allocated for the NAV ATT data - if (packetUBXNAVATT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVATT == NULL) + initPacketUBXNAVATT(); // Check that RAM has been allocated for the NAV ATT data + if (packetUBXNAVATT == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXNAVATT->moduleQueried.moduleQueried.bits.roll == false) getNAVATT(maxWait); - packetUBXNAVATT->moduleQueried.moduleQueried.bits.roll = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVATT->moduleQueried.moduleQueried.bits.roll = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVATT->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVATT->data.roll) / 100000.0); // Convert to degrees } float SFE_UBLOX_GNSS::getATTpitch(uint16_t maxWait) // Returned as degrees { - if (packetUBXNAVATT == NULL) initPacketUBXNAVATT(); //Check that RAM has been allocated for the NAV ATT data - if (packetUBXNAVATT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVATT == NULL) + initPacketUBXNAVATT(); // Check that RAM has been allocated for the NAV ATT data + if (packetUBXNAVATT == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXNAVATT->moduleQueried.moduleQueried.bits.pitch == false) getNAVATT(maxWait); - packetUBXNAVATT->moduleQueried.moduleQueried.bits.pitch = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVATT->moduleQueried.moduleQueried.bits.pitch = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVATT->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVATT->data.pitch) / 100000.0); // Convert to degrees } float SFE_UBLOX_GNSS::getATTheading(uint16_t maxWait) // Returned as degrees { - if (packetUBXNAVATT == NULL) initPacketUBXNAVATT(); //Check that RAM has been allocated for the NAV ATT data - if (packetUBXNAVATT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVATT == NULL) + initPacketUBXNAVATT(); // Check that RAM has been allocated for the NAV ATT data + if (packetUBXNAVATT == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXNAVATT->moduleQueried.moduleQueried.bits.heading == false) getNAVATT(maxWait); - packetUBXNAVATT->moduleQueried.moduleQueried.bits.heading = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVATT->moduleQueried.moduleQueried.bits.heading = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVATT->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVATT->data.heading) / 100000.0); // Convert to degrees } @@ -14129,134 +14398,144 @@ float SFE_UBLOX_GNSS::getATTheading(uint16_t maxWait) // Returned as degrees uint32_t SFE_UBLOX_GNSS::getTimeOfWeek(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.iTOW == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.iTOW = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.iTOW = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.iTOW); } -//Get the current year +// Get the current year uint16_t SFE_UBLOX_GNSS::getYear(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.year == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.year = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.year = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.year); } -//Get the current month +// Get the current month uint8_t SFE_UBLOX_GNSS::getMonth(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.month == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.month = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.month = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.month); } -//Get the current day +// Get the current day uint8_t SFE_UBLOX_GNSS::getDay(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.day == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.day = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.day = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.day); } -//Get the current hour +// Get the current hour uint8_t SFE_UBLOX_GNSS::getHour(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hour == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hour = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hour = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.hour); } -//Get the current minute +// Get the current minute uint8_t SFE_UBLOX_GNSS::getMinute(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.min == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.min = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.min = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.min); } -//Get the current second +// Get the current second uint8_t SFE_UBLOX_GNSS::getSecond(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.sec == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.sec = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.sec = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.sec); } -//Get the current millisecond +// Get the current millisecond uint16_t SFE_UBLOX_GNSS::getMillisecond(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.iTOW == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.iTOW = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.iTOW = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.iTOW % 1000); } -//Get the current nanoseconds - includes milliseconds +// Get the current nanoseconds - includes milliseconds int32_t SFE_UBLOX_GNSS::getNanosecond(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.nano == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.nano = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.nano = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.nano); } -//Get the current Unix epoch time rounded up to the nearest second +// Get the current Unix epoch time rounded up to the nearest second uint32_t SFE_UBLOX_GNSS::getUnixEpoch(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.sec == false) @@ -14270,19 +14549,23 @@ uint32_t SFE_UBLOX_GNSS::getUnixEpoch(uint16_t maxWait) packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; // assemble time elements into time_t - credits to Thomas Roell @ https://github.com/GrumpyOldPizza uint32_t t = ((((((((uint32_t)packetUBXNAVPVT->data.year - 1970) * 365) + ((((uint32_t)packetUBXNAVPVT->data.year - 1970) + 3) / 4)) + - DAYS_SINCE_MONTH[((uint32_t)packetUBXNAVPVT->data.year - 1970) & 3][(uint32_t)packetUBXNAVPVT->data.month] + - ((uint32_t)packetUBXNAVPVT->data.day - 1)) * 24 + - (uint32_t)packetUBXNAVPVT->data.hour) * 60 + - (uint32_t)packetUBXNAVPVT->data.min) * 60 + - (uint32_t)packetUBXNAVPVT->data.sec); + DAYS_SINCE_MONTH[((uint32_t)packetUBXNAVPVT->data.year - 1970) & 3][(uint32_t)packetUBXNAVPVT->data.month] + + ((uint32_t)packetUBXNAVPVT->data.day - 1)) * + 24 + + (uint32_t)packetUBXNAVPVT->data.hour) * + 60 + + (uint32_t)packetUBXNAVPVT->data.min) * + 60 + + (uint32_t)packetUBXNAVPVT->data.sec); return t; } -//Get the current Unix epoch including microseconds -uint32_t SFE_UBLOX_GNSS::getUnixEpoch(uint32_t& microsecond, uint16_t maxWait) +// Get the current Unix epoch including microseconds +uint32_t SFE_UBLOX_GNSS::getUnixEpoch(uint32_t µsecond, uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.nano == false) @@ -14297,420 +14580,452 @@ uint32_t SFE_UBLOX_GNSS::getUnixEpoch(uint32_t& microsecond, uint16_t maxWait) packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; // assemble time elements into time_t - credits to Thomas Roell @ https://github.com/GrumpyOldPizza uint32_t t = ((((((((uint32_t)packetUBXNAVPVT->data.year - 1970) * 365) + ((((uint32_t)packetUBXNAVPVT->data.year - 1970) + 3) / 4)) + - DAYS_SINCE_MONTH[((uint32_t)packetUBXNAVPVT->data.year - 1970) & 3][(uint32_t)packetUBXNAVPVT->data.month] + - ((uint32_t)packetUBXNAVPVT->data.day - 1)) * 24 + - (uint32_t)packetUBXNAVPVT->data.hour) * 60 + - (uint32_t)packetUBXNAVPVT->data.min) * 60 + - (uint32_t)packetUBXNAVPVT->data.sec); + DAYS_SINCE_MONTH[((uint32_t)packetUBXNAVPVT->data.year - 1970) & 3][(uint32_t)packetUBXNAVPVT->data.month] + + ((uint32_t)packetUBXNAVPVT->data.day - 1)) * + 24 + + (uint32_t)packetUBXNAVPVT->data.hour) * + 60 + + (uint32_t)packetUBXNAVPVT->data.min) * + 60 + + (uint32_t)packetUBXNAVPVT->data.sec); int32_t us = packetUBXNAVPVT->data.nano / 1000; microsecond = (uint32_t)us; // adjust t if nano is negative - if(us < 0) { + if (us < 0) + { microsecond = (uint32_t)(us + 1000000); t--; } return t; } -//Get the current date validity +// Get the current date validity bool SFE_UBLOX_GNSS::getDateValid(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.validDate == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.validDate = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.validDate = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return ((bool)packetUBXNAVPVT->data.valid.bits.validDate); } -//Get the current time validity +// Get the current time validity bool SFE_UBLOX_GNSS::getTimeValid(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.validTime == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.validTime = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.validTime = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return ((bool)packetUBXNAVPVT->data.valid.bits.validTime); } -//Check to see if the UTC time has been fully resolved +// Check to see if the UTC time has been fully resolved bool SFE_UBLOX_GNSS::getTimeFullyResolved(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fullyResolved == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fullyResolved = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fullyResolved = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return ((bool)packetUBXNAVPVT->data.valid.bits.fullyResolved); } - -//Get the confirmed date validity -bool SFE_UBLOX_GNSS:: getConfirmedDate(uint16_t maxWait) +// Get the confirmed date validity +bool SFE_UBLOX_GNSS::getConfirmedDate(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.confirmedDate == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.confirmedDate = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.confirmedDate = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return ((bool)packetUBXNAVPVT->data.flags2.bits.confirmedDate); } -//Get the confirmed time validity -bool SFE_UBLOX_GNSS:: getConfirmedTime(uint16_t maxWait) +// Get the confirmed time validity +bool SFE_UBLOX_GNSS::getConfirmedTime(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.confirmedTime == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.confirmedTime = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.confirmedTime = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return ((bool)packetUBXNAVPVT->data.flags2.bits.confirmedTime); } -//Get the current fix type -//0=no fix, 1=dead reckoning, 2=2D, 3=3D, 4=GNSS, 5=Time fix +// Get the current fix type +// 0=no fix, 1=dead reckoning, 2=2D, 3=3D, 4=GNSS, 5=Time fix uint8_t SFE_UBLOX_GNSS::getFixType(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fixType == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fixType = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fixType = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.fixType); } -//Get whether we have a valid fix (i.e within DOP & accuracy masks) +// Get whether we have a valid fix (i.e within DOP & accuracy masks) bool SFE_UBLOX_GNSS::getGnssFixOk(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.gnssFixOK == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.gnssFixOK = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.gnssFixOK = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.flags.bits.gnssFixOK); } -//Get whether differential corrections were applied +// Get whether differential corrections were applied bool SFE_UBLOX_GNSS::getDiffSoln(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.diffSoln == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.diffSoln = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.diffSoln = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.flags.bits.diffSoln); } -//Get whether head vehicle valid or not +// Get whether head vehicle valid or not bool SFE_UBLOX_GNSS::getHeadVehValid(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.headVehValid == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.headVehValid = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.headVehValid = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.flags.bits.headVehValid); } -//Get the carrier phase range solution status -//Useful when querying module to see if it has high-precision RTK fix -//0=No solution, 1=Float solution, 2=Fixed solution +// Get the carrier phase range solution status +// Useful when querying module to see if it has high-precision RTK fix +// 0=No solution, 1=Float solution, 2=Fixed solution uint8_t SFE_UBLOX_GNSS::getCarrierSolutionType(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.carrSoln == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.carrSoln = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.carrSoln = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.flags.bits.carrSoln); } -//Get the number of satellites used in fix +// Get the number of satellites used in fix uint8_t SFE_UBLOX_GNSS::getSIV(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.numSV == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.numSV = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.numSV = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.numSV); } -//Get the current longitude in degrees -//Returns a long representing the number of degrees *10^-7 +// Get the current longitude in degrees +// Returns a long representing the number of degrees *10^-7 int32_t SFE_UBLOX_GNSS::getLongitude(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.lon == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.lon = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.lon = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.lon); } -//Get the current latitude in degrees -//Returns a long representing the number of degrees *10^-7 +// Get the current latitude in degrees +// Returns a long representing the number of degrees *10^-7 int32_t SFE_UBLOX_GNSS::getLatitude(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.lat == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.lat = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.lat = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.lat); } -//Get the current altitude in mm according to ellipsoid model +// Get the current altitude in mm according to ellipsoid model int32_t SFE_UBLOX_GNSS::getAltitude(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.height == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.height = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.height = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.height); } -//Get the current altitude in mm according to mean sea level -//Ellipsoid model: https://www.esri.com/news/arcuser/0703/geoid1of3.html -//Difference between Ellipsoid Model and Mean Sea Level: https://eos-gnss.com/elevation-for-beginners/ +// Get the current altitude in mm according to mean sea level +// Ellipsoid model: https://www.esri.com/news/arcuser/0703/geoid1of3.html +// Difference between Ellipsoid Model and Mean Sea Level: https://eos-gnss.com/elevation-for-beginners/ int32_t SFE_UBLOX_GNSS::getAltitudeMSL(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hMSL == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hMSL = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hMSL = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.hMSL); } int32_t SFE_UBLOX_GNSS::getHorizontalAccEst(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hAcc == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.hAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.hAcc); } int32_t SFE_UBLOX_GNSS::getVerticalAccEst(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.vAcc == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.vAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.vAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.vAcc); } int32_t SFE_UBLOX_GNSS::getNedNorthVel(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.velN == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.velN = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.velN = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.velN); } int32_t SFE_UBLOX_GNSS::getNedEastVel(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.velE == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.velE = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.velE = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.velE); } int32_t SFE_UBLOX_GNSS::getNedDownVel(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.velD == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.velD = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.velD = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.velD); } -//Get the ground speed in mm/s +// Get the ground speed in mm/s int32_t SFE_UBLOX_GNSS::getGroundSpeed(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.gSpeed == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.gSpeed = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.gSpeed = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.gSpeed); } -//Get the heading of motion (as opposed to heading of car) in degrees * 10^-5 +// Get the heading of motion (as opposed to heading of car) in degrees * 10^-5 int32_t SFE_UBLOX_GNSS::getHeading(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headMot == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headMot = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headMot = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.headMot); } uint32_t SFE_UBLOX_GNSS::getSpeedAccEst(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.sAcc == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.sAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.sAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.sAcc); } uint32_t SFE_UBLOX_GNSS::getHeadingAccEst(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headAcc == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.headAcc); } -//Get the positional dillution of precision * 10^-2 (dimensionless) +// Get the positional dillution of precision * 10^-2 (dimensionless) uint16_t SFE_UBLOX_GNSS::getPDOP(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.pDOP == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.pDOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.pDOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.pDOP); } bool SFE_UBLOX_GNSS::getInvalidLlh(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.invalidLlh == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.invalidLlh = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.invalidLlh = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return ((bool)packetUBXNAVPVT->data.flags3.bits.invalidLlh); } int32_t SFE_UBLOX_GNSS::getHeadVeh(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headVeh == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headVeh = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.headVeh = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.headVeh); } int16_t SFE_UBLOX_GNSS::getMagDec(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.magDec == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.magDec = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.magDec = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.magDec); } uint16_t SFE_UBLOX_GNSS::getMagAcc(uint16_t maxWait) { - if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data - if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVT == NULL) + initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data + if (packetUBXNAVPVT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.magAcc == false) getPVT(maxWait); - packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.magAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVT->moduleQueried.moduleQueried2.bits.magAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVT->data.magAcc); } @@ -14718,31 +15033,33 @@ uint16_t SFE_UBLOX_GNSS::getMagAcc(uint16_t maxWait) // getGeoidSeparation is currently redundant. The geoid separation seems to only be provided in NMEA GGA and GNS messages. int32_t SFE_UBLOX_GNSS::getGeoidSeparation(uint16_t maxWait) { - uint16_t ignoreMe = maxWait; ignoreMe += 0; // Do something with maxWait just to get rid of the pesky compiler warning + uint16_t ignoreMe = maxWait; + ignoreMe += 0; // Do something with maxWait just to get rid of the pesky compiler warning return (0); } // ***** HPPOSECEF Helper Functions -//Get the current 3D high precision positional accuracy - a fun thing to watch -//Returns a long representing the 3D accuracy in millimeters +// Get the current 3D high precision positional accuracy - a fun thing to watch +// Returns a long representing the 3D accuracy in millimeters uint32_t SFE_UBLOX_GNSS::getPositionAccuracy(uint16_t maxWait) { - if (packetUBXNAVHPPOSECEF == NULL) initPacketUBXNAVHPPOSECEF(); //Check that RAM has been allocated for the HPPOSECEF data - if (packetUBXNAVHPPOSECEF == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSECEF == NULL) + initPacketUBXNAVHPPOSECEF(); // Check that RAM has been allocated for the HPPOSECEF data + if (packetUBXNAVHPPOSECEF == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.bits.pAcc == false) getNAVHPPOSECEF(maxWait); - packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.bits.pAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.bits.pAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSECEF->moduleQueried.moduleQueried.bits.all = false; uint32_t tempAccuracy = packetUBXNAVHPPOSECEF->data.pAcc; if ((tempAccuracy % 10) >= 5) - tempAccuracy += 5; //Round fraction of mm up to next mm if .5 or above - tempAccuracy /= 10; //Convert 0.1mm units to mm + tempAccuracy += 5; // Round fraction of mm up to next mm if .5 or above + tempAccuracy /= 10; // Convert 0.1mm units to mm return (tempAccuracy); } @@ -14751,143 +15068,154 @@ uint32_t SFE_UBLOX_GNSS::getPositionAccuracy(uint16_t maxWait) uint32_t SFE_UBLOX_GNSS::getTimeOfWeekFromHPPOSLLH(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.iTOW == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.iTOW = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.iTOW = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.iTOW); } int32_t SFE_UBLOX_GNSS::getHighResLongitude(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lon == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lon = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lon = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.lon); } int32_t SFE_UBLOX_GNSS::getHighResLatitude(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lat == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lat = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lat = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.lat); } int32_t SFE_UBLOX_GNSS::getElipsoid(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.height == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.height = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.height = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.height); } int32_t SFE_UBLOX_GNSS::getMeanSeaLevel(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hMSL == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hMSL = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hMSL = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.hMSL); } int8_t SFE_UBLOX_GNSS::getHighResLongitudeHp(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lonHp == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lonHp = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.lonHp = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.lonHp); } int8_t SFE_UBLOX_GNSS::getHighResLatitudeHp(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.latHp == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.latHp = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.latHp = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.latHp); } int8_t SFE_UBLOX_GNSS::getElipsoidHp(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.heightHp == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.heightHp = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.heightHp = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.heightHp); } int8_t SFE_UBLOX_GNSS::getMeanSeaLevelHp(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hMSLHp == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hMSLHp = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hMSLHp = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.hMSLHp); } uint32_t SFE_UBLOX_GNSS::getHorizontalAccuracy(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hAcc == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.hAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.hAcc); } uint32_t SFE_UBLOX_GNSS::getVerticalAccuracy(uint16_t maxWait) { - if (packetUBXNAVHPPOSLLH == NULL) initPacketUBXNAVHPPOSLLH(); //Check that RAM has been allocated for the HPPOSLLH data - if (packetUBXNAVHPPOSLLH == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVHPPOSLLH == NULL) + initPacketUBXNAVHPPOSLLH(); // Check that RAM has been allocated for the HPPOSLLH data + if (packetUBXNAVHPPOSLLH == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.vAcc == false) getHPPOSLLH(maxWait); - packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.vAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.vAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVHPPOSLLH->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVHPPOSLLH->data.vAcc); } @@ -14896,52 +15224,56 @@ uint32_t SFE_UBLOX_GNSS::getVerticalAccuracy(uint16_t maxWait) int32_t SFE_UBLOX_GNSS::getVehicleRoll(uint16_t maxWait) { - if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data - if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVAT == NULL) + initPacketUBXNAVPVAT(); // Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehRoll == false) getNAVPVAT(maxWait); - packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehRoll = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehRoll = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVAT->data.vehRoll); } int32_t SFE_UBLOX_GNSS::getVehiclePitch(uint16_t maxWait) { - if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data - if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVAT == NULL) + initPacketUBXNAVPVAT(); // Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehPitch == false) getNAVPVAT(maxWait); - packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehPitch = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehPitch = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVAT->data.vehPitch); } int32_t SFE_UBLOX_GNSS::getVehicleHeading(uint16_t maxWait) { - if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data - if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVAT == NULL) + initPacketUBXNAVPVAT(); // Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehHeading == false) getNAVPVAT(maxWait); - packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehHeading = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.vehHeading = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVAT->data.vehHeading); } int32_t SFE_UBLOX_GNSS::getMotionHeading(uint16_t maxWait) { - if (packetUBXNAVPVAT == NULL) initPacketUBXNAVPVAT(); //Check that RAM has been allocated for the PVAT data - if (packetUBXNAVPVAT == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVPVAT == NULL) + initPacketUBXNAVPVAT(); // Check that RAM has been allocated for the PVAT data + if (packetUBXNAVPVAT == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.motHeading == false) getNAVPVAT(maxWait); - packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.motHeading = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.motHeading = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false; return (packetUBXNAVPVAT->data.motHeading); } @@ -14950,81 +15282,86 @@ int32_t SFE_UBLOX_GNSS::getMotionHeading(uint16_t maxWait) bool SFE_UBLOX_GNSS::getSurveyInActive(uint16_t maxWait) { - if (packetUBXNAVSVIN == NULL) initPacketUBXNAVSVIN(); //Check that RAM has been allocated for the SVIN data - if (packetUBXNAVSVIN == NULL) //Bail if the RAM allocation failed + 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; if (packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.active == false) getSurveyStatus(maxWait); - packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.active = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.active = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.all = false; return ((bool)packetUBXNAVSVIN->data.active); } bool SFE_UBLOX_GNSS::getSurveyInValid(uint16_t maxWait) { - if (packetUBXNAVSVIN == NULL) initPacketUBXNAVSVIN(); //Check that RAM has been allocated for the SVIN data - if (packetUBXNAVSVIN == NULL) //Bail if the RAM allocation failed + 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; if (packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.valid == false) getSurveyStatus(maxWait); - packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.valid = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.valid = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.all = false; return ((bool)packetUBXNAVSVIN->data.valid); } uint16_t SFE_UBLOX_GNSS::getSurveyInObservationTime(uint16_t maxWait) // Truncated to 65535 seconds { - if (packetUBXNAVSVIN == NULL) initPacketUBXNAVSVIN(); //Check that RAM has been allocated for the SVIN data - if (packetUBXNAVSVIN == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVSVIN == NULL) + initPacketUBXNAVSVIN(); // Check that RAM has been allocated for the SVIN data + if (packetUBXNAVSVIN == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.dur == false) getSurveyStatus(maxWait); - packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.dur = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.dur = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.all = false; - //dur (Passed survey-in observation time) is U4 (uint32_t) seconds. We truncate to 16 bits + // dur (Passed survey-in observation time) is U4 (uint32_t) seconds. We truncate to 16 bits //(waiting more than 65535 seconds (18.2 hours) seems excessive!) uint32_t tmpObsTime = packetUBXNAVSVIN->data.dur; if (tmpObsTime <= 0xFFFF) { - return((uint16_t)tmpObsTime); + return ((uint16_t)tmpObsTime); } else { - return(0xFFFF); + return (0xFFFF); } } float SFE_UBLOX_GNSS::getSurveyInMeanAccuracy(uint16_t maxWait) // Returned as m { - if (packetUBXNAVSVIN == NULL) initPacketUBXNAVSVIN(); //Check that RAM has been allocated for the SVIN data - if (packetUBXNAVSVIN == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVSVIN == NULL) + initPacketUBXNAVSVIN(); // Check that RAM has been allocated for the SVIN data + if (packetUBXNAVSVIN == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.meanAcc == false) getSurveyStatus(maxWait); - packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.meanAcc = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.meanAcc = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVSVIN->moduleQueried.moduleQueried.bits.all = false; // meanAcc is U4 (uint32_t) in 0.1mm. We convert this to float. uint32_t tempFloat = packetUBXNAVSVIN->data.meanAcc; - return (((float)tempFloat) / 10000.0); //Convert 0.1mm to m + return (((float)tempFloat) / 10000.0); // Convert 0.1mm to m } // ***** TIMELS Helper Functions -uint8_t SFE_UBLOX_GNSS::getLeapIndicator(int32_t& timeToLsEvent, uint16_t maxWait) +uint8_t SFE_UBLOX_GNSS::getLeapIndicator(int32_t &timeToLsEvent, uint16_t maxWait) { - if (packetUBXNAVTIMELS == NULL) initPacketUBXNAVTIMELS(); //Check that RAM has been allocated for the TIMELS data - if (packetUBXNAVTIMELS == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVTIMELS == NULL) + initPacketUBXNAVTIMELS(); // Check that RAM has been allocated for the TIMELS data + if (packetUBXNAVTIMELS == NULL) // Bail if the RAM allocation failed return 3; if (packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validTimeToLsEvent == false) getLeapSecondEvent(maxWait); - packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validTimeToLsEvent = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validTimeToLsEvent = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.lsChange = false; packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.timeToLsEvent = false; packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.all = false; @@ -15037,15 +15374,16 @@ uint8_t SFE_UBLOX_GNSS::getLeapIndicator(int32_t& timeToLsEvent, uint16_t maxWai return ((bool)packetUBXNAVTIMELS->data.valid.bits.validTimeToLsEvent ? (uint8_t)(packetUBXNAVTIMELS->data.lsChange == -1 ? 2 : packetUBXNAVTIMELS->data.lsChange) : 3); } -int8_t SFE_UBLOX_GNSS::getCurrentLeapSeconds(sfe_ublox_ls_src_e& source, uint16_t maxWait) +int8_t SFE_UBLOX_GNSS::getCurrentLeapSeconds(sfe_ublox_ls_src_e &source, uint16_t maxWait) { - if (packetUBXNAVTIMELS == NULL) initPacketUBXNAVTIMELS(); //Check that RAM has been allocated for the TIMELS data - if (packetUBXNAVTIMELS == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVTIMELS == NULL) + initPacketUBXNAVTIMELS(); // Check that RAM has been allocated for the TIMELS data + if (packetUBXNAVTIMELS == NULL) // Bail if the RAM allocation failed return false; if (packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validCurrLs == false) getLeapSecondEvent(maxWait); - packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validCurrLs = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validCurrLs = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.srcOfCurrLs = false; packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.currLs = false; packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.all = false; @@ -15057,78 +15395,84 @@ int8_t SFE_UBLOX_GNSS::getCurrentLeapSeconds(sfe_ublox_ls_src_e& source, uint16_ float SFE_UBLOX_GNSS::getRelPosN(uint16_t maxWait) // Returned as m { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosN == false) getRELPOSNED(maxWait); - packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosN = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosN = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVRELPOSNED->data.relPosN) / 100.0); // Convert to m } float SFE_UBLOX_GNSS::getRelPosE(uint16_t maxWait) // Returned as m { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosE == false) getRELPOSNED(maxWait); - packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosE = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosE = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVRELPOSNED->data.relPosE) / 100.0); // Convert to m } float SFE_UBLOX_GNSS::getRelPosD(uint16_t maxWait) // Returned as m { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosD == false) getRELPOSNED(maxWait); - packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosD = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.relPosD = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVRELPOSNED->data.relPosD) / 100.0); // Convert to m } float SFE_UBLOX_GNSS::getRelPosAccN(uint16_t maxWait) // Returned as m { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accN == false) getRELPOSNED(maxWait); - packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accN = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accN = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVRELPOSNED->data.accN) / 10000.0); // Convert to m } float SFE_UBLOX_GNSS::getRelPosAccE(uint16_t maxWait) // Returned as m { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accE == false) getRELPOSNED(maxWait); - packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accE = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accE = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVRELPOSNED->data.accE) / 10000.0); // Convert to m } float SFE_UBLOX_GNSS::getRelPosAccD(uint16_t maxWait) // Returned as m { - if (packetUBXNAVRELPOSNED == NULL) initPacketUBXNAVRELPOSNED(); //Check that RAM has been allocated for the RELPOSNED data - if (packetUBXNAVRELPOSNED == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVRELPOSNED == NULL) + initPacketUBXNAVRELPOSNED(); // Check that RAM has been allocated for the RELPOSNED data + if (packetUBXNAVRELPOSNED == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accD == false) getRELPOSNED(maxWait); - packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accD = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.accD = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVRELPOSNED->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXNAVRELPOSNED->data.accD) / 10000.0); // Convert to m } @@ -15137,26 +15481,28 @@ float SFE_UBLOX_GNSS::getRelPosAccD(uint16_t maxWait) // Returned as m uint8_t SFE_UBLOX_GNSS::getAOPSTATUSuseAOP(uint16_t maxWait) { - if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the AOPSTATUS data - if (packetUBXNAVAOPSTATUS == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVAOPSTATUS == NULL) + initPacketUBXNAVAOPSTATUS(); // Check that RAM has been allocated for the AOPSTATUS data + if (packetUBXNAVAOPSTATUS == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.useAOP == false) getAOPSTATUS(maxWait); - packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.useAOP = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.useAOP = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVAOPSTATUS->data.aopCfg.bits.useAOP); } uint8_t SFE_UBLOX_GNSS::getAOPSTATUSstatus(uint16_t maxWait) { - if (packetUBXNAVAOPSTATUS == NULL) initPacketUBXNAVAOPSTATUS(); //Check that RAM has been allocated for the AOPSTATUS data - if (packetUBXNAVAOPSTATUS == NULL) //Bail if the RAM allocation failed + if (packetUBXNAVAOPSTATUS == NULL) + initPacketUBXNAVAOPSTATUS(); // Check that RAM has been allocated for the AOPSTATUS data + if (packetUBXNAVAOPSTATUS == NULL) // Bail if the RAM allocation failed return 0; if (packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.status == false) getAOPSTATUS(maxWait); - packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.status = false; //Since we are about to give this to user, mark this data as stale + packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.status = false; // Since we are about to give this to user, mark this data as stale packetUBXNAVAOPSTATUS->moduleQueried.moduleQueried.bits.all = false; return (packetUBXNAVAOPSTATUS->data.status); } @@ -15165,52 +15511,56 @@ uint8_t SFE_UBLOX_GNSS::getAOPSTATUSstatus(uint16_t maxWait) float SFE_UBLOX_GNSS::getESFroll(uint16_t maxWait) // Returned as degrees { - if (packetUBXESFALG == NULL) initPacketUBXESFALG(); //Check that RAM has been allocated for the ESF ALG data - if (packetUBXESFALG == NULL) //Bail if the RAM allocation failed + if (packetUBXESFALG == NULL) + initPacketUBXESFALG(); // Check that RAM has been allocated for the ESF ALG data + if (packetUBXESFALG == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXESFALG->moduleQueried.moduleQueried.bits.roll == false) getESFALG(maxWait); - packetUBXESFALG->moduleQueried.moduleQueried.bits.roll = false; //Since we are about to give this to user, mark this data as stale + packetUBXESFALG->moduleQueried.moduleQueried.bits.roll = false; // Since we are about to give this to user, mark this data as stale packetUBXESFALG->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXESFALG->data.roll) / 100.0); // Convert to degrees } float SFE_UBLOX_GNSS::getESFpitch(uint16_t maxWait) // Returned as degrees { - if (packetUBXESFALG == NULL) initPacketUBXESFALG(); //Check that RAM has been allocated for the ESF ALG data - if (packetUBXESFALG == NULL) //Bail if the RAM allocation failed + if (packetUBXESFALG == NULL) + initPacketUBXESFALG(); // Check that RAM has been allocated for the ESF ALG data + if (packetUBXESFALG == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXESFALG->moduleQueried.moduleQueried.bits.pitch == false) getESFALG(maxWait); - packetUBXESFALG->moduleQueried.moduleQueried.bits.pitch = false; //Since we are about to give this to user, mark this data as stale + packetUBXESFALG->moduleQueried.moduleQueried.bits.pitch = false; // Since we are about to give this to user, mark this data as stale packetUBXESFALG->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXESFALG->data.pitch) / 100.0); // Convert to degrees } float SFE_UBLOX_GNSS::getESFyaw(uint16_t maxWait) // Returned as degrees { - if (packetUBXESFALG == NULL) initPacketUBXESFALG(); //Check that RAM has been allocated for the ESF ALG data - if (packetUBXESFALG == NULL) //Bail if the RAM allocation failed + if (packetUBXESFALG == NULL) + initPacketUBXESFALG(); // Check that RAM has been allocated for the ESF ALG data + if (packetUBXESFALG == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXESFALG->moduleQueried.moduleQueried.bits.yaw == false) getESFALG(maxWait); - packetUBXESFALG->moduleQueried.moduleQueried.bits.yaw = false; //Since we are about to give this to user, mark this data as stale + packetUBXESFALG->moduleQueried.moduleQueried.bits.yaw = false; // Since we are about to give this to user, mark this data as stale packetUBXESFALG->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXESFALG->data.yaw) / 100.0); // Convert to degrees } bool SFE_UBLOX_GNSS::getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait) { - if (packetUBXESFMEAS == NULL) initPacketUBXESFMEAS(); //Check that RAM has been allocated for the ESF MEAS data - if (packetUBXESFMEAS == NULL) //Bail if the RAM allocation failed + if (packetUBXESFMEAS == NULL) + initPacketUBXESFMEAS(); // Check that RAM has been allocated for the ESF MEAS data + if (packetUBXESFMEAS == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXESFMEAS->moduleQueried.moduleQueried.bits.data & ((1 << sensor) == 0)) getESFMEAS(maxWait); - packetUBXESFMEAS->moduleQueried.moduleQueried.bits.data &= ~(1 << sensor); //Since we are about to give this to user, mark this data as stale + packetUBXESFMEAS->moduleQueried.moduleQueried.bits.data &= ~(1 << sensor); // Since we are about to give this to user, mark this data as stale packetUBXESFMEAS->moduleQueried.moduleQueried.bits.all = false; sensorData->data.all = packetUBXESFMEAS->data.data[sensor].data.all; return (true); @@ -15224,13 +15574,14 @@ bool SFE_UBLOX_GNSS::getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *senso bool SFE_UBLOX_GNSS::getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait) { - if (packetUBXESFRAW == NULL) initPacketUBXESFRAW(); //Check that RAM has been allocated for the ESF RAW data - if (packetUBXESFRAW == NULL) //Bail if the RAM allocation failed + if (packetUBXESFRAW == NULL) + initPacketUBXESFRAW(); // Check that RAM has been allocated for the ESF RAW data + if (packetUBXESFRAW == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXESFRAW->moduleQueried.moduleQueried.bits.data & ((1 << sensor) == 0)) getESFRAW(maxWait); - packetUBXESFRAW->moduleQueried.moduleQueried.bits.data &= ~(1 << sensor); //Since we are about to give this to user, mark this data as stale + packetUBXESFRAW->moduleQueried.moduleQueried.bits.data &= ~(1 << sensor); // Since we are about to give this to user, mark this data as stale packetUBXESFRAW->moduleQueried.moduleQueried.bits.all = false; sensorData->data.all = packetUBXESFRAW->data.data[sensor].data.all; sensorData->sTag = packetUBXESFRAW->data.data[sensor].sTag; @@ -15246,13 +15597,14 @@ bool SFE_UBLOX_GNSS::getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorDat bool SFE_UBLOX_GNSS::getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, uint8_t sensor, uint16_t maxWait) { - if (packetUBXESFSTATUS == NULL) initPacketUBXESFSTATUS(); //Check that RAM has been allocated for the ESF STATUS data - if (packetUBXESFSTATUS == NULL) //Bail if the RAM allocation failed + if (packetUBXESFSTATUS == NULL) + initPacketUBXESFSTATUS(); // Check that RAM has been allocated for the ESF STATUS data + if (packetUBXESFSTATUS == NULL) // Bail if the RAM allocation failed return (false); if (packetUBXESFSTATUS->moduleQueried.moduleQueried.bits.status & ((1 << sensor) == 0)) getESFSTATUS(maxWait); - packetUBXESFSTATUS->moduleQueried.moduleQueried.bits.status &= ~(1 << sensor); //Since we are about to give this to user, mark this data as stale + packetUBXESFSTATUS->moduleQueried.moduleQueried.bits.status &= ~(1 << sensor); // Since we are about to give this to user, mark this data as stale packetUBXESFSTATUS->moduleQueried.moduleQueried.bits.all = false; sensorStatus->sensStatus1.all = packetUBXESFSTATUS->data.status[sensor].sensStatus1.all; sensorStatus->sensStatus2.all = packetUBXESFSTATUS->data.status[sensor].sensStatus2.all; @@ -15282,9 +15634,9 @@ bool SFE_UBLOX_GNSS::setHNRNavigationRate(uint8_t rate, uint16_t maxWait) if (rate > 40) rate = 40; // Limit rate to 40Hz so i2cPollingWait is set correctly - //Adjust the I2C polling timeout based on update rate - //Do this even if the sendCommand is not ACK'd - i2cPollingWaitHNR = 1000 / (((int)rate) * 4); //This is the number of ms to wait between checks for new I2C data. Max 250. Min 6. + // Adjust the I2C polling timeout based on update rate + // Do this even if the sendCommand is not ACK'd + i2cPollingWaitHNR = 1000 / (((int)rate) * 4); // This is the number of ms to wait between checks for new I2C data. Max 250. Min 6. i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR packetCfg.cls = UBX_CLASS_CFG; @@ -15292,14 +15644,14 @@ bool SFE_UBLOX_GNSS::setHNRNavigationRate(uint8_t rate, uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current HNR settings. Loads into payloadCfg. + // Ask module for the current HNR settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (false); - //Load the new navigation rate into payloadCfg + // Load the new navigation rate into payloadCfg payloadCfg[0] = rate; - //Update the navigation rate + // Update the navigation rate sfe_ublox_status_e result = sendCommand(&packetCfg, maxWait); // We are only expecting an ACK return (result == SFE_UBLOX_STATUS_DATA_SENT); @@ -15314,49 +15666,52 @@ uint8_t SFE_UBLOX_GNSS::getHNRNavigationRate(uint16_t maxWait) packetCfg.len = 0; packetCfg.startingSpot = 0; - //Ask module for the current HNR settings. Loads into payloadCfg. + // Ask module for the current HNR settings. Loads into payloadCfg. if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) return (0); - //Return the navigation rate + // Return the navigation rate return (payloadCfg[0]); } float SFE_UBLOX_GNSS::getHNRroll(uint16_t maxWait) // Returned as degrees { - if (packetUBXHNRATT == NULL) initPacketUBXHNRATT(); //Check that RAM has been allocated for the HNR ATT data - if (packetUBXHNRATT == NULL) //Bail if the RAM allocation failed + if (packetUBXHNRATT == NULL) + initPacketUBXHNRATT(); // Check that RAM has been allocated for the HNR ATT data + if (packetUBXHNRATT == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXHNRATT->moduleQueried.moduleQueried.bits.roll == false) getHNRATT(maxWait); - packetUBXHNRATT->moduleQueried.moduleQueried.bits.roll = false; //Since we are about to give this to user, mark this data as stale + packetUBXHNRATT->moduleQueried.moduleQueried.bits.roll = false; // Since we are about to give this to user, mark this data as stale packetUBXHNRATT->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXHNRATT->data.roll) / 100000.0); // Convert to degrees } float SFE_UBLOX_GNSS::getHNRpitch(uint16_t maxWait) // Returned as degrees { - if (packetUBXHNRATT == NULL) initPacketUBXHNRATT(); //Check that RAM has been allocated for the HNR ATT data - if (packetUBXHNRATT == NULL) //Bail if the RAM allocation failed + if (packetUBXHNRATT == NULL) + initPacketUBXHNRATT(); // Check that RAM has been allocated for the HNR ATT data + if (packetUBXHNRATT == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXHNRATT->moduleQueried.moduleQueried.bits.pitch == false) getHNRATT(maxWait); - packetUBXHNRATT->moduleQueried.moduleQueried.bits.pitch = false; //Since we are about to give this to user, mark this data as stale + packetUBXHNRATT->moduleQueried.moduleQueried.bits.pitch = false; // Since we are about to give this to user, mark this data as stale packetUBXHNRATT->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXHNRATT->data.pitch) / 100000.0); // Convert to degrees } float SFE_UBLOX_GNSS::getHNRheading(uint16_t maxWait) // Returned as degrees { - if (packetUBXHNRATT == NULL) initPacketUBXHNRATT(); //Check that RAM has been allocated for the HNR ATT data - if (packetUBXHNRATT == NULL) //Bail if the RAM allocation failed + if (packetUBXHNRATT == NULL) + initPacketUBXHNRATT(); // Check that RAM has been allocated for the HNR ATT data + if (packetUBXHNRATT == NULL) // Bail if the RAM allocation failed return (0); if (packetUBXHNRATT->moduleQueried.moduleQueried.bits.heading == false) getHNRATT(maxWait); - packetUBXHNRATT->moduleQueried.moduleQueried.bits.heading = false; //Since we are about to give this to user, mark this data as stale + packetUBXHNRATT->moduleQueried.moduleQueried.bits.heading = false; // Since we are about to give this to user, mark this data as stale packetUBXHNRATT->moduleQueried.moduleQueried.bits.all = false; return (((float)packetUBXHNRATT->data.heading) / 100000.0); // Convert to degrees } @@ -15364,7 +15719,7 @@ float SFE_UBLOX_GNSS::getHNRheading(uint16_t maxWait) // Returned as degrees // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket // From v2.0: These are public. The user can call these to extract data from custom packets -//Given a spot in the payload array, extract eight bytes and build a uint64_t +// Given a spot in the payload array, extract eight bytes and build a uint64_t uint64_t SFE_UBLOX_GNSS::extractLongLong(ubxPacket *msg, uint16_t spotToStart) { uint64_t val = 0; @@ -15379,7 +15734,7 @@ uint64_t SFE_UBLOX_GNSS::extractLongLong(ubxPacket *msg, uint16_t spotToStart) return (val); } -//Given a spot in the payload array, extract four bytes and build a long +// Given a spot in the payload array, extract four bytes and build a long uint32_t SFE_UBLOX_GNSS::extractLong(ubxPacket *msg, uint16_t spotToStart) { uint32_t val = 0; @@ -15390,20 +15745,20 @@ uint32_t SFE_UBLOX_GNSS::extractLong(ubxPacket *msg, uint16_t spotToStart) return (val); } -//Just so there is no ambiguity about whether a uint32_t will cast to a int32_t correctly... +// Just so there is no ambiguity about whether a uint32_t will cast to a int32_t correctly... int32_t SFE_UBLOX_GNSS::extractSignedLong(ubxPacket *msg, uint16_t spotToStart) { union // Use a union to convert from uint32_t to int32_t { - uint32_t unsignedLong; - int32_t signedLong; + uint32_t unsignedLong; + int32_t signedLong; } unsignedSigned; unsignedSigned.unsignedLong = extractLong(msg, spotToStart); return (unsignedSigned.signedLong); } -//Given a spot in the payload array, extract two bytes and build an int +// Given a spot in the payload array, extract two bytes and build an int uint16_t SFE_UBLOX_GNSS::extractInt(ubxPacket *msg, uint16_t spotToStart) { uint16_t val = 0; @@ -15412,32 +15767,32 @@ uint16_t SFE_UBLOX_GNSS::extractInt(ubxPacket *msg, uint16_t spotToStart) return (val); } -//Just so there is no ambiguity about whether a uint16_t will cast to a int16_t correctly... +// Just so there is no ambiguity about whether a uint16_t will cast to a int16_t correctly... int16_t SFE_UBLOX_GNSS::extractSignedInt(ubxPacket *msg, uint16_t spotToStart) { union // Use a union to convert from uint16_t to int16_t { - uint16_t unsignedInt; - int16_t signedInt; + uint16_t unsignedInt; + int16_t signedInt; } stSignedInt; stSignedInt.unsignedInt = extractInt(msg, spotToStart); return (stSignedInt.signedInt); } -//Given a spot, extract a byte from the payload +// Given a spot, extract a byte from the payload uint8_t SFE_UBLOX_GNSS::extractByte(ubxPacket *msg, uint16_t spotToStart) { return (msg->payload[spotToStart]); } -//Given a spot, extract a signed 8-bit value from the payload +// Given a spot, extract a signed 8-bit value from the payload int8_t SFE_UBLOX_GNSS::extractSignedChar(ubxPacket *msg, uint16_t spotToStart) { union // Use a union to convert from uint8_t to int8_t { - uint8_t unsignedByte; - int8_t signedByte; + uint8_t unsignedByte; + int8_t signedByte; } stSignedByte; stSignedByte.unsignedByte = extractByte(msg, spotToStart); diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index b8f96cf..d587362 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1,43 +1,43 @@ /* - This is a library written for the u-blox ZED-F9P and NEO-M8P-2 - SparkFun sells these at its website: www.sparkfun.com - Do you like this library? Help support SparkFun. Buy a board! - https://www.sparkfun.com/products/16481 - https://www.sparkfun.com/products/15136 - https://www.sparkfun.com/products/15005 - https://www.sparkfun.com/products/15733 - https://www.sparkfun.com/products/15193 - https://www.sparkfun.com/products/15210 - - Original version by Nathan Seidle @ SparkFun Electronics, September 6th, 2018 - v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 - - This library handles configuring and handling the responses - from a u-blox GPS module. Works with most modules from u-blox including - the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. - - https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library - - Development environment specifics: - Arduino IDE 1.8.13 - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). - The MIT License (MIT) - Copyright (c) 2016 SparkFun Electronics - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - associated documentation files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the Software is furnished to - do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + This is a library written for the u-blox ZED-F9P and NEO-M8P-2 + SparkFun sells these at its website: www.sparkfun.com + Do you like this library? Help support SparkFun. Buy a board! + https://www.sparkfun.com/products/16481 + https://www.sparkfun.com/products/15136 + https://www.sparkfun.com/products/15005 + https://www.sparkfun.com/products/15733 + https://www.sparkfun.com/products/15193 + https://www.sparkfun.com/products/15210 + + Original version by Nathan Seidle @ SparkFun Electronics, September 6th, 2018 + v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 + + This library handles configuring and handling the responses + from a u-blox GPS module. Works with most modules from u-blox including + the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. + + https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library + + Development environment specifics: + Arduino IDE 1.8.13 + + SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). + The MIT License (MIT) + Copyright (c) 2016 SparkFun Electronics + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the Software is furnished to + do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef SPARKFUN_UBLOX_ARDUINO_LIBRARY_H @@ -56,46 +56,46 @@ #include "u-blox_config_keys.h" #include "u-blox_structs.h" -//Uncomment the next line (or add SFE_UBLOX_REDUCED_PROG_MEM as a compiler directive) to reduce the amount of program memory used by the library +// Uncomment the next line (or add SFE_UBLOX_REDUCED_PROG_MEM as a compiler directive) to reduce the amount of program memory used by the library //#define SFE_UBLOX_REDUCED_PROG_MEM // Uncommenting this line will delete the minor debug messages to save memory -//The code just about fills the program memory on the ATmega328P (Arduino Uno), so let's delete the minor debug messages anyway +// The code just about fills the program memory on the ATmega328P (Arduino Uno), so let's delete the minor debug messages anyway #if !defined(SFE_UBLOX_REDUCED_PROG_MEM) && defined(ARDUINO_ARCH_AVR) #define SFE_UBLOX_REDUCED_PROG_MEM #endif //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -//Define a digital pin to aid debugging -//Leave set to -1 if not needed +// Define a digital pin to aid debugging +// Leave set to -1 if not needed const int debugPin = -1; // Global Status Returns typedef enum { - SFE_UBLOX_STATUS_SUCCESS, - SFE_UBLOX_STATUS_FAIL, - SFE_UBLOX_STATUS_CRC_FAIL, - SFE_UBLOX_STATUS_TIMEOUT, - SFE_UBLOX_STATUS_COMMAND_NACK, // Indicates that the command was unrecognised, invalid or that the module is too busy to respond - SFE_UBLOX_STATUS_OUT_OF_RANGE, - SFE_UBLOX_STATUS_INVALID_ARG, - SFE_UBLOX_STATUS_INVALID_OPERATION, - SFE_UBLOX_STATUS_MEM_ERR, - SFE_UBLOX_STATUS_HW_ERR, - SFE_UBLOX_STATUS_DATA_SENT, // This indicates that a 'set' was successful - SFE_UBLOX_STATUS_DATA_RECEIVED, // This indicates that a 'get' (poll) was successful - SFE_UBLOX_STATUS_I2C_COMM_FAILURE, - SFE_UBLOX_STATUS_DATA_OVERWRITTEN // This is an error - the data was valid but has been or _is being_ overwritten by another packet + SFE_UBLOX_STATUS_SUCCESS, + SFE_UBLOX_STATUS_FAIL, + SFE_UBLOX_STATUS_CRC_FAIL, + SFE_UBLOX_STATUS_TIMEOUT, + SFE_UBLOX_STATUS_COMMAND_NACK, // Indicates that the command was unrecognised, invalid or that the module is too busy to respond + SFE_UBLOX_STATUS_OUT_OF_RANGE, + SFE_UBLOX_STATUS_INVALID_ARG, + SFE_UBLOX_STATUS_INVALID_OPERATION, + SFE_UBLOX_STATUS_MEM_ERR, + SFE_UBLOX_STATUS_HW_ERR, + SFE_UBLOX_STATUS_DATA_SENT, // This indicates that a 'set' was successful + SFE_UBLOX_STATUS_DATA_RECEIVED, // This indicates that a 'get' (poll) was successful + SFE_UBLOX_STATUS_I2C_COMM_FAILURE, + SFE_UBLOX_STATUS_DATA_OVERWRITTEN // This is an error - the data was valid but has been or _is being_ overwritten by another packet } sfe_ublox_status_e; // ubxPacket validity typedef enum { - SFE_UBLOX_PACKET_VALIDITY_NOT_VALID, - SFE_UBLOX_PACKET_VALIDITY_VALID, - SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, - SFE_UBLOX_PACKET_NOTACKNOWLEDGED // This indicates that we received a NACK + SFE_UBLOX_PACKET_VALIDITY_NOT_VALID, + SFE_UBLOX_PACKET_VALIDITY_VALID, + SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, + SFE_UBLOX_PACKET_NOTACKNOWLEDGED // This indicates that we received a NACK } sfe_ublox_packet_validity_e; // Identify which packet buffer is in use: @@ -103,10 +103,10 @@ typedef enum // packetAuto is used to store expected "automatic" messages typedef enum { - SFE_UBLOX_PACKET_PACKETCFG, - SFE_UBLOX_PACKET_PACKETACK, - SFE_UBLOX_PACKET_PACKETBUF, - SFE_UBLOX_PACKET_PACKETAUTO + SFE_UBLOX_PACKET_PACKETCFG, + SFE_UBLOX_PACKET_PACKETACK, + SFE_UBLOX_PACKET_PACKETBUF, + SFE_UBLOX_PACKET_PACKETAUTO } sfe_ublox_packet_buffer_e; // Define a struct to allow selective logging / processing of NMEA messages @@ -114,328 +114,328 @@ typedef enum // Setting bits.all will pass all messages to the file buffer and processNMEA typedef struct { - union - { - uint32_t all; - struct - { - uint32_t all : 1; - uint32_t UBX_NMEA_DTM : 1; - uint32_t UBX_NMEA_GAQ : 1; - uint32_t UBX_NMEA_GBQ : 1; - uint32_t UBX_NMEA_GBS : 1; - uint32_t UBX_NMEA_GGA : 1; - uint32_t UBX_NMEA_GLL : 1; - uint32_t UBX_NMEA_GLQ : 1; - uint32_t UBX_NMEA_GNQ : 1; - uint32_t UBX_NMEA_GNS : 1; - uint32_t UBX_NMEA_GPQ : 1; - uint32_t UBX_NMEA_GQQ : 1; - uint32_t UBX_NMEA_GRS : 1; - uint32_t UBX_NMEA_GSA : 1; - uint32_t UBX_NMEA_GST : 1; - uint32_t UBX_NMEA_GSV : 1; - uint32_t UBX_NMEA_RLM : 1; - uint32_t UBX_NMEA_RMC : 1; - uint32_t UBX_NMEA_TXT : 1; - uint32_t UBX_NMEA_VLW : 1; - uint32_t UBX_NMEA_VTG : 1; - uint32_t UBX_NMEA_ZDA : 1; - } bits; - }; + union + { + uint32_t all; + struct + { + uint32_t all : 1; + uint32_t UBX_NMEA_DTM : 1; + uint32_t UBX_NMEA_GAQ : 1; + uint32_t UBX_NMEA_GBQ : 1; + uint32_t UBX_NMEA_GBS : 1; + uint32_t UBX_NMEA_GGA : 1; + uint32_t UBX_NMEA_GLL : 1; + uint32_t UBX_NMEA_GLQ : 1; + uint32_t UBX_NMEA_GNQ : 1; + uint32_t UBX_NMEA_GNS : 1; + uint32_t UBX_NMEA_GPQ : 1; + uint32_t UBX_NMEA_GQQ : 1; + uint32_t UBX_NMEA_GRS : 1; + uint32_t UBX_NMEA_GSA : 1; + uint32_t UBX_NMEA_GST : 1; + uint32_t UBX_NMEA_GSV : 1; + uint32_t UBX_NMEA_RLM : 1; + uint32_t UBX_NMEA_RMC : 1; + uint32_t UBX_NMEA_TXT : 1; + uint32_t UBX_NMEA_VLW : 1; + uint32_t UBX_NMEA_VTG : 1; + uint32_t UBX_NMEA_ZDA : 1; + } bits; + }; } sfe_ublox_nmea_filtering_t; // Define an enum to make it easy to enable/disable selected NMEA messages for logging / processing typedef enum { - SFE_UBLOX_FILTER_NMEA_ALL = 0x00000001, - SFE_UBLOX_FILTER_NMEA_DTM = 0x00000002, - SFE_UBLOX_FILTER_NMEA_GAQ = 0x00000004, - SFE_UBLOX_FILTER_NMEA_GBQ = 0x00000008, - SFE_UBLOX_FILTER_NMEA_GBS = 0x00000010, - SFE_UBLOX_FILTER_NMEA_GGA = 0x00000020, - SFE_UBLOX_FILTER_NMEA_GLL = 0x00000040, - SFE_UBLOX_FILTER_NMEA_GLQ = 0x00000080, - SFE_UBLOX_FILTER_NMEA_GNQ = 0x00000100, - SFE_UBLOX_FILTER_NMEA_GNS = 0x00000200, - SFE_UBLOX_FILTER_NMEA_GPQ = 0x00000400, - SFE_UBLOX_FILTER_NMEA_GQQ = 0x00000800, - SFE_UBLOX_FILTER_NMEA_GRS = 0x00001000, - SFE_UBLOX_FILTER_NMEA_GSA = 0x00002000, - SFE_UBLOX_FILTER_NMEA_GST = 0x00004000, - SFE_UBLOX_FILTER_NMEA_GSV = 0x00008000, - SFE_UBLOX_FILTER_NMEA_RLM = 0x00010000, - SFE_UBLOX_FILTER_NMEA_RMC = 0x00020000, - SFE_UBLOX_FILTER_NMEA_TXT = 0x00040000, - SFE_UBLOX_FILTER_NMEA_VLW = 0x00080000, - SFE_UBLOX_FILTER_NMEA_VTG = 0x00100000, - SFE_UBLOX_FILTER_NMEA_ZDA = 0x00200000 + SFE_UBLOX_FILTER_NMEA_ALL = 0x00000001, + SFE_UBLOX_FILTER_NMEA_DTM = 0x00000002, + SFE_UBLOX_FILTER_NMEA_GAQ = 0x00000004, + SFE_UBLOX_FILTER_NMEA_GBQ = 0x00000008, + SFE_UBLOX_FILTER_NMEA_GBS = 0x00000010, + SFE_UBLOX_FILTER_NMEA_GGA = 0x00000020, + SFE_UBLOX_FILTER_NMEA_GLL = 0x00000040, + SFE_UBLOX_FILTER_NMEA_GLQ = 0x00000080, + SFE_UBLOX_FILTER_NMEA_GNQ = 0x00000100, + SFE_UBLOX_FILTER_NMEA_GNS = 0x00000200, + SFE_UBLOX_FILTER_NMEA_GPQ = 0x00000400, + SFE_UBLOX_FILTER_NMEA_GQQ = 0x00000800, + SFE_UBLOX_FILTER_NMEA_GRS = 0x00001000, + SFE_UBLOX_FILTER_NMEA_GSA = 0x00002000, + SFE_UBLOX_FILTER_NMEA_GST = 0x00004000, + SFE_UBLOX_FILTER_NMEA_GSV = 0x00008000, + SFE_UBLOX_FILTER_NMEA_RLM = 0x00010000, + SFE_UBLOX_FILTER_NMEA_RMC = 0x00020000, + SFE_UBLOX_FILTER_NMEA_TXT = 0x00040000, + SFE_UBLOX_FILTER_NMEA_VLW = 0x00080000, + SFE_UBLOX_FILTER_NMEA_VTG = 0x00100000, + SFE_UBLOX_FILTER_NMEA_ZDA = 0x00200000 } sfe_ublox_nmea_filtering_e; -//Registers +// Registers const uint8_t UBX_SYNCH_1 = 0xB5; const uint8_t UBX_SYNCH_2 = 0x62; -//The following are UBX Class IDs. Descriptions taken from ZED-F9P Interface Description Document page 32, NEO-M8P Interface Description page 145 -const uint8_t UBX_CLASS_NAV = 0x01; //Navigation Results Messages: Position, Speed, Time, Acceleration, Heading, DOP, SVs used -const uint8_t UBX_CLASS_RXM = 0x02; //Receiver Manager Messages: Satellite Status, RTC Status -const uint8_t UBX_CLASS_INF = 0x04; //Information Messages: Printf-Style Messages, with IDs such as Error, Warning, Notice -const uint8_t UBX_CLASS_ACK = 0x05; //Ack/Nak Messages: Acknowledge or Reject messages to UBX-CFG input messages -const uint8_t UBX_CLASS_CFG = 0x06; //Configuration Input Messages: Configure the receiver. -const uint8_t UBX_CLASS_UPD = 0x09; //Firmware Update Messages: Memory/Flash erase/write, Reboot, Flash identification, etc. -const uint8_t UBX_CLASS_MON = 0x0A; //Monitoring Messages: Communication Status, CPU Load, Stack Usage, Task Status -const uint8_t UBX_CLASS_AID = 0x0B; //(NEO-M8P ONLY!!!) AssistNow Aiding Messages: Ephemeris, Almanac, other A-GPS data input -const uint8_t UBX_CLASS_TIM = 0x0D; //Timing Messages: Time Pulse Output, Time Mark Results -const uint8_t UBX_CLASS_ESF = 0x10; //(NEO-M8P ONLY!!!) External Sensor Fusion Messages: External Sensor Measurements and Status Information -const uint8_t UBX_CLASS_MGA = 0x13; //Multiple GNSS Assistance Messages: Assistance data for various GNSS -const uint8_t UBX_CLASS_LOG = 0x21; //Logging Messages: Log creation, deletion, info and retrieval -const uint8_t UBX_CLASS_SEC = 0x27; //Security Feature Messages -const uint8_t UBX_CLASS_HNR = 0x28; //(NEO-M8P ONLY!!!) High Rate Navigation Results Messages: High rate time, position speed, heading -const uint8_t UBX_CLASS_NMEA = 0xF0; //NMEA Strings: standard NMEA strings - -//Class: CFG -//The following are used for configuration. Descriptions are from the ZED-F9P Interface Description pg 33-34 and NEO-M9N Interface Description pg 47-48 -const uint8_t UBX_CFG_ANT = 0x13; //Antenna Control Settings. Used to configure the antenna control settings -const uint8_t UBX_CFG_BATCH = 0x93; //Get/set data batching configuration. -const uint8_t UBX_CFG_CFG = 0x09; //Clear, Save, and Load Configurations. Used to save current configuration -const uint8_t UBX_CFG_DAT = 0x06; //Set User-defined Datum or The currently defined Datum -const uint8_t UBX_CFG_DGNSS = 0x70; //DGNSS configuration -const uint8_t UBX_CFG_ESFALG = 0x56; //ESF alignment -const uint8_t UBX_CFG_ESFA = 0x4C; //ESF accelerometer -const uint8_t UBX_CFG_ESFG = 0x4D; //ESF gyro -const uint8_t UBX_CFG_GEOFENCE = 0x69; //Geofencing configuration. Used to configure a geofence -const uint8_t UBX_CFG_GNSS = 0x3E; //GNSS system configuration -const uint8_t UBX_CFG_HNR = 0x5C; //High Navigation Rate -const uint8_t UBX_CFG_INF = 0x02; //Depending on packet length, either: poll configuration for one protocol, or information message configuration -const uint8_t UBX_CFG_ITFM = 0x39; //Jamming/Interference Monitor configuration -const uint8_t UBX_CFG_LOGFILTER = 0x47; //Data Logger Configuration -const uint8_t UBX_CFG_MSG = 0x01; //Poll a message configuration, or Set Message Rate(s), or Set Message Rate -const uint8_t UBX_CFG_NAV5 = 0x24; //Navigation Engine Settings. Used to configure the navigation engine including the dynamic model. -const uint8_t UBX_CFG_NAVX5 = 0x23; //Navigation Engine Expert Settings -const uint8_t UBX_CFG_NMEA = 0x17; //Extended NMEA protocol configuration V1 -const uint8_t UBX_CFG_ODO = 0x1E; //Odometer, Low-speed COG Engine Settings -const uint8_t UBX_CFG_PM2 = 0x3B; //Extended power management configuration -const uint8_t UBX_CFG_PMS = 0x86; //Power mode setup -const uint8_t UBX_CFG_PRT = 0x00; //Used to configure port specifics. Polls the configuration for one I/O Port, or Port configuration for UART ports, or Port configuration for USB port, or Port configuration for SPI port, or Port configuration for DDC port -const uint8_t UBX_CFG_PWR = 0x57; //Put receiver in a defined power state -const uint8_t UBX_CFG_RATE = 0x08; //Navigation/Measurement Rate Settings. Used to set port baud rates. -const uint8_t UBX_CFG_RINV = 0x34; //Contents of Remote Inventory -const uint8_t UBX_CFG_RST = 0x04; //Reset Receiver / Clear Backup Data Structures. Used to reset device. -const uint8_t UBX_CFG_RXM = 0x11; //RXM configuration -const uint8_t UBX_CFG_SBAS = 0x16; //SBAS configuration -const uint8_t UBX_CFG_TMODE3 = 0x71; //Time Mode Settings 3. Used to enable Survey In Mode -const uint8_t UBX_CFG_TP5 = 0x31; //Time Pulse Parameters -const uint8_t UBX_CFG_USB = 0x1B; //USB Configuration -const uint8_t UBX_CFG_VALDEL = 0x8C; //Used for config of higher version u-blox modules (ie protocol v27 and above). Deletes values corresponding to provided keys/ provided keys with a transaction -const uint8_t UBX_CFG_VALGET = 0x8B; //Used for config of higher version u-blox modules (ie protocol v27 and above). Configuration Items -const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version u-blox modules (ie protocol v27 and above). Sets values corresponding to provided key-value pairs/ provided key-value pairs within a transaction. - -//Class: NMEA -//The following are used to enable NMEA messages. Descriptions come from the NMEA messages overview in the ZED-F9P Interface Description -const uint8_t UBX_NMEA_MSB = 0xF0; //All NMEA enable commands have 0xF0 as MSB. Equal to UBX_CLASS_NMEA -const uint8_t UBX_NMEA_DTM = 0x0A; //GxDTM (datum reference) -const uint8_t UBX_NMEA_GAQ = 0x45; //GxGAQ (poll a standard message (if the current talker ID is GA)) -const uint8_t UBX_NMEA_GBQ = 0x44; //GxGBQ (poll a standard message (if the current Talker ID is GB)) -const uint8_t UBX_NMEA_GBS = 0x09; //GxGBS (GNSS satellite fault detection) -const uint8_t UBX_NMEA_GGA = 0x00; //GxGGA (Global positioning system fix data) -const uint8_t UBX_NMEA_GLL = 0x01; //GxGLL (latitude and long, whith time of position fix and status) -const uint8_t UBX_NMEA_GLQ = 0x43; //GxGLQ (poll a standard message (if the current Talker ID is GL)) -const uint8_t UBX_NMEA_GNQ = 0x42; //GxGNQ (poll a standard message (if the current Talker ID is GN)) -const uint8_t UBX_NMEA_GNS = 0x0D; //GxGNS (GNSS fix data) -const uint8_t UBX_NMEA_GPQ = 0x40; //GxGPQ (poll a standard message (if the current Talker ID is GP)) -const uint8_t UBX_NMEA_GQQ = 0x47; //GxGQQ (poll a standard message (if the current Talker ID is GQ)) -const uint8_t UBX_NMEA_GRS = 0x06; //GxGRS (GNSS range residuals) -const uint8_t UBX_NMEA_GSA = 0x02; //GxGSA (GNSS DOP and Active satellites) -const uint8_t UBX_NMEA_GST = 0x07; //GxGST (GNSS Pseudo Range Error Statistics) -const uint8_t UBX_NMEA_GSV = 0x03; //GxGSV (GNSS satellites in view) -const uint8_t UBX_NMEA_RLM = 0x0B; //GxRMC (Return link message (RLM)) -const uint8_t UBX_NMEA_RMC = 0x04; //GxRMC (Recommended minimum data) -const uint8_t UBX_NMEA_TXT = 0x41; //GxTXT (text transmission) -const uint8_t UBX_NMEA_VLW = 0x0F; //GxVLW (dual ground/water distance) -const uint8_t UBX_NMEA_VTG = 0x05; //GxVTG (course over ground and Ground speed) -const uint8_t UBX_NMEA_ZDA = 0x08; //GxZDA (Time and Date) - -//The following are used to configure the NMEA protocol main talker ID and GSV talker ID -const uint8_t UBX_NMEA_MAINTALKERID_NOTOVERRIDDEN = 0x00; //main talker ID is system dependent -const uint8_t UBX_NMEA_MAINTALKERID_GP = 0x01; //main talker ID is GPS -const uint8_t UBX_NMEA_MAINTALKERID_GL = 0x02; //main talker ID is GLONASS -const uint8_t UBX_NMEA_MAINTALKERID_GN = 0x03; //main talker ID is combined receiver -const uint8_t UBX_NMEA_MAINTALKERID_GA = 0x04; //main talker ID is Galileo -const uint8_t UBX_NMEA_MAINTALKERID_GB = 0x05; //main talker ID is BeiDou -const uint8_t UBX_NMEA_GSVTALKERID_GNSS = 0x00; //GNSS specific Talker ID (as defined by NMEA) -const uint8_t UBX_NMEA_GSVTALKERID_MAIN = 0x01; //use the main Talker ID - -//Class: HNR -//The following are used to configure the HNR message rates -const uint8_t UBX_HNR_ATT = 0x01; //HNR Attitude -const uint8_t UBX_HNR_INS = 0x02; //HNR Vehicle Dynamics -const uint8_t UBX_HNR_PVT = 0x00; //HNR PVT - -//Class: INF -//The following are used to configure INF UBX messages (information messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34) -const uint8_t UBX_INF_CLASS = 0x04; //All INF messages have 0x04 as the class -const uint8_t UBX_INF_DEBUG = 0x04; //ASCII output with debug contents -const uint8_t UBX_INF_ERROR = 0x00; //ASCII output with error contents -const uint8_t UBX_INF_NOTICE = 0x02; //ASCII output with informational contents -const uint8_t UBX_INF_TEST = 0x03; //ASCII output with test contents -const uint8_t UBX_INF_WARNING = 0x01; //ASCII output with warning contents - -//Class: LOG -//The following are used to configure LOG UBX messages (loggings messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34) -const uint8_t UBX_LOG_CREATE = 0x07; //Create Log File -const uint8_t UBX_LOG_ERASE = 0x03; //Erase Logged Data -const uint8_t UBX_LOG_FINDTIME = 0x0E; //Find index of a log entry based on a given time, or response to FINDTIME requested -const uint8_t UBX_LOG_INFO = 0x08; //Poll for log information, or Log information -const uint8_t UBX_LOG_RETRIEVEPOSEXTRA = 0x0F; //Odometer log entry -const uint8_t UBX_LOG_RETRIEVEPOS = 0x0B; //Position fix log entry -const uint8_t UBX_LOG_RETRIEVESTRING = 0x0D; //Byte string log entry -const uint8_t UBX_LOG_RETRIEVE = 0x09; //Request log data -const uint8_t UBX_LOG_STRING = 0x04; //Store arbitrary string on on-board flash - -//Class: MGA -//The following are used to configure MGA UBX messages (Multiple GNSS Assistance Messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34) -const uint8_t UBX_MGA_ACK_DATA0 = 0x60; //Multiple GNSS Acknowledge message -const uint8_t UBX_MGA_ANO = 0x20; //Multiple GNSS AssistNow Offline assistance - NOT SUPPORTED BY THE ZED-F9P! "The ZED-F9P supports AssistNow Online only." -const uint8_t UBX_MGA_BDS_EPH = 0x03; //BDS Ephemeris Assistance -const uint8_t UBX_MGA_BDS_ALM = 0x03; //BDS Almanac Assistance -const uint8_t UBX_MGA_BDS_HEALTH = 0x03; //BDS Health Assistance -const uint8_t UBX_MGA_BDS_UTC = 0x03; //BDS UTC Assistance -const uint8_t UBX_MGA_BDS_IONO = 0x03; //BDS Ionospheric Assistance -const uint8_t UBX_MGA_DBD = 0x80; //Either: Poll the Navigation Database, or Navigation Database Dump Entry -const uint8_t UBX_MGA_GAL_EPH = 0x02; //Galileo Ephemeris Assistance -const uint8_t UBX_MGA_GAL_ALM = 0x02; //Galileo Almanac Assitance -const uint8_t UBX_MGA_GAL_TIMOFFSET = 0x02; //Galileo GPS time offset assistance -const uint8_t UBX_MGA_GAL_UTC = 0x02; //Galileo UTC Assistance -const uint8_t UBX_MGA_GLO_EPH = 0x06; //GLONASS Ephemeris Assistance -const uint8_t UBX_MGA_GLO_ALM = 0x06; //GLONASS Almanac Assistance -const uint8_t UBX_MGA_GLO_TIMEOFFSET = 0x06; //GLONASS Auxiliary Time Offset Assistance -const uint8_t UBX_MGA_GPS_EPH = 0x00; //GPS Ephemeris Assistance -const uint8_t UBX_MGA_GPS_ALM = 0x00; //GPS Almanac Assistance -const uint8_t UBX_MGA_GPS_HEALTH = 0x00; //GPS Health Assistance -const uint8_t UBX_MGA_GPS_UTC = 0x00; //GPS UTC Assistance -const uint8_t UBX_MGA_GPS_IONO = 0x00; //GPS Ionosphere Assistance -const uint8_t UBX_MGA_INI_POS_XYZ = 0x40; //Initial Position Assistance -const uint8_t UBX_MGA_INI_POS_LLH = 0x40; //Initial Position Assitance -const uint8_t UBX_MGA_INI_TIME_UTC = 0x40; //Initial Time Assistance -const uint8_t UBX_MGA_INI_TIME_GNSS = 0x40; //Initial Time Assistance -const uint8_t UBX_MGA_INI_CLKD = 0x40; //Initial Clock Drift Assitance -const uint8_t UBX_MGA_INI_FREQ = 0x40; //Initial Frequency Assistance -const uint8_t UBX_MGA_INI_EOP = 0x40; //Earth Orientation Parameters Assistance -const uint8_t UBX_MGA_QZSS_EPH = 0x05; //QZSS Ephemeris Assistance -const uint8_t UBX_MGA_QZSS_ALM = 0x05; //QZSS Almanac Assistance -const uint8_t UBX_MGA_QZAA_HEALTH = 0x05; //QZSS Health Assistance - -//Class: MON -//The following are used to configure the MON UBX messages (monitoring messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 35) -const uint8_t UBX_MON_COMMS = 0x36; //Comm port information -const uint8_t UBX_MON_GNSS = 0x28; //Information message major GNSS selection -const uint8_t UBX_MON_HW2 = 0x0B; //Extended Hardware Status -const uint8_t UBX_MON_HW3 = 0x37; //HW I/O pin information -const uint8_t UBX_MON_HW = 0x09; //Hardware Status -const uint8_t UBX_MON_IO = 0x02; //I/O Subsystem Status -const uint8_t UBX_MON_MSGPP = 0x06; //Message Parse and Process Status -const uint8_t UBX_MON_PATCH = 0x27; //Output information about installed patches -const uint8_t UBX_MON_RF = 0x38; //RF information -const uint8_t UBX_MON_RXBUF = 0x07; //Receiver Buffer Status -const uint8_t UBX_MON_RXR = 0x21; //Receiver Status Information -const uint8_t UBX_MON_SPAN = 0x31; //Signal characteristics -const uint8_t UBX_MON_SYS = 0x39; //Current system performance information -const uint8_t UBX_MON_TXBUF = 0x08; //Transmitter Buffer Status. Used for query tx buffer size/state. -const uint8_t UBX_MON_VER = 0x04; //Receiver/Software Version. Used for obtaining Protocol Version. - -//Class: NAV -//The following are used to configure the NAV UBX messages (navigation results messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 35-36) -const uint8_t UBX_NAV_ATT = 0x05; //Vehicle "Attitude" Solution -const uint8_t UBX_NAV_CLOCK = 0x22; //Clock Solution -const uint8_t UBX_NAV_DOP = 0x04; //Dilution of precision -const uint8_t UBX_NAV_EOE = 0x61; //End of Epoch -const uint8_t UBX_NAV_GEOFENCE = 0x39; //Geofencing status. Used to poll the geofence status -const uint8_t UBX_NAV_HPPOSECEF = 0x13; //High Precision Position Solution in ECEF. Used to find our positional accuracy (high precision). -const uint8_t UBX_NAV_HPPOSLLH = 0x14; //High Precision Geodetic Position Solution. Used for obtaining lat/long/alt in high precision -const uint8_t UBX_NAV_ODO = 0x09; //Odometer Solution -const uint8_t UBX_NAV_ORB = 0x34; //GNSS Orbit Database Info -const uint8_t UBX_NAV_PL = 0x62; //Protection Level Information -const uint8_t UBX_NAV_POSECEF = 0x01; //Position Solution in ECEF -const uint8_t UBX_NAV_POSLLH = 0x02; //Geodetic Position Solution -const uint8_t UBX_NAV_PVT = 0x07; //All the things! Position, velocity, time, PDOP, height, h/v accuracies, number of satellites. Navigation Position Velocity Time Solution. -const uint8_t UBX_NAV_PVAT = 0x17; //Navigation position velocity attitude time solution (ZED-F9R only) -const uint8_t UBX_NAV_RELPOSNED = 0x3C; //Relative Positioning Information in NED frame -const uint8_t UBX_NAV_RESETODO = 0x10; //Reset odometer -const uint8_t UBX_NAV_SAT = 0x35; //Satellite Information -const uint8_t UBX_NAV_SIG = 0x43; //Signal Information -const uint8_t UBX_NAV_STATUS = 0x03; //Receiver Navigation Status -const uint8_t UBX_NAV_SVIN = 0x3B; //Survey-in data. Used for checking Survey In status -const uint8_t UBX_NAV_TIMEBDS = 0x24; //BDS Time Solution -const uint8_t UBX_NAV_TIMEGAL = 0x25; //Galileo Time Solution -const uint8_t UBX_NAV_TIMEGLO = 0x23; //GLO Time Solution -const uint8_t UBX_NAV_TIMEGPS = 0x20; //GPS Time Solution -const uint8_t UBX_NAV_TIMELS = 0x26; //Leap second event information -const uint8_t UBX_NAV_TIMEUTC = 0x21; //UTC Time Solution -const uint8_t UBX_NAV_VELECEF = 0x11; //Velocity Solution in ECEF -const uint8_t UBX_NAV_VELNED = 0x12; //Velocity Solution in NED -const uint8_t UBX_NAV_AOPSTATUS = 0x60; //AssistNow Autonomous status - -//Class: RXM -//The following are used to configure the RXM UBX messages (receiver manager messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) -const uint8_t UBX_RXM_COR = 0x34; // Differential correction input status -const uint8_t UBX_RXM_MEASX = 0x14; //Satellite Measurements for RRLP -const uint8_t UBX_RXM_PMP = 0x72; //PMP raw data (NEO-D9S) (two different versions) (packet size for version 0x01 is variable) -const uint8_t UBX_RXM_PMREQ = 0x41; //Requests a Power Management task (two different packet sizes) -const uint8_t UBX_RXM_RAWX = 0x15; //Multi-GNSS Raw Measurement Data -const uint8_t UBX_RXM_RLM = 0x59; //Galileo SAR Short-RLM report (two different packet sizes) -const uint8_t UBX_RXM_RTCM = 0x32; //RTCM input status -const uint8_t UBX_RXM_SFRBX = 0x13; //Broadcast Navigation Data Subframe -const uint8_t UBX_RXM_SPARTN = 0x33; //SPARTN input status -const uint8_t UBX_RXM_SPARTNKEY = 0x36; //Poll/transfer dynamic SPARTN keys - -//Class: SEC -//The following are used to configure the SEC UBX messages (security feature messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) -const uint8_t UBX_SEC_UNIQID = 0x03; //Unique chip ID - -//Class: TIM -//The following are used to configure the TIM UBX messages (timing messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) -const uint8_t UBX_TIM_TM2 = 0x03; //Time mark data -const uint8_t UBX_TIM_TP = 0x01; //Time Pulse Timedata -const uint8_t UBX_TIM_VRFY = 0x06; //Sourced Time Verification - -//Class: UPD -//The following are used to configure the UPD UBX messages (firmware update messages). Descriptions from UBX messages overview (ZED-F9P Interface Description Document page 36) -const uint8_t UBX_UPD_SOS = 0x14; //Poll Backup Fil Restore Status, Create Backup File in Flash, Clear Backup File in Flash, Backup File Creation Acknowledge, System Restored from Backup - -//The following are used to enable RTCM messages -const uint8_t UBX_RTCM_MSB = 0xF5; //All RTCM enable commands have 0xF5 as MSB -const uint8_t UBX_RTCM_1005 = 0x05; //Stationary RTK reference ARP -const uint8_t UBX_RTCM_1074 = 0x4A; //GPS MSM4 -const uint8_t UBX_RTCM_1077 = 0x4D; //GPS MSM7 -const uint8_t UBX_RTCM_1084 = 0x54; //GLONASS MSM4 -const uint8_t UBX_RTCM_1087 = 0x57; //GLONASS MSM7 -const uint8_t UBX_RTCM_1094 = 0x5E; //Galileo MSM4 -const uint8_t UBX_RTCM_1097 = 0x61; //Galileo MSM7 -const uint8_t UBX_RTCM_1124 = 0x7C; //BeiDou MSM4 -const uint8_t UBX_RTCM_1127 = 0x7F; //BeiDou MSM7 -const uint8_t UBX_RTCM_1230 = 0xE6; //GLONASS code-phase biases, set to once every 10 seconds -const uint8_t UBX_RTCM_4072_0 = 0xFE; //Reference station PVT (ublox proprietary RTCM message) -const uint8_t UBX_RTCM_4072_1 = 0xFD; //Additional reference station information (ublox proprietary RTCM message) +// The following are UBX Class IDs. Descriptions taken from ZED-F9P Interface Description Document page 32, NEO-M8P Interface Description page 145 +const uint8_t UBX_CLASS_NAV = 0x01; // Navigation Results Messages: Position, Speed, Time, Acceleration, Heading, DOP, SVs used +const uint8_t UBX_CLASS_RXM = 0x02; // Receiver Manager Messages: Satellite Status, RTC Status +const uint8_t UBX_CLASS_INF = 0x04; // Information Messages: Printf-Style Messages, with IDs such as Error, Warning, Notice +const uint8_t UBX_CLASS_ACK = 0x05; // Ack/Nak Messages: Acknowledge or Reject messages to UBX-CFG input messages +const uint8_t UBX_CLASS_CFG = 0x06; // Configuration Input Messages: Configure the receiver. +const uint8_t UBX_CLASS_UPD = 0x09; // Firmware Update Messages: Memory/Flash erase/write, Reboot, Flash identification, etc. +const uint8_t UBX_CLASS_MON = 0x0A; // Monitoring Messages: Communication Status, CPU Load, Stack Usage, Task Status +const uint8_t UBX_CLASS_AID = 0x0B; //(NEO-M8P ONLY!!!) AssistNow Aiding Messages: Ephemeris, Almanac, other A-GPS data input +const uint8_t UBX_CLASS_TIM = 0x0D; // Timing Messages: Time Pulse Output, Time Mark Results +const uint8_t UBX_CLASS_ESF = 0x10; //(NEO-M8P ONLY!!!) External Sensor Fusion Messages: External Sensor Measurements and Status Information +const uint8_t UBX_CLASS_MGA = 0x13; // Multiple GNSS Assistance Messages: Assistance data for various GNSS +const uint8_t UBX_CLASS_LOG = 0x21; // Logging Messages: Log creation, deletion, info and retrieval +const uint8_t UBX_CLASS_SEC = 0x27; // Security Feature Messages +const uint8_t UBX_CLASS_HNR = 0x28; //(NEO-M8P ONLY!!!) High Rate Navigation Results Messages: High rate time, position speed, heading +const uint8_t UBX_CLASS_NMEA = 0xF0; // NMEA Strings: standard NMEA strings + +// Class: CFG +// The following are used for configuration. Descriptions are from the ZED-F9P Interface Description pg 33-34 and NEO-M9N Interface Description pg 47-48 +const uint8_t UBX_CFG_ANT = 0x13; // Antenna Control Settings. Used to configure the antenna control settings +const uint8_t UBX_CFG_BATCH = 0x93; // Get/set data batching configuration. +const uint8_t UBX_CFG_CFG = 0x09; // Clear, Save, and Load Configurations. Used to save current configuration +const uint8_t UBX_CFG_DAT = 0x06; // Set User-defined Datum or The currently defined Datum +const uint8_t UBX_CFG_DGNSS = 0x70; // DGNSS configuration +const uint8_t UBX_CFG_ESFALG = 0x56; // ESF alignment +const uint8_t UBX_CFG_ESFA = 0x4C; // ESF accelerometer +const uint8_t UBX_CFG_ESFG = 0x4D; // ESF gyro +const uint8_t UBX_CFG_GEOFENCE = 0x69; // Geofencing configuration. Used to configure a geofence +const uint8_t UBX_CFG_GNSS = 0x3E; // GNSS system configuration +const uint8_t UBX_CFG_HNR = 0x5C; // High Navigation Rate +const uint8_t UBX_CFG_INF = 0x02; // Depending on packet length, either: poll configuration for one protocol, or information message configuration +const uint8_t UBX_CFG_ITFM = 0x39; // Jamming/Interference Monitor configuration +const uint8_t UBX_CFG_LOGFILTER = 0x47; // Data Logger Configuration +const uint8_t UBX_CFG_MSG = 0x01; // Poll a message configuration, or Set Message Rate(s), or Set Message Rate +const uint8_t UBX_CFG_NAV5 = 0x24; // Navigation Engine Settings. Used to configure the navigation engine including the dynamic model. +const uint8_t UBX_CFG_NAVX5 = 0x23; // Navigation Engine Expert Settings +const uint8_t UBX_CFG_NMEA = 0x17; // Extended NMEA protocol configuration V1 +const uint8_t UBX_CFG_ODO = 0x1E; // Odometer, Low-speed COG Engine Settings +const uint8_t UBX_CFG_PM2 = 0x3B; // Extended power management configuration +const uint8_t UBX_CFG_PMS = 0x86; // Power mode setup +const uint8_t UBX_CFG_PRT = 0x00; // Used to configure port specifics. Polls the configuration for one I/O Port, or Port configuration for UART ports, or Port configuration for USB port, or Port configuration for SPI port, or Port configuration for DDC port +const uint8_t UBX_CFG_PWR = 0x57; // Put receiver in a defined power state +const uint8_t UBX_CFG_RATE = 0x08; // Navigation/Measurement Rate Settings. Used to set port baud rates. +const uint8_t UBX_CFG_RINV = 0x34; // Contents of Remote Inventory +const uint8_t UBX_CFG_RST = 0x04; // Reset Receiver / Clear Backup Data Structures. Used to reset device. +const uint8_t UBX_CFG_RXM = 0x11; // RXM configuration +const uint8_t UBX_CFG_SBAS = 0x16; // SBAS configuration +const uint8_t UBX_CFG_TMODE3 = 0x71; // Time Mode Settings 3. Used to enable Survey In Mode +const uint8_t UBX_CFG_TP5 = 0x31; // Time Pulse Parameters +const uint8_t UBX_CFG_USB = 0x1B; // USB Configuration +const uint8_t UBX_CFG_VALDEL = 0x8C; // Used for config of higher version u-blox modules (ie protocol v27 and above). Deletes values corresponding to provided keys/ provided keys with a transaction +const uint8_t UBX_CFG_VALGET = 0x8B; // Used for config of higher version u-blox modules (ie protocol v27 and above). Configuration Items +const uint8_t UBX_CFG_VALSET = 0x8A; // Used for config of higher version u-blox modules (ie protocol v27 and above). Sets values corresponding to provided key-value pairs/ provided key-value pairs within a transaction. + +// Class: NMEA +// The following are used to enable NMEA messages. Descriptions come from the NMEA messages overview in the ZED-F9P Interface Description +const uint8_t UBX_NMEA_MSB = 0xF0; // All NMEA enable commands have 0xF0 as MSB. Equal to UBX_CLASS_NMEA +const uint8_t UBX_NMEA_DTM = 0x0A; // GxDTM (datum reference) +const uint8_t UBX_NMEA_GAQ = 0x45; // GxGAQ (poll a standard message (if the current talker ID is GA)) +const uint8_t UBX_NMEA_GBQ = 0x44; // GxGBQ (poll a standard message (if the current Talker ID is GB)) +const uint8_t UBX_NMEA_GBS = 0x09; // GxGBS (GNSS satellite fault detection) +const uint8_t UBX_NMEA_GGA = 0x00; // GxGGA (Global positioning system fix data) +const uint8_t UBX_NMEA_GLL = 0x01; // GxGLL (latitude and long, whith time of position fix and status) +const uint8_t UBX_NMEA_GLQ = 0x43; // GxGLQ (poll a standard message (if the current Talker ID is GL)) +const uint8_t UBX_NMEA_GNQ = 0x42; // GxGNQ (poll a standard message (if the current Talker ID is GN)) +const uint8_t UBX_NMEA_GNS = 0x0D; // GxGNS (GNSS fix data) +const uint8_t UBX_NMEA_GPQ = 0x40; // GxGPQ (poll a standard message (if the current Talker ID is GP)) +const uint8_t UBX_NMEA_GQQ = 0x47; // GxGQQ (poll a standard message (if the current Talker ID is GQ)) +const uint8_t UBX_NMEA_GRS = 0x06; // GxGRS (GNSS range residuals) +const uint8_t UBX_NMEA_GSA = 0x02; // GxGSA (GNSS DOP and Active satellites) +const uint8_t UBX_NMEA_GST = 0x07; // GxGST (GNSS Pseudo Range Error Statistics) +const uint8_t UBX_NMEA_GSV = 0x03; // GxGSV (GNSS satellites in view) +const uint8_t UBX_NMEA_RLM = 0x0B; // GxRMC (Return link message (RLM)) +const uint8_t UBX_NMEA_RMC = 0x04; // GxRMC (Recommended minimum data) +const uint8_t UBX_NMEA_TXT = 0x41; // GxTXT (text transmission) +const uint8_t UBX_NMEA_VLW = 0x0F; // GxVLW (dual ground/water distance) +const uint8_t UBX_NMEA_VTG = 0x05; // GxVTG (course over ground and Ground speed) +const uint8_t UBX_NMEA_ZDA = 0x08; // GxZDA (Time and Date) + +// The following are used to configure the NMEA protocol main talker ID and GSV talker ID +const uint8_t UBX_NMEA_MAINTALKERID_NOTOVERRIDDEN = 0x00; // main talker ID is system dependent +const uint8_t UBX_NMEA_MAINTALKERID_GP = 0x01; // main talker ID is GPS +const uint8_t UBX_NMEA_MAINTALKERID_GL = 0x02; // main talker ID is GLONASS +const uint8_t UBX_NMEA_MAINTALKERID_GN = 0x03; // main talker ID is combined receiver +const uint8_t UBX_NMEA_MAINTALKERID_GA = 0x04; // main talker ID is Galileo +const uint8_t UBX_NMEA_MAINTALKERID_GB = 0x05; // main talker ID is BeiDou +const uint8_t UBX_NMEA_GSVTALKERID_GNSS = 0x00; // GNSS specific Talker ID (as defined by NMEA) +const uint8_t UBX_NMEA_GSVTALKERID_MAIN = 0x01; // use the main Talker ID + +// Class: HNR +// The following are used to configure the HNR message rates +const uint8_t UBX_HNR_ATT = 0x01; // HNR Attitude +const uint8_t UBX_HNR_INS = 0x02; // HNR Vehicle Dynamics +const uint8_t UBX_HNR_PVT = 0x00; // HNR PVT + +// Class: INF +// The following are used to configure INF UBX messages (information messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34) +const uint8_t UBX_INF_CLASS = 0x04; // All INF messages have 0x04 as the class +const uint8_t UBX_INF_DEBUG = 0x04; // ASCII output with debug contents +const uint8_t UBX_INF_ERROR = 0x00; // ASCII output with error contents +const uint8_t UBX_INF_NOTICE = 0x02; // ASCII output with informational contents +const uint8_t UBX_INF_TEST = 0x03; // ASCII output with test contents +const uint8_t UBX_INF_WARNING = 0x01; // ASCII output with warning contents + +// Class: LOG +// The following are used to configure LOG UBX messages (loggings messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34) +const uint8_t UBX_LOG_CREATE = 0x07; // Create Log File +const uint8_t UBX_LOG_ERASE = 0x03; // Erase Logged Data +const uint8_t UBX_LOG_FINDTIME = 0x0E; // Find index of a log entry based on a given time, or response to FINDTIME requested +const uint8_t UBX_LOG_INFO = 0x08; // Poll for log information, or Log information +const uint8_t UBX_LOG_RETRIEVEPOSEXTRA = 0x0F; // Odometer log entry +const uint8_t UBX_LOG_RETRIEVEPOS = 0x0B; // Position fix log entry +const uint8_t UBX_LOG_RETRIEVESTRING = 0x0D; // Byte string log entry +const uint8_t UBX_LOG_RETRIEVE = 0x09; // Request log data +const uint8_t UBX_LOG_STRING = 0x04; // Store arbitrary string on on-board flash + +// Class: MGA +// The following are used to configure MGA UBX messages (Multiple GNSS Assistance Messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34) +const uint8_t UBX_MGA_ACK_DATA0 = 0x60; // Multiple GNSS Acknowledge message +const uint8_t UBX_MGA_ANO = 0x20; // Multiple GNSS AssistNow Offline assistance - NOT SUPPORTED BY THE ZED-F9P! "The ZED-F9P supports AssistNow Online only." +const uint8_t UBX_MGA_BDS_EPH = 0x03; // BDS Ephemeris Assistance +const uint8_t UBX_MGA_BDS_ALM = 0x03; // BDS Almanac Assistance +const uint8_t UBX_MGA_BDS_HEALTH = 0x03; // BDS Health Assistance +const uint8_t UBX_MGA_BDS_UTC = 0x03; // BDS UTC Assistance +const uint8_t UBX_MGA_BDS_IONO = 0x03; // BDS Ionospheric Assistance +const uint8_t UBX_MGA_DBD = 0x80; // Either: Poll the Navigation Database, or Navigation Database Dump Entry +const uint8_t UBX_MGA_GAL_EPH = 0x02; // Galileo Ephemeris Assistance +const uint8_t UBX_MGA_GAL_ALM = 0x02; // Galileo Almanac Assitance +const uint8_t UBX_MGA_GAL_TIMOFFSET = 0x02; // Galileo GPS time offset assistance +const uint8_t UBX_MGA_GAL_UTC = 0x02; // Galileo UTC Assistance +const uint8_t UBX_MGA_GLO_EPH = 0x06; // GLONASS Ephemeris Assistance +const uint8_t UBX_MGA_GLO_ALM = 0x06; // GLONASS Almanac Assistance +const uint8_t UBX_MGA_GLO_TIMEOFFSET = 0x06; // GLONASS Auxiliary Time Offset Assistance +const uint8_t UBX_MGA_GPS_EPH = 0x00; // GPS Ephemeris Assistance +const uint8_t UBX_MGA_GPS_ALM = 0x00; // GPS Almanac Assistance +const uint8_t UBX_MGA_GPS_HEALTH = 0x00; // GPS Health Assistance +const uint8_t UBX_MGA_GPS_UTC = 0x00; // GPS UTC Assistance +const uint8_t UBX_MGA_GPS_IONO = 0x00; // GPS Ionosphere Assistance +const uint8_t UBX_MGA_INI_POS_XYZ = 0x40; // Initial Position Assistance +const uint8_t UBX_MGA_INI_POS_LLH = 0x40; // Initial Position Assitance +const uint8_t UBX_MGA_INI_TIME_UTC = 0x40; // Initial Time Assistance +const uint8_t UBX_MGA_INI_TIME_GNSS = 0x40; // Initial Time Assistance +const uint8_t UBX_MGA_INI_CLKD = 0x40; // Initial Clock Drift Assitance +const uint8_t UBX_MGA_INI_FREQ = 0x40; // Initial Frequency Assistance +const uint8_t UBX_MGA_INI_EOP = 0x40; // Earth Orientation Parameters Assistance +const uint8_t UBX_MGA_QZSS_EPH = 0x05; // QZSS Ephemeris Assistance +const uint8_t UBX_MGA_QZSS_ALM = 0x05; // QZSS Almanac Assistance +const uint8_t UBX_MGA_QZAA_HEALTH = 0x05; // QZSS Health Assistance + +// Class: MON +// The following are used to configure the MON UBX messages (monitoring messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 35) +const uint8_t UBX_MON_COMMS = 0x36; // Comm port information +const uint8_t UBX_MON_GNSS = 0x28; // Information message major GNSS selection +const uint8_t UBX_MON_HW2 = 0x0B; // Extended Hardware Status +const uint8_t UBX_MON_HW3 = 0x37; // HW I/O pin information +const uint8_t UBX_MON_HW = 0x09; // Hardware Status +const uint8_t UBX_MON_IO = 0x02; // I/O Subsystem Status +const uint8_t UBX_MON_MSGPP = 0x06; // Message Parse and Process Status +const uint8_t UBX_MON_PATCH = 0x27; // Output information about installed patches +const uint8_t UBX_MON_RF = 0x38; // RF information +const uint8_t UBX_MON_RXBUF = 0x07; // Receiver Buffer Status +const uint8_t UBX_MON_RXR = 0x21; // Receiver Status Information +const uint8_t UBX_MON_SPAN = 0x31; // Signal characteristics +const uint8_t UBX_MON_SYS = 0x39; // Current system performance information +const uint8_t UBX_MON_TXBUF = 0x08; // Transmitter Buffer Status. Used for query tx buffer size/state. +const uint8_t UBX_MON_VER = 0x04; // Receiver/Software Version. Used for obtaining Protocol Version. + +// Class: NAV +// The following are used to configure the NAV UBX messages (navigation results messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 35-36) +const uint8_t UBX_NAV_ATT = 0x05; // Vehicle "Attitude" Solution +const uint8_t UBX_NAV_CLOCK = 0x22; // Clock Solution +const uint8_t UBX_NAV_DOP = 0x04; // Dilution of precision +const uint8_t UBX_NAV_EOE = 0x61; // End of Epoch +const uint8_t UBX_NAV_GEOFENCE = 0x39; // Geofencing status. Used to poll the geofence status +const uint8_t UBX_NAV_HPPOSECEF = 0x13; // High Precision Position Solution in ECEF. Used to find our positional accuracy (high precision). +const uint8_t UBX_NAV_HPPOSLLH = 0x14; // High Precision Geodetic Position Solution. Used for obtaining lat/long/alt in high precision +const uint8_t UBX_NAV_ODO = 0x09; // Odometer Solution +const uint8_t UBX_NAV_ORB = 0x34; // GNSS Orbit Database Info +const uint8_t UBX_NAV_PL = 0x62; // Protection Level Information +const uint8_t UBX_NAV_POSECEF = 0x01; // Position Solution in ECEF +const uint8_t UBX_NAV_POSLLH = 0x02; // Geodetic Position Solution +const uint8_t UBX_NAV_PVT = 0x07; // All the things! Position, velocity, time, PDOP, height, h/v accuracies, number of satellites. Navigation Position Velocity Time Solution. +const uint8_t UBX_NAV_PVAT = 0x17; // Navigation position velocity attitude time solution (ZED-F9R only) +const uint8_t UBX_NAV_RELPOSNED = 0x3C; // Relative Positioning Information in NED frame +const uint8_t UBX_NAV_RESETODO = 0x10; // Reset odometer +const uint8_t UBX_NAV_SAT = 0x35; // Satellite Information +const uint8_t UBX_NAV_SIG = 0x43; // Signal Information +const uint8_t UBX_NAV_STATUS = 0x03; // Receiver Navigation Status +const uint8_t UBX_NAV_SVIN = 0x3B; // Survey-in data. Used for checking Survey In status +const uint8_t UBX_NAV_TIMEBDS = 0x24; // BDS Time Solution +const uint8_t UBX_NAV_TIMEGAL = 0x25; // Galileo Time Solution +const uint8_t UBX_NAV_TIMEGLO = 0x23; // GLO Time Solution +const uint8_t UBX_NAV_TIMEGPS = 0x20; // GPS Time Solution +const uint8_t UBX_NAV_TIMELS = 0x26; // Leap second event information +const uint8_t UBX_NAV_TIMEUTC = 0x21; // UTC Time Solution +const uint8_t UBX_NAV_VELECEF = 0x11; // Velocity Solution in ECEF +const uint8_t UBX_NAV_VELNED = 0x12; // Velocity Solution in NED +const uint8_t UBX_NAV_AOPSTATUS = 0x60; // AssistNow Autonomous status + +// Class: RXM +// The following are used to configure the RXM UBX messages (receiver manager messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) +const uint8_t UBX_RXM_COR = 0x34; // Differential correction input status +const uint8_t UBX_RXM_MEASX = 0x14; // Satellite Measurements for RRLP +const uint8_t UBX_RXM_PMP = 0x72; // PMP raw data (NEO-D9S) (two different versions) (packet size for version 0x01 is variable) +const uint8_t UBX_RXM_PMREQ = 0x41; // Requests a Power Management task (two different packet sizes) +const uint8_t UBX_RXM_RAWX = 0x15; // Multi-GNSS Raw Measurement Data +const uint8_t UBX_RXM_RLM = 0x59; // Galileo SAR Short-RLM report (two different packet sizes) +const uint8_t UBX_RXM_RTCM = 0x32; // RTCM input status +const uint8_t UBX_RXM_SFRBX = 0x13; // Broadcast Navigation Data Subframe +const uint8_t UBX_RXM_SPARTN = 0x33; // SPARTN input status +const uint8_t UBX_RXM_SPARTNKEY = 0x36; // Poll/transfer dynamic SPARTN keys + +// Class: SEC +// The following are used to configure the SEC UBX messages (security feature messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) +const uint8_t UBX_SEC_UNIQID = 0x03; // Unique chip ID + +// Class: TIM +// The following are used to configure the TIM UBX messages (timing messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36) +const uint8_t UBX_TIM_TM2 = 0x03; // Time mark data +const uint8_t UBX_TIM_TP = 0x01; // Time Pulse Timedata +const uint8_t UBX_TIM_VRFY = 0x06; // Sourced Time Verification + +// Class: UPD +// The following are used to configure the UPD UBX messages (firmware update messages). Descriptions from UBX messages overview (ZED-F9P Interface Description Document page 36) +const uint8_t UBX_UPD_SOS = 0x14; // Poll Backup Fil Restore Status, Create Backup File in Flash, Clear Backup File in Flash, Backup File Creation Acknowledge, System Restored from Backup + +// The following are used to enable RTCM messages +const uint8_t UBX_RTCM_MSB = 0xF5; // All RTCM enable commands have 0xF5 as MSB +const uint8_t UBX_RTCM_1005 = 0x05; // Stationary RTK reference ARP +const uint8_t UBX_RTCM_1074 = 0x4A; // GPS MSM4 +const uint8_t UBX_RTCM_1077 = 0x4D; // GPS MSM7 +const uint8_t UBX_RTCM_1084 = 0x54; // GLONASS MSM4 +const uint8_t UBX_RTCM_1087 = 0x57; // GLONASS MSM7 +const uint8_t UBX_RTCM_1094 = 0x5E; // Galileo MSM4 +const uint8_t UBX_RTCM_1097 = 0x61; // Galileo MSM7 +const uint8_t UBX_RTCM_1124 = 0x7C; // BeiDou MSM4 +const uint8_t UBX_RTCM_1127 = 0x7F; // BeiDou MSM7 +const uint8_t UBX_RTCM_1230 = 0xE6; // GLONASS code-phase biases, set to once every 10 seconds +const uint8_t UBX_RTCM_4072_0 = 0xFE; // Reference station PVT (ublox proprietary RTCM message) +const uint8_t UBX_RTCM_4072_1 = 0xFD; // Additional reference station information (ublox proprietary RTCM message) // Class: ACK const uint8_t UBX_ACK_NACK = 0x00; const uint8_t UBX_ACK_ACK = 0x01; -const uint8_t UBX_ACK_NONE = 0x02; //Not a real value +const uint8_t UBX_ACK_NONE = 0x02; // Not a real value -//Class: ESF -// The following constants are used to get External Sensor Measurements and Status -// Information. +// Class: ESF +// The following constants are used to get External Sensor Measurements and Status +// Information. const uint8_t UBX_ESF_MEAS = 0x02; const uint8_t UBX_ESF_RAW = 0x03; const uint8_t UBX_ESF_STATUS = 0x10; const uint8_t UBX_ESF_RESETALG = 0x13; const uint8_t UBX_ESF_ALG = 0x14; -const uint8_t UBX_ESF_INS = 0x15; //36 bytes +const uint8_t UBX_ESF_INS = 0x15; // 36 bytes const uint8_t SVIN_MODE_DISABLE = 0x00; const uint8_t SVIN_MODE_ENABLE = 0x01; -//The following consts are used to configure the various ports and streams for those ports. See -CFG-PRT. +// The following consts are used to configure the various ports and streams for those ports. See -CFG-PRT. const uint8_t COM_PORT_I2C = 0; const uint8_t COM_PORT_UART1 = 1; const uint8_t COM_PORT_UART2 = 2; @@ -448,110 +448,110 @@ const uint8_t COM_TYPE_RTCM3 = (1 << 5); const uint8_t COM_TYPE_SPARTN = (1 << 6); // Configuration Sub-Section mask definitions for saveConfigSelective (UBX-CFG-CFG) -const uint32_t VAL_CFG_SUBSEC_IOPORT = 0x00000001; // ioPort - communications port settings (causes IO system reset!) -const uint32_t VAL_CFG_SUBSEC_MSGCONF = 0x00000002; // msgConf - message configuration -const uint32_t VAL_CFG_SUBSEC_INFMSG = 0x00000004; // infMsg - INF message configuration -const uint32_t VAL_CFG_SUBSEC_NAVCONF = 0x00000008; // navConf - navigation configuration -const uint32_t VAL_CFG_SUBSEC_RXMCONF = 0x00000010; // rxmConf - receiver manager configuration -const uint32_t VAL_CFG_SUBSEC_SENCONF = 0x00000100; // senConf - sensor interface configuration (requires protocol 19+) +const uint32_t VAL_CFG_SUBSEC_IOPORT = 0x00000001; // ioPort - communications port settings (causes IO system reset!) +const uint32_t VAL_CFG_SUBSEC_MSGCONF = 0x00000002; // msgConf - message configuration +const uint32_t VAL_CFG_SUBSEC_INFMSG = 0x00000004; // infMsg - INF message configuration +const uint32_t VAL_CFG_SUBSEC_NAVCONF = 0x00000008; // navConf - navigation configuration +const uint32_t VAL_CFG_SUBSEC_RXMCONF = 0x00000010; // rxmConf - receiver manager configuration +const uint32_t VAL_CFG_SUBSEC_SENCONF = 0x00000100; // senConf - sensor interface configuration (requires protocol 19+) const uint32_t VAL_CFG_SUBSEC_RINVCONF = 0x00000200; // rinvConf - remove inventory configuration -const uint32_t VAL_CFG_SUBSEC_ANTCONF = 0x00000400; // antConf - antenna configuration -const uint32_t VAL_CFG_SUBSEC_LOGCONF = 0x00000800; // logConf - logging configuration -const uint32_t VAL_CFG_SUBSEC_FTSCONF = 0x00001000; // ftsConf - FTS configuration (FTS products only) +const uint32_t VAL_CFG_SUBSEC_ANTCONF = 0x00000400; // antConf - antenna configuration +const uint32_t VAL_CFG_SUBSEC_LOGCONF = 0x00000800; // logConf - logging configuration +const uint32_t VAL_CFG_SUBSEC_FTSCONF = 0x00001000; // ftsConf - FTS configuration (FTS products only) // Bitfield wakeupSources for UBX_RXM_PMREQ -const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_UARTRX = 0x00000008; // uartrx +const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_UARTRX = 0x00000008; // uartrx const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0 = 0x00000020; // extint0 const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT1 = 0x00000040; // extint1 -const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_SPICS = 0x00000080; // spics +const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_SPICS = 0x00000080; // spics enum dynModel // Possible values for the dynamic platform model, which provide more accuract position output for the situation. Description extracted from ZED-F9P Integration Manual { - DYN_MODEL_PORTABLE = 0, //Applications with low acceleration, e.g. portable devices. Suitable for most situations. - // 1 is not defined - DYN_MODEL_STATIONARY = 2, //Used in timing applications (antenna must be stationary) or other stationary applications. Velocity restricted to 0 m/s. Zero dynamics assumed. - DYN_MODEL_PEDESTRIAN, //Applications with low acceleration and speed, e.g. how a pedestrian would move. Low acceleration assumed. - DYN_MODEL_AUTOMOTIVE, //Used for applications with equivalent dynamics to those of a passenger car. Low vertical acceleration assumed - DYN_MODEL_SEA, //Recommended for applications at sea, with zero vertical velocity. Zero vertical velocity assumed. Sea level assumed. - DYN_MODEL_AIRBORNE1g, //Airborne <1g acceleration. Used for applications with a higher dynamic range and greater vertical acceleration than a passenger car. No 2D position fixes supported. - DYN_MODEL_AIRBORNE2g, //Airborne <2g acceleration. Recommended for typical airborne environments. No 2D position fixes supported. - DYN_MODEL_AIRBORNE4g, //Airborne <4g acceleration. Only recommended for extremely dynamic environments. No 2D position fixes supported. - DYN_MODEL_WRIST, // Not supported in protocol versions less than 18. Only recommended for wrist worn applications. Receiver will filter out arm motion. - DYN_MODEL_BIKE, // Supported in protocol versions 19.2. (not available in all products) - DYN_MODEL_MOWER, // Added in HPS 1.21 (not available in all products) - DYN_MODEL_ESCOOTER, // Added in HPS 1.21 (not available in all products) - DYN_MODEL_UNKNOWN = 255 // getDynamicModel will return 255 if sendCommand fails + DYN_MODEL_PORTABLE = 0, // Applications with low acceleration, e.g. portable devices. Suitable for most situations. + // 1 is not defined + DYN_MODEL_STATIONARY = 2, // Used in timing applications (antenna must be stationary) or other stationary applications. Velocity restricted to 0 m/s. Zero dynamics assumed. + DYN_MODEL_PEDESTRIAN, // Applications with low acceleration and speed, e.g. how a pedestrian would move. Low acceleration assumed. + DYN_MODEL_AUTOMOTIVE, // Used for applications with equivalent dynamics to those of a passenger car. Low vertical acceleration assumed + DYN_MODEL_SEA, // Recommended for applications at sea, with zero vertical velocity. Zero vertical velocity assumed. Sea level assumed. + DYN_MODEL_AIRBORNE1g, // Airborne <1g acceleration. Used for applications with a higher dynamic range and greater vertical acceleration than a passenger car. No 2D position fixes supported. + DYN_MODEL_AIRBORNE2g, // Airborne <2g acceleration. Recommended for typical airborne environments. No 2D position fixes supported. + DYN_MODEL_AIRBORNE4g, // Airborne <4g acceleration. Only recommended for extremely dynamic environments. No 2D position fixes supported. + DYN_MODEL_WRIST, // Not supported in protocol versions less than 18. Only recommended for wrist worn applications. Receiver will filter out arm motion. + DYN_MODEL_BIKE, // Supported in protocol versions 19.2. (not available in all products) + DYN_MODEL_MOWER, // Added in HPS 1.21 (not available in all products) + DYN_MODEL_ESCOOTER, // Added in HPS 1.21 (not available in all products) + DYN_MODEL_UNKNOWN = 255 // getDynamicModel will return 255 if sendCommand fails }; // The GNSS identifiers - used by UBX-CFG-GNSS (0x06 0x3E) GNSS system configuration enum sfe_ublox_gnss_ids_e { - SFE_UBLOX_GNSS_ID_GPS, - SFE_UBLOX_GNSS_ID_SBAS, - SFE_UBLOX_GNSS_ID_GALILEO, - SFE_UBLOX_GNSS_ID_BEIDOU, - SFE_UBLOX_GNSS_ID_IMES, - SFE_UBLOX_GNSS_ID_QZSS, - SFE_UBLOX_GNSS_ID_GLONASS + SFE_UBLOX_GNSS_ID_GPS, + SFE_UBLOX_GNSS_ID_SBAS, + SFE_UBLOX_GNSS_ID_GALILEO, + SFE_UBLOX_GNSS_ID_BEIDOU, + SFE_UBLOX_GNSS_ID_IMES, + SFE_UBLOX_GNSS_ID_QZSS, + SFE_UBLOX_GNSS_ID_GLONASS }; // The GNSS identifiers of leap second event info source - used by UBX-NAV-TIMELS enum sfe_ublox_ls_src_e { - SFE_UBLOX_LS_SRC_DEFAULT, - SFE_UBLOX_LS_SRC_GLONASS, - SFE_UBLOX_LS_SRC_GPS, - SFE_UBLOX_LS_SRC_SBAS, - SFE_UBLOX_LS_SRC_BEIDOU, - SFE_UBLOX_LS_SRC_GALILEO, - SFE_UBLOX_LS_SRC_AIDED, - SFE_UBLOX_LS_SRC_CONFIGURED, - SFE_UBLOX_LS_SRC_UNKNOWN = 255 + SFE_UBLOX_LS_SRC_DEFAULT, + SFE_UBLOX_LS_SRC_GLONASS, + SFE_UBLOX_LS_SRC_GPS, + SFE_UBLOX_LS_SRC_SBAS, + SFE_UBLOX_LS_SRC_BEIDOU, + SFE_UBLOX_LS_SRC_GALILEO, + SFE_UBLOX_LS_SRC_AIDED, + SFE_UBLOX_LS_SRC_CONFIGURED, + SFE_UBLOX_LS_SRC_UNKNOWN = 255 }; typedef enum { - SFE_UBLOX_MGA_ASSIST_ACK_NO, // Do not expect UBX-MGA-ACK's. If the module outputs them, they will be ignored - SFE_UBLOX_MGA_ASSIST_ACK_YES, // Expect and check for UBX-MGA-ACK's - SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE // Check UBX-CFG-NAVX5 ackAiding to determine if UBX-MGA-ACK's are expected -} sfe_ublox_mga_assist_ack_e; + SFE_UBLOX_MGA_ASSIST_ACK_NO, // Do not expect UBX-MGA-ACK's. If the module outputs them, they will be ignored + SFE_UBLOX_MGA_ASSIST_ACK_YES, // Expect and check for UBX-MGA-ACK's + SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE // Check UBX-CFG-NAVX5 ackAiding to determine if UBX-MGA-ACK's are expected +} sfe_ublox_mga_assist_ack_e; // The infoCode byte included in UBX-MGA-ACK-DATA0 enum sfe_ublox_mga_ack_infocode_e { - SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED, - SFE_UBLOX_MGA_ACK_INFOCODE_NO_TIME, - SFE_UBLOX_MGA_ACK_INFOCODE_NOT_SUPPORTED, - SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH, - SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED, - SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY, - SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN + SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED, + SFE_UBLOX_MGA_ACK_INFOCODE_NO_TIME, + SFE_UBLOX_MGA_ACK_INFOCODE_NOT_SUPPORTED, + SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH, + SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED, + SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY, + SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN }; // The mainTalkerId, set by UBX-CFG-NMEA setMainTalkerID enum sfe_ublox_talker_ids_e { - SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, - SFE_UBLOX_MAIN_TALKER_ID_GP, - SFE_UBLOX_MAIN_TALKER_ID_GL, - SFE_UBLOX_MAIN_TALKER_ID_GN, - SFE_UBLOX_MAIN_TALKER_ID_GA, - SFE_UBLOX_MAIN_TALKER_ID_GB, - SFE_UBLOX_MAIN_TALKER_ID_GQ + SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, + SFE_UBLOX_MAIN_TALKER_ID_GP, + SFE_UBLOX_MAIN_TALKER_ID_GL, + SFE_UBLOX_MAIN_TALKER_ID_GN, + SFE_UBLOX_MAIN_TALKER_ID_GA, + SFE_UBLOX_MAIN_TALKER_ID_GB, + SFE_UBLOX_MAIN_TALKER_ID_GQ }; // The DGNSS differential mode enum sfe_ublox_dgnss_mode_e { - SFE_UBLOX_DGNSS_MODE_FLOAT = 2, // No attempts are made to fix ambiguities - SFE_UBLOX_DGNSS_MODE_FIXED // Ambiguities are fixed whenever possible + SFE_UBLOX_DGNSS_MODE_FLOAT = 2, // No attempts are made to fix ambiguities + SFE_UBLOX_DGNSS_MODE_FIXED // Ambiguities are fixed whenever possible }; //-=-=-=-=- #ifndef MAX_PAYLOAD_SIZE // v2.0: keep this for backwards-compatibility, but this is largely superseded by setPacketCfgPayloadSize -#define MAX_PAYLOAD_SIZE 256 //We need ~220 bytes for getProtocolVersion on most ublox modules +#define MAX_PAYLOAD_SIZE 256 // We need ~220 bytes for getProtocolVersion on most ublox modules //#define MAX_PAYLOAD_SIZE 768 //Worst case: UBX_CFG_VALSET packet with 64 keyIDs each with 64 bit values #endif @@ -567,56 +567,56 @@ enum sfe_ublox_dgnss_mode_e //-=-=-=-=- UBX binary specific variables struct ubxPacket { - uint8_t cls; - uint8_t id; - uint16_t len; //Length of the payload. Does not include cls, id, or checksum bytes - uint16_t counter; //Keeps track of number of overall bytes received. Some responses are larger than 255 bytes. - uint16_t startingSpot; //The counter value needed to go past before we begin recording into payload array - uint8_t *payload; // We will allocate RAM for the payload if/when needed. - uint8_t checksumA; //Given to us from module. Checked against the rolling calculated A/B checksums. - uint8_t checksumB; - sfe_ublox_packet_validity_e valid; //Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked - sfe_ublox_packet_validity_e classAndIDmatch; // Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID + uint8_t cls; + uint8_t id; + uint16_t len; // Length of the payload. Does not include cls, id, or checksum bytes + uint16_t counter; // Keeps track of number of overall bytes received. Some responses are larger than 255 bytes. + uint16_t startingSpot; // The counter value needed to go past before we begin recording into payload array + uint8_t *payload; // We will allocate RAM for the payload if/when needed. + uint8_t checksumA; // Given to us from module. Checked against the rolling calculated A/B checksums. + uint8_t checksumB; + sfe_ublox_packet_validity_e valid; // Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked + sfe_ublox_packet_validity_e classAndIDmatch; // Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID }; // Struct to hold the results returned by getGeofenceState (returned by UBX-NAV-GEOFENCE) typedef struct { - uint8_t status; // Geofencing status: 0 - Geofencing not available or not reliable; 1 - Geofencing active - uint8_t numFences; // Number of geofences - uint8_t combState; // Combined (logical OR) state of all geofences: 0 - Unknown; 1 - Inside; 2 - Outside - uint8_t states[4]; // Geofence states: 0 - Unknown; 1 - Inside; 2 - Outside + uint8_t status; // Geofencing status: 0 - Geofencing not available or not reliable; 1 - Geofencing active + uint8_t numFences; // Number of geofences + uint8_t combState; // Combined (logical OR) state of all geofences: 0 - Unknown; 1 - Inside; 2 - Outside + uint8_t states[4]; // Geofence states: 0 - Unknown; 1 - Inside; 2 - Outside } geofenceState; // Struct to hold the current geofence parameters typedef struct { - uint8_t numFences; // Number of active geofences - int32_t lats[4]; // Latitudes of geofences (in degrees * 10^-7) - int32_t longs[4]; // Longitudes of geofences (in degrees * 10^-7) - uint32_t rads[4]; // Radii of geofences (in m * 10^-2) + uint8_t numFences; // Number of active geofences + int32_t lats[4]; // Latitudes of geofences (in degrees * 10^-7) + int32_t longs[4]; // Longitudes of geofences (in degrees * 10^-7) + uint32_t rads[4]; // Radii of geofences (in m * 10^-2) } geofenceParams_t; // Struct to hold the module software version typedef struct { - uint8_t versionLow; //Loaded from getProtocolVersion(). - uint8_t versionHigh; - bool moduleQueried; + uint8_t versionLow; // Loaded from getProtocolVersion(). + uint8_t versionHigh; + bool moduleQueried; } moduleSWVersion_t; -const uint16_t DAYS_SINCE_MONTH[4][16] = -{ - { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 335, 335, 335 }, - { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 334, 334, 334 }, - { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 334, 334, 334 }, - { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 334, 334, 334 }, +const uint16_t DAYS_SINCE_MONTH[4][16] = + { + {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 335, 335, 335}, + {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 334, 334, 334}, + {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 334, 334, 334}, + {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 334, 334, 334}, }; class SFE_UBLOX_GNSS { public: - SFE_UBLOX_GNSS(void); + SFE_UBLOX_GNSS(void); // A default of 250ms for maxWait seems fine for I2C but is not enough for SerialUSB. // If you know you are only going to be using I2C / Qwiic communication, you can @@ -625,1049 +625,1048 @@ class SFE_UBLOX_GNSS #define defaultMaxWait 1100 #endif - //New in v2.0: allow the payload size for packetCfg to be changed - bool setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize - - //Begin communication with the GNSS. Advanced users can assume success if required. Useful if the port is already outputting messages at high navigation rate. - //Begin will then return true if "signs of life" have been seen: reception of _any_ valid UBX packet or _any_ valid NMEA header. - //By default use the default I2C address, and use Wire port - bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); //Returns true if module is detected - //serialPort needs to be perviously initialized to correct baud rate - bool begin(Stream &serialPort, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); //Returns true if module is detected - //SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz) - bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); - - void end(void); //Stop all automatic message processing. Free all used RAM - - void setI2CpollingWait(uint8_t newPollingWait_ms); // Allow the user to change the I2C polling wait if required - void setSPIpollingWait(uint8_t newPollingWait_ms); // Allow the user to change the SPI polling wait if required - - //Set the max number of bytes set in a given I2C transaction - uint8_t i2cTransactionSize = 32; //Default to ATmega328 limit - - //Control the size of the internal I2C transaction amount - void setI2CTransactionSize(uint8_t bufferSize); - uint8_t getI2CTransactionSize(void); - - // Support for platforms like ESP32 which do not support multiple I2C restarts - // If _i2cStopRestart is true, endTransmission will always use a stop. If false, a restart will be used where needed. - // The default value for _i2cStopRestart is set in the class instantiation code. - void setI2cStopRestart(bool stop) { _i2cStopRestart = stop; }; - bool getI2cStopRestart(void) { return (_i2cStopRestart); }; - - //Control the size of the spi buffer. If the buffer isn't big enough, we'll start to lose bytes - //That we receive if the buffer is full! - void setSpiTransactionSize(uint8_t bufferSize); - uint8_t getSpiTransactionSize(void); - - //Control the size of maxNMEAByteCount - void setMaxNMEAByteCount(int8_t newMax); - int8_t getMaxNMEAByteCount(void); - - //Returns true if device answers on _gpsI2Caddress address or via Serial - bool isConnected(uint16_t maxWait = defaultMaxWait); - - // Enable debug messages using the chosen Serial port (Stream) - // Boards like the RedBoard Turbo use SerialUSB (not Serial). - // But other boards like the SAMD51 Thing Plus use Serial (not SerialUSB). - // These lines let the code compile cleanly on as many SAMD boards as possible. - #if defined(ARDUINO_ARCH_SAMD) // Is this a SAMD board? - #if defined(USB_VID) // Is the USB Vendor ID defined? - #if (USB_VID == 0x1B4F) // Is this a SparkFun board? - #if !defined(ARDUINO_SAMD51_THING_PLUS) & !defined(ARDUINO_SAMD51_MICROMOD) // If it is not a SAMD51 Thing Plus or SAMD51 MicroMod - void enableDebugging(Stream &debugPort = SerialUSB, bool printLimitedDebug = false); //Given a port to print to, enable debug messages. Default to all, not limited. - #else - void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); //Given a port to print to, enable debug messages. Default to all, not limited. - #endif - #else - void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); //Given a port to print to, enable debug messages. Default to all, not limited. - #endif - #else - void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); //Given a port to print to, enable debug messages. Default to all, not limited. - #endif - #else - void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); //Given a port to print to, enable debug messages. Default to all, not limited. - #endif - - void disableDebugging(void); //Turn off debug statements - void debugPrint(char *message); //Safely print debug statements - void debugPrintln(char *message); //Safely print debug statements - const char *statusString(sfe_ublox_status_e stat); //Pretty print the return value - - // Check for the arrival of new I2C/Serial data - - void disableUBX7Fcheck(bool disabled = true); // When logging RAWX data, we need to be able to disable the "7F" check in checkUbloxI2C - - //Changed in V1.8.1: provides backward compatibility for the examples that call checkUblox directly - //Will default to using packetCfg to look for explicit autoPVT packets so they get processed correctly by processUBX - bool checkUblox(uint8_t requestedClass = 0, uint8_t requestedID = 0); //Checks module with user selected commType - - bool checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for I2C polling of data, passing any new bytes to process() - bool checkUbloxSerial(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for serial polling of data, passing any new bytes to process() - bool checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for spi polling of data, passing any new bytes to process() - - // Process the incoming data - - void process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Processes NMEA and UBX binary sentences one byte at a time - void processNMEA(char incoming) __attribute__((weak)); //Given a NMEA character, do something with it. User can overwrite if desired to use something like tinyGPS or MicroNMEA libraries - void processRTCMframe(uint8_t incoming); //Monitor the incoming bytes for start and length bytes - void processRTCM(uint8_t incoming) __attribute__((weak)); //Given rtcm byte, do something with it. User can overwrite if desired to pipe bytes to radio, internet, etc. - void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Given a character, file it away into the uxb packet structure - void processUBXpacket(ubxPacket *msg); //Once a packet has been received and validated, identify this packet's class/id and update internal flags - - // Send I2C/Serial/SPI commands to the module - - void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages - sfe_ublox_status_e sendCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait, bool expectACKonly = false); //Given a packet and payload, send everything including CRC bytes, return true if we got a response - sfe_ublox_status_e sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait); - void sendSerialCommand(ubxPacket *outgoingUBX); - void sendSpiCommand(ubxPacket *outgoingUBX); - - void printPacket(ubxPacket *packet, bool alwaysPrintPayload = false); //Useful for debugging - - // After sending a message to the module, wait for the expected response (data+ACK or just data) - - sfe_ublox_status_e waitForACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime = defaultMaxWait); //Poll the module until a config packet and an ACK is received, or just an ACK - sfe_ublox_status_e waitForNoACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime = defaultMaxWait); //Poll the module until a config packet is received - - // Check if any callbacks need to be called - void checkCallbacks(void); - - // Push (e.g.) RTCM data directly to the module - // Warning: this function does not check that the data is valid. It is the user's responsibility to ensure the data is valid before pushing. - // Default to using a restart between transmissions. But processors like ESP32 seem to need a stop (#30). Set stop to true to use a stop instead. - bool pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool stop = false); - - // Push MGA AssistNow data to the module. - // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE). - // Wait for maxWait millis after sending each packet (if mgaAck is NO). - // Return how many bytes were pushed successfully. - // If skipTime is true, any UBX-MGA-INI-TIME_UTC or UBX-MGA-INI-TIME_GNSS packets found in the data will be skipped, - // allowing the user to override with their own time data with setUTCTimeAssistance. - // offset allows a sub-set of the data to be sent - starting from offset. - #define defaultMGAdelay 7 // Default to waiting for 7ms between each MGA message - size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - - // Provide initial time assistance - #define defaultMGAINITIMEtAccS 2 // Default to setting the seconds time accuracy to 2 seconds - #define defaultMGAINITIMEtAccNs 0 // Default to setting the nanoseconds time accuracy to zero - #define defaultMGAINITIMEsource 0 // Set default source to none, i.e. on receipt of message (will be inaccurate!) - bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, - uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, - sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - - // Provide initial position assistance - // The units for ecefX/Y/Z and posAcc (stddev) are cm. - bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - // The units for lat and lon are degrees * 1e-7 (WGS84) - // The units for alt (WGS84) and posAcc (stddev) are cm. - bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); - - // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day - // The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date - // Returns numDataBytes if unsuccessful - // TO DO: enhance this so it will find the nearest data for the chosen day - instead of an exact match - size_t findMGAANOForDate(const String &dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); - size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); - - // Read the whole navigation data base. The receiver will send all available data from its internal database. - // Data is written to dataBytes. Set maxNumDataBytes to the (maximum) size of dataBytes. - // If the database exceeds maxNumDataBytes, the excess bytes will be lost. - // The function returns the number of database bytes written to dataBytes. - // The return value will be equal to maxNumDataBytes if excess data was received. - // The function will timeout after maxWait milliseconds - in case the final UBX-MGA-ACK was missed. - #define defaultNavDBDMaxWait 3100 - size_t readNavigationDatabase(uint8_t *dataBytes, size_t maxNumDataBytes, uint16_t maxWait = defaultNavDBDMaxWait); - - // Support for data logging - void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. - uint16_t getFileBufferSize(void); // Return the size of the file buffer - uint16_t extractFileBufferData(uint8_t *destination, uint16_t numBytes); // Extract numBytes of data from the file buffer. Copy it to destination. It is the user's responsibility to ensure destination is large enough. - uint16_t fileBufferAvailable(void); // Returns the number of bytes available in file buffer which are waiting to be read - uint16_t getMaxFileBufferAvail(void); // Returns the maximum number of bytes which the file buffer has contained. Handy for checking the buffer is large enough to handle all the incoming data. - void clearFileBuffer(void); // Empty the file buffer - discard all contents - void clearMaxFileBufferAvail(void); // Reset fileBufferMaxAvail - - // Specific commands - - //Port configurations - bool getPortSettings(uint8_t portID, uint16_t maxWait = defaultMaxWait); //Returns the current protocol bits in the UBX-CFG-PRT command for a given port - bool setPortOutput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure a given port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof - bool setPortInput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure a given port to input UBX, NMEA, RTCM3, SPARTN or a combination thereof - - bool setI2CAddress(uint8_t deviceAddress, uint16_t maxTime = defaultMaxWait); //Changes the I2C address of the u-blox module - void setSerialRate(uint32_t baudrate, uint8_t uartPort = COM_PORT_UART1, uint16_t maxTime = defaultMaxWait); //Changes the serial baud rate of the u-blox module, uartPort should be COM_PORT_UART1/2 - - bool setI2COutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure I2C port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof - bool setUART1Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure UART1 port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof - bool setUART2Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure UART2 port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof - bool setUSBOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure USB port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof - bool setSPIOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); //Configure SPI port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof - void setNMEAOutputPort(Stream &nmeaOutputPort); //Sets the internal variable for the port to direct NMEA characters to - - //Reset to defaults - - void factoryReset(); //Send factory reset sequence (i.e. load "default" configuration and perform hardReset) - void hardReset(); //Perform a reset leading to a cold start (zero info start-up) - void softwareResetGNSSOnly(); //Controlled Software Reset (GNSS only) only restarts the GNSS tasks, without reinitializing the full system or reloading any stored configuration. - bool factoryDefault(uint16_t maxWait = defaultMaxWait); //Reset module to factory defaults - - //Save configuration to BBR / Flash - - bool saveConfiguration(uint16_t maxWait = defaultMaxWait); //Save current configuration to flash and BBR (battery backed RAM) - bool saveConfigSelective(uint32_t configMask, uint16_t maxWait = defaultMaxWait); //Save the selected configuration sub-sections to flash and BBR (battery backed RAM) - - //Functions to turn on/off message types for a given port ID (see COM_PORT_I2C, etc above) - bool configureMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate, uint16_t maxWait = defaultMaxWait); - bool enableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate = 1, uint16_t maxWait = defaultMaxWait); - bool disableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint16_t maxWait = defaultMaxWait); - bool enableNMEAMessage(uint8_t msgID, uint8_t portID, uint8_t sendRate = 1, uint16_t maxWait = defaultMaxWait); - bool disableNMEAMessage(uint8_t msgID, uint8_t portID, uint16_t maxWait = defaultMaxWait); - bool enableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint8_t sendRate, uint16_t maxWait = defaultMaxWait); //Given a message number turns on a message ID for output over given PortID - bool disableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint16_t maxWait = defaultMaxWait); //Turn off given RTCM message from a given port - - //Functions used for RTK and base station setup - //It is probably safe to assume that users of the RTK will be using I2C / Qwiic. So let's leave maxWait set to 250ms. - bool getSurveyMode(uint16_t maxWait = 250); //Get the current TimeMode3 settings - bool setSurveyMode(uint8_t mode, uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); //Control survey in mode - bool enableSurveyMode(uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); //Begin Survey-In for NEO-M8P - bool disableSurveyMode(uint16_t maxWait = 250); //Stop Survey-In mode - // Given coordinates, put receiver into static position. Set latlong to true to pass in lat/long values instead of ecef. - // For ECEF the units are: cm, 0.1mm, cm, 0.1mm, cm, 0.1mm - // For Lat/Lon/Alt the units are: degrees^-7, degrees^-9, degrees^-7, degrees^-9, cm, 0.1mm - bool setStaticPosition(int32_t ecefXOrLat, int8_t ecefXOrLatHP, int32_t ecefYOrLon, int8_t ecefYOrLonHP, int32_t ecefZOrAlt, int8_t ecefZOrAltHP, bool latLong = false, uint16_t maxWait = 250); - bool setStaticPosition(int32_t ecefXOrLat, int32_t ecefYOrLon, int32_t ecefZOrAlt, bool latLong = false, uint16_t maxWait = 250); - bool setDGNSSConfiguration(sfe_ublox_dgnss_mode_e dgnssMode = SFE_UBLOX_DGNSS_MODE_FIXED, uint16_t maxWait = defaultMaxWait); // Set the DGNSS differential mode - - //Read the module's protocol version - uint8_t getProtocolVersionHigh(uint16_t maxWait = defaultMaxWait); //Returns the PROTVER XX.00 from UBX-MON-VER register - uint8_t getProtocolVersionLow(uint16_t maxWait = defaultMaxWait); //Returns the PROTVER 00.XX from UBX-MON-VER register - bool getProtocolVersion(uint16_t maxWait = defaultMaxWait); //Queries module, loads low/high bytes - moduleSWVersion_t *moduleSWVersion = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - //Support for geofences - bool addGeofence(int32_t latitude, int32_t longitude, uint32_t radius, byte confidence = 0, byte pinPolarity = 0, byte pin = 0, uint16_t maxWait = defaultMaxWait); // Add a new geofence - bool clearGeofences(uint16_t maxWait = defaultMaxWait); //Clears all geofences - bool clearAntPIO(uint16_t maxWait = defaultMaxWait); //Clears the antenna control pin settings to release the PIOs - bool getGeofenceState(geofenceState ¤tGeofenceState, uint16_t maxWait = defaultMaxWait); //Returns the combined geofence state - // Storage for the geofence parameters. RAM is allocated for this if/when required. - geofenceParams_t *currentGeofenceParams = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - //Power save / off - bool powerSaveMode(bool power_save = true, uint16_t maxWait = defaultMaxWait); - uint8_t getPowerSaveMode(uint16_t maxWait = defaultMaxWait); // Returns 255 if the sendCommand fails - bool powerOff(uint32_t durationInMs, uint16_t maxWait = defaultMaxWait); - bool powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, bool forceWhileUsb = true, uint16_t maxWait = defaultMaxWait); - - //Change the dynamic platform model using UBX-CFG-NAV5 - bool setDynamicModel(dynModel newDynamicModel = DYN_MODEL_PORTABLE, uint16_t maxWait = defaultMaxWait); - uint8_t getDynamicModel(uint16_t maxWait = defaultMaxWait); // Get the dynamic model - returns 255 if the sendCommand fails - - //Reset the odometer - bool resetOdometer(uint16_t maxWait = defaultMaxWait); // Reset the odometer - - //Enable/Disable individual GNSS systems using UBX-CFG-GNSS - //Note: you must leave at least one major GNSS enabled! If in doubt, enable GPS before disabling the others - //TO DO: Add support for sigCfgMask and maxTrkCh. (Need to resolve ambiguity with maxWait) - bool enableGNSS(bool enable, sfe_ublox_gnss_ids_e id, uint16_t maxWait = defaultMaxWait); - bool isGNSSenabled(sfe_ublox_gnss_ids_e id, uint16_t maxWait = defaultMaxWait); - - //Reset ESF automatic IMU-mount alignment - bool resetIMUalignment(uint16_t maxWait = defaultMaxWait); - - //Enable/disable esfAutoAlignment - bool getESFAutoAlignment(uint16_t maxWait = defaultMaxWait); - bool setESFAutoAlignment(bool enable, uint16_t maxWait = defaultMaxWait); - - //Configure Time Pulse Parameters - bool getTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Get the time pulse parameters using UBX_CFG_TP5 - bool setTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Set the time pulse parameters using UBX_CFG_TP5 - - //UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data - uint8_t getAckAiding(uint16_t maxWait = defaultMaxWait); // Get the ackAiding byte - returns 255 if the sendCommand fails - bool setAckAiding(uint8_t ackAiding, uint16_t maxWait = defaultMaxWait); // Set the ackAiding byte - - //AssistNow Autonomous support - //UBX-CFG-NAVX5 - get/set the aopCfg byte and set the aopOrdMaxErr word. If aopOrbMaxErr is 0 (default), the max orbit error is reset to the firmware default. - uint8_t getAopCfg(uint16_t maxWait = defaultMaxWait); // Get the AssistNow Autonomous configuration (aopCfg) - returns 255 if the sendCommand fails - bool setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr = 0, uint16_t maxWait = defaultMaxWait); // Set the aopCfg byte and the aopOrdMaxErr word - - //SPARTN dynamic keys - //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. - //"Every time the 'current' key is expired, 'next' takes its place." - //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. - //The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. - bool setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait = defaultMaxWait); - bool setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const uint8_t *key1, - uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2, uint16_t maxWait = defaultMaxWait); - - //General configuration (used only on protocol v27 and higher - ie, ZED-F9P) - - //It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic. - //If they are using Serial then the higher baud rate will also help. So let's leave maxWait set to 250ms. - uint32_t createKey(uint16_t group, uint16_t id, uint8_t size); //Form 32-bit key from group/id/size - sfe_ublox_status_e getVal(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Load payload with response - uint8_t getVal8(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location - uint16_t getVal16(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location - uint32_t getVal32(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location - uint64_t getVal64(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given key location - uint8_t getVal8(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location - uint16_t getVal16(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location - uint32_t getVal32(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location - uint64_t getVal64(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); //Returns the value at a given group/id/size location - uint8_t setVal(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 16-bit value at a given group/id/size location - uint8_t setVal8(uint32_t keyID, uint8_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 8-bit value at a given group/id/size location - uint8_t setVal16(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 16-bit value at a given group/id/size location - uint8_t setVal32(uint32_t keyID, uint32_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 32-bit value at a given group/id/size location - uint8_t setVal64(uint32_t keyID, uint64_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); //Sets the 64-bit value at a given group/id/size location - uint8_t newCfgValset8(uint32_t keyID, uint8_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 8-bit value - uint8_t newCfgValset16(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 16-bit value - uint8_t newCfgValset32(uint32_t keyID, uint32_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 32-bit value - uint8_t newCfgValset64(uint32_t keyID, uint64_t value, uint8_t layer = VAL_LAYER_ALL); //Define a new UBX-CFG-VALSET with the given KeyID and 64-bit value - uint8_t addCfgValset8(uint32_t keyID, uint8_t value); //Add a new KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket - uint8_t addCfgValset16(uint32_t keyID, uint16_t value); //Add a new KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket - uint8_t addCfgValset32(uint32_t keyID, uint32_t value); //Add a new KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket - uint8_t addCfgValset64(uint32_t keyID, uint64_t value); //Add a new KeyID and 64-bit value to an existing UBX-CFG-VALSET ubxPacket - uint8_t sendCfgValset8(uint32_t keyID, uint8_t value, uint16_t maxWait = 250); //Add the final KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket and send it - uint8_t sendCfgValset16(uint32_t keyID, uint16_t value, uint16_t maxWait = 250); //Add the final KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket and send it - uint8_t sendCfgValset32(uint32_t keyID, uint32_t value, uint16_t maxWait = 250); //Add the final KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket and send it - uint8_t sendCfgValset64(uint32_t keyID, uint64_t value, uint16_t maxWait = 250); //Add the final KeyID and 64-bit value to an existing UBX-CFG-VALSET ubxPacket and send it - - // get and set functions for all of the "automatic" message processing - - // Navigation (NAV) - - // getPVT will only return data once in each navigation cycle. By default, that is once per second. - // Therefore we should set defaultMaxWait to slightly longer than that. - // If you change the navigation frequency to (e.g.) 4Hz using setNavigationFrequency(4) - // then you should use a shorter maxWait. 300msec would be about right: getPVT(300) - - bool getNAVPOSECEF(uint16_t maxWait = defaultMaxWait); // NAV POSECEF - bool setAutoNAVPOSECEF(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic POSECEF reports at the navigation frequency - bool setAutoNAVPOSECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic POSECEF 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 setAutoNAVPOSECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic POSECEF reports - bool setAutoNAVPOSECEFcallback(void (*callbackPointer)(UBX_NAV_POSECEF_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic POSECEF reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_POSECEF_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic POSECEF reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVPOSECEF(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and POSECEF is send cyclically already - void flushNAVPOSECEF(); //Mark all the data as read/stale - void logNAVPOSECEF(bool enabled = true); // Log data to file buffer - - bool getNAVSTATUS(uint16_t maxWait = defaultMaxWait); // NAV STATUS - bool setAutoNAVSTATUS(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic STATUS reports at the navigation frequency - bool setAutoNAVSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic STATUS 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 setAutoNAVSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic STATUS reports - bool setAutoNAVSTATUScallback(void (*callbackPointer)(UBX_NAV_STATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_STATUS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and STATUS is send cyclically already - void flushNAVSTATUS(); //Mark all the data as read/stale - void logNAVSTATUS(bool enabled = true); // Log data to file buffer - - bool getDOP(uint16_t maxWait = defaultMaxWait); //Query module for latest dilution of precision values and load global vars:. If autoDOP is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new DOP is available. - bool setAutoDOP(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic DOP reports at the navigation frequency - bool setAutoDOP(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic DOP 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 setAutoDOPrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic DOP reports - bool setAutoDOPcallback(void (*callbackPointer)(UBX_NAV_DOP_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic DOP reports at the navigation frequency. Data is accessed from the callback. - bool setAutoDOPcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_DOP_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic DOP reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoDOP(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and DOP is send cyclically already - void flushDOP(); //Mark all the DOP data as read/stale - void logNAVDOP(bool enabled = true); // Log data to file buffer - - bool getVehAtt(uint16_t maxWait = defaultMaxWait); // NAV ATT Helper - bool getNAVATT(uint16_t maxWait = defaultMaxWait); // NAV ATT - bool setAutoNAVATT(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic vehicle attitude reports at the navigation frequency - bool setAutoNAVATT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic vehicle attitude 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 setAutoNAVATTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ATT reports - bool setAutoNAVATTcallback(void (*callbackPointer)(UBX_NAV_ATT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVATTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ATT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVATT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and vehicle attitude is send cyclically already - void flushNAVATT(); //Mark all the data as read/stale - void logNAVATT(bool enabled = true); // Log data to file buffer - - bool getPVT(uint16_t maxWait = defaultMaxWait); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new PVT is available. - bool setAutoPVT(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVT reports at the navigation frequency - bool setAutoPVT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVT 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 setAutoPVTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic PVT reports - bool setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. - bool setAutoPVTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoPVT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and PVT is send cyclically already - void flushPVT(); //Mark all the PVT data as read/stale - void logNAVPVT(bool enabled = true); // Log data to file buffer - - bool getNAVODO(uint16_t maxWait = defaultMaxWait); // NAV ODO - bool setAutoNAVODO(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ODO reports at the navigation frequency - bool setAutoNAVODO(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ODO 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 setAutoNAVODOrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ODO reports - bool setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVODOcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ODO_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVODO(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ODO is send cyclically already - void flushNAVODO(); //Mark all the data as read/stale - void logNAVODO(bool enabled = true); // Log data to file buffer - - bool getNAVVELECEF(uint16_t maxWait = defaultMaxWait); // NAV VELECEF - bool setAutoNAVVELECEF(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELECEF reports at the navigation frequency - bool setAutoNAVVELECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELECEF 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 setAutoNAVVELECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic VELECEF reports - bool setAutoNAVVELECEFcallback(void (*callbackPointer)(UBX_NAV_VELECEF_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic VELECEF reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVVELECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELECEF_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic VELECEF reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVVELECEF(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and VELECEF is send cyclically already - void flushNAVVELECEF(); //Mark all the data as read/stale - void logNAVVELECEF(bool enabled = true); // Log data to file buffer - - bool getNAVVELNED(uint16_t maxWait = defaultMaxWait); // NAV VELNED - bool setAutoNAVVELNED(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELNED reports at the navigation frequency - bool setAutoNAVVELNED(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELNED 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 setAutoNAVVELNEDrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic VELNED reports - bool setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VELNED_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic VELNED reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVVELNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELNED_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic VELNED reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVVELNED(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and VELNED is send cyclically already - void flushNAVVELNED(); //Mark all the data as read/stale - void logNAVVELNED(bool enabled = true); // Log data to file buffer - - bool getNAVHPPOSECEF(uint16_t maxWait = defaultMaxWait); // NAV HPPOSECEF - bool setAutoNAVHPPOSECEF(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSECEF reports at the navigation frequency - bool setAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSECEF 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 setAutoNAVHPPOSECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic HPPOSECEF reports - bool setAutoNAVHPPOSECEFcallback(void (*callbackPointer)(UBX_NAV_HPPOSECEF_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSECEF reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVHPPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSECEF_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSECEF reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HPPOSECEF is send cyclically already - void flushNAVHPPOSECEF(); //Mark all the data as read/stale - void logNAVHPPOSECEF(bool enabled = true); // Log data to file buffer - - bool getHPPOSLLH(uint16_t maxWait = defaultMaxWait); // NAV HPPOSLLH - bool setAutoHPPOSLLH(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSLLH reports at the navigation frequency - bool setAutoHPPOSLLH(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HPPOSLLH 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 setAutoHPPOSLLHrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic HPPOSLLH reports - bool setAutoHPPOSLLHcallback(void (*callbackPointer)(UBX_NAV_HPPOSLLH_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSLLH reports at the navigation frequency. Data is accessed from the callback. - bool setAutoHPPOSLLHcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSLLH_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic HPPOSLLH reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoHPPOSLLH(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HPPOSLLH is send cyclically already - void flushHPPOSLLH(); //Mark all the HPPPOSLLH data as read/stale. This is handy to get data alignment after CRC failure - void logNAVHPPOSLLH(bool enabled = true); // Log data to file buffer - - bool getNAVPVAT(uint16_t maxWait = defaultMaxWait); // NAV PVAT - bool setAutoNAVPVAT(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVAT reports at the navigation frequency - bool setAutoNAVPVAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVAT 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 setAutoNAVPVATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic PVAT reports - bool setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVAT reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVPVATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVAT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic PVAT reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVPVAT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and PVAT is send cyclically already - void flushNAVPVAT(); //Mark all the PVAT data as read/stale - void logNAVPVAT(bool enabled = true); // Log data to file buffer - - bool getNAVCLOCK(uint16_t maxWait = defaultMaxWait); // NAV CLOCK - bool setAutoNAVCLOCK(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic clock reports at the navigation frequency - bool setAutoNAVCLOCK(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic clock 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 setAutoNAVCLOCKrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic CLOCK reports - bool setAutoNAVCLOCKcallback(void (*callbackPointer)(UBX_NAV_CLOCK_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic CLOCK reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVCLOCKcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_CLOCK_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic CLOCK reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and clock is send cyclically already - 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 - - // Add "auto" support for NAV TIMELS - to avoid needing 'global' storage - bool getLeapSecondEvent(uint16_t maxWait); //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 - bool setAutoNAVSAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic NAVSAT 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 setAutoNAVSATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic NAVSAT reports - bool setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic NAVSAT reports at the navigation frequency. Data is accessed from the callback. - bool setAutoNAVSATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SAT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic NAVSAT reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoNAVSAT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and NAVSAT is send cyclically already - void flushNAVSAT(); //Mark all the NAVSAT data as read/stale - void logNAVSAT(bool enabled = true); // Log data to file buffer - - bool getRELPOSNED(uint16_t maxWait = defaultMaxWait); //Get Relative Positioning Information of the NED frame - bool setAutoRELPOSNED(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RELPOSNED reports - bool setAutoRELPOSNED(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RELPOSNED, 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 setAutoRELPOSNEDrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic RELPOSNEDreports - bool setAutoRELPOSNEDcallback(void (*callbackPointer)(UBX_NAV_RELPOSNED_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic RELPOSNED reports at the navigation frequency. Data is accessed from the callback. - bool setAutoRELPOSNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_RELPOSNED_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic RELPOSNED reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoRELPOSNED(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and RELPOSNED is send cyclically already - void flushNAVRELPOSNED(); //Mark all the data as read/stale - void logNAVRELPOSNED(bool enabled = true); // Log data to file buffer - - bool getAOPSTATUS(uint16_t maxWait = defaultMaxWait); //Query module for latest AssistNow Autonomous status and load global vars:. If autoAOPSTATUS is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new AOPSTATUS is available. - bool setAutoAOPSTATUS(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic AOPSTATUS reports at the navigation frequency - bool setAutoAOPSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic AOPSTATUS 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 setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic AOPSTATUS reports - bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. - bool setAutoAOPSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_AOPSTATUS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and AOPSTATUS is send cyclically already - void flushAOPSTATUS(); //Mark all the AOPSTATUS data as read/stale - void logAOPSTATUS(bool enabled = true); // Log data to file buffer - - // Receiver Manager Messages (RXM) - - // Configure a callback for the UBX-RXM-PMP messages produced by the NEO-D9S - // Note: on the NEO-D9S, the UBX-RXM-PMP messages are enabled by default on all ports. - // You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 0) - // The NEO-D9S does not support UBX-CFG-MSG - bool setAutoRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! - - bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX - bool setAutoRXMSFRBX(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM SFRBX reports at the navigation frequency - bool setAutoRXMSFRBX(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM SFRBX 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 setAutoRXMSFRBXrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic SFRBX reports - bool setAutoRXMSFRBXcallback(void (*callbackPointer)(UBX_RXM_SFRBX_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic SFRBX reports at the navigation frequency. Data is accessed from the callback. - bool setAutoRXMSFRBXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_SFRBX_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic SFRBX reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoRXMSFRBX(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and RXM SFRBX is send cyclically already - void flushRXMSFRBX(); //Mark all the data as read/stale - void logRXMSFRBX(bool enabled = true); // Log data to file buffer - - bool getRXMRAWX(uint16_t maxWait = defaultMaxWait); // RXM RAWX - bool setAutoRXMRAWX(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM RAWX reports at the navigation frequency - bool setAutoRXMRAWX(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RXM RAWX 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 setAutoRXMRAWXrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic RAWX reports - bool setAutoRXMRAWXcallback(void (*callbackPointer)(UBX_RXM_RAWX_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic RAWX reports at the navigation frequency. Data is accessed from the callback. - bool setAutoRXMRAWXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_RAWX_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic RAWX reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoRXMRAWX(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and RXM RAWX is send cyclically already - void flushRXMRAWX(); //Mark all the data as read/stale - void logRXMRAWX(bool enabled = true); // Log data to file buffer - - // Configuration (CFG) - - // Add "auto" support for CFG PRT - because we use it for isConnected (to stop it being mugged by other messages) - bool getPortSettingsInternal(uint8_t portID, uint16_t maxWait = defaultMaxWait); //Read the port configuration for a given port using UBX-CFG-PRT - bool getNavigationFrequencyInternal(uint16_t maxWait = defaultMaxWait); //Get the number of nav solutions sent per second currently being output by module - - // Timing messages (TIM) - - bool getTIMTM2(uint16_t maxWait = defaultMaxWait); // TIM TM2 - bool setAutoTIMTM2(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic TIM TM2 reports at the navigation frequency - bool setAutoTIMTM2(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic TIM TM2 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 setAutoTIMTM2rate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic TIM TM2 reports - bool setAutoTIMTM2callback(void (*callbackPointer)(UBX_TIM_TM2_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic TM2 reports at the navigation frequency. Data is accessed from the callback. - bool setAutoTIMTM2callbackPtr(void (*callbackPointerPtr)(UBX_TIM_TM2_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic TM2 reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoTIMTM2(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and TIM TM2 is send cyclically already - void flushTIMTM2(); //Mark all the data as read/stale - void logTIMTM2(bool enabled = true); // Log data to file buffer - - // Sensor fusion (dead reckoning) (ESF) - - bool getEsfAlignment(uint16_t maxWait = defaultMaxWait); // ESF ALG Helper - bool getESFALG(uint16_t maxWait = defaultMaxWait); // ESF ALG - bool setAutoESFALG(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF ALG reports - bool setAutoESFALG(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF ALG reports, 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 setAutoESFALGrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ALG reports - bool setAutoESFALGcallback(void (*callbackPointer)(UBX_ESF_ALG_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ALG reports at the navigation frequency. Data is accessed from the callback. - bool setAutoESFALGcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_ALG_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ALG reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoESFALG(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF ALG is send cyclically already - void flushESFALG(); //Mark all the data as read/stale - void logESFALG(bool enabled = true); // Log data to file buffer - - bool getEsfInfo(uint16_t maxWait = defaultMaxWait); // ESF STATUS Helper - bool getESFSTATUS(uint16_t maxWait = defaultMaxWait); // ESF STATUS - bool setAutoESFSTATUS(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF STATUS reports - bool setAutoESFSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF STATUS reports, 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 setAutoESFSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic STATUS reports - bool setAutoESFSTATUScallback(void (*callbackPointer)(UBX_ESF_STATUS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. - bool setAutoESFSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_STATUS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoESFSTATUS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF STATUS is send cyclically already - void flushESFSTATUS(); //Mark all the data as read/stale - void logESFSTATUS(bool enabled = true); // Log data to file buffer - - bool getEsfIns(uint16_t maxWait = defaultMaxWait); // ESF INS Helper - bool getESFINS(uint16_t maxWait = defaultMaxWait); // ESF INS - bool setAutoESFINS(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF INS reports - bool setAutoESFINS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF INS reports, 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 setAutoESFINSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic INS reports - bool setAutoESFINScallback(void (*callbackPointer)(UBX_ESF_INS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. - bool setAutoESFINScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_INS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoESFINS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF INS is send cyclically already - void flushESFINS(); //Mark all the data as read/stale - void logESFINS(bool enabled = true); // Log data to file buffer - - bool getEsfDataInfo(uint16_t maxWait = defaultMaxWait); // ESF MEAS Helper - bool getESFMEAS(uint16_t maxWait = defaultMaxWait); // ESF MEAS - bool setAutoESFMEAS(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF MEAS reports - bool setAutoESFMEAS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF MEAS reports, 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 setAutoESFMEASrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic MEAS reports - bool setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback. - bool setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoESFMEAS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF MEAS is send cyclically already - void flushESFMEAS(); //Mark all the data as read/stale - void logESFMEAS(bool enabled = true); // Log data to file buffer - - bool getEsfRawDataInfo(uint16_t maxWait = defaultMaxWait); // ESF RAW Helper - bool getESFRAW(uint16_t maxWait = defaultMaxWait); // ESF RAW - bool setAutoESFRAW(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF RAW reports - bool setAutoESFRAW(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic ESF RAW reports, 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 setAutoESFRAWrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic RAW reports - bool setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback. - bool setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoESFRAW(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and ESF RAW is send cyclically already - void flushESFRAW(); //Mark all the data as read/stale - void logESFRAW(bool enabled = true); // Log data to file buffer - - // High navigation rate (HNR) - - bool getHNRAtt(uint16_t maxWait = defaultMaxWait); // HNR ATT Helper - bool getHNRATT(uint16_t maxWait = defaultMaxWait); // Returns true if the get HNR attitude is successful - bool setAutoHNRATT(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR Attitude reports at the HNR rate - bool setAutoHNRATT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR Attitude reports at the HNR rate, 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 setAutoHNRATTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic ATT reports - bool setAutoHNRATTcallback(void (*callbackPointer)(UBX_HNR_ATT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. - bool setAutoHNRATTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_ATT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoHNRATT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HNR Attitude is send cyclically already - void flushHNRATT(); //Mark all the data as read/stale - void logHNRATT(bool enabled = true); // Log data to file buffer - - bool getHNRDyn(uint16_t maxWait = defaultMaxWait); // HNR INS Helper - bool getHNRINS(uint16_t maxWait = defaultMaxWait); // Returns true if the get HNR dynamics is successful - bool setAutoHNRINS(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR dynamics reports at the HNR rate - bool setAutoHNRINS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR dynamics reports at the HNR rate, 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 setAutoHNRINSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic INS reports - bool setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. - bool setAutoHNRINScallbackPtr(void (*callbackPointerPtr)(UBX_HNR_INS_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoHNRINS(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HNR dynamics is send cyclically already - void flushHNRINS(); //Mark all the data as read/stale - void logHNRINS(bool enabled = true); // Log data to file buffer - - bool getHNRPVT(uint16_t maxWait = defaultMaxWait); // Returns true if the get HNR PVT is successful - bool setAutoHNRPVT(bool enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR PVT reports at the HNR rate - bool setAutoHNRPVT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic HNR PVT reports at the HNR rate, 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 setAutoHNRPVTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Set the rate for automatic PVT reports - bool setAutoHNRPVTcallback(void (*callbackPointer)(UBX_HNR_PVT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. - bool setAutoHNRPVTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_PVT_data_t *), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. - bool assumeAutoHNRPVT(bool enabled, bool implicitUpdate = true); //In case no config access to the GPS is possible and HNR PVT is send cyclically already - void flushHNRPVT(); //Mark all the data as read/stale - void logHNRPVT(bool enabled = true); // Log data to file buffer - - // Helper functions for CFG RATE - - bool setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = defaultMaxWait); //Set the number of nav solutions sent per second - uint8_t getNavigationFrequency(uint16_t maxWait = defaultMaxWait); //Get the number of nav solutions sent per second currently being output by module - bool setMeasurementRate(uint16_t rate, uint16_t maxWait = defaultMaxWait); //Set the elapsed time between GNSS measurements in milliseconds, which defines the rate - uint16_t getMeasurementRate(uint16_t maxWait = defaultMaxWait); //Return the elapsed time between GNSS measurements in milliseconds - bool setNavigationRate(uint16_t rate, uint16_t maxWait = defaultMaxWait); //Set the ratio between the number of measurements and the number of navigation solutions. Unit is cycles. Max is 127 - uint16_t getNavigationRate(uint16_t maxWait = defaultMaxWait); //Return the ratio between the number of measurements and the number of navigation solutions. Unit is cycles - void flushCFGRATE(); // Mark the measurement and navigation rate data as stale - used by the set rate functions - - // Helper functions for DOP - - uint16_t getGeometricDOP(uint16_t maxWait = defaultMaxWait); - uint16_t getPositionDOP(uint16_t maxWait = defaultMaxWait); - uint16_t getTimeDOP(uint16_t maxWait = defaultMaxWait); - uint16_t getVerticalDOP(uint16_t maxWait = defaultMaxWait); - uint16_t getHorizontalDOP(uint16_t maxWait = defaultMaxWait); - uint16_t getNorthingDOP(uint16_t maxWait = defaultMaxWait); - uint16_t getEastingDOP(uint16_t maxWait = defaultMaxWait); - - // Helper functions for ATT - - float getATTroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees - float getATTpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees - float getATTheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees - - // Helper functions for PVT - - uint32_t getTimeOfWeek(uint16_t maxWait = defaultMaxWait); - uint16_t getYear(uint16_t maxWait = defaultMaxWait); - uint8_t getMonth(uint16_t maxWait = defaultMaxWait); - uint8_t getDay(uint16_t maxWait = defaultMaxWait); - uint8_t getHour(uint16_t maxWait = defaultMaxWait); - uint8_t getMinute(uint16_t maxWait = defaultMaxWait); - uint8_t getSecond(uint16_t maxWait = defaultMaxWait); - uint16_t getMillisecond(uint16_t maxWait = defaultMaxWait); - int32_t getNanosecond(uint16_t maxWait = defaultMaxWait); - uint32_t getUnixEpoch(uint16_t maxWait = defaultMaxWait); - uint32_t getUnixEpoch(uint32_t& microsecond, uint16_t maxWait = defaultMaxWait); - - bool getDateValid(uint16_t maxWait = defaultMaxWait); - bool getTimeValid(uint16_t maxWait = defaultMaxWait); - bool getTimeFullyResolved(uint16_t maxWait = defaultMaxWait); - bool getConfirmedDate(uint16_t maxWait = defaultMaxWait); - bool getConfirmedTime(uint16_t maxWait = defaultMaxWait); - - uint8_t getFixType(uint16_t maxWait = defaultMaxWait); //Returns the type of fix: 0=no, 3=3D, 4=GNSS+Deadreckoning - - bool getGnssFixOk(uint16_t maxWait = defaultMaxWait); //Get whether we have a valid fix (i.e within DOP & accuracy masks) - bool getDiffSoln(uint16_t maxWait = defaultMaxWait); //Get whether differential corrections were applied - bool getHeadVehValid(uint16_t maxWait = defaultMaxWait); - uint8_t getCarrierSolutionType(uint16_t maxWait = defaultMaxWait); //Returns RTK solution: 0=no, 1=float solution, 2=fixed solution - - uint8_t getSIV(uint16_t maxWait = defaultMaxWait); //Returns number of sats used in fix - int32_t getLongitude(uint16_t maxWait = defaultMaxWait); //Returns the current longitude in degrees * 10-7. Auto selects between HighPrecision and Regular depending on ability of module. - int32_t getLatitude(uint16_t maxWait = defaultMaxWait); //Returns the current latitude in degrees * 10^-7. Auto selects between HighPrecision and Regular depending on ability of module. - int32_t getAltitude(uint16_t maxWait = defaultMaxWait); //Returns the current altitude in mm above ellipsoid - int32_t getAltitudeMSL(uint16_t maxWait = defaultMaxWait); //Returns the current altitude in mm above mean sea level - int32_t getHorizontalAccEst(uint16_t maxWait = defaultMaxWait); - int32_t getVerticalAccEst(uint16_t maxWait = defaultMaxWait); - int32_t getNedNorthVel(uint16_t maxWait = defaultMaxWait); - int32_t getNedEastVel(uint16_t maxWait = defaultMaxWait); - int32_t getNedDownVel(uint16_t maxWait = defaultMaxWait); - int32_t getGroundSpeed(uint16_t maxWait = defaultMaxWait); //Returns speed in mm/s - int32_t getHeading(uint16_t maxWait = defaultMaxWait); //Returns heading in degrees * 10^-5 - uint32_t getSpeedAccEst(uint16_t maxWait = defaultMaxWait); - uint32_t getHeadingAccEst(uint16_t maxWait = defaultMaxWait); - uint16_t getPDOP(uint16_t maxWait = defaultMaxWait); //Returns positional dillution of precision * 10^-2 (dimensionless) - - bool getInvalidLlh(uint16_t maxWait = defaultMaxWait); - - int32_t getHeadVeh(uint16_t maxWait = defaultMaxWait); - int16_t getMagDec(uint16_t maxWait = defaultMaxWait); - uint16_t getMagAcc(uint16_t maxWait = defaultMaxWait); - - int32_t getGeoidSeparation(uint16_t maxWait = defaultMaxWait); - - // Helper functions for HPPOSECEF - - uint32_t getPositionAccuracy(uint16_t maxWait = defaultMaxWait); //Returns the 3D accuracy of the current high-precision fix, in mm. Supported on NEO-M8P, ZED-F9P, - - // Helper functions for HPPOSLLH - - uint32_t getTimeOfWeekFromHPPOSLLH(uint16_t maxWait = defaultMaxWait); - int32_t getHighResLongitude(uint16_t maxWait = defaultMaxWait); - int32_t getHighResLatitude(uint16_t maxWait = defaultMaxWait); - int32_t getElipsoid(uint16_t maxWait = defaultMaxWait); - int32_t getMeanSeaLevel(uint16_t maxWait = defaultMaxWait); - int8_t getHighResLongitudeHp(uint16_t maxWait = defaultMaxWait); - int8_t getHighResLatitudeHp(uint16_t maxWait = defaultMaxWait); - int8_t getElipsoidHp(uint16_t maxWait = defaultMaxWait); - int8_t getMeanSeaLevelHp(uint16_t maxWait = defaultMaxWait); - uint32_t getHorizontalAccuracy(uint16_t maxWait = defaultMaxWait); - uint32_t getVerticalAccuracy(uint16_t maxWait = defaultMaxWait); - - // Helper functions for PVAT - - int32_t getVehicleRoll(uint16_t maxWait = defaultMaxWait); // Returns vehicle roll in degrees * 10^-5 - int32_t getVehiclePitch(uint16_t maxWait = defaultMaxWait); // Returns vehicle pitch in degrees * 10^-5 - int32_t getVehicleHeading(uint16_t maxWait = defaultMaxWait); // Returns vehicle heading in degrees * 10^-5 - int32_t getMotionHeading(uint16_t maxWait = defaultMaxWait); // Returns the motion heading in degrees * 10^-5 - - // Helper functions for SVIN - - bool getSurveyInActive(uint16_t maxWait = defaultMaxWait); - bool getSurveyInValid(uint16_t maxWait = defaultMaxWait); - uint16_t getSurveyInObservationTime(uint16_t maxWait = defaultMaxWait); // Truncated to 65535 seconds - float getSurveyInMeanAccuracy(uint16_t maxWait = defaultMaxWait); // Returned as m - - // Helper functions for TIMELS - - uint8_t getLeapIndicator(int32_t& timeToLsEvent, uint16_t maxWait = defaultMaxWait); - int8_t getCurrentLeapSeconds(sfe_ublox_ls_src_e& source, uint16_t maxWait = defaultMaxWait); - - // Helper functions for RELPOSNED - - float getRelPosN(uint16_t maxWait = defaultMaxWait); // Returned as m - float getRelPosE(uint16_t maxWait = defaultMaxWait); // Returned as m - float getRelPosD(uint16_t maxWait = defaultMaxWait); // Returned as m - float getRelPosAccN(uint16_t maxWait = defaultMaxWait); // Returned as m - float getRelPosAccE(uint16_t maxWait = defaultMaxWait); // Returned as m - float getRelPosAccD(uint16_t maxWait = defaultMaxWait); // Returned as m - - // Helper functions for AOPSTATUS - - uint8_t getAOPSTATUSuseAOP(uint16_t maxWait = defaultMaxWait); // Returns the UBX-NAV-AOPSTATUS useAOP flag. Don't confuse this with getAopCfg - which returns the aopCfg byte from UBX-CFG-NAVX5 - uint8_t getAOPSTATUSstatus(uint16_t maxWait = defaultMaxWait); // Returns the UBX-NAV-AOPSTATUS status field. A host application can determine the optimal time to shut down the receiver by monitoring the status field for a steady 0. - - // Helper functions for ESF - - float getESFroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees - float getESFpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees - float getESFyaw(uint16_t maxWait = defaultMaxWait); // Returned as degrees - bool getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait = defaultMaxWait); - bool getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, UBX_ESF_MEAS_data_t ubxDataStruct, uint8_t sensor); - bool getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait = defaultMaxWait); - bool getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, UBX_ESF_RAW_data_t ubxDataStruct, uint8_t sensor); - bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, uint8_t sensor, uint16_t maxWait = defaultMaxWait); - bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, UBX_ESF_STATUS_data_t ubxDataStruct, uint8_t sensor); - - // Helper functions for HNR - - bool setHNRNavigationRate(uint8_t rate, uint16_t maxWait = defaultMaxWait); // Returns true if the setHNRNavigationRate is successful - uint8_t getHNRNavigationRate(uint16_t maxWait = defaultMaxWait); // Returns 0 if the getHNRNavigationRate fails - float getHNRroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees - float getHNRpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees - float getHNRheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees - - // Set the mainTalkerId used by NMEA messages - allows all NMEA messages except GSV to be prefixed with GP instead of GN - bool setMainTalkerID(sfe_ublox_talker_ids_e id = SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, uint16_t maxWait = defaultMaxWait); - - // Enable/Disable NMEA High Precision Mode - include extra decimal places in the Lat and Lon - bool setHighPrecisionMode(bool enable = true, uint16_t maxWait = defaultMaxWait); - - // Helper functions for NMEA logging - void setNMEALoggingMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Add selected NMEA messages to file buffer - if enabled. Default to adding ALL messages to the file buffer - uint32_t getNMEALoggingMask(); // Return which NMEA messages are selected for logging to the file buffer - if enabled - - // Helper functions to control which NMEA messages are passed to processNMEA - void setProcessNMEAMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Control which NMEA messages are passed to processNMEA. Default to passing ALL messages - uint32_t getProcessNMEAMask(); // Return which NMEA messages are passed to processNMEA - - // Support for "auto" storage of NMEA messages - uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data - bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message - bool setNMEAGPGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)); //Enable a callback on the arrival of a GPGGA message - uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data - bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GNGGA message - bool setNMEAGNGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)); //Enable a callback on the arrival of a GNGGA message - - // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket - // From v2.0: These are public. The user can call these to extract data from custom packets - uint64_t extractLongLong(ubxPacket *msg, uint16_t spotToStart); //Combine eight bytes from payload into uint64_t - uint32_t extractLong(ubxPacket *msg, uint16_t spotToStart); //Combine four bytes from payload into long - int32_t extractSignedLong(ubxPacket *msg, uint16_t spotToStart); //Combine four bytes from payload into signed long (avoiding any ambiguity caused by casting) - uint16_t extractInt(ubxPacket *msg, uint16_t spotToStart); //Combine two bytes from payload into int - int16_t extractSignedInt(ubxPacket *msg, uint16_t spotToStart); - uint8_t extractByte(ubxPacket *msg, uint16_t spotToStart); //Get byte from payload - int8_t extractSignedChar(ubxPacket *msg, uint16_t spotToStart); //Get signed 8-bit value from payload - - // Pointers to storage for the "automatic" messages - // RAM is allocated for these if/when required. - - UBX_NAV_POSECEF_t *packetUBXNAVPOSECEF = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_STATUS_t *packetUBXNAVSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_DOP_t *packetUBXNAVDOP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_ATT_t *packetUBXNAVATT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_PVT_t *packetUBXNAVPVT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_ODO_t *packetUBXNAVODO = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_VELECEF_t *packetUBXNAVVELECEF = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_VELNED_t *packetUBXNAVVELNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_HPPOSECEF_t *packetUBXNAVHPPOSECEF = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_HPPOSLLH_t *packetUBXNAVHPPOSLLH = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_PVAT_t *packetUBXNAVPVAT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_CLOCK_t *packetUBXNAVCLOCK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_TIMELS_t *packetUBXNAVTIMELS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_SVIN_t *packetUBXNAVSVIN = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_SAT_t *packetUBXNAVSAT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_RELPOSNED_t *packetUBXNAVRELPOSNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_NAV_AOPSTATUS_t *packetUBXNAVAOPSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - UBX_RXM_PMP_t *packetUBXRXMPMP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - UBX_CFG_PRT_t *packetUBXCFGPRT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_CFG_RATE_t *packetUBXCFGRATE = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - UBX_TIM_TM2_t *packetUBXTIMTM2 = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - UBX_ESF_ALG_t *packetUBXESFALG = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_ESF_INS_t *packetUBXESFINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_ESF_MEAS_t *packetUBXESFMEAS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_ESF_RAW_t *packetUBXESFRAW = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_ESF_STATUS_t *packetUBXESFSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - UBX_HNR_PVT_t *packetUBXHNRPVT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_HNR_ATT_t *packetUBXHNRATT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_HNR_INS_t *packetUBXHNRINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - UBX_MGA_ACK_DATA0_t *packetUBXMGAACK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_MGA_DBD_t *packetUBXMGADBD = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - NMEA_GPGGA_t *storageNMEAGPGGA = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - NMEA_GNGGA_t *storageNMEAGNGGA = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - - uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame + // New in v2.0: allow the payload size for packetCfg to be changed + bool setPacketCfgPayloadSize(size_t payloadSize); // Set packetCfgPayloadSize + + // Begin communication with the GNSS. Advanced users can assume success if required. Useful if the port is already outputting messages at high navigation rate. + // Begin will then return true if "signs of life" have been seen: reception of _any_ valid UBX packet or _any_ valid NMEA header. + // By default use the default I2C address, and use Wire port + bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); // Returns true if module is detected + // serialPort needs to be perviously initialized to correct baud rate + bool begin(Stream &serialPort, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); // Returns true if module is detected + // SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz) + bool begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed, uint16_t maxWait = defaultMaxWait, bool assumeSuccess = false); + + void end(void); // Stop all automatic message processing. Free all used RAM + + void setI2CpollingWait(uint8_t newPollingWait_ms); // Allow the user to change the I2C polling wait if required + void setSPIpollingWait(uint8_t newPollingWait_ms); // Allow the user to change the SPI polling wait if required + + // Set the max number of bytes set in a given I2C transaction + uint8_t i2cTransactionSize = 32; // Default to ATmega328 limit + + // Control the size of the internal I2C transaction amount + void setI2CTransactionSize(uint8_t bufferSize); + uint8_t getI2CTransactionSize(void); + + // Support for platforms like ESP32 which do not support multiple I2C restarts + // If _i2cStopRestart is true, endTransmission will always use a stop. If false, a restart will be used where needed. + // The default value for _i2cStopRestart is set in the class instantiation code. + void setI2cStopRestart(bool stop) { _i2cStopRestart = stop; }; + bool getI2cStopRestart(void) { return (_i2cStopRestart); }; + + // Control the size of the spi buffer. If the buffer isn't big enough, we'll start to lose bytes + // That we receive if the buffer is full! + void setSpiTransactionSize(uint8_t bufferSize); + uint8_t getSpiTransactionSize(void); + + // Control the size of maxNMEAByteCount + void setMaxNMEAByteCount(int8_t newMax); + int8_t getMaxNMEAByteCount(void); + + // Returns true if device answers on _gpsI2Caddress address or via Serial + bool isConnected(uint16_t maxWait = defaultMaxWait); + +// Enable debug messages using the chosen Serial port (Stream) +// Boards like the RedBoard Turbo use SerialUSB (not Serial). +// But other boards like the SAMD51 Thing Plus use Serial (not SerialUSB). +// These lines let the code compile cleanly on as many SAMD boards as possible. +#if defined(ARDUINO_ARCH_SAMD) // Is this a SAMD board? +#if defined(USB_VID) // Is the USB Vendor ID defined? +#if (USB_VID == 0x1B4F) // Is this a SparkFun board? +#if !defined(ARDUINO_SAMD51_THING_PLUS) & !defined(ARDUINO_SAMD51_MICROMOD) // If it is not a SAMD51 Thing Plus or SAMD51 MicroMod + void enableDebugging(Stream &debugPort = SerialUSB, bool printLimitedDebug = false); // Given a port to print to, enable debug messages. Default to all, not limited. +#else + void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); // Given a port to print to, enable debug messages. Default to all, not limited. +#endif +#else + void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); // Given a port to print to, enable debug messages. Default to all, not limited. +#endif +#else + void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); // Given a port to print to, enable debug messages. Default to all, not limited. +#endif +#else + void enableDebugging(Stream &debugPort = Serial, bool printLimitedDebug = false); // Given a port to print to, enable debug messages. Default to all, not limited. +#endif -private: - //Depending on the sentence type the processor will load characters into different arrays - enum SentenceTypes - { - NONE = 0, - NMEA, - UBX, - RTCM - } currentSentence = NONE; - - //Depending on the ubx binary response class, store binary responses into different places - enum classTypes - { - CLASS_NONE = 0, - CLASS_ACK, - CLASS_NOT_AN_ACK - } ubxFrameClass = CLASS_NONE; - - enum commTypes - { - COMM_TYPE_I2C = 0, - COMM_TYPE_SERIAL, - COMM_TYPE_SPI - } commType = COMM_TYPE_I2C; //Controls which port we look to for incoming bytes - - //Functions - bool checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass = 255, uint8_t requestedID = 255); //Checks module with user selected commType - void addToChecksum(uint8_t incoming); //Given an incoming byte, adjust rollingChecksumA/B - size_t pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); - size_t findMGAANOForDateInternal(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture); - - //Return true if this "automatic" message has storage allocated for it - bool checkAutomatic(uint8_t Class, uint8_t ID); - - //Calculate how much RAM is needed to store the payload for a given automatic message - uint16_t getMaxPayloadSize(uint8_t Class, uint8_t ID); - - //Do the actual transfer to SPI - void spiTransfer(uint8_t byteToTransfer); - - bool initGeofenceParams(); // Allocate RAM for currentGeofenceParams and initialize it - bool initModuleSWVersion(); // Allocate RAM for moduleSWVersion and initialize it - - // The initPacket functions need to be private as they don't check if memory has already been allocated. - // Functions like setAutoNAVPOSECEF will check that memory has not been allocated before calling initPacket. - bool initPacketUBXNAVPOSECEF(); // Allocate RAM for packetUBXNAVPOSECEF and initialize it - bool initPacketUBXNAVSTATUS(); // Allocate RAM for packetUBXNAVSTATUS and initialize it - bool initPacketUBXNAVDOP(); // Allocate RAM for packetUBXNAVDOP and initialize it - bool initPacketUBXNAVATT(); // Allocate RAM for packetUBXNAVATT and initialize it - bool initPacketUBXNAVPVT(); // Allocate RAM for packetUBXNAVPVT and initialize it - bool initPacketUBXNAVODO(); // Allocate RAM for packetUBXNAVODO and initialize it - bool initPacketUBXNAVVELECEF(); // Allocate RAM for packetUBXNAVVELECEF and initialize it - bool initPacketUBXNAVVELNED(); // Allocate RAM for packetUBXNAVVELNED and initialize it - bool initPacketUBXNAVHPPOSECEF(); // Allocate RAM for packetUBXNAVHPPOSECEF and initialize it - bool initPacketUBXNAVHPPOSLLH(); // Allocate RAM for packetUBXNAVHPPOSLLH and initialize it - bool initPacketUBXNAVPVAT(); // Allocate RAM for packetUBXNAVPVAT and initialize it - bool initPacketUBXNAVCLOCK(); // Allocate RAM for packetUBXNAVCLOCK and initialize it - bool initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it - bool initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it - bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it - bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it - bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it - bool initPacketUBXRXMPMP(); // Allocate RAM for packetUBXRXMPMP and initialize it - bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it - bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it - bool initPacketUBXCFGPRT(); // Allocate RAM for packetUBXCFGPRT and initialize it - bool initPacketUBXCFGRATE(); // Allocate RAM for packetUBXCFGRATE and initialize it - bool initPacketUBXTIMTM2(); // Allocate RAM for packetUBXTIMTM2 and initialize it - bool initPacketUBXESFALG(); // Allocate RAM for packetUBXESFALG and initialize it - bool initPacketUBXESFSTATUS(); // Allocate RAM for packetUBXESFSTATUS and initialize it - bool initPacketUBXESFINS(); // Allocate RAM for packetUBXESFINS and initialize it - bool initPacketUBXESFMEAS(); // Allocate RAM for packetUBXESFMEAS and initialize it - bool initPacketUBXESFRAW(); // Allocate RAM for packetUBXESFRAW and initialize it - bool initPacketUBXHNRATT(); // Allocate RAM for packetUBXHNRATT and initialize it - bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it - bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it - bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it - bool initPacketUBXMGADBD(); // Allocate RAM for packetUBXMGADBD and initialize it - - bool initStorageNMEAGPGGA(); // Allocate RAM for incoming NMEA GPGGA messages and initialize it - bool initStorageNMEAGNGGA(); // Allocate RAM for incoming NMEA GNGGA messages and initialize it - - //Variables - TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware - Stream *_serialPort; //The generic connection to user's chosen Serial hardware - Stream *_nmeaOutputPort = NULL; //The user can assign an output port to print NMEA sentences if they wish - Stream *_debugSerial; //The stream to send debug messages to if enabled - - SPIClass *_spiPort; //The instance of SPIClass - uint8_t _csPin; //The chip select pin - uint32_t _spiSpeed; //The speed to use for SPI (Hz) - - uint8_t _gpsI2Caddress = 0x42; //Default 7-bit unshifted address of the ublox 6/7/8/M8/F9 series - //This can be changed using the ublox configuration software - - bool _printDebug = false; //Flag to print the serial commands we are sending to the Serial port for debug - bool _printLimitedDebug = false; //Flag to print limited debug messages. Useful for I2C debugging or high navigation rates - - bool ubx7FcheckDisabled = false; // Flag to indicate if the "7F" check should be ignored in checkUbloxI2C - - sfe_ublox_nmea_filtering_t _logNMEA; // Flags to indicate which NMEA messages should be added to the file buffer for logging - sfe_ublox_nmea_filtering_t _processNMEA; // Flags to indicate which NMEA messages should be passed to processNMEA - - //The packet buffers - //These are pointed at from within the ubxPacket - uint8_t payloadAck[2]; // Holds the requested ACK/NACK - uint8_t payloadBuf[2]; // Temporary buffer used to screen incoming packets or dump unrequested packets - size_t packetCfgPayloadSize = 0; // Size for the packetCfg payload. .begin will set this to MAX_PAYLOAD_SIZE if necessary. User can change with setPacketCfgPayloadSize - uint8_t *payloadCfg = NULL; - uint8_t *payloadAuto = NULL; - - uint8_t *spiBuffer = NULL; // A buffer to store any bytes being recieved back from the device while we are sending via SPI - uint8_t spiBufferIndex = 0; // Index into the SPI buffer - uint8_t spiTransactionSize = SFE_UBLOX_SPI_BUFFER_SIZE; //Default size of the SPI buffer - - //Init the packet structures and init them with pointers to the payloadAck, payloadCfg, payloadBuf and payloadAuto arrays - ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; - ubxPacket packetBuf = {0, 0, 0, 0, 0, payloadBuf, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; - ubxPacket packetCfg = {0, 0, 0, 0, 0, payloadCfg, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; - ubxPacket packetAuto = {0, 0, 0, 0, 0, payloadAuto, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; - - //Flag if this packet is unrequested (and so should be ignored and not copied into packetCfg or packetAck) - bool ignoreThisPayload = false; - - //Identify which buffer is in use - //Data is stored in packetBuf until the requested class and ID can be validated - //If a match is seen, data is diverted into packetAck or packetCfg - //"Automatic" messages which have RAM allocated for them are diverted into packetAuto - sfe_ublox_packet_buffer_e activePacketBuffer = SFE_UBLOX_PACKET_PACKETBUF; - - //Limit checking of new data to every X ms - //If we are expecting an update every X Hz then we should check every quarter that amount of time - //Otherwise we may block ourselves from seeing new data - uint8_t i2cPollingWait = 100; //Default to 100ms. Adjusted when user calls setNavigationFrequency() or setHNRNavigationRate() or setMeasurementRate() - uint8_t i2cPollingWaitNAV = 100; //We need to record the desired polling rate for standard nav messages - uint8_t i2cPollingWaitHNR = 100; //and for HNR too so we can set i2cPollingWait to the lower of the two - - //The SPI polling wait is a little different. checkUbloxSpi will delay for this amount before returning if - //there is no data waiting to be read. This prevents waitForACKResponse from pounding the SPI bus too hard. - uint8_t spiPollingWait = 9; //Default to 9ms; waitForACKResponse delays for 1ms on top of this. User can adjust with setSPIPollingWait. - - unsigned long lastCheck = 0; - - uint16_t ubxFrameCounter; //Count all UBX frame bytes. [Fixed header(2bytes), CLS(1byte), ID(1byte), length(2bytes), payload(x bytes), checksums(2bytes)] - uint8_t rollingChecksumA; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes - uint8_t rollingChecksumB; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes - - int8_t nmeaByteCounter; //Count all NMEA message bytes. - // Abort NMEA message reception if nmeaByteCounter exceeds maxNMEAByteCount. - // The user can adjust maxNMEAByteCount by calling setMaxNMEAByteCount - int8_t maxNMEAByteCount = SFE_UBLOX_MAX_NMEA_BYTE_COUNT; - uint8_t nmeaAddressField[6]; // NMEA Address Field - includes the start character (*) - bool logThisNMEA(); // Return true if we should log this NMEA message - bool processThisNMEA(); // Return true if we should pass this NMEA message to processNMEA - bool isNMEAHeaderValid(); // Return true if the six byte NMEA header appears valid. Used to set _signsOfLife - - bool isThisNMEAauto(); // Check if the NMEA message (in nmeaAddressField) is "auto" (i.e. has RAM allocated for it) - bool doesThisNMEAHaveCallback(); // Do we need to copy the data into the callback copy? - uint8_t *getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length - uint8_t *getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data - uint8_t *getNMEACompleteLengthPtr(); // Get a pointer to the complete copy length - uint8_t *getNMEACompleteNMEAPtr(); // Get a pointer to the complete copy NMEA data - uint8_t *getNMEACallbackLengthPtr(); // Get a pointer to the callback copy length - uint8_t *getNMEACallbackNMEAPtr(); // Get a pointer to the callback copy NMEA data - uint8_t getNMEAMaxLength(); // Get the maximum length of this NMEA message - nmeaAutomaticFlags *getNMEAFlagsPtr(); // Get a pointer to the flags - - uint16_t rtcmLen = 0; - - // Flag to prevent reentry into checkCallbacks - // Prevent badness if the user accidentally calls checkCallbacks from inside a callback - volatile bool checkCallbacksReentrant = false; - - // Support for data logging - uint8_t *ubxFileBuffer = NULL; // Pointer to the file buffer. RAM is allocated for this if required in .begin - uint16_t fileBufferSize = 0; // The size of the file buffer. This can be changed by calling setFileBufferSize _before_ .begin - uint16_t fileBufferHead; // The incoming byte is written into the file buffer at this location - uint16_t fileBufferTail; // The next byte to be read from the buffer will be read from this location - uint16_t fileBufferMaxAvail = 0; // The maximum number of bytes the file buffer has contained. Handy for checking the buffer is large enough to handle all the incoming data. - bool createFileBuffer(void); // Create the file buffer. Called by .begin - uint16_t fileBufferSpaceAvailable(void); // Check how much space is available in the buffer - uint16_t fileBufferSpaceUsed(void); // Check how much space is used in the buffer - bool storePacket(ubxPacket *msg); // Add a UBX packet to the file buffer - bool storeFileBytes(uint8_t *theBytes, uint16_t numBytes); // Add theBytes to the file buffer - void writeToFileBuffer(uint8_t *theBytes, uint16_t numBytes); // Write theBytes to the file buffer - - // Support for platforms like ESP32 which do not support multiple I2C restarts - // If _i2cStopRestart is true, endTransmission will always use a stop. If false, a restart will be used where needed. - // The default value for _i2cStopRestart is set in the class instantiation code. - bool _i2cStopRestart; - - // Storage just in case the user tries to push a single byte using pushRawBytes - bool _pushSingleByte = false; - uint8_t _pushThisSingleByte; - - // .begin will return true if the assumeSuccess parameter is true and if _signsOfLife is true - // _signsOfLife is set to true when: a valid UBX message is seen; a valig NMEA header is seen. - bool _signsOfLife; + void disableDebugging(void); // Turn off debug statements + void debugPrint(char *message); // Safely print debug statements + void debugPrintln(char *message); // Safely print debug statements + const char *statusString(sfe_ublox_status_e stat); // Pretty print the return value + + // Check for the arrival of new I2C/Serial data + + void disableUBX7Fcheck(bool disabled = true); // When logging RAWX data, we need to be able to disable the "7F" check in checkUbloxI2C + + // Changed in V1.8.1: provides backward compatibility for the examples that call checkUblox directly + // Will default to using packetCfg to look for explicit autoPVT packets so they get processed correctly by processUBX + bool checkUblox(uint8_t requestedClass = 0, uint8_t requestedID = 0); // Checks module with user selected commType + + bool checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Method for I2C polling of data, passing any new bytes to process() + bool checkUbloxSerial(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Method for serial polling of data, passing any new bytes to process() + bool checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Method for spi polling of data, passing any new bytes to process() + + // Process the incoming data + + void process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Processes NMEA and UBX binary sentences one byte at a time + void processNMEA(char incoming) __attribute__((weak)); // Given a NMEA character, do something with it. User can overwrite if desired to use something like tinyGPS or MicroNMEA libraries + void processRTCMframe(uint8_t incoming); // Monitor the incoming bytes for start and length bytes + void processRTCM(uint8_t incoming) __attribute__((weak)); // Given rtcm byte, do something with it. User can overwrite if desired to pipe bytes to radio, internet, etc. + void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Given a character, file it away into the uxb packet structure + void processUBXpacket(ubxPacket *msg); // Once a packet has been received and validated, identify this packet's class/id and update internal flags + + // Send I2C/Serial/SPI commands to the module + + void calcChecksum(ubxPacket *msg); // Sets the checksumA and checksumB of a given messages + sfe_ublox_status_e sendCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait, bool expectACKonly = false); // Given a packet and payload, send everything including CRC bytes, return true if we got a response + sfe_ublox_status_e sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait); + void sendSerialCommand(ubxPacket *outgoingUBX); + void sendSpiCommand(ubxPacket *outgoingUBX); + + void printPacket(ubxPacket *packet, bool alwaysPrintPayload = false); // Useful for debugging + + // After sending a message to the module, wait for the expected response (data+ACK or just data) + + sfe_ublox_status_e waitForACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime = defaultMaxWait); // Poll the module until a config packet and an ACK is received, or just an ACK + sfe_ublox_status_e waitForNoACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime = defaultMaxWait); // Poll the module until a config packet is received + + // Check if any callbacks need to be called + void checkCallbacks(void); + + // Push (e.g.) RTCM data directly to the module + // Warning: this function does not check that the data is valid. It is the user's responsibility to ensure the data is valid before pushing. + // Default to using a restart between transmissions. But processors like ESP32 seem to need a stop (#30). Set stop to true to use a stop instead. + bool pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool stop = false); + +// Push MGA AssistNow data to the module. +// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE). +// Wait for maxWait millis after sending each packet (if mgaAck is NO). +// Return how many bytes were pushed successfully. +// If skipTime is true, any UBX-MGA-INI-TIME_UTC or UBX-MGA-INI-TIME_GNSS packets found in the data will be skipped, +// allowing the user to override with their own time data with setUTCTimeAssistance. +// offset allows a sub-set of the data to be sent - starting from offset. +#define defaultMGAdelay 7 // Default to waiting for 7ms between each MGA message + size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + +// Provide initial time assistance +#define defaultMGAINITIMEtAccS 2 // Default to setting the seconds time accuracy to 2 seconds +#define defaultMGAINITIMEtAccNs 0 // Default to setting the nanoseconds time accuracy to zero +#define defaultMGAINITIMEsource 0 // Set default source to none, i.e. on receipt of message (will be inaccurate!) + bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, + uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, + sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + + // Provide initial position assistance + // The units for ecefX/Y/Z and posAcc (stddev) are cm. + bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // The units for lat and lon are degrees * 1e-7 (WGS84) + // The units for alt (WGS84) and posAcc (stddev) are cm. + bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + + // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day + // The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date + // Returns numDataBytes if unsuccessful + // TO DO: enhance this so it will find the nearest data for the chosen day - instead of an exact match + size_t findMGAANOForDate(const String &dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); + size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture = 0); + +// Read the whole navigation data base. The receiver will send all available data from its internal database. +// Data is written to dataBytes. Set maxNumDataBytes to the (maximum) size of dataBytes. +// If the database exceeds maxNumDataBytes, the excess bytes will be lost. +// The function returns the number of database bytes written to dataBytes. +// The return value will be equal to maxNumDataBytes if excess data was received. +// The function will timeout after maxWait milliseconds - in case the final UBX-MGA-ACK was missed. +#define defaultNavDBDMaxWait 3100 + size_t readNavigationDatabase(uint8_t *dataBytes, size_t maxNumDataBytes, uint16_t maxWait = defaultNavDBDMaxWait); + + // Support for data logging + void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. + uint16_t getFileBufferSize(void); // Return the size of the file buffer + uint16_t extractFileBufferData(uint8_t *destination, uint16_t numBytes); // Extract numBytes of data from the file buffer. Copy it to destination. It is the user's responsibility to ensure destination is large enough. + uint16_t fileBufferAvailable(void); // Returns the number of bytes available in file buffer which are waiting to be read + uint16_t getMaxFileBufferAvail(void); // Returns the maximum number of bytes which the file buffer has contained. Handy for checking the buffer is large enough to handle all the incoming data. + void clearFileBuffer(void); // Empty the file buffer - discard all contents + void clearMaxFileBufferAvail(void); // Reset fileBufferMaxAvail + + // Specific commands + + // Port configurations + bool getPortSettings(uint8_t portID, uint16_t maxWait = defaultMaxWait); // Returns the current protocol bits in the UBX-CFG-PRT command for a given port + bool setPortOutput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure a given port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setPortInput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure a given port to input UBX, NMEA, RTCM3, SPARTN or a combination thereof + + bool setI2CAddress(uint8_t deviceAddress, uint16_t maxTime = defaultMaxWait); // Changes the I2C address of the u-blox module + void setSerialRate(uint32_t baudrate, uint8_t uartPort = COM_PORT_UART1, uint16_t maxTime = defaultMaxWait); // Changes the serial baud rate of the u-blox module, uartPort should be COM_PORT_UART1/2 + + bool setI2COutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure I2C port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setUART1Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure UART1 port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setUART2Output(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure UART2 port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setUSBOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure USB port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + bool setSPIOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure SPI port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof + void setNMEAOutputPort(Stream &nmeaOutputPort); // Sets the internal variable for the port to direct NMEA characters to + + // Reset to defaults + + void factoryReset(); // Send factory reset sequence (i.e. load "default" configuration and perform hardReset) + void hardReset(); // Perform a reset leading to a cold start (zero info start-up) + void softwareResetGNSSOnly(); // Controlled Software Reset (GNSS only) only restarts the GNSS tasks, without reinitializing the full system or reloading any stored configuration. + bool factoryDefault(uint16_t maxWait = defaultMaxWait); // Reset module to factory defaults + + // Save configuration to BBR / Flash + + bool saveConfiguration(uint16_t maxWait = defaultMaxWait); // Save current configuration to flash and BBR (battery backed RAM) + bool saveConfigSelective(uint32_t configMask, uint16_t maxWait = defaultMaxWait); // Save the selected configuration sub-sections to flash and BBR (battery backed RAM) + + // Functions to turn on/off message types for a given port ID (see COM_PORT_I2C, etc above) + bool configureMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate, uint16_t maxWait = defaultMaxWait); + bool enableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate = 1, uint16_t maxWait = defaultMaxWait); + bool disableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint16_t maxWait = defaultMaxWait); + bool enableNMEAMessage(uint8_t msgID, uint8_t portID, uint8_t sendRate = 1, uint16_t maxWait = defaultMaxWait); + bool disableNMEAMessage(uint8_t msgID, uint8_t portID, uint16_t maxWait = defaultMaxWait); + bool enableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint8_t sendRate, uint16_t maxWait = defaultMaxWait); // Given a message number turns on a message ID for output over given PortID + bool disableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint16_t maxWait = defaultMaxWait); // Turn off given RTCM message from a given port + + // Functions used for RTK and base station setup + // It is probably safe to assume that users of the RTK will be using I2C / Qwiic. So let's leave maxWait set to 250ms. + bool getSurveyMode(uint16_t maxWait = 250); // Get the current TimeMode3 settings + bool setSurveyMode(uint8_t mode, uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); // Control survey in mode + bool enableSurveyMode(uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); // Begin Survey-In for NEO-M8P + bool disableSurveyMode(uint16_t maxWait = 250); // Stop Survey-In mode + // Given coordinates, put receiver into static position. Set latlong to true to pass in lat/long values instead of ecef. + // For ECEF the units are: cm, 0.1mm, cm, 0.1mm, cm, 0.1mm + // For Lat/Lon/Alt the units are: degrees^-7, degrees^-9, degrees^-7, degrees^-9, cm, 0.1mm + bool setStaticPosition(int32_t ecefXOrLat, int8_t ecefXOrLatHP, int32_t ecefYOrLon, int8_t ecefYOrLonHP, int32_t ecefZOrAlt, int8_t ecefZOrAltHP, bool latLong = false, uint16_t maxWait = 250); + bool setStaticPosition(int32_t ecefXOrLat, int32_t ecefYOrLon, int32_t ecefZOrAlt, bool latLong = false, uint16_t maxWait = 250); + bool setDGNSSConfiguration(sfe_ublox_dgnss_mode_e dgnssMode = SFE_UBLOX_DGNSS_MODE_FIXED, uint16_t maxWait = defaultMaxWait); // Set the DGNSS differential mode + + // Read the module's protocol version + uint8_t getProtocolVersionHigh(uint16_t maxWait = defaultMaxWait); // Returns the PROTVER XX.00 from UBX-MON-VER register + uint8_t getProtocolVersionLow(uint16_t maxWait = defaultMaxWait); // Returns the PROTVER 00.XX from UBX-MON-VER register + bool getProtocolVersion(uint16_t maxWait = defaultMaxWait); // Queries module, loads low/high bytes + moduleSWVersion_t *moduleSWVersion = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + // Support for geofences + bool addGeofence(int32_t latitude, int32_t longitude, uint32_t radius, byte confidence = 0, byte pinPolarity = 0, byte pin = 0, uint16_t maxWait = defaultMaxWait); // Add a new geofence + bool clearGeofences(uint16_t maxWait = defaultMaxWait); // Clears all geofences + bool clearAntPIO(uint16_t maxWait = defaultMaxWait); // Clears the antenna control pin settings to release the PIOs + bool getGeofenceState(geofenceState ¤tGeofenceState, uint16_t maxWait = defaultMaxWait); // Returns the combined geofence state + // Storage for the geofence parameters. RAM is allocated for this if/when required. + geofenceParams_t *currentGeofenceParams = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + // Power save / off + bool powerSaveMode(bool power_save = true, uint16_t maxWait = defaultMaxWait); + uint8_t getPowerSaveMode(uint16_t maxWait = defaultMaxWait); // Returns 255 if the sendCommand fails + bool powerOff(uint32_t durationInMs, uint16_t maxWait = defaultMaxWait); + bool powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, bool forceWhileUsb = true, uint16_t maxWait = defaultMaxWait); + + // Change the dynamic platform model using UBX-CFG-NAV5 + bool setDynamicModel(dynModel newDynamicModel = DYN_MODEL_PORTABLE, uint16_t maxWait = defaultMaxWait); + uint8_t getDynamicModel(uint16_t maxWait = defaultMaxWait); // Get the dynamic model - returns 255 if the sendCommand fails + + // Reset the odometer + bool resetOdometer(uint16_t maxWait = defaultMaxWait); // Reset the odometer + + // Enable/Disable individual GNSS systems using UBX-CFG-GNSS + // Note: you must leave at least one major GNSS enabled! If in doubt, enable GPS before disabling the others + // TO DO: Add support for sigCfgMask and maxTrkCh. (Need to resolve ambiguity with maxWait) + bool enableGNSS(bool enable, sfe_ublox_gnss_ids_e id, uint16_t maxWait = defaultMaxWait); + bool isGNSSenabled(sfe_ublox_gnss_ids_e id, uint16_t maxWait = defaultMaxWait); + + // Reset ESF automatic IMU-mount alignment + bool resetIMUalignment(uint16_t maxWait = defaultMaxWait); + + // Enable/disable esfAutoAlignment + bool getESFAutoAlignment(uint16_t maxWait = defaultMaxWait); + bool setESFAutoAlignment(bool enable, uint16_t maxWait = defaultMaxWait); + + // Configure Time Pulse Parameters + bool getTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Get the time pulse parameters using UBX_CFG_TP5 + bool setTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Set the time pulse parameters using UBX_CFG_TP5 + + // UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data + uint8_t getAckAiding(uint16_t maxWait = defaultMaxWait); // Get the ackAiding byte - returns 255 if the sendCommand fails + bool setAckAiding(uint8_t ackAiding, uint16_t maxWait = defaultMaxWait); // Set the ackAiding byte + + // AssistNow Autonomous support + // UBX-CFG-NAVX5 - get/set the aopCfg byte and set the aopOrdMaxErr word. If aopOrbMaxErr is 0 (default), the max orbit error is reset to the firmware default. + uint8_t getAopCfg(uint16_t maxWait = defaultMaxWait); // Get the AssistNow Autonomous configuration (aopCfg) - returns 255 if the sendCommand fails + bool setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr = 0, uint16_t maxWait = defaultMaxWait); // Set the aopCfg byte and the aopOrdMaxErr word + + // SPARTN dynamic keys + //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. + //"Every time the 'current' key is expired, 'next' takes its place." + //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. + // The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. + bool setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait = defaultMaxWait); + bool setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const uint8_t *key1, + uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2, uint16_t maxWait = defaultMaxWait); + + // General configuration (used only on protocol v27 and higher - ie, ZED-F9P) + + // It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic. + // If they are using Serial then the higher baud rate will also help. So let's leave maxWait set to 250ms. + uint32_t createKey(uint16_t group, uint16_t id, uint8_t size); // Form 32-bit key from group/id/size + sfe_ublox_status_e getVal(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Load payload with response + uint8_t getVal8(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given key location + uint16_t getVal16(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given key location + uint32_t getVal32(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given key location + uint64_t getVal64(uint32_t keyID, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given key location + uint8_t getVal8(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given group/id/size location + uint16_t getVal16(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given group/id/size location + uint32_t getVal32(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given group/id/size location + uint64_t getVal64(uint16_t group, uint16_t id, uint8_t size, uint8_t layer = VAL_LAYER_RAM, uint16_t maxWait = 250); // Returns the value at a given group/id/size location + uint8_t setVal(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); // Sets the 16-bit value at a given group/id/size location + uint8_t setVal8(uint32_t keyID, uint8_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); // Sets the 8-bit value at a given group/id/size location + uint8_t setVal16(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); // Sets the 16-bit value at a given group/id/size location + uint8_t setVal32(uint32_t keyID, uint32_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); // Sets the 32-bit value at a given group/id/size location + uint8_t setVal64(uint32_t keyID, uint64_t value, uint8_t layer = VAL_LAYER_ALL, uint16_t maxWait = 250); // Sets the 64-bit value at a given group/id/size location + uint8_t newCfgValset8(uint32_t keyID, uint8_t value, uint8_t layer = VAL_LAYER_ALL); // Define a new UBX-CFG-VALSET with the given KeyID and 8-bit value + uint8_t newCfgValset16(uint32_t keyID, uint16_t value, uint8_t layer = VAL_LAYER_ALL); // Define a new UBX-CFG-VALSET with the given KeyID and 16-bit value + uint8_t newCfgValset32(uint32_t keyID, uint32_t value, uint8_t layer = VAL_LAYER_ALL); // Define a new UBX-CFG-VALSET with the given KeyID and 32-bit value + uint8_t newCfgValset64(uint32_t keyID, uint64_t value, uint8_t layer = VAL_LAYER_ALL); // Define a new UBX-CFG-VALSET with the given KeyID and 64-bit value + uint8_t addCfgValset8(uint32_t keyID, uint8_t value); // Add a new KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket + uint8_t addCfgValset16(uint32_t keyID, uint16_t value); // Add a new KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket + uint8_t addCfgValset32(uint32_t keyID, uint32_t value); // Add a new KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket + uint8_t addCfgValset64(uint32_t keyID, uint64_t value); // Add a new KeyID and 64-bit value to an existing UBX-CFG-VALSET ubxPacket + uint8_t sendCfgValset8(uint32_t keyID, uint8_t value, uint16_t maxWait = 250); // Add the final KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket and send it + uint8_t sendCfgValset16(uint32_t keyID, uint16_t value, uint16_t maxWait = 250); // Add the final KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket and send it + uint8_t sendCfgValset32(uint32_t keyID, uint32_t value, uint16_t maxWait = 250); // Add the final KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket and send it + uint8_t sendCfgValset64(uint32_t keyID, uint64_t value, uint16_t maxWait = 250); // Add the final KeyID and 64-bit value to an existing UBX-CFG-VALSET ubxPacket and send it + + // get and set functions for all of the "automatic" message processing + + // Navigation (NAV) + + // getPVT will only return data once in each navigation cycle. By default, that is once per second. + // Therefore we should set defaultMaxWait to slightly longer than that. + // If you change the navigation frequency to (e.g.) 4Hz using setNavigationFrequency(4) + // then you should use a shorter maxWait. 300msec would be about right: getPVT(300) + + bool getNAVPOSECEF(uint16_t maxWait = defaultMaxWait); // NAV POSECEF + bool setAutoNAVPOSECEF(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic POSECEF reports at the navigation frequency + bool setAutoNAVPOSECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic POSECEF 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 setAutoNAVPOSECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic POSECEF reports + bool setAutoNAVPOSECEFcallback(void (*callbackPointer)(UBX_NAV_POSECEF_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic POSECEF reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_POSECEF_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic POSECEF reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVPOSECEF(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and POSECEF is send cyclically already + void flushNAVPOSECEF(); // Mark all the data as read/stale + void logNAVPOSECEF(bool enabled = true); // Log data to file buffer + + bool getNAVSTATUS(uint16_t maxWait = defaultMaxWait); // NAV STATUS + bool setAutoNAVSTATUS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic STATUS reports at the navigation frequency + bool setAutoNAVSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic STATUS 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 setAutoNAVSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic STATUS reports + bool setAutoNAVSTATUScallback(void (*callbackPointer)(UBX_NAV_STATUS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_STATUS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVSTATUS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and STATUS is send cyclically already + void flushNAVSTATUS(); // Mark all the data as read/stale + void logNAVSTATUS(bool enabled = true); // Log data to file buffer + + bool getDOP(uint16_t maxWait = defaultMaxWait); // Query module for latest dilution of precision values and load global vars:. If autoDOP is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new DOP is available. + bool setAutoDOP(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic DOP reports at the navigation frequency + bool setAutoDOP(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic DOP 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 setAutoDOPrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic DOP reports + bool setAutoDOPcallback(void (*callbackPointer)(UBX_NAV_DOP_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic DOP reports at the navigation frequency. Data is accessed from the callback. + bool setAutoDOPcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_DOP_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic DOP reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoDOP(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and DOP is send cyclically already + void flushDOP(); // Mark all the DOP data as read/stale + void logNAVDOP(bool enabled = true); // Log data to file buffer + + bool getVehAtt(uint16_t maxWait = defaultMaxWait); // NAV ATT Helper + bool getNAVATT(uint16_t maxWait = defaultMaxWait); // NAV ATT + bool setAutoNAVATT(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic vehicle attitude reports at the navigation frequency + bool setAutoNAVATT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic vehicle attitude 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 setAutoNAVATTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic ATT reports + bool setAutoNAVATTcallback(void (*callbackPointer)(UBX_NAV_ATT_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVATTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ATT_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVATT(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and vehicle attitude is send cyclically already + void flushNAVATT(); // Mark all the data as read/stale + void logNAVATT(bool enabled = true); // Log data to file buffer + + bool getPVT(uint16_t maxWait = defaultMaxWait); // Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new PVT is available. + bool setAutoPVT(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic PVT reports at the navigation frequency + bool setAutoPVT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic PVT 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 setAutoPVTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic PVT reports + bool setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoPVTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVT_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoPVT(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and PVT is send cyclically already + void flushPVT(); // Mark all the PVT data as read/stale + void logNAVPVT(bool enabled = true); // Log data to file buffer + + bool getNAVODO(uint16_t maxWait = defaultMaxWait); // NAV ODO + bool setAutoNAVODO(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ODO reports at the navigation frequency + bool setAutoNAVODO(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ODO 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 setAutoNAVODOrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic ODO reports + bool setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVODOcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ODO_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVODO(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ODO is send cyclically already + void flushNAVODO(); // Mark all the data as read/stale + void logNAVODO(bool enabled = true); // Log data to file buffer + + bool getNAVVELECEF(uint16_t maxWait = defaultMaxWait); // NAV VELECEF + bool setAutoNAVVELECEF(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic VELECEF reports at the navigation frequency + bool setAutoNAVVELECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic VELECEF 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 setAutoNAVVELECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic VELECEF reports + bool setAutoNAVVELECEFcallback(void (*callbackPointer)(UBX_NAV_VELECEF_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic VELECEF reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVVELECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELECEF_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic VELECEF reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVVELECEF(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and VELECEF is send cyclically already + void flushNAVVELECEF(); // Mark all the data as read/stale + void logNAVVELECEF(bool enabled = true); // Log data to file buffer + + bool getNAVVELNED(uint16_t maxWait = defaultMaxWait); // NAV VELNED + bool setAutoNAVVELNED(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic VELNED reports at the navigation frequency + bool setAutoNAVVELNED(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic VELNED 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 setAutoNAVVELNEDrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic VELNED reports + bool setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VELNED_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic VELNED reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVVELNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_VELNED_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic VELNED reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVVELNED(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and VELNED is send cyclically already + void flushNAVVELNED(); // Mark all the data as read/stale + void logNAVVELNED(bool enabled = true); // Log data to file buffer + + bool getNAVHPPOSECEF(uint16_t maxWait = defaultMaxWait); // NAV HPPOSECEF + bool setAutoNAVHPPOSECEF(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HPPOSECEF reports at the navigation frequency + bool setAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HPPOSECEF 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 setAutoNAVHPPOSECEFrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic HPPOSECEF reports + bool setAutoNAVHPPOSECEFcallback(void (*callbackPointer)(UBX_NAV_HPPOSECEF_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic HPPOSECEF reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVHPPOSECEFcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSECEF_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic HPPOSECEF reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVHPPOSECEF(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and HPPOSECEF is send cyclically already + void flushNAVHPPOSECEF(); // Mark all the data as read/stale + void logNAVHPPOSECEF(bool enabled = true); // Log data to file buffer + + bool getHPPOSLLH(uint16_t maxWait = defaultMaxWait); // NAV HPPOSLLH + bool setAutoHPPOSLLH(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HPPOSLLH reports at the navigation frequency + bool setAutoHPPOSLLH(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HPPOSLLH 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 setAutoHPPOSLLHrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic HPPOSLLH reports + bool setAutoHPPOSLLHcallback(void (*callbackPointer)(UBX_NAV_HPPOSLLH_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic HPPOSLLH reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHPPOSLLHcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_HPPOSLLH_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic HPPOSLLH reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoHPPOSLLH(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and HPPOSLLH is send cyclically already + void flushHPPOSLLH(); // Mark all the HPPPOSLLH data as read/stale. This is handy to get data alignment after CRC failure + void logNAVHPPOSLLH(bool enabled = true); // Log data to file buffer + + bool getNAVPVAT(uint16_t maxWait = defaultMaxWait); // NAV PVAT + bool setAutoNAVPVAT(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic PVAT reports at the navigation frequency + bool setAutoNAVPVAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic PVAT 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 setAutoNAVPVATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic PVAT reports + bool setAutoNAVPVATcallback(void (*callbackPointer)(UBX_NAV_PVAT_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic PVAT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVPVATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_PVAT_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic PVAT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVPVAT(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and PVAT is send cyclically already + void flushNAVPVAT(); // Mark all the PVAT data as read/stale + void logNAVPVAT(bool enabled = true); // Log data to file buffer + + bool getNAVCLOCK(uint16_t maxWait = defaultMaxWait); // NAV CLOCK + bool setAutoNAVCLOCK(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic clock reports at the navigation frequency + bool setAutoNAVCLOCK(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic clock 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 setAutoNAVCLOCKrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic CLOCK reports + bool setAutoNAVCLOCKcallback(void (*callbackPointer)(UBX_NAV_CLOCK_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic CLOCK reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVCLOCKcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_CLOCK_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic CLOCK reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVCLOCK(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and clock is send cyclically already + 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 + + // Add "auto" support for NAV TIMELS - to avoid needing 'global' storage + bool getLeapSecondEvent(uint16_t maxWait); // 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 + bool setAutoNAVSAT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic NAVSAT 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 setAutoNAVSATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic NAVSAT reports + bool setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_SAT_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic NAVSAT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoNAVSATcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SAT_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic NAVSAT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVSAT(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and NAVSAT is send cyclically already + void flushNAVSAT(); // Mark all the NAVSAT data as read/stale + void logNAVSAT(bool enabled = true); // Log data to file buffer + + bool getRELPOSNED(uint16_t maxWait = defaultMaxWait); // Get Relative Positioning Information of the NED frame + bool setAutoRELPOSNED(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic RELPOSNED reports + bool setAutoRELPOSNED(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic RELPOSNED, 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 setAutoRELPOSNEDrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic RELPOSNEDreports + bool setAutoRELPOSNEDcallback(void (*callbackPointer)(UBX_NAV_RELPOSNED_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic RELPOSNED reports at the navigation frequency. Data is accessed from the callback. + bool setAutoRELPOSNEDcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_RELPOSNED_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic RELPOSNED reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoRELPOSNED(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and RELPOSNED is send cyclically already + void flushNAVRELPOSNED(); // Mark all the data as read/stale + void logNAVRELPOSNED(bool enabled = true); // Log data to file buffer + + bool getAOPSTATUS(uint16_t maxWait = defaultMaxWait); // Query module for latest AssistNow Autonomous status and load global vars:. If autoAOPSTATUS is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new AOPSTATUS is available. + bool setAutoAOPSTATUS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic AOPSTATUS reports at the navigation frequency + bool setAutoAOPSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic AOPSTATUS 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 setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic AOPSTATUS reports + bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoAOPSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_NAV_AOPSTATUS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic AOPSTATUS reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and AOPSTATUS is send cyclically already + void flushAOPSTATUS(); // Mark all the AOPSTATUS data as read/stale + void logAOPSTATUS(bool enabled = true); // Log data to file buffer + + // Receiver Manager Messages (RXM) + + // Configure a callback for the UBX-RXM-PMP messages produced by the NEO-D9S + // Note: on the NEO-D9S, the UBX-RXM-PMP messages are enabled by default on all ports. + // You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 0) + // The NEO-D9S does not support UBX-CFG-MSG + bool setAutoRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! + + bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX + bool setAutoRXMSFRBX(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic RXM SFRBX reports at the navigation frequency + bool setAutoRXMSFRBX(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic RXM SFRBX 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 setAutoRXMSFRBXrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic SFRBX reports + bool setAutoRXMSFRBXcallback(void (*callbackPointer)(UBX_RXM_SFRBX_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic SFRBX reports at the navigation frequency. Data is accessed from the callback. + bool setAutoRXMSFRBXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_SFRBX_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic SFRBX reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoRXMSFRBX(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and RXM SFRBX is send cyclically already + void flushRXMSFRBX(); // Mark all the data as read/stale + void logRXMSFRBX(bool enabled = true); // Log data to file buffer + + bool getRXMRAWX(uint16_t maxWait = defaultMaxWait); // RXM RAWX + bool setAutoRXMRAWX(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic RXM RAWX reports at the navigation frequency + bool setAutoRXMRAWX(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic RXM RAWX 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 setAutoRXMRAWXrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic RAWX reports + bool setAutoRXMRAWXcallback(void (*callbackPointer)(UBX_RXM_RAWX_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic RAWX reports at the navigation frequency. Data is accessed from the callback. + bool setAutoRXMRAWXcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_RAWX_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic RAWX reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoRXMRAWX(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and RXM RAWX is send cyclically already + void flushRXMRAWX(); // Mark all the data as read/stale + void logRXMRAWX(bool enabled = true); // Log data to file buffer + + // Configuration (CFG) + + // Add "auto" support for CFG PRT - because we use it for isConnected (to stop it being mugged by other messages) + bool getPortSettingsInternal(uint8_t portID, uint16_t maxWait = defaultMaxWait); // Read the port configuration for a given port using UBX-CFG-PRT + bool getNavigationFrequencyInternal(uint16_t maxWait = defaultMaxWait); // Get the number of nav solutions sent per second currently being output by module + + // Timing messages (TIM) + + bool getTIMTM2(uint16_t maxWait = defaultMaxWait); // TIM TM2 + bool setAutoTIMTM2(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic TIM TM2 reports at the navigation frequency + bool setAutoTIMTM2(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic TIM TM2 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 setAutoTIMTM2rate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic TIM TM2 reports + bool setAutoTIMTM2callback(void (*callbackPointer)(UBX_TIM_TM2_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic TM2 reports at the navigation frequency. Data is accessed from the callback. + bool setAutoTIMTM2callbackPtr(void (*callbackPointerPtr)(UBX_TIM_TM2_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic TM2 reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoTIMTM2(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and TIM TM2 is send cyclically already + void flushTIMTM2(); // Mark all the data as read/stale + void logTIMTM2(bool enabled = true); // Log data to file buffer + + // Sensor fusion (dead reckoning) (ESF) + + bool getEsfAlignment(uint16_t maxWait = defaultMaxWait); // ESF ALG Helper + bool getESFALG(uint16_t maxWait = defaultMaxWait); // ESF ALG + bool setAutoESFALG(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF ALG reports + bool setAutoESFALG(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF ALG reports, 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 setAutoESFALGrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic ALG reports + bool setAutoESFALGcallback(void (*callbackPointer)(UBX_ESF_ALG_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic ALG reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFALGcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_ALG_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic ALG reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoESFALG(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF ALG is send cyclically already + void flushESFALG(); // Mark all the data as read/stale + void logESFALG(bool enabled = true); // Log data to file buffer + + bool getEsfInfo(uint16_t maxWait = defaultMaxWait); // ESF STATUS Helper + bool getESFSTATUS(uint16_t maxWait = defaultMaxWait); // ESF STATUS + bool setAutoESFSTATUS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF STATUS reports + bool setAutoESFSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF STATUS reports, 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 setAutoESFSTATUSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic STATUS reports + bool setAutoESFSTATUScallback(void (*callbackPointer)(UBX_ESF_STATUS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFSTATUScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_STATUS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic STATUS reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoESFSTATUS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF STATUS is send cyclically already + void flushESFSTATUS(); // Mark all the data as read/stale + void logESFSTATUS(bool enabled = true); // Log data to file buffer + + bool getEsfIns(uint16_t maxWait = defaultMaxWait); // ESF INS Helper + bool getESFINS(uint16_t maxWait = defaultMaxWait); // ESF INS + bool setAutoESFINS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF INS reports + bool setAutoESFINS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF INS reports, 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 setAutoESFINSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic INS reports + bool setAutoESFINScallback(void (*callbackPointer)(UBX_ESF_INS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFINScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_INS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoESFINS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF INS is send cyclically already + void flushESFINS(); // Mark all the data as read/stale + void logESFINS(bool enabled = true); // Log data to file buffer + + bool getEsfDataInfo(uint16_t maxWait = defaultMaxWait); // ESF MEAS Helper + bool getESFMEAS(uint16_t maxWait = defaultMaxWait); // ESF MEAS + bool setAutoESFMEAS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF MEAS reports + bool setAutoESFMEAS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF MEAS reports, 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 setAutoESFMEASrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic MEAS reports + bool setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoESFMEAS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF MEAS is send cyclically already + void flushESFMEAS(); // Mark all the data as read/stale + void logESFMEAS(bool enabled = true); // Log data to file buffer + + bool getEsfRawDataInfo(uint16_t maxWait = defaultMaxWait); // ESF RAW Helper + bool getESFRAW(uint16_t maxWait = defaultMaxWait); // ESF RAW + bool setAutoESFRAW(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF RAW reports + bool setAutoESFRAW(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF RAW reports, 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 setAutoESFRAWrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic RAW reports + bool setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback. + bool setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoESFRAW(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF RAW is send cyclically already + void flushESFRAW(); // Mark all the data as read/stale + void logESFRAW(bool enabled = true); // Log data to file buffer + + // High navigation rate (HNR) + + bool getHNRAtt(uint16_t maxWait = defaultMaxWait); // HNR ATT Helper + bool getHNRATT(uint16_t maxWait = defaultMaxWait); // Returns true if the get HNR attitude is successful + bool setAutoHNRATT(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HNR Attitude reports at the HNR rate + bool setAutoHNRATT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HNR Attitude reports at the HNR rate, 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 setAutoHNRATTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic ATT reports + bool setAutoHNRATTcallback(void (*callbackPointer)(UBX_HNR_ATT_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHNRATTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_ATT_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic ATT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoHNRATT(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and HNR Attitude is send cyclically already + void flushHNRATT(); // Mark all the data as read/stale + void logHNRATT(bool enabled = true); // Log data to file buffer + + bool getHNRDyn(uint16_t maxWait = defaultMaxWait); // HNR INS Helper + bool getHNRINS(uint16_t maxWait = defaultMaxWait); // Returns true if the get HNR dynamics is successful + bool setAutoHNRINS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HNR dynamics reports at the HNR rate + bool setAutoHNRINS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HNR dynamics reports at the HNR rate, 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 setAutoHNRINSrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic INS reports + bool setAutoHNRINScallback(void (*callbackPointer)(UBX_HNR_INS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHNRINScallbackPtr(void (*callbackPointerPtr)(UBX_HNR_INS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic INS reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoHNRINS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and HNR dynamics is send cyclically already + void flushHNRINS(); // Mark all the data as read/stale + void logHNRINS(bool enabled = true); // Log data to file buffer + + bool getHNRPVT(uint16_t maxWait = defaultMaxWait); // Returns true if the get HNR PVT is successful + bool setAutoHNRPVT(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HNR PVT reports at the HNR rate + bool setAutoHNRPVT(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic HNR PVT reports at the HNR rate, 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 setAutoHNRPVTrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic PVT reports + bool setAutoHNRPVTcallback(void (*callbackPointer)(UBX_HNR_PVT_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. + bool setAutoHNRPVTcallbackPtr(void (*callbackPointerPtr)(UBX_HNR_PVT_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoHNRPVT(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and HNR PVT is send cyclically already + void flushHNRPVT(); // Mark all the data as read/stale + void logHNRPVT(bool enabled = true); // Log data to file buffer + + // Helper functions for CFG RATE + + bool setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = defaultMaxWait); // Set the number of nav solutions sent per second + uint8_t getNavigationFrequency(uint16_t maxWait = defaultMaxWait); // Get the number of nav solutions sent per second currently being output by module + bool setMeasurementRate(uint16_t rate, uint16_t maxWait = defaultMaxWait); // Set the elapsed time between GNSS measurements in milliseconds, which defines the rate + uint16_t getMeasurementRate(uint16_t maxWait = defaultMaxWait); // Return the elapsed time between GNSS measurements in milliseconds + bool setNavigationRate(uint16_t rate, uint16_t maxWait = defaultMaxWait); // Set the ratio between the number of measurements and the number of navigation solutions. Unit is cycles. Max is 127 + uint16_t getNavigationRate(uint16_t maxWait = defaultMaxWait); // Return the ratio between the number of measurements and the number of navigation solutions. Unit is cycles + void flushCFGRATE(); // Mark the measurement and navigation rate data as stale - used by the set rate functions + + // Helper functions for DOP + + uint16_t getGeometricDOP(uint16_t maxWait = defaultMaxWait); + uint16_t getPositionDOP(uint16_t maxWait = defaultMaxWait); + uint16_t getTimeDOP(uint16_t maxWait = defaultMaxWait); + uint16_t getVerticalDOP(uint16_t maxWait = defaultMaxWait); + uint16_t getHorizontalDOP(uint16_t maxWait = defaultMaxWait); + uint16_t getNorthingDOP(uint16_t maxWait = defaultMaxWait); + uint16_t getEastingDOP(uint16_t maxWait = defaultMaxWait); + + // Helper functions for ATT + + float getATTroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees + float getATTpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees + float getATTheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees + + // Helper functions for PVT + + uint32_t getTimeOfWeek(uint16_t maxWait = defaultMaxWait); + uint16_t getYear(uint16_t maxWait = defaultMaxWait); + uint8_t getMonth(uint16_t maxWait = defaultMaxWait); + uint8_t getDay(uint16_t maxWait = defaultMaxWait); + uint8_t getHour(uint16_t maxWait = defaultMaxWait); + uint8_t getMinute(uint16_t maxWait = defaultMaxWait); + uint8_t getSecond(uint16_t maxWait = defaultMaxWait); + uint16_t getMillisecond(uint16_t maxWait = defaultMaxWait); + int32_t getNanosecond(uint16_t maxWait = defaultMaxWait); + uint32_t getUnixEpoch(uint16_t maxWait = defaultMaxWait); + uint32_t getUnixEpoch(uint32_t µsecond, uint16_t maxWait = defaultMaxWait); + + bool getDateValid(uint16_t maxWait = defaultMaxWait); + bool getTimeValid(uint16_t maxWait = defaultMaxWait); + bool getTimeFullyResolved(uint16_t maxWait = defaultMaxWait); + bool getConfirmedDate(uint16_t maxWait = defaultMaxWait); + bool getConfirmedTime(uint16_t maxWait = defaultMaxWait); + + uint8_t getFixType(uint16_t maxWait = defaultMaxWait); // Returns the type of fix: 0=no, 3=3D, 4=GNSS+Deadreckoning + + bool getGnssFixOk(uint16_t maxWait = defaultMaxWait); // Get whether we have a valid fix (i.e within DOP & accuracy masks) + bool getDiffSoln(uint16_t maxWait = defaultMaxWait); // Get whether differential corrections were applied + bool getHeadVehValid(uint16_t maxWait = defaultMaxWait); + uint8_t getCarrierSolutionType(uint16_t maxWait = defaultMaxWait); // Returns RTK solution: 0=no, 1=float solution, 2=fixed solution + + uint8_t getSIV(uint16_t maxWait = defaultMaxWait); // Returns number of sats used in fix + int32_t getLongitude(uint16_t maxWait = defaultMaxWait); // Returns the current longitude in degrees * 10-7. Auto selects between HighPrecision and Regular depending on ability of module. + int32_t getLatitude(uint16_t maxWait = defaultMaxWait); // Returns the current latitude in degrees * 10^-7. Auto selects between HighPrecision and Regular depending on ability of module. + int32_t getAltitude(uint16_t maxWait = defaultMaxWait); // Returns the current altitude in mm above ellipsoid + int32_t getAltitudeMSL(uint16_t maxWait = defaultMaxWait); // Returns the current altitude in mm above mean sea level + int32_t getHorizontalAccEst(uint16_t maxWait = defaultMaxWait); + int32_t getVerticalAccEst(uint16_t maxWait = defaultMaxWait); + int32_t getNedNorthVel(uint16_t maxWait = defaultMaxWait); + int32_t getNedEastVel(uint16_t maxWait = defaultMaxWait); + int32_t getNedDownVel(uint16_t maxWait = defaultMaxWait); + int32_t getGroundSpeed(uint16_t maxWait = defaultMaxWait); // Returns speed in mm/s + int32_t getHeading(uint16_t maxWait = defaultMaxWait); // Returns heading in degrees * 10^-5 + uint32_t getSpeedAccEst(uint16_t maxWait = defaultMaxWait); + uint32_t getHeadingAccEst(uint16_t maxWait = defaultMaxWait); + uint16_t getPDOP(uint16_t maxWait = defaultMaxWait); // Returns positional dillution of precision * 10^-2 (dimensionless) + + bool getInvalidLlh(uint16_t maxWait = defaultMaxWait); + + int32_t getHeadVeh(uint16_t maxWait = defaultMaxWait); + int16_t getMagDec(uint16_t maxWait = defaultMaxWait); + uint16_t getMagAcc(uint16_t maxWait = defaultMaxWait); + + int32_t getGeoidSeparation(uint16_t maxWait = defaultMaxWait); + + // Helper functions for HPPOSECEF + + uint32_t getPositionAccuracy(uint16_t maxWait = defaultMaxWait); // Returns the 3D accuracy of the current high-precision fix, in mm. Supported on NEO-M8P, ZED-F9P, + + // Helper functions for HPPOSLLH + + uint32_t getTimeOfWeekFromHPPOSLLH(uint16_t maxWait = defaultMaxWait); + int32_t getHighResLongitude(uint16_t maxWait = defaultMaxWait); + int32_t getHighResLatitude(uint16_t maxWait = defaultMaxWait); + int32_t getElipsoid(uint16_t maxWait = defaultMaxWait); + int32_t getMeanSeaLevel(uint16_t maxWait = defaultMaxWait); + int8_t getHighResLongitudeHp(uint16_t maxWait = defaultMaxWait); + int8_t getHighResLatitudeHp(uint16_t maxWait = defaultMaxWait); + int8_t getElipsoidHp(uint16_t maxWait = defaultMaxWait); + int8_t getMeanSeaLevelHp(uint16_t maxWait = defaultMaxWait); + uint32_t getHorizontalAccuracy(uint16_t maxWait = defaultMaxWait); + uint32_t getVerticalAccuracy(uint16_t maxWait = defaultMaxWait); + + // Helper functions for PVAT + + int32_t getVehicleRoll(uint16_t maxWait = defaultMaxWait); // Returns vehicle roll in degrees * 10^-5 + int32_t getVehiclePitch(uint16_t maxWait = defaultMaxWait); // Returns vehicle pitch in degrees * 10^-5 + int32_t getVehicleHeading(uint16_t maxWait = defaultMaxWait); // Returns vehicle heading in degrees * 10^-5 + int32_t getMotionHeading(uint16_t maxWait = defaultMaxWait); // Returns the motion heading in degrees * 10^-5 + + // Helper functions for SVIN + + bool getSurveyInActive(uint16_t maxWait = defaultMaxWait); + bool getSurveyInValid(uint16_t maxWait = defaultMaxWait); + uint16_t getSurveyInObservationTime(uint16_t maxWait = defaultMaxWait); // Truncated to 65535 seconds + float getSurveyInMeanAccuracy(uint16_t maxWait = defaultMaxWait); // Returned as m + + // Helper functions for TIMELS + + uint8_t getLeapIndicator(int32_t &timeToLsEvent, uint16_t maxWait = defaultMaxWait); + int8_t getCurrentLeapSeconds(sfe_ublox_ls_src_e &source, uint16_t maxWait = defaultMaxWait); + + // Helper functions for RELPOSNED + + float getRelPosN(uint16_t maxWait = defaultMaxWait); // Returned as m + float getRelPosE(uint16_t maxWait = defaultMaxWait); // Returned as m + float getRelPosD(uint16_t maxWait = defaultMaxWait); // Returned as m + float getRelPosAccN(uint16_t maxWait = defaultMaxWait); // Returned as m + float getRelPosAccE(uint16_t maxWait = defaultMaxWait); // Returned as m + float getRelPosAccD(uint16_t maxWait = defaultMaxWait); // Returned as m + + // Helper functions for AOPSTATUS + + uint8_t getAOPSTATUSuseAOP(uint16_t maxWait = defaultMaxWait); // Returns the UBX-NAV-AOPSTATUS useAOP flag. Don't confuse this with getAopCfg - which returns the aopCfg byte from UBX-CFG-NAVX5 + uint8_t getAOPSTATUSstatus(uint16_t maxWait = defaultMaxWait); // Returns the UBX-NAV-AOPSTATUS status field. A host application can determine the optimal time to shut down the receiver by monitoring the status field for a steady 0. + + // Helper functions for ESF + + float getESFroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees + float getESFpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees + float getESFyaw(uint16_t maxWait = defaultMaxWait); // Returned as degrees + bool getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait = defaultMaxWait); + bool getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, UBX_ESF_MEAS_data_t ubxDataStruct, uint8_t sensor); + bool getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait = defaultMaxWait); + bool getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, UBX_ESF_RAW_data_t ubxDataStruct, uint8_t sensor); + bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, uint8_t sensor, uint16_t maxWait = defaultMaxWait); + bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, UBX_ESF_STATUS_data_t ubxDataStruct, uint8_t sensor); + + // Helper functions for HNR + + bool setHNRNavigationRate(uint8_t rate, uint16_t maxWait = defaultMaxWait); // Returns true if the setHNRNavigationRate is successful + uint8_t getHNRNavigationRate(uint16_t maxWait = defaultMaxWait); // Returns 0 if the getHNRNavigationRate fails + float getHNRroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees + float getHNRpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees + float getHNRheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees + + // Set the mainTalkerId used by NMEA messages - allows all NMEA messages except GSV to be prefixed with GP instead of GN + bool setMainTalkerID(sfe_ublox_talker_ids_e id = SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, uint16_t maxWait = defaultMaxWait); + + // Enable/Disable NMEA High Precision Mode - include extra decimal places in the Lat and Lon + bool setHighPrecisionMode(bool enable = true, uint16_t maxWait = defaultMaxWait); + + // Helper functions for NMEA logging + void setNMEALoggingMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Add selected NMEA messages to file buffer - if enabled. Default to adding ALL messages to the file buffer + uint32_t getNMEALoggingMask(); // Return which NMEA messages are selected for logging to the file buffer - if enabled + + // Helper functions to control which NMEA messages are passed to processNMEA + void setProcessNMEAMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Control which NMEA messages are passed to processNMEA. Default to passing ALL messages + uint32_t getProcessNMEAMask(); // Return which NMEA messages are passed to processNMEA + + // Support for "auto" storage of NMEA messages + uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data + bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); // Enable a callback on the arrival of a GPGGA message + bool setNMEAGPGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)); // Enable a callback on the arrival of a GPGGA message + uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data + bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); // Enable a callback on the arrival of a GNGGA message + bool setNMEAGNGGAcallbackPtr(void (*callbackPointerPtr)(NMEA_GGA_data_t *)); // Enable a callback on the arrival of a GNGGA message + + // Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket + // From v2.0: These are public. The user can call these to extract data from custom packets + uint64_t extractLongLong(ubxPacket *msg, uint16_t spotToStart); // Combine eight bytes from payload into uint64_t + uint32_t extractLong(ubxPacket *msg, uint16_t spotToStart); // Combine four bytes from payload into long + int32_t extractSignedLong(ubxPacket *msg, uint16_t spotToStart); // Combine four bytes from payload into signed long (avoiding any ambiguity caused by casting) + uint16_t extractInt(ubxPacket *msg, uint16_t spotToStart); // Combine two bytes from payload into int + int16_t extractSignedInt(ubxPacket *msg, uint16_t spotToStart); + uint8_t extractByte(ubxPacket *msg, uint16_t spotToStart); // Get byte from payload + int8_t extractSignedChar(ubxPacket *msg, uint16_t spotToStart); // Get signed 8-bit value from payload + + // Pointers to storage for the "automatic" messages + // RAM is allocated for these if/when required. + + UBX_NAV_POSECEF_t *packetUBXNAVPOSECEF = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_STATUS_t *packetUBXNAVSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_DOP_t *packetUBXNAVDOP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_ATT_t *packetUBXNAVATT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_PVT_t *packetUBXNAVPVT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_ODO_t *packetUBXNAVODO = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_VELECEF_t *packetUBXNAVVELECEF = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_VELNED_t *packetUBXNAVVELNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_HPPOSECEF_t *packetUBXNAVHPPOSECEF = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_HPPOSLLH_t *packetUBXNAVHPPOSLLH = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_PVAT_t *packetUBXNAVPVAT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_CLOCK_t *packetUBXNAVCLOCK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_TIMELS_t *packetUBXNAVTIMELS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_SVIN_t *packetUBXNAVSVIN = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_SAT_t *packetUBXNAVSAT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_RELPOSNED_t *packetUBXNAVRELPOSNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_AOPSTATUS_t *packetUBXNAVAOPSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + UBX_RXM_PMP_t *packetUBXRXMPMP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + UBX_CFG_PRT_t *packetUBXCFGPRT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_CFG_RATE_t *packetUBXCFGRATE = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + UBX_TIM_TM2_t *packetUBXTIMTM2 = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + UBX_ESF_ALG_t *packetUBXESFALG = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_ESF_INS_t *packetUBXESFINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_ESF_MEAS_t *packetUBXESFMEAS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_ESF_RAW_t *packetUBXESFRAW = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_ESF_STATUS_t *packetUBXESFSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + UBX_HNR_PVT_t *packetUBXHNRPVT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_HNR_ATT_t *packetUBXHNRATT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_HNR_INS_t *packetUBXHNRINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + UBX_MGA_ACK_DATA0_t *packetUBXMGAACK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_MGA_DBD_t *packetUBXMGADBD = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + NMEA_GPGGA_t *storageNMEAGPGGA = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + NMEA_GNGGA_t *storageNMEAGNGGA = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + + uint16_t rtcmFrameCounter = 0; // Tracks the type of incoming byte inside RTCM frame +private: + // Depending on the sentence type the processor will load characters into different arrays + enum SentenceTypes + { + NONE = 0, + NMEA, + UBX, + RTCM + } currentSentence = NONE; + + // Depending on the ubx binary response class, store binary responses into different places + enum classTypes + { + CLASS_NONE = 0, + CLASS_ACK, + CLASS_NOT_AN_ACK + } ubxFrameClass = CLASS_NONE; + + enum commTypes + { + COMM_TYPE_I2C = 0, + COMM_TYPE_SERIAL, + COMM_TYPE_SPI + } commType = COMM_TYPE_I2C; // Controls which port we look to for incoming bytes + + // Functions + bool checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass = 255, uint8_t requestedID = 255); // Checks module with user selected commType + void addToChecksum(uint8_t incoming); // Given an incoming byte, adjust rollingChecksumA/B + size_t pushAssistNowDataInternal(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + size_t findMGAANOForDateInternal(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture); + + // Return true if this "automatic" message has storage allocated for it + bool checkAutomatic(uint8_t Class, uint8_t ID); + + // Calculate how much RAM is needed to store the payload for a given automatic message + uint16_t getMaxPayloadSize(uint8_t Class, uint8_t ID); + + // Do the actual transfer to SPI + void spiTransfer(uint8_t byteToTransfer); + + bool initGeofenceParams(); // Allocate RAM for currentGeofenceParams and initialize it + bool initModuleSWVersion(); // Allocate RAM for moduleSWVersion and initialize it + + // The initPacket functions need to be private as they don't check if memory has already been allocated. + // Functions like setAutoNAVPOSECEF will check that memory has not been allocated before calling initPacket. + bool initPacketUBXNAVPOSECEF(); // Allocate RAM for packetUBXNAVPOSECEF and initialize it + bool initPacketUBXNAVSTATUS(); // Allocate RAM for packetUBXNAVSTATUS and initialize it + bool initPacketUBXNAVDOP(); // Allocate RAM for packetUBXNAVDOP and initialize it + bool initPacketUBXNAVATT(); // Allocate RAM for packetUBXNAVATT and initialize it + bool initPacketUBXNAVPVT(); // Allocate RAM for packetUBXNAVPVT and initialize it + bool initPacketUBXNAVODO(); // Allocate RAM for packetUBXNAVODO and initialize it + bool initPacketUBXNAVVELECEF(); // Allocate RAM for packetUBXNAVVELECEF and initialize it + bool initPacketUBXNAVVELNED(); // Allocate RAM for packetUBXNAVVELNED and initialize it + bool initPacketUBXNAVHPPOSECEF(); // Allocate RAM for packetUBXNAVHPPOSECEF and initialize it + bool initPacketUBXNAVHPPOSLLH(); // Allocate RAM for packetUBXNAVHPPOSLLH and initialize it + bool initPacketUBXNAVPVAT(); // Allocate RAM for packetUBXNAVPVAT and initialize it + bool initPacketUBXNAVCLOCK(); // Allocate RAM for packetUBXNAVCLOCK and initialize it + bool initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it + bool initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it + bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it + bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it + bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it + bool initPacketUBXRXMPMP(); // Allocate RAM for packetUBXRXMPMP and initialize it + bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it + bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it + bool initPacketUBXCFGPRT(); // Allocate RAM for packetUBXCFGPRT and initialize it + bool initPacketUBXCFGRATE(); // Allocate RAM for packetUBXCFGRATE and initialize it + bool initPacketUBXTIMTM2(); // Allocate RAM for packetUBXTIMTM2 and initialize it + bool initPacketUBXESFALG(); // Allocate RAM for packetUBXESFALG and initialize it + bool initPacketUBXESFSTATUS(); // Allocate RAM for packetUBXESFSTATUS and initialize it + bool initPacketUBXESFINS(); // Allocate RAM for packetUBXESFINS and initialize it + bool initPacketUBXESFMEAS(); // Allocate RAM for packetUBXESFMEAS and initialize it + bool initPacketUBXESFRAW(); // Allocate RAM for packetUBXESFRAW and initialize it + bool initPacketUBXHNRATT(); // Allocate RAM for packetUBXHNRATT and initialize it + bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it + bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it + bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it + bool initPacketUBXMGADBD(); // Allocate RAM for packetUBXMGADBD and initialize it + + bool initStorageNMEAGPGGA(); // Allocate RAM for incoming NMEA GPGGA messages and initialize it + bool initStorageNMEAGNGGA(); // Allocate RAM for incoming NMEA GNGGA messages and initialize it + + // Variables + TwoWire *_i2cPort; // The generic connection to user's chosen I2C hardware + Stream *_serialPort; // The generic connection to user's chosen Serial hardware + Stream *_nmeaOutputPort = NULL; // The user can assign an output port to print NMEA sentences if they wish + Stream *_debugSerial; // The stream to send debug messages to if enabled + + SPIClass *_spiPort; // The instance of SPIClass + uint8_t _csPin; // The chip select pin + uint32_t _spiSpeed; // The speed to use for SPI (Hz) + + uint8_t _gpsI2Caddress = 0x42; // Default 7-bit unshifted address of the ublox 6/7/8/M8/F9 series + // This can be changed using the ublox configuration software + + bool _printDebug = false; // Flag to print the serial commands we are sending to the Serial port for debug + bool _printLimitedDebug = false; // Flag to print limited debug messages. Useful for I2C debugging or high navigation rates + + bool ubx7FcheckDisabled = false; // Flag to indicate if the "7F" check should be ignored in checkUbloxI2C + + sfe_ublox_nmea_filtering_t _logNMEA; // Flags to indicate which NMEA messages should be added to the file buffer for logging + sfe_ublox_nmea_filtering_t _processNMEA; // Flags to indicate which NMEA messages should be passed to processNMEA + + // The packet buffers + // These are pointed at from within the ubxPacket + uint8_t payloadAck[2]; // Holds the requested ACK/NACK + uint8_t payloadBuf[2]; // Temporary buffer used to screen incoming packets or dump unrequested packets + size_t packetCfgPayloadSize = 0; // Size for the packetCfg payload. .begin will set this to MAX_PAYLOAD_SIZE if necessary. User can change with setPacketCfgPayloadSize + uint8_t *payloadCfg = NULL; + uint8_t *payloadAuto = NULL; + + uint8_t *spiBuffer = NULL; // A buffer to store any bytes being recieved back from the device while we are sending via SPI + uint8_t spiBufferIndex = 0; // Index into the SPI buffer + uint8_t spiTransactionSize = SFE_UBLOX_SPI_BUFFER_SIZE; // Default size of the SPI buffer + + // Init the packet structures and init them with pointers to the payloadAck, payloadCfg, payloadBuf and payloadAuto arrays + ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; + ubxPacket packetBuf = {0, 0, 0, 0, 0, payloadBuf, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; + ubxPacket packetCfg = {0, 0, 0, 0, 0, payloadCfg, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; + ubxPacket packetAuto = {0, 0, 0, 0, 0, payloadAuto, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED}; + + // Flag if this packet is unrequested (and so should be ignored and not copied into packetCfg or packetAck) + bool ignoreThisPayload = false; + + // Identify which buffer is in use + // Data is stored in packetBuf until the requested class and ID can be validated + // If a match is seen, data is diverted into packetAck or packetCfg + //"Automatic" messages which have RAM allocated for them are diverted into packetAuto + sfe_ublox_packet_buffer_e activePacketBuffer = SFE_UBLOX_PACKET_PACKETBUF; + + // Limit checking of new data to every X ms + // If we are expecting an update every X Hz then we should check every quarter that amount of time + // Otherwise we may block ourselves from seeing new data + uint8_t i2cPollingWait = 100; // Default to 100ms. Adjusted when user calls setNavigationFrequency() or setHNRNavigationRate() or setMeasurementRate() + uint8_t i2cPollingWaitNAV = 100; // We need to record the desired polling rate for standard nav messages + uint8_t i2cPollingWaitHNR = 100; // and for HNR too so we can set i2cPollingWait to the lower of the two + + // The SPI polling wait is a little different. checkUbloxSpi will delay for this amount before returning if + // there is no data waiting to be read. This prevents waitForACKResponse from pounding the SPI bus too hard. + uint8_t spiPollingWait = 9; // Default to 9ms; waitForACKResponse delays for 1ms on top of this. User can adjust with setSPIPollingWait. + + unsigned long lastCheck = 0; + + uint16_t ubxFrameCounter; // Count all UBX frame bytes. [Fixed header(2bytes), CLS(1byte), ID(1byte), length(2bytes), payload(x bytes), checksums(2bytes)] + uint8_t rollingChecksumA; // Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes + uint8_t rollingChecksumB; // Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes + + int8_t nmeaByteCounter; // Count all NMEA message bytes. + // Abort NMEA message reception if nmeaByteCounter exceeds maxNMEAByteCount. + // The user can adjust maxNMEAByteCount by calling setMaxNMEAByteCount + int8_t maxNMEAByteCount = SFE_UBLOX_MAX_NMEA_BYTE_COUNT; + uint8_t nmeaAddressField[6]; // NMEA Address Field - includes the start character (*) + bool logThisNMEA(); // Return true if we should log this NMEA message + bool processThisNMEA(); // Return true if we should pass this NMEA message to processNMEA + bool isNMEAHeaderValid(); // Return true if the six byte NMEA header appears valid. Used to set _signsOfLife + + bool isThisNMEAauto(); // Check if the NMEA message (in nmeaAddressField) is "auto" (i.e. has RAM allocated for it) + bool doesThisNMEAHaveCallback(); // Do we need to copy the data into the callback copy? + uint8_t *getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length + uint8_t *getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t *getNMEACompleteLengthPtr(); // Get a pointer to the complete copy length + uint8_t *getNMEACompleteNMEAPtr(); // Get a pointer to the complete copy NMEA data + uint8_t *getNMEACallbackLengthPtr(); // Get a pointer to the callback copy length + uint8_t *getNMEACallbackNMEAPtr(); // Get a pointer to the callback copy NMEA data + uint8_t getNMEAMaxLength(); // Get the maximum length of this NMEA message + nmeaAutomaticFlags *getNMEAFlagsPtr(); // Get a pointer to the flags + + uint16_t rtcmLen = 0; + + // Flag to prevent reentry into checkCallbacks + // Prevent badness if the user accidentally calls checkCallbacks from inside a callback + volatile bool checkCallbacksReentrant = false; + + // Support for data logging + uint8_t *ubxFileBuffer = NULL; // Pointer to the file buffer. RAM is allocated for this if required in .begin + uint16_t fileBufferSize = 0; // The size of the file buffer. This can be changed by calling setFileBufferSize _before_ .begin + uint16_t fileBufferHead; // The incoming byte is written into the file buffer at this location + uint16_t fileBufferTail; // The next byte to be read from the buffer will be read from this location + uint16_t fileBufferMaxAvail = 0; // The maximum number of bytes the file buffer has contained. Handy for checking the buffer is large enough to handle all the incoming data. + bool createFileBuffer(void); // Create the file buffer. Called by .begin + uint16_t fileBufferSpaceAvailable(void); // Check how much space is available in the buffer + uint16_t fileBufferSpaceUsed(void); // Check how much space is used in the buffer + bool storePacket(ubxPacket *msg); // Add a UBX packet to the file buffer + bool storeFileBytes(uint8_t *theBytes, uint16_t numBytes); // Add theBytes to the file buffer + void writeToFileBuffer(uint8_t *theBytes, uint16_t numBytes); // Write theBytes to the file buffer + + // Support for platforms like ESP32 which do not support multiple I2C restarts + // If _i2cStopRestart is true, endTransmission will always use a stop. If false, a restart will be used where needed. + // The default value for _i2cStopRestart is set in the class instantiation code. + bool _i2cStopRestart; + + // Storage just in case the user tries to push a single byte using pushRawBytes + bool _pushSingleByte = false; + uint8_t _pushThisSingleByte; + + // .begin will return true if the assumeSuccess parameter is true and if _signsOfLife is true + // _signsOfLife is set to true when: a valid UBX message is seen; a valig NMEA header is seen. + bool _signsOfLife; }; #endif diff --git a/src/u-blox_config_keys.h b/src/u-blox_config_keys.h index 9c273de..d8893c2 100644 --- a/src/u-blox_config_keys.h +++ b/src/u-blox_config_keys.h @@ -1,63 +1,63 @@ /* - This is a library written for the u-blox ZED-F9P and NEO-M8P-2 - SparkFun sells these at its website: www.sparkfun.com - Do you like this library? Help support SparkFun. Buy a board! - https://www.sparkfun.com/products/16481 - https://www.sparkfun.com/products/15136 - https://www.sparkfun.com/products/15005 - https://www.sparkfun.com/products/15733 - https://www.sparkfun.com/products/15193 - https://www.sparkfun.com/products/15210 + This is a library written for the u-blox ZED-F9P and NEO-M8P-2 + SparkFun sells these at its website: www.sparkfun.com + Do you like this library? Help support SparkFun. Buy a board! + https://www.sparkfun.com/products/16481 + https://www.sparkfun.com/products/15136 + https://www.sparkfun.com/products/15005 + https://www.sparkfun.com/products/15733 + https://www.sparkfun.com/products/15193 + https://www.sparkfun.com/products/15210 Original version by Nathan Seidle @ SparkFun Electronics, September 6th, 2018 - v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 - - This library handles configuring and handling the responses - from a u-blox GPS module. Works with most modules from u-blox including - the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. - - https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library - - Development environment specifics: - Arduino IDE 1.8.13 - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). - The MIT License (MIT) - Copyright (c) 2016 SparkFun Electronics - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - associated documentation files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the Software is furnished to - do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 + + This library handles configuring and handling the responses + from a u-blox GPS module. Works with most modules from u-blox including + the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. + + https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library + + Development environment specifics: + Arduino IDE 1.8.13 + + SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). + The MIT License (MIT) + Copyright (c) 2016 SparkFun Electronics + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the Software is furnished to + do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __u_blox_config_keys_h__ #define __u_blox_config_keys_h__ -//The following consts are used to generate KEY values for the advanced protocol functions of VELGET/SET/DEL -const uint8_t VAL_SIZE_1 = 0x01; //One bit -const uint8_t VAL_SIZE_8 = 0x02; //One byte -const uint8_t VAL_SIZE_16 = 0x03; //Two bytes -const uint8_t VAL_SIZE_32 = 0x04; //Four bytes -const uint8_t VAL_SIZE_64 = 0x05; //Eight bytes +// The following consts are used to generate KEY values for the advanced protocol functions of VELGET/SET/DEL +const uint8_t VAL_SIZE_1 = 0x01; // One bit +const uint8_t VAL_SIZE_8 = 0x02; // One byte +const uint8_t VAL_SIZE_16 = 0x03; // Two bytes +const uint8_t VAL_SIZE_32 = 0x04; // Four bytes +const uint8_t VAL_SIZE_64 = 0x05; // Eight bytes -//These are the Bitfield layers definitions for the UBX-CFG-VALSET message (not to be confused with Bitfield deviceMask in UBX-CFG-CFG) +// These are the Bitfield layers definitions for the UBX-CFG-VALSET message (not to be confused with Bitfield deviceMask in UBX-CFG-CFG) const uint8_t VAL_LAYER_RAM = (1 << 0); const uint8_t VAL_LAYER_BBR = (1 << 1); const uint8_t VAL_LAYER_FLASH = (1 << 2); -const uint8_t VAL_LAYER_ALL = VAL_LAYER_RAM | VAL_LAYER_BBR | VAL_LAYER_FLASH; //Not valid with getVal() +const uint8_t VAL_LAYER_ALL = VAL_LAYER_RAM | VAL_LAYER_BBR | VAL_LAYER_FLASH; // Not valid with getVal() -//Below are various Groups, IDs, and sizes for various settings -//These can be used to call getVal/setVal/delVal +// Below are various Groups, IDs, and sizes for various settings +// These can be used to call getVal/setVal/delVal //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint8_t VAL_ID_PROT_UBX = 0x01; const uint8_t VAL_ID_PROT_NMEA = 0x02; @@ -72,1139 +72,1138 @@ const uint8_t VAL_GROUP_UART2OUTPROT = 0x76; const uint8_t VAL_GROUP_USBINPROT = 0x77; const uint8_t VAL_GROUP_USBOUTPROT = 0x78; -const uint8_t VAL_GROUP_UART_SIZE = VAL_SIZE_1; //All fields in UART group are currently 1 bit -const uint8_t VAL_GROUP_I2C_SIZE = VAL_SIZE_8; //All fields in I2C group are currently 1 byte +const uint8_t VAL_GROUP_UART_SIZE = VAL_SIZE_1; // All fields in UART group are currently 1 bit +const uint8_t VAL_GROUP_I2C_SIZE = VAL_SIZE_8; // All fields in I2C group are currently 1 byte const uint8_t VAL_ID_I2C_ADDRESS = 0x01; -//Below are the key values for a given configuration setting +// Below are the key values for a given configuration setting -//CFG-BDS: BeiDou system configuration +// CFG-BDS: BeiDou system configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_BDS_USE_PRN_1_TO_5 = 0x10340014; // Use BeiDou geostationary satellites (PRN 1-5) -//CFG-GEOFENCE: Geofencing configuration +// CFG-GEOFENCE: Geofencing configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_GEOFENCE_CONFLVL = 0x20240011; // Required confidence level for state evaluation -const uint32_t UBLOX_CFG_GEOFENCE_USE_PIO = 0x10240012; // Use PIO combined fence state output -const uint32_t UBLOX_CFG_GEOFENCE_PINPOL = 0x20240013; // PIO pin polarity -const uint32_t UBLOX_CFG_GEOFENCE_PIN = 0x20240014; // PIO pin number -const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE1 = 0x10240020; // Use frst geofence -const uint32_t UBLOX_CFG_GEOFENCE_FENCE1_LAT = 0x40240021; // Latitude of the first geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE1_LON = 0x40240022; // Longitude of the first geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE1_RAD = 0x40240023; // Radius of the first geofence circle -const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE2 = 0x10240030; // Use second geofence -const uint32_t UBLOX_CFG_GEOFENCE_FENCE2_LAT = 0x40240031; // Latitude of the second geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE2_LON = 0x40240032; // Longitude of the second geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE2_RAD = 0x40240033; // Radius of the second geofence circle -const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE3 = 0x10240040; // Use third geofence -const uint32_t UBLOX_CFG_GEOFENCE_FENCE3_LAT = 0x40240041; // Latitude of the third geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE3_LON = 0x40240042; // Longitude of the third geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE3_RAD = 0x40240043; // Radius of the third geofence circle -const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE4 = 0x10240050; // Use fourth geofence -const uint32_t UBLOX_CFG_GEOFENCE_FENCE4_LAT = 0x40240051; // Latitude of the fourth geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE4_LON = 0x40240052; // Longitude of the fourth geofence circle center -const uint32_t UBLOX_CFG_GEOFENCE_FENCE4_RAD = 0x40240053; // Radius of the fourth geofence circle - -//CFG-HW: Hardware configuration +const uint32_t UBLOX_CFG_GEOFENCE_CONFLVL = 0x20240011; // Required confidence level for state evaluation +const uint32_t UBLOX_CFG_GEOFENCE_USE_PIO = 0x10240012; // Use PIO combined fence state output +const uint32_t UBLOX_CFG_GEOFENCE_PINPOL = 0x20240013; // PIO pin polarity +const uint32_t UBLOX_CFG_GEOFENCE_PIN = 0x20240014; // PIO pin number +const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE1 = 0x10240020; // Use frst geofence +const uint32_t UBLOX_CFG_GEOFENCE_FENCE1_LAT = 0x40240021; // Latitude of the first geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE1_LON = 0x40240022; // Longitude of the first geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE1_RAD = 0x40240023; // Radius of the first geofence circle +const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE2 = 0x10240030; // Use second geofence +const uint32_t UBLOX_CFG_GEOFENCE_FENCE2_LAT = 0x40240031; // Latitude of the second geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE2_LON = 0x40240032; // Longitude of the second geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE2_RAD = 0x40240033; // Radius of the second geofence circle +const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE3 = 0x10240040; // Use third geofence +const uint32_t UBLOX_CFG_GEOFENCE_FENCE3_LAT = 0x40240041; // Latitude of the third geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE3_LON = 0x40240042; // Longitude of the third geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE3_RAD = 0x40240043; // Radius of the third geofence circle +const uint32_t UBLOX_CFG_GEOFENCE_USE_FENCE4 = 0x10240050; // Use fourth geofence +const uint32_t UBLOX_CFG_GEOFENCE_FENCE4_LAT = 0x40240051; // Latitude of the fourth geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE4_LON = 0x40240052; // Longitude of the fourth geofence circle center +const uint32_t UBLOX_CFG_GEOFENCE_FENCE4_RAD = 0x40240053; // Radius of the fourth geofence circle + +// CFG-HW: Hardware configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_HW_ANT_CFG_VOLTCTRL = 0x10a3002e; // Active antenna voltage control flag -const uint32_t UBLOX_CFG_HW_ANT_CFG_SHORTDET = 0x10a3002f; // Short antenna detection flag -const uint32_t UBLOX_CFG_HW_ANT_CFG_SHORTDET_POL = 0x10a30030; // Short antenna detection polarity -const uint32_t UBLOX_CFG_HW_ANT_CFG_OPENDET = 0x10a30031; // Open antenna detection flag -const uint32_t UBLOX_CFG_HW_ANT_CFG_OPENDET_POL = 0x10a30032; // Open antenna detection polarity -const uint32_t UBLOX_CFG_HW_ANT_CFG_PWRDOWN = 0x10a30033; // Power down antenna flag -const uint32_t UBLOX_CFG_HW_ANT_CFG_PWRDOWN_POL = 0x10a30034; // Power down antenna logic polarity -const uint32_t UBLOX_CFG_HW_ANT_CFG_RECOVER = 0x10a30035; // Automatic recovery from short state flag -const uint32_t UBLOX_CFG_HW_ANT_SUP_SWITCH_PIN = 0x20a30036; // ANT1 PIO number -const uint32_t UBLOX_CFG_HW_ANT_SUP_SHORT_PIN = 0x20a30037; // ANT0 PIO number -const uint32_t UBLOX_CFG_HW_ANT_SUP_OPEN_PIN = 0x20a30038; // ANT2 PIO number -const uint32_t UBLOX_CFG_HW_ANT_SUP_ENGINE = 0x20a30054; // Antenna supervisor engine selection -const uint32_t UBLOX_CFG_HW_ANT_SUP_SHORT_THR = 0x20a30055; // Antenna supervisor MADC engine short detection threshold -const uint32_t UBLOX_CFG_HW_ANT_SUP_OPEN_THR = 0x20a30056; // Antenna supervisor MADC engine open detection threshold - -//CFG-I2C: Configuration of the I2C interface +const uint32_t UBLOX_CFG_HW_ANT_CFG_VOLTCTRL = 0x10a3002e; // Active antenna voltage control flag +const uint32_t UBLOX_CFG_HW_ANT_CFG_SHORTDET = 0x10a3002f; // Short antenna detection flag +const uint32_t UBLOX_CFG_HW_ANT_CFG_SHORTDET_POL = 0x10a30030; // Short antenna detection polarity +const uint32_t UBLOX_CFG_HW_ANT_CFG_OPENDET = 0x10a30031; // Open antenna detection flag +const uint32_t UBLOX_CFG_HW_ANT_CFG_OPENDET_POL = 0x10a30032; // Open antenna detection polarity +const uint32_t UBLOX_CFG_HW_ANT_CFG_PWRDOWN = 0x10a30033; // Power down antenna flag +const uint32_t UBLOX_CFG_HW_ANT_CFG_PWRDOWN_POL = 0x10a30034; // Power down antenna logic polarity +const uint32_t UBLOX_CFG_HW_ANT_CFG_RECOVER = 0x10a30035; // Automatic recovery from short state flag +const uint32_t UBLOX_CFG_HW_ANT_SUP_SWITCH_PIN = 0x20a30036; // ANT1 PIO number +const uint32_t UBLOX_CFG_HW_ANT_SUP_SHORT_PIN = 0x20a30037; // ANT0 PIO number +const uint32_t UBLOX_CFG_HW_ANT_SUP_OPEN_PIN = 0x20a30038; // ANT2 PIO number +const uint32_t UBLOX_CFG_HW_ANT_SUP_ENGINE = 0x20a30054; // Antenna supervisor engine selection +const uint32_t UBLOX_CFG_HW_ANT_SUP_SHORT_THR = 0x20a30055; // Antenna supervisor MADC engine short detection threshold +const uint32_t UBLOX_CFG_HW_ANT_SUP_OPEN_THR = 0x20a30056; // Antenna supervisor MADC engine open detection threshold + +// CFG-I2C: Configuration of the I2C interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_I2C_ADDRESS = 0x20510001; // I2C slave address of the receiver (7 bits) -const uint32_t UBLOX_CFG_I2C_EXTENDEDTIMEOUT = 0x10510002; // Flag to disable timeouting the interface after 1.5 s -const uint32_t UBLOX_CFG_I2C_ENABLED = 0x10510003; // Flag to indicate if the I2C interface should be enabled +const uint32_t UBLOX_CFG_I2C_ADDRESS = 0x20510001; // I2C slave address of the receiver (7 bits) +const uint32_t UBLOX_CFG_I2C_EXTENDEDTIMEOUT = 0x10510002; // Flag to disable timeouting the interface after 1.5 s +const uint32_t UBLOX_CFG_I2C_ENABLED = 0x10510003; // Flag to indicate if the I2C interface should be enabled -//CFG-I2CINPROT: Input protocol configuration of the I2C interface +// CFG-I2CINPROT: Input protocol configuration of the I2C interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_I2CINPROT_UBX = 0x10710001; // Flag to indicate if UBX should be an input protocol on I2C -const uint32_t UBLOX_CFG_I2CINPROT_NMEA = 0x10710002; // Flag to indicate if NMEA should be an input protocol on I2C -const uint32_t UBLOX_CFG_I2CINPROT_RTCM3X = 0x10710004; // Flag to indicate if RTCM3X should be an input protocol on I2C -const uint32_t UBLOX_CFG_I2CINPROT_SPARTN = 0x10710005; // Flag to indicate if SPARTN should be an input protocol on I2C +const uint32_t UBLOX_CFG_I2CINPROT_UBX = 0x10710001; // Flag to indicate if UBX should be an input protocol on I2C +const uint32_t UBLOX_CFG_I2CINPROT_NMEA = 0x10710002; // Flag to indicate if NMEA should be an input protocol on I2C +const uint32_t UBLOX_CFG_I2CINPROT_RTCM3X = 0x10710004; // Flag to indicate if RTCM3X should be an input protocol on I2C +const uint32_t UBLOX_CFG_I2CINPROT_SPARTN = 0x10710005; // Flag to indicate if SPARTN should be an input protocol on I2C -//CFG-I2COUTPROT: Output protocol configuration of the I2C interface +// CFG-I2COUTPROT: Output protocol configuration of the I2C interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_I2COUTPROT_UBX = 0x10720001; // Flag to indicate if UBX should be an output protocol on I2C -const uint32_t UBLOX_CFG_I2COUTPROT_NMEA = 0x10720002; // Flag to indicate if NMEA should be an output protocol on I2C -const uint32_t UBLOX_CFG_I2COUTPROT_RTCM3X = 0x10720004; // Flag to indicate if RTCM3X should be an output protocol on I2C +const uint32_t UBLOX_CFG_I2COUTPROT_UBX = 0x10720001; // Flag to indicate if UBX should be an output protocol on I2C +const uint32_t UBLOX_CFG_I2COUTPROT_NMEA = 0x10720002; // Flag to indicate if NMEA should be an output protocol on I2C +const uint32_t UBLOX_CFG_I2COUTPROT_RTCM3X = 0x10720004; // Flag to indicate if RTCM3X should be an output protocol on I2C -//CFG-INFMSG: Information message configuration +// CFG-INFMSG: Information message configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_INFMSG_UBX_I2C = 0x20920001; // Information message enable flags for the UBX protocol on the I2C interface -const uint32_t UBLOX_CFG_INFMSG_UBX_UART1 = 0x20920002; // Information message enable flags for the UBX protocol on the UART1 interface -const uint32_t UBLOX_CFG_INFMSG_UBX_UART2 = 0x20920003; // Information message enable flags for the UBX protocol on the UART2 interface -const uint32_t UBLOX_CFG_INFMSG_UBX_USB = 0x20920004; // Information message enable flags for the UBX protocol on the USB interface -const uint32_t UBLOX_CFG_INFMSG_UBX_SPI = 0x20920005; // Information message enable flags for the UBX protocol on the SPI interface -const uint32_t UBLOX_CFG_INFMSG_NMEA_I2C = 0x20920006; // Information message enable flags for the NMEA protocol on the I2C interface -const uint32_t UBLOX_CFG_INFMSG_NMEA_UART1 = 0x20920007; // Information message enable flags for the NMEA protocol on the UART1 interface -const uint32_t UBLOX_CFG_INFMSG_NMEA_UART2 = 0x20920008; // Information message enable flags for the NMEA protocol on the UART2 interface -const uint32_t UBLOX_CFG_INFMSG_NMEA_USB = 0x20920009; // Information message enable flags for the NMEA protocol on the USB interface -const uint32_t UBLOX_CFG_INFMSG_NMEA_SPI = 0x2092000a; // Information message enable flags for the NMEA protocol on the SPI interface - -//CFG-ITFM: Jamming and interference monitor configuration +const uint32_t UBLOX_CFG_INFMSG_UBX_I2C = 0x20920001; // Information message enable flags for the UBX protocol on the I2C interface +const uint32_t UBLOX_CFG_INFMSG_UBX_UART1 = 0x20920002; // Information message enable flags for the UBX protocol on the UART1 interface +const uint32_t UBLOX_CFG_INFMSG_UBX_UART2 = 0x20920003; // Information message enable flags for the UBX protocol on the UART2 interface +const uint32_t UBLOX_CFG_INFMSG_UBX_USB = 0x20920004; // Information message enable flags for the UBX protocol on the USB interface +const uint32_t UBLOX_CFG_INFMSG_UBX_SPI = 0x20920005; // Information message enable flags for the UBX protocol on the SPI interface +const uint32_t UBLOX_CFG_INFMSG_NMEA_I2C = 0x20920006; // Information message enable flags for the NMEA protocol on the I2C interface +const uint32_t UBLOX_CFG_INFMSG_NMEA_UART1 = 0x20920007; // Information message enable flags for the NMEA protocol on the UART1 interface +const uint32_t UBLOX_CFG_INFMSG_NMEA_UART2 = 0x20920008; // Information message enable flags for the NMEA protocol on the UART2 interface +const uint32_t UBLOX_CFG_INFMSG_NMEA_USB = 0x20920009; // Information message enable flags for the NMEA protocol on the USB interface +const uint32_t UBLOX_CFG_INFMSG_NMEA_SPI = 0x2092000a; // Information message enable flags for the NMEA protocol on the SPI interface + +// CFG-ITFM: Jamming and interference monitor configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_ITFM_BBTHRESHOLD = 0x20410001; // Broadband jamming detection threshold -const uint32_t UBLOX_CFG_ITFM_CWTHRESHOLD = 0x20410002; // CW jamming detection threshold -const uint32_t UBLOX_CFG_ITFM_ENABLE = 0x1041000d; // Enable interference detection -const uint32_t UBLOX_CFG_ITFM_ANTSETTING = 0x20410010; // Antenna setting -const uint32_t UBLOX_CFG_ITFM_ENABLE_AUX = 0x10410013; // Scan auxiliary bands +const uint32_t UBLOX_CFG_ITFM_BBTHRESHOLD = 0x20410001; // Broadband jamming detection threshold +const uint32_t UBLOX_CFG_ITFM_CWTHRESHOLD = 0x20410002; // CW jamming detection threshold +const uint32_t UBLOX_CFG_ITFM_ENABLE = 0x1041000d; // Enable interference detection +const uint32_t UBLOX_CFG_ITFM_ANTSETTING = 0x20410010; // Antenna setting +const uint32_t UBLOX_CFG_ITFM_ENABLE_AUX = 0x10410013; // Scan auxiliary bands -//CFG-LOGFILTER: Data logger configuration +// CFG-LOGFILTER: Data logger configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_LOGFILTER_RECORD_ENA = 0x10de0002; // Recording enabled -const uint32_t UBLOX_CFG_LOGFILTER_ONCE_PER_WAKE_UP_ENA = 0x10de0003; // Once per wake up -const uint32_t UBLOX_CFG_LOGFILTER_APPLY_ALL_FILTERS = 0x10de0004; // Apply all filter settings -const uint32_t UBLOX_CFG_LOGFILTER_MIN_INTERVAL = 0x30de0005; // Minimum time interval between loggedpositions -const uint32_t UBLOX_CFG_LOGFILTER_TIME_THRS = 0x30de0006; // Time threshold -const uint32_t UBLOX_CFG_LOGFILTER_SPEED_THRS = 0x30de0007; // Speed threshold -const uint32_t UBLOX_CFG_LOGFILTER_POSITION_THRS = 0x40de0008; // Position threshold - -//CFG-MOT: Motion detector configuration +const uint32_t UBLOX_CFG_LOGFILTER_RECORD_ENA = 0x10de0002; // Recording enabled +const uint32_t UBLOX_CFG_LOGFILTER_ONCE_PER_WAKE_UP_ENA = 0x10de0003; // Once per wake up +const uint32_t UBLOX_CFG_LOGFILTER_APPLY_ALL_FILTERS = 0x10de0004; // Apply all filter settings +const uint32_t UBLOX_CFG_LOGFILTER_MIN_INTERVAL = 0x30de0005; // Minimum time interval between loggedpositions +const uint32_t UBLOX_CFG_LOGFILTER_TIME_THRS = 0x30de0006; // Time threshold +const uint32_t UBLOX_CFG_LOGFILTER_SPEED_THRS = 0x30de0007; // Speed threshold +const uint32_t UBLOX_CFG_LOGFILTER_POSITION_THRS = 0x40de0008; // Position threshold + +// CFG-MOT: Motion detector configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_MOT_GNSSSPEED_THRS = 0x20250038; // GNSS speed threshold below which platform is considered as stationary (a.k.a. static hold threshold) -const uint32_t UBLOX_CFG_MOT_GNSSDIST_THRS = 0x3025003b; // Distance above which GNSS-based stationary motion is exit (a.k.a. static hold distance threshold) +const uint32_t UBLOX_CFG_MOT_GNSSSPEED_THRS = 0x20250038; // GNSS speed threshold below which platform is considered as stationary (a.k.a. static hold threshold) +const uint32_t UBLOX_CFG_MOT_GNSSDIST_THRS = 0x3025003b; // Distance above which GNSS-based stationary motion is exit (a.k.a. static hold distance threshold) // CFG-MSGOUT: Message output configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // For each message and port a separate output rate (per second, per epoch) can be configured. -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_I2C = 0x209100a6; //Output rate of the NMEA-GX-DTM message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_SPI = 0x209100aa; //Output rate of the NMEA-GX-DTM message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_UART1 = 0x209100a7; //Output rate of the NMEA-GX-DTM message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_UART2 = 0x209100a8; //Output rate of the NMEA-GX-DTM message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_USB = 0x209100a9; //Output rate of the NMEA-GX-DTM message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_I2C = 0x209100dd; //Output rate of the NMEA-GX-GBS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_SPI = 0x209100e1; //Output rate of the NMEA-GX-GBS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_UART1 = 0x209100de; //Output rate of the NMEA-GX-GBS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_UART2 = 0x209100df; //Output rate of the NMEA-GX-GBS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_USB = 0x209100e0; //Output rate of the NMEA-GX-GBS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_I2C = 0x209100ba; //Output rate of the NMEA-GX-GGA message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_SPI = 0x209100be; //Output rate of the NMEA-GX-GGA message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_UART1 = 0x209100bb; //Output rate of the NMEA-GX-GGA message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_UART2 = 0x209100bc; //Output rate of the NMEA-GX-GGA message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_USB = 0x209100bd; //Output rate of the NMEA-GX-GGA message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_I2C = 0x209100c9; //Output rate of the NMEA-GX-GLL message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_SPI = 0x209100cd; //Output rate of the NMEA-GX-GLL message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_UART1 = 0x209100ca; //Output rate of the NMEA-GX-GLL message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_UART2 = 0x209100cb; //Output rate of the NMEA-GX-GLL message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_USB = 0x209100cc; //Output rate of the NMEA-GX-GLL message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_I2C = 0x209100b5; //Output rate of the NMEA-GX-GNS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_SPI = 0x209100b9; //Output rate of the NMEA-GX-GNS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_UART1 = 0x209100b6; //Output rate of the NMEA-GX-GNS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_UART2 = 0x209100b7; //Output rate of the NMEA-GX-GNS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_USB = 0x209100b8; //Output rate of the NMEA-GX-GNS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_I2C = 0x209100ce; //Output rate of the NMEA-GX-GRS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_SPI = 0x209100d2; //Output rate of the NMEA-GX-GRS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_UART1 = 0x209100cf; //Output rate of the NMEA-GX-GRS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_UART2 = 0x209100d0; //Output rate of the NMEA-GX-GRS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_USB = 0x209100d1; //Output rate of the NMEA-GX-GRS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_I2C = 0x209100bf; //Output rate of the NMEA-GX-GSA message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_SPI = 0x209100c3; //Output rate of the NMEA-GX-GSA message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_UART1 = 0x209100c0; //Output rate of the NMEA-GX-GSA message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_UART2 = 0x209100c1; //Output rate of the NMEA-GX-GSA message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_USB = 0x209100c2; //Output rate of the NMEA-GX-GSA message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_I2C = 0x209100d3; //Output rate of the NMEA-GX-GST message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_SPI = 0x209100d7; //Output rate of the NMEA-GX-GST message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_UART1 = 0x209100d4; //Output rate of the NMEA-GX-GST message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_UART2 = 0x209100d5; //Output rate of the NMEA-GX-GST message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_USB = 0x209100d6; //Output rate of the NMEA-GX-GST message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_I2C = 0x209100c4; //Output rate of the NMEA-GX-GSV message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_SPI = 0x209100c8; //Output rate of the NMEA-GX-GSV message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_UART1 = 0x209100c5; //Output rate of the NMEA-GX-GSV message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_UART2 = 0x209100c6; //Output rate of the NMEA-GX-GSV message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_USB = 0x209100c7; //Output rate of the NMEA-GX-GSV message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_I2C = 0x20910400; //Output rate of the NMEA-GX-RLM message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_SPI = 0x20910404; //Output rate of the NMEA-GX-RLM message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_UART1 = 0x20910401; //Output rate of the NMEA-GX-RLM message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_UART2 = 0x20910402; //Output rate of the NMEA-GX-RLM message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_USB = 0x20910403; //Output rate of the NMEA-GX-RLM message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_I2C = 0x209100ab; //Output rate of the NMEA-GX-RMC message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_SPI = 0x209100af; //Output rate of the NMEA-GX-RMC message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_UART1 = 0x209100ac; //Output rate of the NMEA-GX-RMC message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_UART2 = 0x209100ad; //Output rate of the NMEA-GX-RMC message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_USB = 0x209100ae; //Output rate of the NMEA-GX-RMC message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_I2C = 0x209100e7; //Output rate of the NMEA-GX-VLW message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_SPI = 0x209100eb; //Output rate of the NMEA-GX-VLW message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_UART1 = 0x209100e8; //Output rate of the NMEA-GX-VLW message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_UART2 = 0x209100e9; //Output rate of the NMEA-GX-VLW message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_USB = 0x209100ea; //Output rate of the NMEA-GX-VLW message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_I2C = 0x209100b0; //Output rate of the NMEA-GX-VTG message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_SPI = 0x209100b4; //Output rate of the NMEA-GX-VTG message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_UART1 = 0x209100b1; //Output rate of the NMEA-GX-VTG message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_UART2 = 0x209100b2; //Output rate of the NMEA-GX-VTG message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_USB = 0x209100b3; //Output rate of the NMEA-GX-VTG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_I2C = 0x209100d8; //Output rate of the NMEA-GX-ZDA message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_SPI = 0x209100dc; //Output rate of the NMEA-GX-ZDA message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_UART1 = 0x209100d9; //Output rate of the NMEA-GX-ZDA message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_UART2 = 0x209100da; //Output rate of the NMEA-GX-ZDA message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_USB = 0x209100db; //Output rate of the NMEA-GX-ZDA message on port USB -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_I2C = 0x209100ec; //Output rate of the NMEA-GX-PUBX00 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_SPI = 0x209100f0; //Output rate of the NMEA-GX-PUBX00 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_UART1 = 0x209100ed; //Output rate of the NMEA-GX-PUBX00 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_UART2 = 0x209100ee; //Output rate of the NMEA-GX-PUBX00 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_USB = 0x209100ef; //Output rate of the NMEA-GX-PUBX00 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_I2C = 0x209100f1; //Output rate of the NMEA-GX-PUBX03 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_SPI = 0x209100f5; //Output rate of the NMEA-GX-PUBX03 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_UART1 = 0x209100f2; //Output rate of the NMEA-GX-PUBX03 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_UART2 = 0x209100f3; //Output rate of the NMEA-GX-PUBX03 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_USB = 0x209100f4; //Output rate of the NMEA-GX-PUBX03 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_I2C = 0x209100f6; //Output rate of the NMEA-GX-PUBX04 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_SPI = 0x209100fa; //Output rate of the NMEA-GX-PUBX04 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_UART1 = 0x209100f7; //Output rate of the NMEA-GX-PUBX04 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_UART2 = 0x209100f8; //Output rate of the NMEA-GX-PUBX04 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_USB = 0x209100f9; //Output rate of the NMEA-GX-PUBX04 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_I2C = 0x209102bd; //Output rate of the RTCM-3X-TYPE1005 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_SPI = 0x209102c1; //Output rate of the RTCM-3X-TYPE1005 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_UART1 = 0x209102be;//Output rate of the RTCM-3X-TYPE1005 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_UART2 = 0x209102bf;//Output rate of the RTCM-3X-TYPE1005 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_USB = 0x209102c0; //Output rate of the RTCM-3X-TYPE1005 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_I2C = 0x2091035e; //Output rate of the RTCM-3X-TYPE1074 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_SPI = 0x20910362; //Output rate of the RTCM-3X-TYPE1074 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_UART1 = 0x2091035f;//Output rate of the RTCM-3X-TYPE1074 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_UART2 = 0x20910360;//Output rate of the RTCM-3X-TYPE1074 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_USB = 0x20910361; //Output rate of the RTCM-3X-TYPE1074 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_I2C = 0x209102cc; //Output rate of the RTCM-3X-TYPE1077 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_SPI = 0x209102d0; //Output rate of the RTCM-3X-TYPE1077 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_UART1 = 0x209102cd;//Output rate of the RTCM-3X-TYPE1077 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_UART2 = 0x209102ce;//Output rate of the RTCM-3X-TYPE1077 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_USB = 0x209102cf; //Output rate of the RTCM-3X-TYPE1077 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_I2C = 0x20910363; //Output rate of the RTCM-3X-TYPE1084 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_SPI = 0x20910367; //Output rate of the RTCM-3X-TYPE1084 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_UART1 = 0x20910364;//Output rate of the RTCM-3X-TYPE1084 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_UART2 = 0x20910365;//Output rate of the RTCM-3X-TYPE1084 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_USB = 0x20910366; //Output rate of the RTCM-3X-TYPE1084 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_I2C = 0x209102d1; //Output rate of the RTCM-3X-TYPE1087 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_SPI = 0x209102d5; //Output rate of the RTCM-3X-TYPE1087 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_UART1 = 0x209102d2;//Output rate of the RTCM-3X-TYPE1087 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_UART2 = 0x209102d3;//Output rate of the RTCM-3X-TYPE1087 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_USB = 0x209102d4; //Output rate of the RTCM-3X-TYPE1087 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_I2C = 0x20910368; //Output rate of the RTCM-3X-TYPE1094 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_SPI = 0x2091036c; //Output rate of the RTCM-3X-TYPE1094 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_UART1 = 0x20910369;//Output rate of the RTCM-3X-TYPE1094 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_UART2 = 0x2091036a;//Output rate of the RTCM-3X-TYPE1094 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_USB = 0x2091036b; //Output rate of the RTCM-3X-TYPE1094 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_I2C = 0x20910318; //Output rate of the RTCM-3X-TYPE1097 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_SPI = 0x2091031c; //Output rate of the RTCM-3X-TYPE1097 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_UART1 = 0x20910319;//Output rate of the RTCM-3X-TYPE1097 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_UART2 = 0x2091031a;//Output rate of the RTCM-3X-TYPE1097 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_USB = 0x2091031b; //Output rate of the RTCM-3X-TYPE1097 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_I2C = 0x2091036d; //Output rate of the RTCM-3X-TYPE1124 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_SPI = 0x20910371; //Output rate of the RTCM-3X-TYPE1124 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_UART1 = 0x2091036e;//Output rate of the RTCM-3X-TYPE1124 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_UART2 = 0x2091036f;//Output rate of the RTCM-3X-TYPE1124 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_USB = 0x20910370; //Output rate of the RTCM-3X-TYPE1124 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_I2C = 0x209102d6; //Output rate of the RTCM-3X-TYPE1127 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_SPI = 0x209102da; //Output rate of the RTCM-3X-TYPE1127 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_UART1 = 0x209102d7;//Output rate of the RTCM-3X-TYPE1127 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_UART2 = 0x209102d8;//Output rate of the RTCM-3X-TYPE1127 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_USB = 0x209102d9; //Output rate of the RTCM-3X-TYPE1127 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_I2C = 0x20910303; //Output rate of the RTCM-3X-TYPE1230 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_SPI = 0x20910307; //Output rate of the RTCM-3X-TYPE1230 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_UART1 = 0x20910304;//Output rate of the RTCM-3X-TYPE1230 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_UART2 = 0x20910305;//Output rate of the RTCM-3X-TYPE1230 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_USB = 0x20910306; //Output rate of the RTCM-3X-TYPE1230 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_I2C = 0x209102fe;//Output rate of the RTCM-3X-TYPE4072_0 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_SPI = 0x20910302;//Output rate of the RTCM-3X-TYPE4072_0 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_UART1 = 0x209102ff; //Output rate of the RTCM-3X-TYPE4072_0 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_UART2 = 0x20910300; //Output rate of the RTCM-3X-TYPE4072_0 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_USB = 0x20910301;//Output rate of the RTCM-3X-TYPE4072_0 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_I2C = 0x20910381;//Output rate of the RTCM-3X-TYPE4072_1 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_SPI = 0x20910385;//Output rate of the RTCM-3X-TYPE4072_1 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_UART1 = 0x20910382; //Output rate of the RTCM-3X-TYPE4072_1 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_UART2 = 0x20910383; //Output rate of the RTCM-3X-TYPE4072_1 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_USB = 0x20910384;//Output rate of the RTCM-3X-TYPE4072_1 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_I2C = 0x20910259; //Output rate of the UBX-LOG-INFO message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_SPI = 0x2091025d; //Output rate of the UBX-LOG-INFO message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_UART1 = 0x2091025a; //Output rate of the UBX-LOG-INFO message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_UART2 = 0x2091025b; //Output rate of the UBX-LOG-INFO message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_USB = 0x2091025c; //Output rate of the UBX-LOG-INFO message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_I2C = 0x2091034f; //Output rate of the UBX-MON-COMMS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_SPI = 0x20910353; //Output rate of the UBX-MON-COMMS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_UART1 = 0x20910350; //Output rate of the UBX-MON-COMMS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_UART2 = 0x20910351; //Output rate of the UBX-MON-COMMS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_USB = 0x20910352; //Output rate of the UBX-MON-COMMS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_I2C = 0x209101b9; //Output rate of the UBX-MON-HW2 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_SPI = 0x209101bd; //Output rate of the UBX-MON-HW2 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_UART1 = 0x209101ba; //Output rate of the UBX-MON-HW2 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_UART2 = 0x209101bb; //Output rate of the UBX-MON-HW2 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_USB = 0x209101bc; //Output rate of the UBX-MON-HW2 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_I2C = 0x20910354; //Output rate of the UBX-MON-HW3 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_SPI = 0x20910358; //Output rate of the UBX-MON-HW3 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_UART1 = 0x20910355; //Output rate of the UBX-MON-HW3 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_UART2 = 0x20910356; //Output rate of the UBX-MON-HW3 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_USB = 0x20910357; //Output rate of the UBX-MON-HW3 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_I2C = 0x209101b4; //Output rate of the UBX-MON-HW message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_SPI = 0x209101b8; //Output rate of the UBX-MON-HW message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_UART1 = 0x209101b5; //Output rate of the UBX-MON-HW message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_UART2 = 0x209101b6; //Output rate of the UBX-MON-HW message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_USB = 0x209101b7; //Output rate of the UBX-MON-HW message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_I2C = 0x209101a5; //Output rate of the UBX-MON-IO message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_SPI = 0x209101a9; //Output rate of the UBX-MON-IO message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_UART1 = 0x209101a6; //Output rate of the UBX-MON-IO message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_UART2 = 0x209101a7; //Output rate of the UBX-MON-IO message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_USB = 0x209101a8; //Output rate of the UBX-MON-IO message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_I2C = 0x20910196; //Output rate of the UBX-MON-MSGPP message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_SPI = 0x2091019a; //Output rate of the UBX-MON-MSGPP message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_UART1 = 0x20910197; //Output rate of the UBX-MON-MSGPP message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_UART2 = 0x20910198; //Output rate of the UBX-MON-MSGPP message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_USB = 0x20910199; //Output rate of the UBX-MON-MSGPP message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_I2C = 0x20910359; //Output rate of the UBX-MON-RF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_SPI = 0x2091035d; //Output rate of the UBX-MON-RF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_UART1 = 0x2091035a; //Output rate of the UBX-MON-RF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_UART2 = 0x2091035b; //Output rate of the UBX-MON-RF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_USB = 0x2091035c; // Output rate of the UBX-MON-RF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_I2C = 0x209101a0; // Output rate of the UBX-MON-RXBUF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_SPI = 0x209101a4; // Output rate of the UBX-MON-RXBUF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_UART1 = 0x209101a1; // Output rate of the UBX-MON-RXBUF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_UART2 = 0x209101a2; // Output rate of the UBX-MON-RXBUF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_USB = 0x209101a3; // Output rate of the UBX-MON-RXBUF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_I2C = 0x20910187; // Output rate of the UBX-MON-RXR message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_SPI = 0x2091018b; // Output rate of the UBX-MON-RXR message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_UART1 = 0x20910188; // Output rate of the UBX-MON-RXR message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_UART2 = 0x20910189; // Output rate of the UBX-MON-RXR message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_USB = 0x2091018a; // Output rate of the UBX-MON-RXR message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_I2C = 0x2091038b; // Output rate of the UBX-MON-SPAN message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_SPI = 0x2091038f; // Output rate of the UBX-MON-SPAN message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART1 = 0x2091038c; // Output rate of the UBX-MON-SPAN message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART2 = 0x2091038d; // Output rate of the UBX-MON-SPAN message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_USB = 0x2091038e; // Output rate of the UBX-MON-SPAN message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_I2C = 0x2091069d; // Output rate of the UBX-MON-SYS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_SPI = 0x209106a1; // Output rate of the UBX-MON-SYS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_UART1 = 0x2091069e; // Output rate of the UBX-MON-SYS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_UART2 = 0x2091069f; // Output rate of the UBX-MON-SYS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_USB = 0x209106a0; // Output rate of the UBX-MON-SYS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_I2C = 0x2091019b; // Output rate of the UBX-MON-TXBUF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_SPI = 0x2091019f; // Output rate of the UBX-MON-TXBUF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_UART1 = 0x2091019c; // Output rate of the UBX-MON-TXBUF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_UART2 = 0x2091019d; // Output rate of the UBX-MON-TXBUF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_USB = 0x2091019e; // Output rate of the UBX-MON-TXBUF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_I2C = 0x2091001f; // Output rate of the UBX_NAV_ATT message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_SPI = 0x20910023; // Output rate of the UBX_NAV_ATT message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_UART1 = 0x20910020; // Output rate of the UBX_NAV_ATT message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_UART2 = 0x20910021; // Output rate of the UBX_NAV_ATT message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_USB = 0x20910022; // Output rate of the UBX_NAV_ATT message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_I2C = 0x20910065; // Output rate of the UBX-NAV-CLOCK message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_SPI = 0x20910069; // Output rate of the UBX-NAV-CLOCK message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_UART1 = 0x20910066; // Output rate of the UBX-NAV-CLOCK message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_UART2 = 0x20910067; // Output rate of the UBX-NAV-CLOCK message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_USB = 0x20910068; // Output rate of the UBX-NAV-CLOCK message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_I2C = 0x20910038; // Output rate of the UBX-NAV-DOP message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_SPI = 0x2091003c; // Output rate of the UBX-NAV-DOP message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_UART1 = 0x20910039; // Output rate of the UBX-NAV-DOP message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_UART2 = 0x2091003a; // Output rate of the UBX-NAV-DOP message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_USB = 0x2091003b; // Output rate of the UBX-NAV-DOP message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_I2C = 0x2091015f; // Output rate of the UBX-NAV-EOE message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_SPI = 0x20910163; // Output rate of the UBX-NAV-EOE message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_UART1 = 0x20910160; // Output rate of the UBX-NAV-EOE message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_UART2 = 0x20910161; // Output rate of the UBX-NAV-EOE message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_USB = 0x20910162; // Output rate of the UBX-NAV-EOE message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_I2C = 0x209100a1; // Output rate of the UBX-NAV-GEOFENCE message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_SPI = 0x209100a5; // Output rate of the UBX-NAV-GEOFENCE message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_UART1 = 0x209100a2;// Output rate of the UBX-NAV-GEOFENCE message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_UART2 = 0x209100a3;// Output rate of the UBX-NAV-GEOFENCE message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_USB = 0x209100a4; // Output rate of the UBX-NAV-GEOFENCE message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_I2C = 0x2091002e;// Output rate of the UBX-NAV-HPPOSECEF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_SPI = 0x20910032;// Output rate of the UBX-NAV-HPPOSECEF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_UART1 = 0x2091002f;// Output rate of the UBX-NAV-HPPOSECEF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_UART2 = 0x20910030;// Output rate of the UBX-NAV-HPPOSECEF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_USB = 0x20910031;// Output rate of the UBX-NAV-HPPOSECEF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_I2C = 0x20910033; // Output rate of the UBX-NAV-HPPOSLLH message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_SPI = 0x20910037; // Output rate of the UBX-NAV-HPPOSLLH message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_UART1 = 0x20910034;// Output rate of the UBX-NAV-HPPOSLLH message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_UART2 = 0x20910035;// Output rate of the UBX-NAV-HPPOSLLH message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_USB = 0x20910036; // Output rate of the UBX-NAV-HPPOSLLH message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_I2C = 0x2091007e; // Output rate of the UBX-NAV-ODO message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_SPI = 0x20910082; // Output rate of the UBX-NAV-ODO message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_UART1 = 0x2091007f; // Output rate of the UBX-NAV-ODO message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_UART2 = 0x20910080; // Output rate of the UBX-NAV-ODO message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_USB = 0x20910081; // Output rate of the UBX-NAV-ODO message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_I2C = 0x20910010; // Output rate of the UBX-NAV-ORB message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_SPI = 0x20910014; // Output rate of the UBX-NAV-ORB message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART1 = 0x20910011; // Output rate of the UBX-NAV-ORB message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART2 = 0x20910012; // Output rate of the UBX-NAV-ORB message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_USB = 0x20910013; // Output rate of the UBX-NAV-ORB message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_I2C = 0x20910415; // Output rate of the UBX-NAV-PL message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_SPI = 0x20910419; // Output rate of the UBX-NAV-PL message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART1 = 0x20910416; // Output rate of the UBX-NAV-PL message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART2 = 0x20910417; // Output rate of the UBX-NAV-PL message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_USB = 0x20910418; // Output rate of the UBX-NAV-PL message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_I2C = 0x20910024; // Output rate of the UBX-NAV-POSECEF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_SPI = 0x20910028; // Output rate of the UBX-NAV-POSECEF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_UART1 = 0x20910025;// Output rate of the UBX-NAV-POSECEF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_UART2 = 0x20910026;// Output rate of the UBX-NAV-POSECEF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_USB = 0x20910027; // Output rate of the UBX-NAV-POSECEF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_I2C = 0x20910029; // Output rate of the UBX-NAV-POSLLH message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_SPI = 0x2091002d; // Output rate of the UBX-NAV-POSLLH message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_UART1 = 0x2091002a; // Output rate of the UBX-NAV-POSLLH message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_UART2 = 0x2091002b; // Output rate of the UBX-NAV-POSLLH message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_USB = 0x2091002c; // Output rate of the UBX-NAV-POSLLH message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_I2C = 0x20910006; // Output rate of the UBX-NAV-PVT message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_SPI = 0x2091000a; // Output rate of the UBX-NAV-PVT message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_UART1 = 0x20910007; // Output rate of the UBX-NAV-PVT message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_UART2 = 0x20910008; // Output rate of the UBX-NAV-PVT message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_USB = 0x20910009; // Output rate of the UBX-NAV-PVT message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_I2C = 0x2091008d; // Output rate of the UBX-NAV-RELPOSNED message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_SPI = 0x20910091; // Output rate of the UBX-NAV-RELPOSNED message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART1 = 0x2091008e; // Output rate of the UBX-NAV-RELPOSNED message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART2 = 0x2091008f; // Output rate of the UBX-NAV-RELPOSNED message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_USB = 0x20910090; // Output rate of the UBX-NAV-RELPOSNED message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_I2C = 0x20910015; // Output rate of the UBX-NAV-SAT message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_SPI = 0x20910019; // Output rate of the UBX-NAV-SAT message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_UART1 = 0x20910016; // Output rate of the UBX-NAV-SAT message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_UART2 = 0x20910017; // Output rate of the UBX-NAV-SAT message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_USB = 0x20910018; // Output rate of the UBX-NAV-SAT message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_I2C = 0x2091006a; // Output rate of the UBX-NAV-SBAS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_SPI = 0x2091006e; // Output rate of the UBX-NAV-SBAS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_UART1 = 0x2091006b; // Output rate of the UBX-NAV-SBAS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_UART2 = 0x2091006c; // Output rate of the UBX-NAV-SBAS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_USB = 0x2091006d; // Output rate of the UBX-NAV-SBAS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_I2C = 0x20910345; // Output rate of the UBX-NAV-SIG message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_SPI = 0x20910349; // Output rate of the UBX-NAV-SIG message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART1 = 0x20910346; // Output rate of the UBX-NAV-SIG message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART2 = 0x20910347; // Output rate of the UBX-NAV-SIG message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_USB = 0x20910348; // Output rate of the UBX-NAV-SIG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_I2C = 0x20910336; // Output rate of the UBX-NAV-SLAS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_SPI = 0x2091033a; // Output rate of the UBX-NAV-SLAS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_UART1 = 0x20910337; // Output rate of the UBX-NAV-SLAS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_UART2 = 0x20910338; // Output rate of the UBX-NAV-SLAS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_USB = 0x20910339; // Output rate of the UBX-NAV-SLAS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_I2C = 0x2091001a; // Output rate of the UBX-NAV-STATUS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_SPI = 0x2091001e; // Output rate of the UBX-NAV-STATUS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_UART1 = 0x2091001b; // Output rate of the UBX-NAV-STATUS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_UART2 = 0x2091001c; // Output rate of the UBX-NAV-STATUS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_USB = 0x2091001d; // Output rate of the UBX-NAV-STATUS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_I2C = 0x20910088; // Output rate of the UBX-NAV-SVIN message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_SPI = 0x2091008c; // Output rate of the UBX-NAV-SVIN message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_UART1 = 0x20910089; // Output rate of the UBX-NAV-SVIN message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_UART2 = 0x2091008a; // Output rate of the UBX-NAV-SVIN message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_USB = 0x2091008b; // Output rate of the UBX-NAV-SVIN message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_I2C = 0x20910051; // Output rate of the UBX-NAV-TIMEBDS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_SPI = 0x20910055; // Output rate of the UBX-NAV-TIMEBDS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_UART1 = 0x20910052;// Output rate of the UBX-NAV-TIMEBDS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_UART2 = 0x20910053;// Output rate of the UBX-NAV-TIMEBDS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_USB = 0x20910054; // Output rate of the UBX-NAV-TIMEBDS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_I2C = 0x20910056; // Output rate of the UBX-NAV-TIMEGAL message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_SPI = 0x2091005a; // Output rate of the UBX-NAV-TIMEGAL message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_UART1 = 0x20910057;// Output rate of the UBX-NAV-TIMEGAL message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_UART2 = 0x20910058;// Output rate of the UBX-NAV-TIMEGAL message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_USB = 0x20910059; // Output rate of the UBX-NAV-TIMEGAL message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_I2C = 0x2091004c; // Output rate of the UBX-NAV-TIMEGLO message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_SPI = 0x20910050; // Output rate of the UBX-NAV-TIMEGLO message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_UART1 = 0x2091004d;// Output rate of the UBX-NAV-TIMEGLO message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_UART2 = 0x2091004e;// Output rate of the UBX-NAV-TIMEGLO message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_USB = 0x2091004f; // Output rate of the UBX-NAV-TIMEGLO message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_I2C = 0x20910047; // Output rate of the UBX-NAV-TIMEGPS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_SPI = 0x2091004b; // Output rate of the UBX-NAV-TIMEGPS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_UART1 = 0x20910048;// Output rate of the UBX-NAV-TIMEGPS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_UART2 = 0x20910049;// Output rate of the UBX-NAV-TIMEGPS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_USB = 0x2091004a; // Output rate of the UBX-NAV-TIMEGPS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_I2C = 0x20910060; // Output rate of the UBX-NAV-TIMELS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_SPI = 0x20910064; // Output rate of the UBX-NAV-TIMELS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_UART1 = 0x20910061; // Output rate of the UBX-NAV-TIMELS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_UART2 = 0x20910062; // Output rate of the UBX-NAV-TIMELS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_USB = 0x20910063; // Output rate of the UBX-NAV-TIMELS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_I2C = 0x20910386; // Output rate of the UBX-NAV-TIMEQZSSmessage on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_SPI = 0x2091038a; // Output rate of the UBX-NAV-TIMEQZSSmessage on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_UART1 = 0x20910387;// Output rate of the UBX-NAV-TIMEQZSSmessage on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_UART2 = 0x20910388;// Output rate of the UBX-NAV-TIMEQZSSmessage on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_USB = 0x20910389; // Output rate of the UBX-NAV-TIMEQZSSmessage on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_I2C = 0x2091005b; // Output rate of the UBX-NAV-TIMEUTC message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_SPI = 0x2091005f; // Output rate of the UBX-NAV-TIMEUTC message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_UART1 = 0x2091005c;// Output rate of the UBX-NAV-TIMEUTC message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_UART2 = 0x2091005d;// Output rate of the UBX-NAV-TIMEUTC message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_USB = 0x2091005e; // Output rate of the UBX-NAV-TIMEUTC message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_I2C = 0x2091003d; // Output rate of the UBX-NAV-VELECEF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_SPI = 0x20910041; // Output rate of the UBX-NAV-VELECEF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_UART1 = 0x2091003e;// Output rate of the UBX-NAV-VELECEF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_UART2 = 0x2091003f;// Output rate of the UBX-NAV-VELECEF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_USB = 0x20910040; // Output rate of the UBX-NAV-VELECEF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_I2C = 0x20910042; // Output rate of the UBX-NAV-VELNED message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_SPI = 0x20910046; // Output rate of the UBX-NAV-VELNED message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_UART1 = 0x20910043; // Output rate of the UBX-NAV-VELNED message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_UART2 = 0x20910044; // Output rate of the UBX-NAV-VELNED message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_USB = 0x20910045; // Output rate of the UBX-NAV-VELNED message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_I2C = 0x209106b6; // Output rate of the UBX-RXM-COR message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_SPI = 0x209106ba; // Output rate of the UBX-RXM-COR message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_UART1 = 0x209106b7; // Output rate of the UBX-RXM-COR message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_UART2 = 0x209106b8; // Output rate of the UBX-RXM-COR message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_USB = 0x209106b9; // Output rate of the UBX-RXM-COR message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_I2C = 0x20910204; // Output rate of the UBX-RXM-MEASX message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_SPI = 0x20910208; // Output rate of the UBX-RXM-MEASX message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_UART1 = 0x20910205; // Output rate of the UBX-RXM-MEASX message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_UART2 = 0x20910206; // Output rate of the UBX-RXM-MEASX message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_USB = 0x20910207; // Output rate of the UBX-RXM-MEASX message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_I2C = 0x209102a4; // Output rate of the UBX-RXM-RAWX message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_SPI = 0x209102a8; // Output rate of the UBX-RXM-RAWX message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_UART1 = 0x209102a5; // Output rate of the UBX-RXM-RAWX message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_UART2 = 0x209102a6; // Output rate of the UBX-RXM-RAWX message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_USB = 0x209102a7; // Output rate of the UBX-RXM-RAWX message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_I2C = 0x2091025e; // Output rate of the UBX-RXM-RLM message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_SPI = 0x20910262; // Output rate of the UBX-RXM-RLM message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_UART1 = 0x2091025f; // Output rate of the UBX-RXM-RLM message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_UART2 = 0x20910260; // Output rate of the UBX-RXM-RLM message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_USB = 0x20910261; // Output rate of the UBX-RXM-RLM message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_I2C = 0x20910268; // Output rate of the UBX-RXM-RTCM message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_SPI = 0x2091026c; // Output rate of the UBX-RXM-RTCM message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_UART1 = 0x20910269; // Output rate of the UBX-RXM-RTCM message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_UART2 = 0x2091026a; // Output rate of the UBX-RXM-RTCM message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_USB = 0x2091026b; // Output rate of the UBX-RXM-RTCM message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_I2C = 0x20910231; // Output rate of the UBX-RXM-SFRBX message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_SPI = 0x20910235; // Output rate of the UBX-RXM-SFRBX message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_UART1 = 0x20910232; // Output rate of the UBX-RXM-SFRBX message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_UART2 = 0x20910233; // Output rate of the UBX-RXM-SFRBX message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_USB = 0x20910234; // Output rate of the UBX-RXM-SFRBX message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_I2C = 0x20910605; // Output rate of the UBX-RXM-SPARTN message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_UART1 = 0x20910606; // Output rate of the UBX-RXM-SPARTN message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_UART2 = 0x20910607; // Output rate of the UBX-RXM-SPARTN message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_USB = 0x20910608; // Output rate of the UBX-RXM-SPARTN message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_SPI = 0x20910609; // Output rate of the UBX-RXM-SPARTN message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_I2C = 0x20910634; // Output rate of the UBX-SEC-SIG message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_SPI = 0x20910638; // Output rate of the UBX-SEC-SIG message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART1 = 0x20910635; // Output rate of the UBX-SEC-SIG message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART2 = 0x20910636; // Output rate of the UBX-SEC-SIG message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_USB = 0x20910637; // Output rate of the UBX-SEC-SIG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_I2C = 0x20910178; // Output rate of the UBX-TIM-TM2 message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_SPI = 0x2091017c; // Output rate of the UBX-TIM-TM2 message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_UART1 = 0x20910179; // Output rate of the UBX-TIM-TM2 message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_UART2 = 0x2091017a; // Output rate of the UBX-TIM-TM2 message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_USB = 0x2091017b; // Output rate of the UBX-TIM-TM2 message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_I2C = 0x2091017d; // Output rate of the UBX-TIM-TP message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_SPI = 0x20910181; // Output rate of the UBX-TIM-TP message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_UART1 = 0x2091017e; // Output rate of the UBX-TIM-TP message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_UART2 = 0x2091017f; // Output rate of the UBX-TIM-TP message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_USB = 0x20910180; // Output rate of the UBX-TIM-TP message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_I2C = 0x20910092; // Output rate of the UBX-TIM-VRFY message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_SPI = 0x20910096; // Output rate of the UBX-TIM-VRFY message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_UART1 = 0x20910093; // Output rate of the UBX-TIM-VRFY message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_UART2 = 0x20910094; // Output rate of the UBX-TIM-VRFY message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_USB = 0x20910095; // Output rate of the UBX-TIM-VRFY message on port USB - -//Additional CFG_MSGOUT keys for the ZED-F9R HPS121 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_I2C = 0x209100a6; // Output rate of the NMEA-GX-DTM message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_SPI = 0x209100aa; // Output rate of the NMEA-GX-DTM message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_UART1 = 0x209100a7; // Output rate of the NMEA-GX-DTM message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_UART2 = 0x209100a8; // Output rate of the NMEA-GX-DTM message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_DTM_USB = 0x209100a9; // Output rate of the NMEA-GX-DTM message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_I2C = 0x209100dd; // Output rate of the NMEA-GX-GBS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_SPI = 0x209100e1; // Output rate of the NMEA-GX-GBS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_UART1 = 0x209100de; // Output rate of the NMEA-GX-GBS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_UART2 = 0x209100df; // Output rate of the NMEA-GX-GBS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GBS_USB = 0x209100e0; // Output rate of the NMEA-GX-GBS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_I2C = 0x209100ba; // Output rate of the NMEA-GX-GGA message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_SPI = 0x209100be; // Output rate of the NMEA-GX-GGA message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_UART1 = 0x209100bb; // Output rate of the NMEA-GX-GGA message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_UART2 = 0x209100bc; // Output rate of the NMEA-GX-GGA message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GGA_USB = 0x209100bd; // Output rate of the NMEA-GX-GGA message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_I2C = 0x209100c9; // Output rate of the NMEA-GX-GLL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_SPI = 0x209100cd; // Output rate of the NMEA-GX-GLL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_UART1 = 0x209100ca; // Output rate of the NMEA-GX-GLL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_UART2 = 0x209100cb; // Output rate of the NMEA-GX-GLL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GLL_USB = 0x209100cc; // Output rate of the NMEA-GX-GLL message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_I2C = 0x209100b5; // Output rate of the NMEA-GX-GNS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_SPI = 0x209100b9; // Output rate of the NMEA-GX-GNS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_UART1 = 0x209100b6; // Output rate of the NMEA-GX-GNS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_UART2 = 0x209100b7; // Output rate of the NMEA-GX-GNS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GNS_USB = 0x209100b8; // Output rate of the NMEA-GX-GNS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_I2C = 0x209100ce; // Output rate of the NMEA-GX-GRS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_SPI = 0x209100d2; // Output rate of the NMEA-GX-GRS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_UART1 = 0x209100cf; // Output rate of the NMEA-GX-GRS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_UART2 = 0x209100d0; // Output rate of the NMEA-GX-GRS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GRS_USB = 0x209100d1; // Output rate of the NMEA-GX-GRS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_I2C = 0x209100bf; // Output rate of the NMEA-GX-GSA message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_SPI = 0x209100c3; // Output rate of the NMEA-GX-GSA message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_UART1 = 0x209100c0; // Output rate of the NMEA-GX-GSA message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_UART2 = 0x209100c1; // Output rate of the NMEA-GX-GSA message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSA_USB = 0x209100c2; // Output rate of the NMEA-GX-GSA message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_I2C = 0x209100d3; // Output rate of the NMEA-GX-GST message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_SPI = 0x209100d7; // Output rate of the NMEA-GX-GST message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_UART1 = 0x209100d4; // Output rate of the NMEA-GX-GST message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_UART2 = 0x209100d5; // Output rate of the NMEA-GX-GST message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GST_USB = 0x209100d6; // Output rate of the NMEA-GX-GST message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_I2C = 0x209100c4; // Output rate of the NMEA-GX-GSV message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_SPI = 0x209100c8; // Output rate of the NMEA-GX-GSV message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_UART1 = 0x209100c5; // Output rate of the NMEA-GX-GSV message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_UART2 = 0x209100c6; // Output rate of the NMEA-GX-GSV message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_GSV_USB = 0x209100c7; // Output rate of the NMEA-GX-GSV message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_I2C = 0x20910400; // Output rate of the NMEA-GX-RLM message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_SPI = 0x20910404; // Output rate of the NMEA-GX-RLM message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_UART1 = 0x20910401; // Output rate of the NMEA-GX-RLM message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_UART2 = 0x20910402; // Output rate of the NMEA-GX-RLM message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RLM_USB = 0x20910403; // Output rate of the NMEA-GX-RLM message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_I2C = 0x209100ab; // Output rate of the NMEA-GX-RMC message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_SPI = 0x209100af; // Output rate of the NMEA-GX-RMC message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_UART1 = 0x209100ac; // Output rate of the NMEA-GX-RMC message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_UART2 = 0x209100ad; // Output rate of the NMEA-GX-RMC message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_RMC_USB = 0x209100ae; // Output rate of the NMEA-GX-RMC message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_I2C = 0x209100e7; // Output rate of the NMEA-GX-VLW message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_SPI = 0x209100eb; // Output rate of the NMEA-GX-VLW message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_UART1 = 0x209100e8; // Output rate of the NMEA-GX-VLW message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_UART2 = 0x209100e9; // Output rate of the NMEA-GX-VLW message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VLW_USB = 0x209100ea; // Output rate of the NMEA-GX-VLW message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_I2C = 0x209100b0; // Output rate of the NMEA-GX-VTG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_SPI = 0x209100b4; // Output rate of the NMEA-GX-VTG message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_UART1 = 0x209100b1; // Output rate of the NMEA-GX-VTG message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_UART2 = 0x209100b2; // Output rate of the NMEA-GX-VTG message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_VTG_USB = 0x209100b3; // Output rate of the NMEA-GX-VTG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_I2C = 0x209100d8; // Output rate of the NMEA-GX-ZDA message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_SPI = 0x209100dc; // Output rate of the NMEA-GX-ZDA message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_UART1 = 0x209100d9; // Output rate of the NMEA-GX-ZDA message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_UART2 = 0x209100da; // Output rate of the NMEA-GX-ZDA message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_USB = 0x209100db; // Output rate of the NMEA-GX-ZDA message on port USB +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_I2C = 0x209100ec; // Output rate of the NMEA-GX-PUBX00 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_SPI = 0x209100f0; // Output rate of the NMEA-GX-PUBX00 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_UART1 = 0x209100ed; // Output rate of the NMEA-GX-PUBX00 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_UART2 = 0x209100ee; // Output rate of the NMEA-GX-PUBX00 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYP_USB = 0x209100ef; // Output rate of the NMEA-GX-PUBX00 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_I2C = 0x209100f1; // Output rate of the NMEA-GX-PUBX03 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_SPI = 0x209100f5; // Output rate of the NMEA-GX-PUBX03 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_UART1 = 0x209100f2; // Output rate of the NMEA-GX-PUBX03 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_UART2 = 0x209100f3; // Output rate of the NMEA-GX-PUBX03 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYS_USB = 0x209100f4; // Output rate of the NMEA-GX-PUBX03 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_I2C = 0x209100f6; // Output rate of the NMEA-GX-PUBX04 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_SPI = 0x209100fa; // Output rate of the NMEA-GX-PUBX04 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_UART1 = 0x209100f7; // Output rate of the NMEA-GX-PUBX04 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_UART2 = 0x209100f8; // Output rate of the NMEA-GX-PUBX04 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_PUBX_ID_POLYT_USB = 0x209100f9; // Output rate of the NMEA-GX-PUBX04 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_I2C = 0x209102bd; // Output rate of the RTCM-3X-TYPE1005 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_SPI = 0x209102c1; // Output rate of the RTCM-3X-TYPE1005 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_UART1 = 0x209102be; // Output rate of the RTCM-3X-TYPE1005 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_UART2 = 0x209102bf; // Output rate of the RTCM-3X-TYPE1005 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_USB = 0x209102c0; // Output rate of the RTCM-3X-TYPE1005 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_I2C = 0x2091035e; // Output rate of the RTCM-3X-TYPE1074 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_SPI = 0x20910362; // Output rate of the RTCM-3X-TYPE1074 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_UART1 = 0x2091035f; // Output rate of the RTCM-3X-TYPE1074 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_UART2 = 0x20910360; // Output rate of the RTCM-3X-TYPE1074 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_USB = 0x20910361; // Output rate of the RTCM-3X-TYPE1074 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_I2C = 0x209102cc; // Output rate of the RTCM-3X-TYPE1077 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_SPI = 0x209102d0; // Output rate of the RTCM-3X-TYPE1077 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_UART1 = 0x209102cd; // Output rate of the RTCM-3X-TYPE1077 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_UART2 = 0x209102ce; // Output rate of the RTCM-3X-TYPE1077 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1077_USB = 0x209102cf; // Output rate of the RTCM-3X-TYPE1077 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_I2C = 0x20910363; // Output rate of the RTCM-3X-TYPE1084 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_SPI = 0x20910367; // Output rate of the RTCM-3X-TYPE1084 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_UART1 = 0x20910364; // Output rate of the RTCM-3X-TYPE1084 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_UART2 = 0x20910365; // Output rate of the RTCM-3X-TYPE1084 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_USB = 0x20910366; // Output rate of the RTCM-3X-TYPE1084 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_I2C = 0x209102d1; // Output rate of the RTCM-3X-TYPE1087 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_SPI = 0x209102d5; // Output rate of the RTCM-3X-TYPE1087 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_UART1 = 0x209102d2; // Output rate of the RTCM-3X-TYPE1087 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_UART2 = 0x209102d3; // Output rate of the RTCM-3X-TYPE1087 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1087_USB = 0x209102d4; // Output rate of the RTCM-3X-TYPE1087 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_I2C = 0x20910368; // Output rate of the RTCM-3X-TYPE1094 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_SPI = 0x2091036c; // Output rate of the RTCM-3X-TYPE1094 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_UART1 = 0x20910369; // Output rate of the RTCM-3X-TYPE1094 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_UART2 = 0x2091036a; // Output rate of the RTCM-3X-TYPE1094 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_USB = 0x2091036b; // Output rate of the RTCM-3X-TYPE1094 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_I2C = 0x20910318; // Output rate of the RTCM-3X-TYPE1097 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_SPI = 0x2091031c; // Output rate of the RTCM-3X-TYPE1097 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_UART1 = 0x20910319; // Output rate of the RTCM-3X-TYPE1097 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_UART2 = 0x2091031a; // Output rate of the RTCM-3X-TYPE1097 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1097_USB = 0x2091031b; // Output rate of the RTCM-3X-TYPE1097 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_I2C = 0x2091036d; // Output rate of the RTCM-3X-TYPE1124 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_SPI = 0x20910371; // Output rate of the RTCM-3X-TYPE1124 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_UART1 = 0x2091036e; // Output rate of the RTCM-3X-TYPE1124 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_UART2 = 0x2091036f; // Output rate of the RTCM-3X-TYPE1124 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_USB = 0x20910370; // Output rate of the RTCM-3X-TYPE1124 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_I2C = 0x209102d6; // Output rate of the RTCM-3X-TYPE1127 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_SPI = 0x209102da; // Output rate of the RTCM-3X-TYPE1127 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_UART1 = 0x209102d7; // Output rate of the RTCM-3X-TYPE1127 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_UART2 = 0x209102d8; // Output rate of the RTCM-3X-TYPE1127 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1127_USB = 0x209102d9; // Output rate of the RTCM-3X-TYPE1127 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_I2C = 0x20910303; // Output rate of the RTCM-3X-TYPE1230 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_SPI = 0x20910307; // Output rate of the RTCM-3X-TYPE1230 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_UART1 = 0x20910304; // Output rate of the RTCM-3X-TYPE1230 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_UART2 = 0x20910305; // Output rate of the RTCM-3X-TYPE1230 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_USB = 0x20910306; // Output rate of the RTCM-3X-TYPE1230 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_I2C = 0x209102fe; // Output rate of the RTCM-3X-TYPE4072_0 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_SPI = 0x20910302; // Output rate of the RTCM-3X-TYPE4072_0 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_UART1 = 0x209102ff; // Output rate of the RTCM-3X-TYPE4072_0 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_UART2 = 0x20910300; // Output rate of the RTCM-3X-TYPE4072_0 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_0_USB = 0x20910301; // Output rate of the RTCM-3X-TYPE4072_0 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_I2C = 0x20910381; // Output rate of the RTCM-3X-TYPE4072_1 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_SPI = 0x20910385; // Output rate of the RTCM-3X-TYPE4072_1 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_UART1 = 0x20910382; // Output rate of the RTCM-3X-TYPE4072_1 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_UART2 = 0x20910383; // Output rate of the RTCM-3X-TYPE4072_1 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_RTCM_3X_TYPE4072_1_USB = 0x20910384; // Output rate of the RTCM-3X-TYPE4072_1 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_I2C = 0x20910259; // Output rate of the UBX-LOG-INFO message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_SPI = 0x2091025d; // Output rate of the UBX-LOG-INFO message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_UART1 = 0x2091025a; // Output rate of the UBX-LOG-INFO message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_UART2 = 0x2091025b; // Output rate of the UBX-LOG-INFO message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_LOG_INFO_USB = 0x2091025c; // Output rate of the UBX-LOG-INFO message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_I2C = 0x2091034f; // Output rate of the UBX-MON-COMMS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_SPI = 0x20910353; // Output rate of the UBX-MON-COMMS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_UART1 = 0x20910350; // Output rate of the UBX-MON-COMMS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_UART2 = 0x20910351; // Output rate of the UBX-MON-COMMS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_COMMS_USB = 0x20910352; // Output rate of the UBX-MON-COMMS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_I2C = 0x209101b9; // Output rate of the UBX-MON-HW2 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_SPI = 0x209101bd; // Output rate of the UBX-MON-HW2 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_UART1 = 0x209101ba; // Output rate of the UBX-MON-HW2 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_UART2 = 0x209101bb; // Output rate of the UBX-MON-HW2 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW2_USB = 0x209101bc; // Output rate of the UBX-MON-HW2 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_I2C = 0x20910354; // Output rate of the UBX-MON-HW3 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_SPI = 0x20910358; // Output rate of the UBX-MON-HW3 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_UART1 = 0x20910355; // Output rate of the UBX-MON-HW3 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_UART2 = 0x20910356; // Output rate of the UBX-MON-HW3 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW3_USB = 0x20910357; // Output rate of the UBX-MON-HW3 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_I2C = 0x209101b4; // Output rate of the UBX-MON-HW message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_SPI = 0x209101b8; // Output rate of the UBX-MON-HW message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_UART1 = 0x209101b5; // Output rate of the UBX-MON-HW message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_UART2 = 0x209101b6; // Output rate of the UBX-MON-HW message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_HW_USB = 0x209101b7; // Output rate of the UBX-MON-HW message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_I2C = 0x209101a5; // Output rate of the UBX-MON-IO message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_SPI = 0x209101a9; // Output rate of the UBX-MON-IO message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_UART1 = 0x209101a6; // Output rate of the UBX-MON-IO message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_UART2 = 0x209101a7; // Output rate of the UBX-MON-IO message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_IO_USB = 0x209101a8; // Output rate of the UBX-MON-IO message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_I2C = 0x20910196; // Output rate of the UBX-MON-MSGPP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_SPI = 0x2091019a; // Output rate of the UBX-MON-MSGPP message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_UART1 = 0x20910197; // Output rate of the UBX-MON-MSGPP message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_UART2 = 0x20910198; // Output rate of the UBX-MON-MSGPP message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_MSGPP_USB = 0x20910199; // Output rate of the UBX-MON-MSGPP message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_I2C = 0x20910359; // Output rate of the UBX-MON-RF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_SPI = 0x2091035d; // Output rate of the UBX-MON-RF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_UART1 = 0x2091035a; // Output rate of the UBX-MON-RF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_UART2 = 0x2091035b; // Output rate of the UBX-MON-RF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RF_USB = 0x2091035c; // Output rate of the UBX-MON-RF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_I2C = 0x209101a0; // Output rate of the UBX-MON-RXBUF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_SPI = 0x209101a4; // Output rate of the UBX-MON-RXBUF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_UART1 = 0x209101a1; // Output rate of the UBX-MON-RXBUF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_UART2 = 0x209101a2; // Output rate of the UBX-MON-RXBUF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXBUF_USB = 0x209101a3; // Output rate of the UBX-MON-RXBUF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_I2C = 0x20910187; // Output rate of the UBX-MON-RXR message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_SPI = 0x2091018b; // Output rate of the UBX-MON-RXR message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_UART1 = 0x20910188; // Output rate of the UBX-MON-RXR message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_UART2 = 0x20910189; // Output rate of the UBX-MON-RXR message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_RXR_USB = 0x2091018a; // Output rate of the UBX-MON-RXR message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_I2C = 0x2091038b; // Output rate of the UBX-MON-SPAN message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_SPI = 0x2091038f; // Output rate of the UBX-MON-SPAN message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART1 = 0x2091038c; // Output rate of the UBX-MON-SPAN message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_UART2 = 0x2091038d; // Output rate of the UBX-MON-SPAN message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SPAN_USB = 0x2091038e; // Output rate of the UBX-MON-SPAN message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_I2C = 0x2091069d; // Output rate of the UBX-MON-SYS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_SPI = 0x209106a1; // Output rate of the UBX-MON-SYS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_UART1 = 0x2091069e; // Output rate of the UBX-MON-SYS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_UART2 = 0x2091069f; // Output rate of the UBX-MON-SYS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_SYS_USB = 0x209106a0; // Output rate of the UBX-MON-SYS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_I2C = 0x2091019b; // Output rate of the UBX-MON-TXBUF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_SPI = 0x2091019f; // Output rate of the UBX-MON-TXBUF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_UART1 = 0x2091019c; // Output rate of the UBX-MON-TXBUF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_UART2 = 0x2091019d; // Output rate of the UBX-MON-TXBUF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_TXBUF_USB = 0x2091019e; // Output rate of the UBX-MON-TXBUF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_I2C = 0x2091001f; // Output rate of the UBX_NAV_ATT message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_SPI = 0x20910023; // Output rate of the UBX_NAV_ATT message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_UART1 = 0x20910020; // Output rate of the UBX_NAV_ATT message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_UART2 = 0x20910021; // Output rate of the UBX_NAV_ATT message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ATT_USB = 0x20910022; // Output rate of the UBX_NAV_ATT message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_I2C = 0x20910065; // Output rate of the UBX-NAV-CLOCK message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_SPI = 0x20910069; // Output rate of the UBX-NAV-CLOCK message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_UART1 = 0x20910066; // Output rate of the UBX-NAV-CLOCK message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_UART2 = 0x20910067; // Output rate of the UBX-NAV-CLOCK message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_CLOCK_USB = 0x20910068; // Output rate of the UBX-NAV-CLOCK message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_I2C = 0x20910038; // Output rate of the UBX-NAV-DOP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_SPI = 0x2091003c; // Output rate of the UBX-NAV-DOP message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_UART1 = 0x20910039; // Output rate of the UBX-NAV-DOP message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_UART2 = 0x2091003a; // Output rate of the UBX-NAV-DOP message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_DOP_USB = 0x2091003b; // Output rate of the UBX-NAV-DOP message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_I2C = 0x2091015f; // Output rate of the UBX-NAV-EOE message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_SPI = 0x20910163; // Output rate of the UBX-NAV-EOE message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_UART1 = 0x20910160; // Output rate of the UBX-NAV-EOE message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_UART2 = 0x20910161; // Output rate of the UBX-NAV-EOE message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EOE_USB = 0x20910162; // Output rate of the UBX-NAV-EOE message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_I2C = 0x209100a1; // Output rate of the UBX-NAV-GEOFENCE message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_SPI = 0x209100a5; // Output rate of the UBX-NAV-GEOFENCE message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_UART1 = 0x209100a2; // Output rate of the UBX-NAV-GEOFENCE message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_UART2 = 0x209100a3; // Output rate of the UBX-NAV-GEOFENCE message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_GEOFENCE_USB = 0x209100a4; // Output rate of the UBX-NAV-GEOFENCE message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_I2C = 0x2091002e; // Output rate of the UBX-NAV-HPPOSECEF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_SPI = 0x20910032; // Output rate of the UBX-NAV-HPPOSECEF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_UART1 = 0x2091002f; // Output rate of the UBX-NAV-HPPOSECEF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_UART2 = 0x20910030; // Output rate of the UBX-NAV-HPPOSECEF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSECEF_USB = 0x20910031; // Output rate of the UBX-NAV-HPPOSECEF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_I2C = 0x20910033; // Output rate of the UBX-NAV-HPPOSLLH message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_SPI = 0x20910037; // Output rate of the UBX-NAV-HPPOSLLH message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_UART1 = 0x20910034; // Output rate of the UBX-NAV-HPPOSLLH message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_UART2 = 0x20910035; // Output rate of the UBX-NAV-HPPOSLLH message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_HPPOSLLH_USB = 0x20910036; // Output rate of the UBX-NAV-HPPOSLLH message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_I2C = 0x2091007e; // Output rate of the UBX-NAV-ODO message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_SPI = 0x20910082; // Output rate of the UBX-NAV-ODO message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_UART1 = 0x2091007f; // Output rate of the UBX-NAV-ODO message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_UART2 = 0x20910080; // Output rate of the UBX-NAV-ODO message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ODO_USB = 0x20910081; // Output rate of the UBX-NAV-ODO message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_I2C = 0x20910010; // Output rate of the UBX-NAV-ORB message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_SPI = 0x20910014; // Output rate of the UBX-NAV-ORB message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART1 = 0x20910011; // Output rate of the UBX-NAV-ORB message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_UART2 = 0x20910012; // Output rate of the UBX-NAV-ORB message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_ORB_USB = 0x20910013; // Output rate of the UBX-NAV-ORB message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_I2C = 0x20910415; // Output rate of the UBX-NAV-PL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_SPI = 0x20910419; // Output rate of the UBX-NAV-PL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART1 = 0x20910416; // Output rate of the UBX-NAV-PL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_UART2 = 0x20910417; // Output rate of the UBX-NAV-PL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PL_USB = 0x20910418; // Output rate of the UBX-NAV-PL message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_I2C = 0x20910024; // Output rate of the UBX-NAV-POSECEF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_SPI = 0x20910028; // Output rate of the UBX-NAV-POSECEF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_UART1 = 0x20910025; // Output rate of the UBX-NAV-POSECEF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_UART2 = 0x20910026; // Output rate of the UBX-NAV-POSECEF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSECEF_USB = 0x20910027; // Output rate of the UBX-NAV-POSECEF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_I2C = 0x20910029; // Output rate of the UBX-NAV-POSLLH message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_SPI = 0x2091002d; // Output rate of the UBX-NAV-POSLLH message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_UART1 = 0x2091002a; // Output rate of the UBX-NAV-POSLLH message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_UART2 = 0x2091002b; // Output rate of the UBX-NAV-POSLLH message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_POSLLH_USB = 0x2091002c; // Output rate of the UBX-NAV-POSLLH message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_I2C = 0x20910006; // Output rate of the UBX-NAV-PVT message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_SPI = 0x2091000a; // Output rate of the UBX-NAV-PVT message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_UART1 = 0x20910007; // Output rate of the UBX-NAV-PVT message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_UART2 = 0x20910008; // Output rate of the UBX-NAV-PVT message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVT_USB = 0x20910009; // Output rate of the UBX-NAV-PVT message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_I2C = 0x2091008d; // Output rate of the UBX-NAV-RELPOSNED message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_SPI = 0x20910091; // Output rate of the UBX-NAV-RELPOSNED message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART1 = 0x2091008e; // Output rate of the UBX-NAV-RELPOSNED message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_UART2 = 0x2091008f; // Output rate of the UBX-NAV-RELPOSNED message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_RELPOSNED_USB = 0x20910090; // Output rate of the UBX-NAV-RELPOSNED message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_I2C = 0x20910015; // Output rate of the UBX-NAV-SAT message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_SPI = 0x20910019; // Output rate of the UBX-NAV-SAT message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_UART1 = 0x20910016; // Output rate of the UBX-NAV-SAT message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_UART2 = 0x20910017; // Output rate of the UBX-NAV-SAT message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SAT_USB = 0x20910018; // Output rate of the UBX-NAV-SAT message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_I2C = 0x2091006a; // Output rate of the UBX-NAV-SBAS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_SPI = 0x2091006e; // Output rate of the UBX-NAV-SBAS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_UART1 = 0x2091006b; // Output rate of the UBX-NAV-SBAS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_UART2 = 0x2091006c; // Output rate of the UBX-NAV-SBAS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SBAS_USB = 0x2091006d; // Output rate of the UBX-NAV-SBAS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_I2C = 0x20910345; // Output rate of the UBX-NAV-SIG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_SPI = 0x20910349; // Output rate of the UBX-NAV-SIG message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART1 = 0x20910346; // Output rate of the UBX-NAV-SIG message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART2 = 0x20910347; // Output rate of the UBX-NAV-SIG message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SIG_USB = 0x20910348; // Output rate of the UBX-NAV-SIG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_I2C = 0x20910336; // Output rate of the UBX-NAV-SLAS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_SPI = 0x2091033a; // Output rate of the UBX-NAV-SLAS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_UART1 = 0x20910337; // Output rate of the UBX-NAV-SLAS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_UART2 = 0x20910338; // Output rate of the UBX-NAV-SLAS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SLAS_USB = 0x20910339; // Output rate of the UBX-NAV-SLAS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_I2C = 0x2091001a; // Output rate of the UBX-NAV-STATUS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_SPI = 0x2091001e; // Output rate of the UBX-NAV-STATUS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_UART1 = 0x2091001b; // Output rate of the UBX-NAV-STATUS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_UART2 = 0x2091001c; // Output rate of the UBX-NAV-STATUS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_STATUS_USB = 0x2091001d; // Output rate of the UBX-NAV-STATUS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_I2C = 0x20910088; // Output rate of the UBX-NAV-SVIN message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_SPI = 0x2091008c; // Output rate of the UBX-NAV-SVIN message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_UART1 = 0x20910089; // Output rate of the UBX-NAV-SVIN message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_UART2 = 0x2091008a; // Output rate of the UBX-NAV-SVIN message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_SVIN_USB = 0x2091008b; // Output rate of the UBX-NAV-SVIN message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_I2C = 0x20910051; // Output rate of the UBX-NAV-TIMEBDS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_SPI = 0x20910055; // Output rate of the UBX-NAV-TIMEBDS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_UART1 = 0x20910052; // Output rate of the UBX-NAV-TIMEBDS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_UART2 = 0x20910053; // Output rate of the UBX-NAV-TIMEBDS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEBDS_USB = 0x20910054; // Output rate of the UBX-NAV-TIMEBDS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_I2C = 0x20910056; // Output rate of the UBX-NAV-TIMEGAL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_SPI = 0x2091005a; // Output rate of the UBX-NAV-TIMEGAL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_UART1 = 0x20910057; // Output rate of the UBX-NAV-TIMEGAL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_UART2 = 0x20910058; // Output rate of the UBX-NAV-TIMEGAL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGAL_USB = 0x20910059; // Output rate of the UBX-NAV-TIMEGAL message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_I2C = 0x2091004c; // Output rate of the UBX-NAV-TIMEGLO message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_SPI = 0x20910050; // Output rate of the UBX-NAV-TIMEGLO message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_UART1 = 0x2091004d; // Output rate of the UBX-NAV-TIMEGLO message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_UART2 = 0x2091004e; // Output rate of the UBX-NAV-TIMEGLO message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGLO_USB = 0x2091004f; // Output rate of the UBX-NAV-TIMEGLO message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_I2C = 0x20910047; // Output rate of the UBX-NAV-TIMEGPS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_SPI = 0x2091004b; // Output rate of the UBX-NAV-TIMEGPS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_UART1 = 0x20910048; // Output rate of the UBX-NAV-TIMEGPS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_UART2 = 0x20910049; // Output rate of the UBX-NAV-TIMEGPS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEGPS_USB = 0x2091004a; // Output rate of the UBX-NAV-TIMEGPS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_I2C = 0x20910060; // Output rate of the UBX-NAV-TIMELS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_SPI = 0x20910064; // Output rate of the UBX-NAV-TIMELS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_UART1 = 0x20910061; // Output rate of the UBX-NAV-TIMELS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_UART2 = 0x20910062; // Output rate of the UBX-NAV-TIMELS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMELS_USB = 0x20910063; // Output rate of the UBX-NAV-TIMELS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_I2C = 0x20910386; // Output rate of the UBX-NAV-TIMEQZSSmessage on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_SPI = 0x2091038a; // Output rate of the UBX-NAV-TIMEQZSSmessage on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_UART1 = 0x20910387; // Output rate of the UBX-NAV-TIMEQZSSmessage on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_UART2 = 0x20910388; // Output rate of the UBX-NAV-TIMEQZSSmessage on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEQZSS_USB = 0x20910389; // Output rate of the UBX-NAV-TIMEQZSSmessage on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_I2C = 0x2091005b; // Output rate of the UBX-NAV-TIMEUTC message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_SPI = 0x2091005f; // Output rate of the UBX-NAV-TIMEUTC message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_UART1 = 0x2091005c; // Output rate of the UBX-NAV-TIMEUTC message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_UART2 = 0x2091005d; // Output rate of the UBX-NAV-TIMEUTC message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_TIMEUTC_USB = 0x2091005e; // Output rate of the UBX-NAV-TIMEUTC message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_I2C = 0x2091003d; // Output rate of the UBX-NAV-VELECEF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_SPI = 0x20910041; // Output rate of the UBX-NAV-VELECEF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_UART1 = 0x2091003e; // Output rate of the UBX-NAV-VELECEF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_UART2 = 0x2091003f; // Output rate of the UBX-NAV-VELECEF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELECEF_USB = 0x20910040; // Output rate of the UBX-NAV-VELECEF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_I2C = 0x20910042; // Output rate of the UBX-NAV-VELNED message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_SPI = 0x20910046; // Output rate of the UBX-NAV-VELNED message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_UART1 = 0x20910043; // Output rate of the UBX-NAV-VELNED message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_UART2 = 0x20910044; // Output rate of the UBX-NAV-VELNED message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_VELNED_USB = 0x20910045; // Output rate of the UBX-NAV-VELNED message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_I2C = 0x209106b6; // Output rate of the UBX-RXM-COR message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_SPI = 0x209106ba; // Output rate of the UBX-RXM-COR message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_UART1 = 0x209106b7; // Output rate of the UBX-RXM-COR message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_UART2 = 0x209106b8; // Output rate of the UBX-RXM-COR message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_COR_USB = 0x209106b9; // Output rate of the UBX-RXM-COR message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_I2C = 0x20910204; // Output rate of the UBX-RXM-MEASX message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_SPI = 0x20910208; // Output rate of the UBX-RXM-MEASX message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_UART1 = 0x20910205; // Output rate of the UBX-RXM-MEASX message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_UART2 = 0x20910206; // Output rate of the UBX-RXM-MEASX message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_MEASX_USB = 0x20910207; // Output rate of the UBX-RXM-MEASX message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_I2C = 0x209102a4; // Output rate of the UBX-RXM-RAWX message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_SPI = 0x209102a8; // Output rate of the UBX-RXM-RAWX message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_UART1 = 0x209102a5; // Output rate of the UBX-RXM-RAWX message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_UART2 = 0x209102a6; // Output rate of the UBX-RXM-RAWX message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RAWX_USB = 0x209102a7; // Output rate of the UBX-RXM-RAWX message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_I2C = 0x2091025e; // Output rate of the UBX-RXM-RLM message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_SPI = 0x20910262; // Output rate of the UBX-RXM-RLM message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_UART1 = 0x2091025f; // Output rate of the UBX-RXM-RLM message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_UART2 = 0x20910260; // Output rate of the UBX-RXM-RLM message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RLM_USB = 0x20910261; // Output rate of the UBX-RXM-RLM message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_I2C = 0x20910268; // Output rate of the UBX-RXM-RTCM message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_SPI = 0x2091026c; // Output rate of the UBX-RXM-RTCM message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_UART1 = 0x20910269; // Output rate of the UBX-RXM-RTCM message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_UART2 = 0x2091026a; // Output rate of the UBX-RXM-RTCM message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_RTCM_USB = 0x2091026b; // Output rate of the UBX-RXM-RTCM message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_I2C = 0x20910231; // Output rate of the UBX-RXM-SFRBX message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_SPI = 0x20910235; // Output rate of the UBX-RXM-SFRBX message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_UART1 = 0x20910232; // Output rate of the UBX-RXM-SFRBX message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_UART2 = 0x20910233; // Output rate of the UBX-RXM-SFRBX message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SFRBX_USB = 0x20910234; // Output rate of the UBX-RXM-SFRBX message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_I2C = 0x20910605; // Output rate of the UBX-RXM-SPARTN message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_UART1 = 0x20910606; // Output rate of the UBX-RXM-SPARTN message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_UART2 = 0x20910607; // Output rate of the UBX-RXM-SPARTN message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_USB = 0x20910608; // Output rate of the UBX-RXM-SPARTN message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_SPARTN_SPI = 0x20910609; // Output rate of the UBX-RXM-SPARTN message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_I2C = 0x20910634; // Output rate of the UBX-SEC-SIG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_SPI = 0x20910638; // Output rate of the UBX-SEC-SIG message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART1 = 0x20910635; // Output rate of the UBX-SEC-SIG message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_UART2 = 0x20910636; // Output rate of the UBX-SEC-SIG message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIG_USB = 0x20910637; // Output rate of the UBX-SEC-SIG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_I2C = 0x20910178; // Output rate of the UBX-TIM-TM2 message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_SPI = 0x2091017c; // Output rate of the UBX-TIM-TM2 message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_UART1 = 0x20910179; // Output rate of the UBX-TIM-TM2 message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_UART2 = 0x2091017a; // Output rate of the UBX-TIM-TM2 message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TM2_USB = 0x2091017b; // Output rate of the UBX-TIM-TM2 message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_I2C = 0x2091017d; // Output rate of the UBX-TIM-TP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_SPI = 0x20910181; // Output rate of the UBX-TIM-TP message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_UART1 = 0x2091017e; // Output rate of the UBX-TIM-TP message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_UART2 = 0x2091017f; // Output rate of the UBX-TIM-TP message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_TP_USB = 0x20910180; // Output rate of the UBX-TIM-TP message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_I2C = 0x20910092; // Output rate of the UBX-TIM-VRFY message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_SPI = 0x20910096; // Output rate of the UBX-TIM-VRFY message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_UART1 = 0x20910093; // Output rate of the UBX-TIM-VRFY message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_UART2 = 0x20910094; // Output rate of the UBX-TIM-VRFY message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_VRFY_USB = 0x20910095; // Output rate of the UBX-TIM-VRFY message on port USB + +// Additional CFG_MSGOUT keys for the ZED-F9R HPS121 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_I2C = 0x20910083; // Output rate of the UBX-NAV-COV message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_UART1 = 0x20910084; // Output rate of the UBX-NAV-COV message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_UART2 = 0x20910085; // Output rate of the UBX-NAV-COV message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_USB = 0x20910086; // Output rate of the UBX-NAV-COV message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_SPI = 0x20910087; // Output rate of the UBX-NAV-COV message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_I2C = 0x209100e2; // Output rate of the NMEA-GX-THS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_UART1 = 0x209100e3; // Output rate of the NMEA-GX-THS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_UART2 = 0x209100e4; // Output rate of the NMEA-GX-THS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_USB = 0x209100e5; // Output rate of the NMEA-GX-THS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_SPI = 0x209100e6; // Output rate of the NMEA-GX-THS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_I2C = 0x20910105; // Output rate of the UBX-ESF-STATUS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_I2C = 0x20910083; // Output rate of the UBX-NAV-COV message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_UART1 = 0x20910084; // Output rate of the UBX-NAV-COV message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_UART2 = 0x20910085; // Output rate of the UBX-NAV-COV message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_USB = 0x20910086; // Output rate of the UBX-NAV-COV message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_COV_SPI = 0x20910087; // Output rate of the UBX-NAV-COV message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_I2C = 0x209100e2; // Output rate of the NMEA-GX-THS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_UART1 = 0x209100e3; // Output rate of the NMEA-GX-THS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_UART2 = 0x209100e4; // Output rate of the NMEA-GX-THS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_USB = 0x209100e5; // Output rate of the NMEA-GX-THS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_ID_THS_SPI = 0x209100e6; // Output rate of the NMEA-GX-THS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_I2C = 0x20910105; // Output rate of the UBX-ESF-STATUS message on port I2C const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_UART1 = 0x20910106; // Output rate of the UBX-ESF-STATUS message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_UART2 = 0x20910107; // Output rate of the UBX-ESF-STATUS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_USB = 0x20910108; // Output rate of the UBX-ESF-STATUS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_SPI = 0x20910109; // Output rate of the UBX-ESF-STATUS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_I2C = 0x2091010f; // Output rate of the UBX-ESF-ALG message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_UART1 = 0x20910110; // Output rate of the UBX-ESF-ALG message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_UART2 = 0x20910111; // Output rate of the UBX-ESF-ALG message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_USB = 0x20910112; // Output rate of the UBX-ESF-ALG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_SPI = 0x20910113; // Output rate of the UBX-ESF-ALG message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_I2C = 0x20910114; // Output rate of the UBX-ESF-INS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_UART1 = 0x20910115; // Output rate of the UBX-ESF-INS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_UART2 = 0x20910116; // Output rate of the UBX-ESF-INS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_USB = 0x20910117; // Output rate of the UBX-ESF-INS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_SPI = 0x20910118; // Output rate of the UBX-ESF-INS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_I2C = 0x20910277; // Output rate of the UBX-ESF-MEAS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_UART1 = 0x20910278; // Output rate of the UBX-ESF-MEAS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_UART2 = 0x20910279; // Output rate of the UBX-ESF-MEAS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_USB = 0x2091027a; // Output rate of the UBX-ESF-MEAS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_SPI = 0x2091027b; // Output rate of the UBX-ESF-MEAS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_I2C = 0x2091029f; // Output rate of the UBX-ESF-RAW message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_UART1 = 0x209102a0; // Output rate of the UBX-ESF-RAW message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_UART2 = 0x209102a1; // Output rate of the UBX-ESF-RAW message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_USB = 0x209102a2; // Output rate of the UBX-ESF-RAW message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_SPI = 0x209102a3; // Output rate of the UBX-ESF-RAW message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_I2C = 0x20910313; // Output rate of the UBX-NAV-EELL message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_UART1 = 0x20910314; // Output rate of the UBX-NAV-EELL message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_UART2 = 0x20910315; // Output rate of the UBX-NAV-EELL message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_USB = 0x20910316; // Output rate of the UBX-NAV-EELL message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_SPI = 0x20910317; // Output rate of the UBX-NAV-EELL message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_I2C = 0x2091062a; // Output rate of the UBX-NAV-PVAT message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_UART1 = 0x2091062b; // Output rate of the UBX-NAV-PVAT message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_UART2 = 0x2091062c; // Output rate of the UBX-NAV-PVAT message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_USB = 0x2091062d; // Output rate of the UBX-NAV-PVAT message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_SPI = 0x2091062e; // Output rate of the UBX-NAV-PVAT message on port SPI - - -//Additional CFG_MSGOUT keys for the ZED-F9T +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_USB = 0x20910108; // Output rate of the UBX-ESF-STATUS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_STATUS_SPI = 0x20910109; // Output rate of the UBX-ESF-STATUS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_I2C = 0x2091010f; // Output rate of the UBX-ESF-ALG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_UART1 = 0x20910110; // Output rate of the UBX-ESF-ALG message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_UART2 = 0x20910111; // Output rate of the UBX-ESF-ALG message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_USB = 0x20910112; // Output rate of the UBX-ESF-ALG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_ALG_SPI = 0x20910113; // Output rate of the UBX-ESF-ALG message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_I2C = 0x20910114; // Output rate of the UBX-ESF-INS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_UART1 = 0x20910115; // Output rate of the UBX-ESF-INS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_UART2 = 0x20910116; // Output rate of the UBX-ESF-INS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_USB = 0x20910117; // Output rate of the UBX-ESF-INS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_INS_SPI = 0x20910118; // Output rate of the UBX-ESF-INS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_I2C = 0x20910277; // Output rate of the UBX-ESF-MEAS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_UART1 = 0x20910278; // Output rate of the UBX-ESF-MEAS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_UART2 = 0x20910279; // Output rate of the UBX-ESF-MEAS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_USB = 0x2091027a; // Output rate of the UBX-ESF-MEAS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_MEAS_SPI = 0x2091027b; // Output rate of the UBX-ESF-MEAS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_I2C = 0x2091029f; // Output rate of the UBX-ESF-RAW message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_UART1 = 0x209102a0; // Output rate of the UBX-ESF-RAW message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_UART2 = 0x209102a1; // Output rate of the UBX-ESF-RAW message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_USB = 0x209102a2; // Output rate of the UBX-ESF-RAW message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_ESF_RAW_SPI = 0x209102a3; // Output rate of the UBX-ESF-RAW message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_I2C = 0x20910313; // Output rate of the UBX-NAV-EELL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_UART1 = 0x20910314; // Output rate of the UBX-NAV-EELL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_UART2 = 0x20910315; // Output rate of the UBX-NAV-EELL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_USB = 0x20910316; // Output rate of the UBX-NAV-EELL message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_EELL_SPI = 0x20910317; // Output rate of the UBX-NAV-EELL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_I2C = 0x2091062a; // Output rate of the UBX-NAV-PVAT message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_UART1 = 0x2091062b; // Output rate of the UBX-NAV-PVAT message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_UART2 = 0x2091062c; // Output rate of the UBX-NAV-PVAT message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_USB = 0x2091062d; // Output rate of the UBX-NAV-PVAT message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_PVAT_SPI = 0x2091062e; // Output rate of the UBX-NAV-PVAT message on port SPI + +// Additional CFG_MSGOUT keys for the ZED-F9T //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_I2C = 0x20910661; // Output rate of the NMEA-NAV2-GX-GGA message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_SPI = 0x20910665; // Output rate of the NMEA-NAV2-GX-GGA message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_UART1 = 0x20910662; // Output rate of the NMEA-NAV2-GX-GGA message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_UART2 = 0x20910663; // Output rate of the NMEA-NAV2-GX-GGA message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_USB = 0x20910664; // Output rate of the NMEA-NAV2-GX-GGA message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_I2C = 0x20910670; // Output rate of the NMEA-NAV2-GX-GLL message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_SPI = 0x20910674; // Output rate of the NMEA-NAV2-GX-GLL message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_UART1 = 0x20910671; // Output rate of the NMEA-NAV2-GX-GLL message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_UART2 = 0x20910672; // Output rate of the NMEA-NAV2-GX-GLL message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_USB = 0x20910673; // Output rate of the NMEA-NAV2-GX-GLL message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_I2C = 0x2091065c; // Output rate of the NMEA-NAV2-GX-GNS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_SPI = 0x20910660; // Output rate of the NMEA-NAV2-GX-GNS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_UART1 = 0x2091065d; // Output rate of the NMEA-NAV2-GX-GNS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_UART2 = 0x2091065e; // Output rate of the NMEA-NAV2-GX-GNS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_USB = 0x2091065f; // Output rate of the NMEA-NAV2-GX-GNS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_I2C = 0x20910666; // Output rate of the NMEA-NAV2-GX-GSA message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_SPI = 0x2091066a; // Output rate of the NMEA-NAV2-GX-GSA message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_UART1 = 0x20910667; // Output rate of the NMEA-NAV2-GX-GSA message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_UART2 = 0x20910668; // Output rate of the NMEA-NAV2-GX-GSA message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_USB = 0x20910669; // Output rate of the NMEA-NAV2-GX-GSA message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_I2C = 0x20910652; // Output rate of the NMEA-NAV2-GX-RMC message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_SPI = 0x20910656; // Output rate of the NMEA-NAV2-GX-RMC message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_UART1 = 0x20910653; // Output rate of the NMEA-NAV2-GX-RMC message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_UART2 = 0x20910654; // Output rate of the NMEA-NAV2-GX-RMC message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_USB = 0x20910655; // Output rate of the NMEA-NAV2-GX-RMC message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_I2C = 0x20910657; // Output rate of the NMEA-NAV2-GX-VTG message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_SPI = 0x2091065b; // Output rate of the NMEA-NAV2-GX-VTG message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_UART1 = 0x20910658; // Output rate of the NMEA-NAV2-GX-VTG message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_UART2 = 0x20910659; // Output rate of the NMEA-NAV2-GX-VTG message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_USB = 0x2091065a; // Output rate of the NMEA-NAV2-GX-VTG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_I2C = 0x2091067f; // Output rate of the NMEA-NAV2-GX-ZDA message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_SPI = 0x20910683; // Output rate of the NMEA-NAV2-GX-ZDA message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_UART1 = 0x20910680; // Output rate of the NMEA-NAV2-GX-ZDA message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_UART2 = 0x20910681; // Output rate of the NMEA-NAV2-GX-ZDA message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_USB = 0x20910682; // Output rate of the NMEA-NAV2-GX-ZDA message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_I2C = 0x20910430; // Output rate of the UBX-NAV2-CLOCK message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_SPI = 0x20910434; // Output rate of the UBX-NAV2-CLOCK message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_UART1 = 0x20910431; // Output rate of the UBX-NAV2-CLOCK message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_UART2 = 0x20910432; // Output rate of the UBX-NAV2-CLOCK message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_USB = 0x20910433; // Output rate of the UBX-NAV2-CLOCK message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_I2C = 0x20910435; // Output rate of the UBX-NAV2-COV message onport I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_SPI = 0x20910439; // Output rate of the UBX-NAV2-COV message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_UART1 = 0x20910436; // Output rate of the UBX-NAV2-COV message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_UART2 = 0x20910437; // Output rate of the UBX-NAV2-COV message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_USB = 0x20910438; // Output rate of the UBX-NAV2-COV message onport USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_I2C = 0x20910465; // Output rate of the UBX-NAV2-DOP message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_SPI = 0x20910469; // Output rate of the UBX-NAV2-DOP message onport SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_UART1 = 0x20910466; // Output rate of the UBX-NAV2-DOP message onport UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_UART2 = 0x20910467; // Output rate of the UBX-NAV2-DOP message onport UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_USB = 0x20910468; // Output rate of the UBX-NAV2-DOP message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_I2C = 0x20910565; // Output rate of the UBX-NAV2-EOE message onport I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_SPI = 0x20910569; // Output rate of the UBX-NAV2-EOE message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_UART1 = 0x20910566; // Output rate of the UBX-NAV2-EOE message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_UART2 = 0x20910567; // Output rate of the UBX-NAV2-EOE message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_USB = 0x20910568; // Output rate of the UBX-NAV2-EOE message onport USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_I2C = 0x20910475; // Output rate of the UBX-NAV2-ODO message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_SPI = 0x20910479; // Output rate of the UBX-NAV2-ODO message onport SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_UART1 = 0x20910476; // Output rate of the UBX-NAV2-ODO message onport UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_UART2 = 0x20910477; // Output rate of the UBX-NAV2-ODO message onport UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_USB = 0x20910478; // Output rate of the UBX-NAV2-ODO message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_I2C = 0x20910480; // Output rate of the UBX-NAV2-POSECEF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_SPI = 0x20910484; // Output rate of the UBX-NAV2-POSECEF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_UART1 = 0x20910481; // Output rate of the UBX-NAV2-POSECEF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_UART2 = 0x20910482; // Output rate of the UBX-NAV2-POSECEF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_USB = 0x20910483; // Output rate of the UBX-NAV2-POSECEF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_I2C = 0x20910485; // Output rate of the UBX-NAV2-POSLLH message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_SPI = 0x20910489; // Output rate of the UBX-NAV2-POSLLH message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_UART1 = 0x20910486; // Output rate of the UBX-NAV2-POSLLH message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_UART2 = 0x20910487; // Output rate of the UBX-NAV2-POSLLH message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_USB = 0x20910488; // Output rate of the UBX-NAV2-POSLLH message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_I2C = 0x20910490; // Output rate of the UBX-NAV2-PVT message onport I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_SPI = 0x20910494; // Output rate of the UBX-NAV2-PVT message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_UART1 = 0x20910491; // Output rate of the UBX-NAV2-PVT message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_UART2 = 0x20910492; // Output rate of the UBX-NAV2-PVT message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_USB = 0x20910493; // Output rate of the UBX-NAV2-PVT message onport USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_I2C = 0x20910495; // Output rate of the UBX-NAV2-SAT message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_SPI = 0x20910499; // Output rate of the UBX-NAV2-SAT message onport SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_UART1 = 0x20910496; // Output rate of the UBX-NAV2-SAT message onport UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_UART2 = 0x20910497; // Output rate of the UBX-NAV2-SAT message onport UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_USB = 0x20910498; // Output rate of the UBX-NAV2-SAT message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_I2C = 0x20910500; // Output rate of the UBX-NAV2-SBAS messageon port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_SPI = 0x20910504; // Output rate of the UBX-NAV2-SBAS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_UART1 = 0x20910501; // Output rate of the UBX-NAV2-SBAS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_UART2 = 0x20910502; // Output rate of the UBX-NAV2-SBAS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_USB = 0x20910503; // Output rate of the UBX-NAV2-SBAS messageon port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_I2C = 0x20910505; // Output rate of the UBX-NAV2-SIG message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_SPI = 0x20910509; // Output rate of the UBX-NAV2-SIG message onport SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_UART1 = 0x20910506; // Output rate of the UBX-NAV2-SIG message onport UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_UART2 = 0x20910507; // Output rate of the UBX-NAV2-SIG message onport UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_USB = 0x20910508; // Output rate of the UBX-NAV2-SIG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_I2C = 0x20910510; // Output rate of the UBX-NAV2-SLAS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_SPI = 0x20910514; // Output rate of the UBX-NAV2-SLAS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_UART1 = 0x20910511; // Output rate of the UBX-NAV2-SLAS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_UART2 = 0x20910512; // Output rate of the UBX-NAV2-SLAS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_USB = 0x20910513; // Output rate of the UBX-NAV2-SLAS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_I2C = 0x20910515; // Output rate of the UBX-NAV2-STATUS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_SPI = 0x20910519; // Output rate of the UBX-NAV2-STATUS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_UART1 = 0x20910516; // Output rate of the UBX-NAV2-STATUS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_UART2 = 0x20910517; // Output rate of the UBX-NAV2-STATUS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_USB = 0x20910518; // Output rate of the UBX-NAV2-STATUS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_I2C = 0x20910520; // Output rate of the UBX-NAV2-SVIN message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_SPI = 0x20910524; // Output rate of the UBX-NAV2-SVIN message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_UART1 = 0x20910521; // Output rate of the UBX-NAV2-SVIN message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_UART2 = 0x20910522; // Output rate of the UBX-NAV2-SVIN message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_USB = 0x20910523; // Output rate of the UBX-NAV2-SVIN message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_I2C = 0x20910525; // Output rate of the UBX-NAV2-TIMEBDS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_SPI = 0x20910529; // Output rate of the UBX-NAV2-TIMEBDS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_UART1 = 0x20910526; // Output rate of the UBX-NAV2-TIMEBDS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_UART2 = 0x20910527; // Output rate of the UBX-NAV2-TIMEBDS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_USB = 0x20910528; // Output rate of the UBX-NAV2-TIMEBDS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_I2C = 0x20910530; // Output rate of the UBX-NAV2-TIMEGAL message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_SPI = 0x20910534; // Output rate of the UBX-NAV2-TIMEGAL message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_UART1 = 0x20910531; // Output rate of the UBX-NAV2-TIMEGAL message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_UART2 = 0x20910532; // Output rate of the UBX-NAV2-TIMEGAL message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_USB = 0x20910533; // Output rate of the UBX-NAV2-TIMEGAL message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_I2C = 0x20910535; // Output rate of the UBX-NAV2-TIMEGLO message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_SPI = 0x20910539; // Output rate of the UBX-NAV2-TIMEGLO message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_UART1 = 0x20910536; // Output rate of the UBX-NAV2-TIMEGLO message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_UART2 = 0x20910537; // Output rate of the UBX-NAV2-TIMEGLO message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_USB = 0x20910538; // Output rate of the UBX-NAV2-TIMEGLO message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_I2C = 0x20910540; // Output rate of the UBX-NAV2-TIMEGPS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_SPI = 0x20910544; // Output rate of the UBX-NAV2-TIMEGPS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_UART1 = 0x20910541; // Output rate of the UBX-NAV2-TIMEGPS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_UART2 = 0x20910542; // Output rate of the UBX-NAV2-TIMEGPS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_USB = 0x20910543; // Output rate of the UBX-NAV2-TIMEGPS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_I2C = 0x20910545; // Output rate of the UBX-NAV2-TIMELS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_SPI = 0x20910549; // Output rate of the UBX-NAV2-TIMELS message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_UART1 = 0x20910546; // Output rate of the UBX-NAV2-TIMELS message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_UART2 = 0x20910547; // Output rate of the UBX-NAV2-TIMELS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_USB = 0x20910548; // Output rate of the UBX-NAV2-TIMELS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_I2C = 0x20910575; // Output rate of the UBX-NAV2-TIMEQZSS message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_SPI = 0x20910579; // Output rate of the UBX-NAV2-TIMEQZSS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_I2C = 0x20910661; // Output rate of the NMEA-NAV2-GX-GGA message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_SPI = 0x20910665; // Output rate of the NMEA-NAV2-GX-GGA message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_UART1 = 0x20910662; // Output rate of the NMEA-NAV2-GX-GGA message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_UART2 = 0x20910663; // Output rate of the NMEA-NAV2-GX-GGA message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GGA_USB = 0x20910664; // Output rate of the NMEA-NAV2-GX-GGA message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_I2C = 0x20910670; // Output rate of the NMEA-NAV2-GX-GLL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_SPI = 0x20910674; // Output rate of the NMEA-NAV2-GX-GLL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_UART1 = 0x20910671; // Output rate of the NMEA-NAV2-GX-GLL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_UART2 = 0x20910672; // Output rate of the NMEA-NAV2-GX-GLL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GLL_USB = 0x20910673; // Output rate of the NMEA-NAV2-GX-GLL message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_I2C = 0x2091065c; // Output rate of the NMEA-NAV2-GX-GNS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_SPI = 0x20910660; // Output rate of the NMEA-NAV2-GX-GNS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_UART1 = 0x2091065d; // Output rate of the NMEA-NAV2-GX-GNS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_UART2 = 0x2091065e; // Output rate of the NMEA-NAV2-GX-GNS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GNS_USB = 0x2091065f; // Output rate of the NMEA-NAV2-GX-GNS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_I2C = 0x20910666; // Output rate of the NMEA-NAV2-GX-GSA message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_SPI = 0x2091066a; // Output rate of the NMEA-NAV2-GX-GSA message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_UART1 = 0x20910667; // Output rate of the NMEA-NAV2-GX-GSA message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_UART2 = 0x20910668; // Output rate of the NMEA-NAV2-GX-GSA message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_GSA_USB = 0x20910669; // Output rate of the NMEA-NAV2-GX-GSA message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_I2C = 0x20910652; // Output rate of the NMEA-NAV2-GX-RMC message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_SPI = 0x20910656; // Output rate of the NMEA-NAV2-GX-RMC message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_UART1 = 0x20910653; // Output rate of the NMEA-NAV2-GX-RMC message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_UART2 = 0x20910654; // Output rate of the NMEA-NAV2-GX-RMC message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_RMC_USB = 0x20910655; // Output rate of the NMEA-NAV2-GX-RMC message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_I2C = 0x20910657; // Output rate of the NMEA-NAV2-GX-VTG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_SPI = 0x2091065b; // Output rate of the NMEA-NAV2-GX-VTG message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_UART1 = 0x20910658; // Output rate of the NMEA-NAV2-GX-VTG message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_UART2 = 0x20910659; // Output rate of the NMEA-NAV2-GX-VTG message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_VTG_USB = 0x2091065a; // Output rate of the NMEA-NAV2-GX-VTG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_I2C = 0x2091067f; // Output rate of the NMEA-NAV2-GX-ZDA message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_SPI = 0x20910683; // Output rate of the NMEA-NAV2-GX-ZDA message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_UART1 = 0x20910680; // Output rate of the NMEA-NAV2-GX-ZDA message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_UART2 = 0x20910681; // Output rate of the NMEA-NAV2-GX-ZDA message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_NMEA_NAV2_ID_ZDA_USB = 0x20910682; // Output rate of the NMEA-NAV2-GX-ZDA message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_I2C = 0x20910430; // Output rate of the UBX-NAV2-CLOCK message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_SPI = 0x20910434; // Output rate of the UBX-NAV2-CLOCK message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_UART1 = 0x20910431; // Output rate of the UBX-NAV2-CLOCK message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_UART2 = 0x20910432; // Output rate of the UBX-NAV2-CLOCK message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_CLOCK_USB = 0x20910433; // Output rate of the UBX-NAV2-CLOCK message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_I2C = 0x20910435; // Output rate of the UBX-NAV2-COV message onport I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_SPI = 0x20910439; // Output rate of the UBX-NAV2-COV message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_UART1 = 0x20910436; // Output rate of the UBX-NAV2-COV message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_UART2 = 0x20910437; // Output rate of the UBX-NAV2-COV message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_COV_USB = 0x20910438; // Output rate of the UBX-NAV2-COV message onport USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_I2C = 0x20910465; // Output rate of the UBX-NAV2-DOP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_SPI = 0x20910469; // Output rate of the UBX-NAV2-DOP message onport SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_UART1 = 0x20910466; // Output rate of the UBX-NAV2-DOP message onport UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_UART2 = 0x20910467; // Output rate of the UBX-NAV2-DOP message onport UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_DOP_USB = 0x20910468; // Output rate of the UBX-NAV2-DOP message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_I2C = 0x20910565; // Output rate of the UBX-NAV2-EOE message onport I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_SPI = 0x20910569; // Output rate of the UBX-NAV2-EOE message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_UART1 = 0x20910566; // Output rate of the UBX-NAV2-EOE message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_UART2 = 0x20910567; // Output rate of the UBX-NAV2-EOE message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_EOE_USB = 0x20910568; // Output rate of the UBX-NAV2-EOE message onport USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_I2C = 0x20910475; // Output rate of the UBX-NAV2-ODO message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_SPI = 0x20910479; // Output rate of the UBX-NAV2-ODO message onport SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_UART1 = 0x20910476; // Output rate of the UBX-NAV2-ODO message onport UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_UART2 = 0x20910477; // Output rate of the UBX-NAV2-ODO message onport UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_ODO_USB = 0x20910478; // Output rate of the UBX-NAV2-ODO message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_I2C = 0x20910480; // Output rate of the UBX-NAV2-POSECEF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_SPI = 0x20910484; // Output rate of the UBX-NAV2-POSECEF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_UART1 = 0x20910481; // Output rate of the UBX-NAV2-POSECEF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_UART2 = 0x20910482; // Output rate of the UBX-NAV2-POSECEF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSECEF_USB = 0x20910483; // Output rate of the UBX-NAV2-POSECEF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_I2C = 0x20910485; // Output rate of the UBX-NAV2-POSLLH message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_SPI = 0x20910489; // Output rate of the UBX-NAV2-POSLLH message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_UART1 = 0x20910486; // Output rate of the UBX-NAV2-POSLLH message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_UART2 = 0x20910487; // Output rate of the UBX-NAV2-POSLLH message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_POSLLH_USB = 0x20910488; // Output rate of the UBX-NAV2-POSLLH message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_I2C = 0x20910490; // Output rate of the UBX-NAV2-PVT message onport I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_SPI = 0x20910494; // Output rate of the UBX-NAV2-PVT message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_UART1 = 0x20910491; // Output rate of the UBX-NAV2-PVT message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_UART2 = 0x20910492; // Output rate of the UBX-NAV2-PVT message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_PVT_USB = 0x20910493; // Output rate of the UBX-NAV2-PVT message onport USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_I2C = 0x20910495; // Output rate of the UBX-NAV2-SAT message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_SPI = 0x20910499; // Output rate of the UBX-NAV2-SAT message onport SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_UART1 = 0x20910496; // Output rate of the UBX-NAV2-SAT message onport UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_UART2 = 0x20910497; // Output rate of the UBX-NAV2-SAT message onport UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SAT_USB = 0x20910498; // Output rate of the UBX-NAV2-SAT message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_I2C = 0x20910500; // Output rate of the UBX-NAV2-SBAS messageon port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_SPI = 0x20910504; // Output rate of the UBX-NAV2-SBAS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_UART1 = 0x20910501; // Output rate of the UBX-NAV2-SBAS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_UART2 = 0x20910502; // Output rate of the UBX-NAV2-SBAS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SBAS_USB = 0x20910503; // Output rate of the UBX-NAV2-SBAS messageon port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_I2C = 0x20910505; // Output rate of the UBX-NAV2-SIG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_SPI = 0x20910509; // Output rate of the UBX-NAV2-SIG message onport SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_UART1 = 0x20910506; // Output rate of the UBX-NAV2-SIG message onport UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_UART2 = 0x20910507; // Output rate of the UBX-NAV2-SIG message onport UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SIG_USB = 0x20910508; // Output rate of the UBX-NAV2-SIG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_I2C = 0x20910510; // Output rate of the UBX-NAV2-SLAS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_SPI = 0x20910514; // Output rate of the UBX-NAV2-SLAS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_UART1 = 0x20910511; // Output rate of the UBX-NAV2-SLAS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_UART2 = 0x20910512; // Output rate of the UBX-NAV2-SLAS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SLAS_USB = 0x20910513; // Output rate of the UBX-NAV2-SLAS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_I2C = 0x20910515; // Output rate of the UBX-NAV2-STATUS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_SPI = 0x20910519; // Output rate of the UBX-NAV2-STATUS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_UART1 = 0x20910516; // Output rate of the UBX-NAV2-STATUS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_UART2 = 0x20910517; // Output rate of the UBX-NAV2-STATUS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_STATUS_USB = 0x20910518; // Output rate of the UBX-NAV2-STATUS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_I2C = 0x20910520; // Output rate of the UBX-NAV2-SVIN message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_SPI = 0x20910524; // Output rate of the UBX-NAV2-SVIN message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_UART1 = 0x20910521; // Output rate of the UBX-NAV2-SVIN message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_UART2 = 0x20910522; // Output rate of the UBX-NAV2-SVIN message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_SVIN_USB = 0x20910523; // Output rate of the UBX-NAV2-SVIN message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_I2C = 0x20910525; // Output rate of the UBX-NAV2-TIMEBDS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_SPI = 0x20910529; // Output rate of the UBX-NAV2-TIMEBDS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_UART1 = 0x20910526; // Output rate of the UBX-NAV2-TIMEBDS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_UART2 = 0x20910527; // Output rate of the UBX-NAV2-TIMEBDS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEBDS_USB = 0x20910528; // Output rate of the UBX-NAV2-TIMEBDS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_I2C = 0x20910530; // Output rate of the UBX-NAV2-TIMEGAL message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_SPI = 0x20910534; // Output rate of the UBX-NAV2-TIMEGAL message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_UART1 = 0x20910531; // Output rate of the UBX-NAV2-TIMEGAL message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_UART2 = 0x20910532; // Output rate of the UBX-NAV2-TIMEGAL message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGAL_USB = 0x20910533; // Output rate of the UBX-NAV2-TIMEGAL message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_I2C = 0x20910535; // Output rate of the UBX-NAV2-TIMEGLO message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_SPI = 0x20910539; // Output rate of the UBX-NAV2-TIMEGLO message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_UART1 = 0x20910536; // Output rate of the UBX-NAV2-TIMEGLO message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_UART2 = 0x20910537; // Output rate of the UBX-NAV2-TIMEGLO message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGLO_USB = 0x20910538; // Output rate of the UBX-NAV2-TIMEGLO message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_I2C = 0x20910540; // Output rate of the UBX-NAV2-TIMEGPS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_SPI = 0x20910544; // Output rate of the UBX-NAV2-TIMEGPS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_UART1 = 0x20910541; // Output rate of the UBX-NAV2-TIMEGPS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_UART2 = 0x20910542; // Output rate of the UBX-NAV2-TIMEGPS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEGPS_USB = 0x20910543; // Output rate of the UBX-NAV2-TIMEGPS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_I2C = 0x20910545; // Output rate of the UBX-NAV2-TIMELS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_SPI = 0x20910549; // Output rate of the UBX-NAV2-TIMELS message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_UART1 = 0x20910546; // Output rate of the UBX-NAV2-TIMELS message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_UART2 = 0x20910547; // Output rate of the UBX-NAV2-TIMELS message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMELS_USB = 0x20910548; // Output rate of the UBX-NAV2-TIMELS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_I2C = 0x20910575; // Output rate of the UBX-NAV2-TIMEQZSS message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_SPI = 0x20910579; // Output rate of the UBX-NAV2-TIMEQZSS message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_UART1 = 0x20910576; // Output rate of the UBX-NAV2-TIMEQZSS message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_UART2 = 0x20910577; // Output rate of the UBX-NAV2-TIMEQZSS message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_USB = 0x20910578; // Output rate of the UBX-NAV2-TIMEQZSS message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_I2C = 0x20910550; // Output rate of the UBX-NAV2-TIMEUTC message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_SPI = 0x20910554; // Output rate of the UBX-NAV2-TIMEUTC message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_UART1 = 0x20910551; // Output rate of the UBX-NAV2-TIMEUTC message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_UART2 = 0x20910552; // Output rate of the UBX-NAV2-TIMEUTC message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_USB = 0x20910553; // Output rate of the UBX-NAV2-TIMEUTC message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_I2C = 0x20910555; // Output rate of the UBX-NAV2-VELECEF message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_SPI = 0x20910559; // Output rate of the UBX-NAV2-VELECEF message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_UART1 = 0x20910556; // Output rate of the UBX-NAV2-VELECEF message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_UART2 = 0x20910557; // Output rate of the UBX-NAV2-VELECEF message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_USB = 0x20910558; // Output rate of the UBX-NAV2-VELECEF message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_I2C = 0x20910560; // Output rate of the UBX-NAV2-VELNED message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_SPI = 0x20910564; // Output rate of the UBX-NAV2-VELNED message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_UART1 = 0x20910561; // Output rate of the UBX-NAV2-VELNED message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_UART2 = 0x20910562; // Output rate of the UBX-NAV2-VELNED message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_USB = 0x20910563; // Output rate of the UBX-NAV2-VELNED message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_I2C = 0x20910590; // Output rate of the UBX-NAV-NMI message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_SPI = 0x20910594; // Output rate of the UBX-NAV-NMI message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_UART1 = 0x20910591; // Output rate of the UBX-NAV-NMI message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_UART2 = 0x20910592; // Output rate of the UBX-NAV-NMI message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_USB = 0x20910593; // Output rate of the UBX-NAV-NMI message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_I2C = 0x20910610; // Output rate of the UBX-RXM-TM message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_SPI = 0x20910614; // Output rate of the UBX-RXM-TM message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_UART1 = 0x20910611; // Output rate of the UBX-RXM-TM message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_UART2 = 0x20910612; // Output rate of the UBX-RXM-TM message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_USB = 0x20910613; // Output rate of the UBX-RXM-TM message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_I2C = 0x20910689; // Output rate of the UBX-SEC-SIGLOG message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_SPI = 0x2091068d; // Output rate of the UBX-SEC-SIGLOG message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_UART1 = 0x2091068a; // Output rate of the UBX-SEC-SIGLOG message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_UART2 = 0x2091068b; // Output rate of the UBX-SEC-SIGLOG message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_USB = 0x2091068c; // Output rate of the UBX-SEC-SIGLOG message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_I2C = 0x20910097; // Output rate of the UBX-TIM-SVIN message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_SPI = 0x2091009b; // Output rate of the UBX-TIM-SVIN message on port SPI -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_UART1 = 0x20910098; // Output rate of the UBX-TIM-SVIN message on port UART1 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_UART2 = 0x20910099; // Output rate of the UBX-TIM-SVIN message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_USB = 0x2091009a; // Output rate of the UBX-TIM-SVIN message on port USB - -//Additional CFG_MSGOUT keys for the NEO-D9S +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEQZSS_USB = 0x20910578; // Output rate of the UBX-NAV2-TIMEQZSS message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_I2C = 0x20910550; // Output rate of the UBX-NAV2-TIMEUTC message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_SPI = 0x20910554; // Output rate of the UBX-NAV2-TIMEUTC message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_UART1 = 0x20910551; // Output rate of the UBX-NAV2-TIMEUTC message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_UART2 = 0x20910552; // Output rate of the UBX-NAV2-TIMEUTC message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_TIMEUTC_USB = 0x20910553; // Output rate of the UBX-NAV2-TIMEUTC message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_I2C = 0x20910555; // Output rate of the UBX-NAV2-VELECEF message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_SPI = 0x20910559; // Output rate of the UBX-NAV2-VELECEF message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_UART1 = 0x20910556; // Output rate of the UBX-NAV2-VELECEF message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_UART2 = 0x20910557; // Output rate of the UBX-NAV2-VELECEF message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELECEF_USB = 0x20910558; // Output rate of the UBX-NAV2-VELECEF message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_I2C = 0x20910560; // Output rate of the UBX-NAV2-VELNED message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_SPI = 0x20910564; // Output rate of the UBX-NAV2-VELNED message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_UART1 = 0x20910561; // Output rate of the UBX-NAV2-VELNED message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_UART2 = 0x20910562; // Output rate of the UBX-NAV2-VELNED message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV2_VELNED_USB = 0x20910563; // Output rate of the UBX-NAV2-VELNED message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_I2C = 0x20910590; // Output rate of the UBX-NAV-NMI message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_SPI = 0x20910594; // Output rate of the UBX-NAV-NMI message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_UART1 = 0x20910591; // Output rate of the UBX-NAV-NMI message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_UART2 = 0x20910592; // Output rate of the UBX-NAV-NMI message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_NAV_NMI_USB = 0x20910593; // Output rate of the UBX-NAV-NMI message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_I2C = 0x20910610; // Output rate of the UBX-RXM-TM message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_SPI = 0x20910614; // Output rate of the UBX-RXM-TM message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_UART1 = 0x20910611; // Output rate of the UBX-RXM-TM message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_UART2 = 0x20910612; // Output rate of the UBX-RXM-TM message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_TM_USB = 0x20910613; // Output rate of the UBX-RXM-TM message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_I2C = 0x20910689; // Output rate of the UBX-SEC-SIGLOG message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_SPI = 0x2091068d; // Output rate of the UBX-SEC-SIGLOG message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_UART1 = 0x2091068a; // Output rate of the UBX-SEC-SIGLOG message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_UART2 = 0x2091068b; // Output rate of the UBX-SEC-SIGLOG message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_SEC_SIGLOG_USB = 0x2091068c; // Output rate of the UBX-SEC-SIGLOG message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_I2C = 0x20910097; // Output rate of the UBX-TIM-SVIN message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_SPI = 0x2091009b; // Output rate of the UBX-TIM-SVIN message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_UART1 = 0x20910098; // Output rate of the UBX-TIM-SVIN message on port UART1 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_UART2 = 0x20910099; // Output rate of the UBX-TIM-SVIN message on port UART2 +const uint32_t UBLOX_CFG_MSGOUT_UBX_TIM_SVIN_USB = 0x2091009a; // Output rate of the UBX-TIM-SVIN message on port USB + +// Additional CFG_MSGOUT keys for the NEO-D9S //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C = 0x2091031d; // Output rate of the UBX_RXM_PMP message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_SPI = 0x20910321; // Output rate of the UBX_RXM_PMP message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C = 0x2091031d; // Output rate of the UBX_RXM_PMP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_SPI = 0x20910321; // Output rate of the UBX_RXM_PMP message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1 = 0x2091031e; // Output rate of the UBX_RXM_PMP message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2 = 0x2091031f; // Output rate of the UBX_RXM_PMP message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_USB = 0x20910320; // Output rate of the UBX_RXM_PMP message on port USB -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_I2C = 0x20910322; // Output rate of the UBX_MON_PMP message on port I2C -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_SPI = 0x20910326; // Output rate of the UBX_MON_PMP message on port SPI +const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_PMP_USB = 0x20910320; // Output rate of the UBX_RXM_PMP message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_I2C = 0x20910322; // Output rate of the UBX_MON_PMP message on port I2C +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_SPI = 0x20910326; // Output rate of the UBX_MON_PMP message on port SPI const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_UART1 = 0x20910323; // Output rate of the UBX_MON_PMP message on port UART1 const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_UART2 = 0x20910324; // Output rate of the UBX_MON_PMP message on port UART2 -const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_USB = 0x20910325; // Output rate of the UBX_MON_PMP message on port USB +const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_USB = 0x20910325; // Output rate of the UBX_MON_PMP message on port USB -//CFG-NAV2: Secondary output configuration +// CFG-NAV2: Secondary output configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_NAV2_OUT_ENABLED = 0x10170001; // Enable secondary (NAV2) output +const uint32_t UBLOX_CFG_NAV2_OUT_ENABLED = 0x10170001; // Enable secondary (NAV2) output const uint32_t UBLOX_CFG_NAV2_SBAS_USE_INTEGRITY = 0x10170002; // Use SBAS integrity information in the secondary output -//CFG-NAVHPG: High precision navigation configuration +// CFG-NAVHPG: High precision navigation configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_NAVHPG_DGNSSMODE = 0x20140011; // Differential corrections mode +const uint32_t UBLOX_CFG_NAVHPG_DGNSSMODE = 0x20140011; // Differential corrections mode -//CFG-NAVSPG: Standard precision navigation configuration +// CFG-NAVSPG: Standard precision navigation configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_NAVSPG_FIXMODE = 0x20110011; // Position fix mode -const uint32_t UBLOX_CFG_NAVSPG_INIFIX3D = 0x10110013; // Initial fix must be a 3D fix -const uint32_t UBLOX_CFG_NAVSPG_WKNROLLOVER = 0x30110017; // GPS week rollover number -const uint32_t UBLOX_CFG_NAVSPG_USE_PPP = 0x10110019; // Use precise point positioning (PPP) -const uint32_t UBLOX_CFG_NAVSPG_UTCSTANDARD = 0x2011001c; // UTC standard to be used -const uint32_t UBLOX_CFG_NAVSPG_DYNMODEL = 0x20110021; // Dynamic platform model -const uint32_t UBLOX_CFG_NAVSPG_ACKAIDING = 0x10110025; // Acknowledge assistance input messages -const uint32_t UBLOX_CFG_NAVSPG_USE_USRDAT = 0x10110061; // Use user geodetic datum parameters -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_MAJA = 0x50110062; // Geodetic datum semi-major axis -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_FLAT = 0x50110063; // Geodetic datum 1.0 flattening -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_DX = 0x40110064; // Geodetic datum X axis shift at the origin -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_DY = 0x40110065; // Geodetic datum Y axis shift at the origin -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_DZ = 0x40110066; // Geodetic datum Z axis shift at the origin -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_ROTX = 0x40110067; // arcsec Geodetic datum rotation about the X axis -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_ROTY = 0x40110068; // arcsec Geodetic datum rotation about the Y axis -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_ROTZ = 0x40110069; // arcsec Geodetic datum rotation about the Z axis -const uint32_t UBLOX_CFG_NAVSPG_USRDAT_SCALE = 0x4011006a; // ppm Geodetic datum scale factor -const uint32_t UBLOX_CFG_NAVSPG_INFIL_MINSVS = 0x201100a1; // Minimum number of satellites for navigation -const uint32_t UBLOX_CFG_NAVSPG_INFIL_MAXSVS = 0x201100a2; // Maximum number of satellites for navigation -const uint32_t UBLOX_CFG_NAVSPG_INFIL_MINCNO = 0x201100a3; // Minimum satellite signal level for navigation -const uint32_t UBLOX_CFG_NAVSPG_INFIL_MINELEV = 0x201100a4; // Minimum elevation for a GNSS satellite to be used in navigation -const uint32_t UBLOX_CFG_NAVSPG_INFIL_NCNOTHRS = 0x201100aa; // Number of satellites required to have C/N0 above const uint32_t UBLOX_CFG_NAVSPG-INFIL_CNOTHRS for a fix to be attempted -const uint32_t UBLOX_CFG_NAVSPG_INFIL_CNOTHRS = 0x201100ab; // C/N0 threshold for deciding whether to attempt a fix -const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_PDOP = 0x301100b1; // Output filter position DOP mask (threshold) -const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_TDOP = 0x301100b2; // Output filter time DOP mask (threshold) -const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_PACC = 0x301100b3; // Output filter position accuracy mask (threshold) -const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_TACC = 0x301100b4; // Output filter time accuracy mask (threshold) -const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_FACC = 0x301100b5; // Output filter frequency accuracy mask (threshold) -const uint32_t UBLOX_CFG_NAVSPG_CONSTR_ALT = 0x401100c1; // Fixed altitude (mean sea level) for 2D fix mode -const uint32_t UBLOX_CFG_NAVSPG_CONSTR_ALTVAR = 0x401100c2; // Fixed altitude variance for 2D mode -const uint32_t UBLOX_CFG_NAVSPG_CONSTR_DGNSSTO = 0x201100c4; // DGNSS timeout -const uint32_t UBLOX_CFG_NAVSPG_SIGATTCOMP = 0x201100d6; // Permanently attenuated signal compensation mode -const uint32_t UBLOX_CFG_NAVSPG_PL_ENA = 0x101100d7; // Enable Protection level. If enabled, protection level computing will be on. - -//CFG-NMEA: NMEA protocol configuration +const uint32_t UBLOX_CFG_NAVSPG_FIXMODE = 0x20110011; // Position fix mode +const uint32_t UBLOX_CFG_NAVSPG_INIFIX3D = 0x10110013; // Initial fix must be a 3D fix +const uint32_t UBLOX_CFG_NAVSPG_WKNROLLOVER = 0x30110017; // GPS week rollover number +const uint32_t UBLOX_CFG_NAVSPG_USE_PPP = 0x10110019; // Use precise point positioning (PPP) +const uint32_t UBLOX_CFG_NAVSPG_UTCSTANDARD = 0x2011001c; // UTC standard to be used +const uint32_t UBLOX_CFG_NAVSPG_DYNMODEL = 0x20110021; // Dynamic platform model +const uint32_t UBLOX_CFG_NAVSPG_ACKAIDING = 0x10110025; // Acknowledge assistance input messages +const uint32_t UBLOX_CFG_NAVSPG_USE_USRDAT = 0x10110061; // Use user geodetic datum parameters +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_MAJA = 0x50110062; // Geodetic datum semi-major axis +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_FLAT = 0x50110063; // Geodetic datum 1.0 flattening +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_DX = 0x40110064; // Geodetic datum X axis shift at the origin +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_DY = 0x40110065; // Geodetic datum Y axis shift at the origin +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_DZ = 0x40110066; // Geodetic datum Z axis shift at the origin +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_ROTX = 0x40110067; // arcsec Geodetic datum rotation about the X axis +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_ROTY = 0x40110068; // arcsec Geodetic datum rotation about the Y axis +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_ROTZ = 0x40110069; // arcsec Geodetic datum rotation about the Z axis +const uint32_t UBLOX_CFG_NAVSPG_USRDAT_SCALE = 0x4011006a; // ppm Geodetic datum scale factor +const uint32_t UBLOX_CFG_NAVSPG_INFIL_MINSVS = 0x201100a1; // Minimum number of satellites for navigation +const uint32_t UBLOX_CFG_NAVSPG_INFIL_MAXSVS = 0x201100a2; // Maximum number of satellites for navigation +const uint32_t UBLOX_CFG_NAVSPG_INFIL_MINCNO = 0x201100a3; // Minimum satellite signal level for navigation +const uint32_t UBLOX_CFG_NAVSPG_INFIL_MINELEV = 0x201100a4; // Minimum elevation for a GNSS satellite to be used in navigation +const uint32_t UBLOX_CFG_NAVSPG_INFIL_NCNOTHRS = 0x201100aa; // Number of satellites required to have C/N0 above const uint32_t UBLOX_CFG_NAVSPG-INFIL_CNOTHRS for a fix to be attempted +const uint32_t UBLOX_CFG_NAVSPG_INFIL_CNOTHRS = 0x201100ab; // C/N0 threshold for deciding whether to attempt a fix +const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_PDOP = 0x301100b1; // Output filter position DOP mask (threshold) +const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_TDOP = 0x301100b2; // Output filter time DOP mask (threshold) +const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_PACC = 0x301100b3; // Output filter position accuracy mask (threshold) +const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_TACC = 0x301100b4; // Output filter time accuracy mask (threshold) +const uint32_t UBLOX_CFG_NAVSPG_OUTFIL_FACC = 0x301100b5; // Output filter frequency accuracy mask (threshold) +const uint32_t UBLOX_CFG_NAVSPG_CONSTR_ALT = 0x401100c1; // Fixed altitude (mean sea level) for 2D fix mode +const uint32_t UBLOX_CFG_NAVSPG_CONSTR_ALTVAR = 0x401100c2; // Fixed altitude variance for 2D mode +const uint32_t UBLOX_CFG_NAVSPG_CONSTR_DGNSSTO = 0x201100c4; // DGNSS timeout +const uint32_t UBLOX_CFG_NAVSPG_SIGATTCOMP = 0x201100d6; // Permanently attenuated signal compensation mode +const uint32_t UBLOX_CFG_NAVSPG_PL_ENA = 0x101100d7; // Enable Protection level. If enabled, protection level computing will be on. + +// CFG-NMEA: NMEA protocol configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_NMEA_PROTVER = 0x20930001; // NMEA protocol version -const uint32_t UBLOX_CFG_NMEA_MAXSVS = 0x20930002; // Maximum number of SVs to report per Talker ID -const uint32_t UBLOX_CFG_NMEA_COMPAT = 0x10930003; // Enable compatibility mode -const uint32_t UBLOX_CFG_NMEA_CONSIDER = 0x10930004; // Enable considering mode -const uint32_t UBLOX_CFG_NMEA_LIMIT82 = 0x10930005; // Enable strict limit to 82 characters maximum NMEA message length -const uint32_t UBLOX_CFG_NMEA_HIGHPREC = 0x10930006; // Enable high precision mode -const uint32_t UBLOX_CFG_NMEA_SVNUMBERING = 0x20930007; // Display configuration for SVs that do not have value defined in NMEA -const uint32_t UBLOX_CFG_NMEA_FILT_GPS = 0x10930011; // Disable reporting of GPS satellites -const uint32_t UBLOX_CFG_NMEA_FILT_SBAS = 0x10930012; // Disable reporting of SBAS satellites -const uint32_t UBLOX_CFG_NMEA_FILT_GAL = 0x10930013; // Disable reporting of Galileo satellites -const uint32_t UBLOX_CFG_NMEA_FILT_QZSS = 0x10930015; // Disable reporting of QZSS satellites -const uint32_t UBLOX_CFG_NMEA_FILT_GLO = 0x10930016; // Disable reporting of GLONASS satellites -const uint32_t UBLOX_CFG_NMEA_FILT_BDS = 0x10930017; // Disable reporting of BeiDou satellites -const uint32_t UBLOX_CFG_NMEA_OUT_INVFIX = 0x10930021; // Enable position output for failed or invalid fixes -const uint32_t UBLOX_CFG_NMEA_OUT_MSKFIX = 0x10930022; // Enable position output for invalid fixes -const uint32_t UBLOX_CFG_NMEA_OUT_INVTIME = 0x10930023; // Enable time output for invalid times -const uint32_t UBLOX_CFG_NMEA_OUT_INVDATE = 0x10930024; // Enable date output for invalid dates -const uint32_t UBLOX_CFG_NMEA_OUT_ONLYGPS = 0x10930025; // Restrict output to GPS satellites only -const uint32_t UBLOX_CFG_NMEA_OUT_FROZENCOG = 0x10930026; // Enable course over ground output even if it is frozen -const uint32_t UBLOX_CFG_NMEA_MAINTALKERID = 0x20930031; // Main Talker ID -const uint32_t UBLOX_CFG_NMEA_GSVTALKERID = 0x20930032; // Talker ID for GSV NMEA messages -const uint32_t UBLOX_CFG_NMEA_BDSTALKERID = 0x30930033; // BeiDou Talker ID - -//CFG-ODO: Odometer and low-speed course over ground filter +const uint32_t UBLOX_CFG_NMEA_PROTVER = 0x20930001; // NMEA protocol version +const uint32_t UBLOX_CFG_NMEA_MAXSVS = 0x20930002; // Maximum number of SVs to report per Talker ID +const uint32_t UBLOX_CFG_NMEA_COMPAT = 0x10930003; // Enable compatibility mode +const uint32_t UBLOX_CFG_NMEA_CONSIDER = 0x10930004; // Enable considering mode +const uint32_t UBLOX_CFG_NMEA_LIMIT82 = 0x10930005; // Enable strict limit to 82 characters maximum NMEA message length +const uint32_t UBLOX_CFG_NMEA_HIGHPREC = 0x10930006; // Enable high precision mode +const uint32_t UBLOX_CFG_NMEA_SVNUMBERING = 0x20930007; // Display configuration for SVs that do not have value defined in NMEA +const uint32_t UBLOX_CFG_NMEA_FILT_GPS = 0x10930011; // Disable reporting of GPS satellites +const uint32_t UBLOX_CFG_NMEA_FILT_SBAS = 0x10930012; // Disable reporting of SBAS satellites +const uint32_t UBLOX_CFG_NMEA_FILT_GAL = 0x10930013; // Disable reporting of Galileo satellites +const uint32_t UBLOX_CFG_NMEA_FILT_QZSS = 0x10930015; // Disable reporting of QZSS satellites +const uint32_t UBLOX_CFG_NMEA_FILT_GLO = 0x10930016; // Disable reporting of GLONASS satellites +const uint32_t UBLOX_CFG_NMEA_FILT_BDS = 0x10930017; // Disable reporting of BeiDou satellites +const uint32_t UBLOX_CFG_NMEA_OUT_INVFIX = 0x10930021; // Enable position output for failed or invalid fixes +const uint32_t UBLOX_CFG_NMEA_OUT_MSKFIX = 0x10930022; // Enable position output for invalid fixes +const uint32_t UBLOX_CFG_NMEA_OUT_INVTIME = 0x10930023; // Enable time output for invalid times +const uint32_t UBLOX_CFG_NMEA_OUT_INVDATE = 0x10930024; // Enable date output for invalid dates +const uint32_t UBLOX_CFG_NMEA_OUT_ONLYGPS = 0x10930025; // Restrict output to GPS satellites only +const uint32_t UBLOX_CFG_NMEA_OUT_FROZENCOG = 0x10930026; // Enable course over ground output even if it is frozen +const uint32_t UBLOX_CFG_NMEA_MAINTALKERID = 0x20930031; // Main Talker ID +const uint32_t UBLOX_CFG_NMEA_GSVTALKERID = 0x20930032; // Talker ID for GSV NMEA messages +const uint32_t UBLOX_CFG_NMEA_BDSTALKERID = 0x30930033; // BeiDou Talker ID + +// CFG-ODO: Odometer and low-speed course over ground filter //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_ODO_USE_ODO = 0x10220001; // Use odometer -const uint32_t UBLOX_CFG_ODO_USE_COG = 0x10220002; // Use low-speed course over ground filter -const uint32_t UBLOX_CFG_ODO_OUTLPVEL = 0x10220003; // Output low-pass filtered velocity -const uint32_t UBLOX_CFG_ODO_OUTLPCOG = 0x10220004; // Output low-pass filtered course over ground (heading) -const uint32_t UBLOX_CFG_ODO_PROFILE = 0x20220005; // Odometer profile configuration -const uint32_t UBLOX_CFG_ODO_COGMAXSPEED = 0x20220021; // Upper speed limit for low-speed course over ground filter -const uint32_t UBLOX_CFG_ODO_COGMAXPOSACC = 0x20220022; // Maximum acceptable position accuracy for computing low-speed filtered course over ground -const uint32_t UBLOX_CFG_ODO_VELLPGAIN = 0x20220031; // Velocity low-pass filter level -const uint32_t UBLOX_CFG_ODO_COGLPGAIN = 0x20220032; // Course over ground low-pass filter level (at speed < 8 m/s) - -//CFG-PM: Configuration for receiver power management (NEO-D9S) +const uint32_t UBLOX_CFG_ODO_USE_ODO = 0x10220001; // Use odometer +const uint32_t UBLOX_CFG_ODO_USE_COG = 0x10220002; // Use low-speed course over ground filter +const uint32_t UBLOX_CFG_ODO_OUTLPVEL = 0x10220003; // Output low-pass filtered velocity +const uint32_t UBLOX_CFG_ODO_OUTLPCOG = 0x10220004; // Output low-pass filtered course over ground (heading) +const uint32_t UBLOX_CFG_ODO_PROFILE = 0x20220005; // Odometer profile configuration +const uint32_t UBLOX_CFG_ODO_COGMAXSPEED = 0x20220021; // Upper speed limit for low-speed course over ground filter +const uint32_t UBLOX_CFG_ODO_COGMAXPOSACC = 0x20220022; // Maximum acceptable position accuracy for computing low-speed filtered course over ground +const uint32_t UBLOX_CFG_ODO_VELLPGAIN = 0x20220031; // Velocity low-pass filter level +const uint32_t UBLOX_CFG_ODO_COGLPGAIN = 0x20220032; // Course over ground low-pass filter level (at speed < 8 m/s) + +// CFG-PM: Configuration for receiver power management (NEO-D9S) //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_PM_EXTINTSEL = 0x20d0000b; // EXTINT pin select -const uint32_t UBLOX_CFG_PM_EXTINTWAKE = 0x10d0000c; // EXTINT pin control (Wake). Enable to keep receiver awake as long as selected EXTINT pin is "high". -const uint32_t UBLOX_CFG_PM_EXTINTBACKUP = 0x10d0000d; // EXTINT pin control (Backup). Enable to force receiver into BACKUP mode when selected EXTINT pin is "low". -const uint32_t UBLOX_CFG_PM_EXTINTINACTIVE = 0x10d0000e; // EXTINT pin control (Inactive). Enable to force backup in case EXTINT Pin is inactive for time longer than CFG-PM-EXTINTINACTIVITY. +const uint32_t UBLOX_CFG_PM_EXTINTSEL = 0x20d0000b; // EXTINT pin select +const uint32_t UBLOX_CFG_PM_EXTINTWAKE = 0x10d0000c; // EXTINT pin control (Wake). Enable to keep receiver awake as long as selected EXTINT pin is "high". +const uint32_t UBLOX_CFG_PM_EXTINTBACKUP = 0x10d0000d; // EXTINT pin control (Backup). Enable to force receiver into BACKUP mode when selected EXTINT pin is "low". +const uint32_t UBLOX_CFG_PM_EXTINTINACTIVE = 0x10d0000e; // EXTINT pin control (Inactive). Enable to force backup in case EXTINT Pin is inactive for time longer than CFG-PM-EXTINTINACTIVITY. const uint32_t UBLOX_CFG_PM_EXTINTINACTIVITY = 0x40d0000f; // Inactivity time out on EXTINT pin if enabled -//CFG-PMP: Point to multipoint (PMP) configuration (NEO-D9S) +// CFG-PMP: Point to multipoint (PMP) configuration (NEO-D9S) //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_PMP_CENTER_FREQUENCY = 0x40b10011; // Center frequency. The center frequency for the receiver can be set from 1525000000 to 1559000000 Hz. -const uint32_t UBLOX_CFG_PMP_SEARCH_WINDOW = 0x30b10012; // Search window. Search window can be set from 0 to 65535 Hz. It is +/- this value from the center frequency set by CENTER_FREQUENCY. -const uint32_t UBLOX_CFG_PMP_USE_SERVICE_ID = 0x10b10016; // Use service ID. Enable/disable service ID check to confirm the correct service is received. -const uint32_t UBLOX_CFG_PMP_SERVICE_ID = 0x30b10017; // Service identifier. Defines the expected service ID. -const uint32_t UBLOX_CFG_PMP_DATA_RATE = 0x30b10013; // bps Data rate. The data rate of the received data. -const uint32_t UBLOX_CFG_PMP_USE_DESCRAMBLER = 0x10b10014; // Use descrambler. Enables/disables the descrambler. -const uint32_t UBLOX_CFG_PMP_DESCRAMBLER_INIT = 0x30b10015; // Descrambler initialization. Set the intialisation value for the descrambler. +const uint32_t UBLOX_CFG_PMP_CENTER_FREQUENCY = 0x40b10011; // Center frequency. The center frequency for the receiver can be set from 1525000000 to 1559000000 Hz. +const uint32_t UBLOX_CFG_PMP_SEARCH_WINDOW = 0x30b10012; // Search window. Search window can be set from 0 to 65535 Hz. It is +/- this value from the center frequency set by CENTER_FREQUENCY. +const uint32_t UBLOX_CFG_PMP_USE_SERVICE_ID = 0x10b10016; // Use service ID. Enable/disable service ID check to confirm the correct service is received. +const uint32_t UBLOX_CFG_PMP_SERVICE_ID = 0x30b10017; // Service identifier. Defines the expected service ID. +const uint32_t UBLOX_CFG_PMP_DATA_RATE = 0x30b10013; // bps Data rate. The data rate of the received data. +const uint32_t UBLOX_CFG_PMP_USE_DESCRAMBLER = 0x10b10014; // Use descrambler. Enables/disables the descrambler. +const uint32_t UBLOX_CFG_PMP_DESCRAMBLER_INIT = 0x30b10015; // Descrambler initialization. Set the intialisation value for the descrambler. const uint32_t UBLOX_CFG_PMP_USE_PRESCRAMBLING = 0x10b10019; // Use prescrambling. Enables/disables the prescrambling. -const uint32_t UBLOX_CFG_PMP_UNIQUE_WORD = 0x50b1001a; // Unique word. Defines value of unique word. +const uint32_t UBLOX_CFG_PMP_UNIQUE_WORD = 0x50b1001a; // Unique word. Defines value of unique word. -//CFG-QZSS: QZSS system configuration +// CFG-QZSS: QZSS system configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_QZSS_USE_SLAS_DGNSS = 0x10370005; // Apply QZSS SLAS DGNSS corrections -const uint32_t UBLOX_CFG_QZSS_USE_SLAS_TESTMODE = 0x10370006; // Use QZSS SLAS data when it is in test mode (SLAS msg 0) -const uint32_t UBLOX_CFG_QZSS_USE_SLAS_RAIM_UNCORR = 0x10370007; // Raim out measurements that are not corrected by QZSS SLAS, if at least 5 measurements are corrected -const uint32_t UBLOX_CFG_QZSS_SLAS_MAX_BASELINE = 0x30370008; // Maximum baseline distance to closest Ground Monitoring Station: km +const uint32_t UBLOX_CFG_QZSS_USE_SLAS_DGNSS = 0x10370005; // Apply QZSS SLAS DGNSS corrections +const uint32_t UBLOX_CFG_QZSS_USE_SLAS_TESTMODE = 0x10370006; // Use QZSS SLAS data when it is in test mode (SLAS msg 0) +const uint32_t UBLOX_CFG_QZSS_USE_SLAS_RAIM_UNCORR = 0x10370007; // Raim out measurements that are not corrected by QZSS SLAS, if at least 5 measurements are corrected +const uint32_t UBLOX_CFG_QZSS_SLAS_MAX_BASELINE = 0x30370008; // Maximum baseline distance to closest Ground Monitoring Station: km -//CFG-RATE: Navigation and measurement rate configuration +// CFG-RATE: Navigation and measurement rate configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_RATE_MEAS = 0x30210001; // Nominal time between GNSS measurements -const uint32_t UBLOX_CFG_RATE_NAV = 0x30210002; // Ratio of number of measurements to number of navigation solutions -const uint32_t UBLOX_CFG_RATE_TIMEREF = 0x20210003; // Time system to which measurements are aligned +const uint32_t UBLOX_CFG_RATE_MEAS = 0x30210001; // Nominal time between GNSS measurements +const uint32_t UBLOX_CFG_RATE_NAV = 0x30210002; // Ratio of number of measurements to number of navigation solutions +const uint32_t UBLOX_CFG_RATE_TIMEREF = 0x20210003; // Time system to which measurements are aligned const uint32_t UBLOX_CFG_RATE_NAV_PRIO = 0x20210004; // Output rate of priority navigation mode messages -//CFG-RINV: Remote inventory +// CFG-RINV: Remote inventory //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_RINV_DUMP = 0x10c70001; // Dump data at startup -const uint32_t UBLOX_CFG_RINV_BINARY = 0x10c70002; // Data is binary -const uint32_t UBLOX_CFG_RINV_DATA_SIZE = 0x20c70003; // Size of data -const uint32_t UBLOX_CFG_RINV_CHUNK0 = 0x50c70004; // Data bytes 1-8 (LSB) -const uint32_t UBLOX_CFG_RINV_CHUNK1 = 0x50c70005; // Data bytes 9-16 -const uint32_t UBLOX_CFG_RINV_CHUNK2 = 0x50c70006; // Data bytes 17-240x44434241. -const uint32_t UBLOX_CFG_RINV_CHUNK3 = 0x50c70007; // Data bytes 25-30 (MSB) - -//CFG-RTCM: RTCM protocol configuration +const uint32_t UBLOX_CFG_RINV_DUMP = 0x10c70001; // Dump data at startup +const uint32_t UBLOX_CFG_RINV_BINARY = 0x10c70002; // Data is binary +const uint32_t UBLOX_CFG_RINV_DATA_SIZE = 0x20c70003; // Size of data +const uint32_t UBLOX_CFG_RINV_CHUNK0 = 0x50c70004; // Data bytes 1-8 (LSB) +const uint32_t UBLOX_CFG_RINV_CHUNK1 = 0x50c70005; // Data bytes 9-16 +const uint32_t UBLOX_CFG_RINV_CHUNK2 = 0x50c70006; // Data bytes 17-240x44434241. +const uint32_t UBLOX_CFG_RINV_CHUNK3 = 0x50c70007; // Data bytes 25-30 (MSB) + +// CFG-RTCM: RTCM protocol configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_RTCM_DF003_OUT = 0x30090001; // RTCM DF003 (Reference station ID) output value -const uint32_t UBLOX_CFG_RTCM_DF003_IN = 0x30090008; // RTCM DF003 (Reference station ID) input value -const uint32_t UBLOX_CFG_RTCM_DF003_IN_FILTER = 0x20090009; // RTCM input filter configuration based on RTCM DF003 (Reference station ID) value +const uint32_t UBLOX_CFG_RTCM_DF003_OUT = 0x30090001; // RTCM DF003 (Reference station ID) output value +const uint32_t UBLOX_CFG_RTCM_DF003_IN = 0x30090008; // RTCM DF003 (Reference station ID) input value +const uint32_t UBLOX_CFG_RTCM_DF003_IN_FILTER = 0x20090009; // RTCM input filter configuration based on RTCM DF003 (Reference station ID) value -//CFG-SBAS: SBAS configuration +// CFG-SBAS: SBAS configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_SBAS_USE_TESTMODE = 0x10360002; // Use SBAS data when it is in test mode (SBAS msg 0) -const uint32_t UBLOX_CFG_SBAS_USE_RANGING = 0x10360003; // Use SBAS GEOs as a ranging source (for navigation) -const uint32_t UBLOX_CFG_SBAS_USE_DIFFCORR = 0x10360004; // Use SBAS differential corrections -const uint32_t UBLOX_CFG_SBAS_USE_INTEGRITY = 0x10360005; // Use SBAS integrity information -const uint32_t UBLOX_CFG_SBAS_PRNSCANMASK = 0x50360006; // SBAS PRN search configuration +const uint32_t UBLOX_CFG_SBAS_USE_TESTMODE = 0x10360002; // Use SBAS data when it is in test mode (SBAS msg 0) +const uint32_t UBLOX_CFG_SBAS_USE_RANGING = 0x10360003; // Use SBAS GEOs as a ranging source (for navigation) +const uint32_t UBLOX_CFG_SBAS_USE_DIFFCORR = 0x10360004; // Use SBAS differential corrections +const uint32_t UBLOX_CFG_SBAS_USE_INTEGRITY = 0x10360005; // Use SBAS integrity information +const uint32_t UBLOX_CFG_SBAS_PRNSCANMASK = 0x50360006; // SBAS PRN search configuration -//CFG-SEC: Security configuration (ZED-F9R) +// CFG-SEC: Security configuration (ZED-F9R) //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_SEC_CFG_LOCK = 0x10f60009; // Configuration lockdown +const uint32_t UBLOX_CFG_SEC_CFG_LOCK = 0x10f60009; // Configuration lockdown const uint32_t UBLOX_CFG_SEC_CFG_LOCK_UNLOCKGRP1 = 0x30f6000a; // Configuration lockdown exempted group 1 const uint32_t UBLOX_CFG_SEC_CFG_LOCK_UNLOCKGRP2 = 0x30f6000b; // Configuration lockdown exempted group 2 -//CFG-SFCORE: Sensor fusion (SF) core configuration (ZED-F9R) +// CFG-SFCORE: Sensor fusion (SF) core configuration (ZED-F9R) //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_SFCORE_USE_SF = 0x10080001; // Use ADR/UDR sensor fusion -//CFG-SFIMU: Sensor fusion (SF) inertial measurement unit (IMU) configuration (ZED-F9R) +// CFG-SFIMU: Sensor fusion (SF) inertial measurement unit (IMU) configuration (ZED-F9R) //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_SFIMU_GYRO_TC_UPDATE_PERIOD = 0x30060007; // Time period between each update for the saved temperature-dependent gyroscope bias table -const uint32_t UBLOX_CFG_SFIMU_GYRO_RMSTHDL = 0x20060008; // Gyroscope sensor RMS threshold -const uint32_t UBLOX_CFG_SFIMU_GYRO_FREQUENCY = 0x20060009; // Nominal gyroscope sensor data sampling frequency -const uint32_t UBLOX_CFG_SFIMU_GYRO_LATENCY = 0x3006000a; // Gyroscope sensor data latency due to e.g. CAN bus -const uint32_t UBLOX_CFG_SFIMU_GYRO_ACCURACY = 0x3006000b; // Gyroscope sensor data accuracy -const uint32_t UBLOX_CFG_SFIMU_ACCEL_RMSTHDL = 0x20060015; // Accelerometer RMS threshold -const uint32_t UBLOX_CFG_SFIMU_ACCEL_FREQUENCY = 0x20060016; // Nominal accelerometer sensor data sampling frequency -const uint32_t UBLOX_CFG_SFIMU_ACCEL_LATENCY = 0x30060017; // Accelerometer sensor data latency due to e.g. CAN bus -const uint32_t UBLOX_CFG_SFIMU_ACCEL_ACCURACY = 0x30060018; // Accelerometer sensor data accuracy -const uint32_t UBLOX_CFG_SFIMU_IMU_EN = 0x1006001d; // IMU enabled -const uint32_t UBLOX_CFG_SFIMU_IMU_I2C_SCL_PIO = 0x2006001e; // SCL PIO of the IMU I2C -const uint32_t UBLOX_CFG_SFIMU_IMU_I2C_SDA_PIO = 0x2006001f; // SDA PIO of the IMU I2C -const uint32_t UBLOX_CFG_SFIMU_AUTO_MNTALG_ENA = 0x10060027; // Enable automatic IMU-mount alignment -const uint32_t UBLOX_CFG_SFIMU_IMU_MNTALG_YAW = 0x4006002d; // User-defined IMU-mount yaw angle [0, 360] -const uint32_t UBLOX_CFG_SFIMU_IMU_MNTALG_PITCH = 0x3006002e; // User-defined IMU-mount pitch angle [-90, 90] -const uint32_t UBLOX_CFG_SFIMU_IMU_MNTALG_ROLL = 0x3006002f; // User-defined IMU-mount roll angle [-180, 180] - -//CFG-SFODO: Sensor fusion (SF) odometer configuration (ZED-F9R) +const uint32_t UBLOX_CFG_SFIMU_GYRO_RMSTHDL = 0x20060008; // Gyroscope sensor RMS threshold +const uint32_t UBLOX_CFG_SFIMU_GYRO_FREQUENCY = 0x20060009; // Nominal gyroscope sensor data sampling frequency +const uint32_t UBLOX_CFG_SFIMU_GYRO_LATENCY = 0x3006000a; // Gyroscope sensor data latency due to e.g. CAN bus +const uint32_t UBLOX_CFG_SFIMU_GYRO_ACCURACY = 0x3006000b; // Gyroscope sensor data accuracy +const uint32_t UBLOX_CFG_SFIMU_ACCEL_RMSTHDL = 0x20060015; // Accelerometer RMS threshold +const uint32_t UBLOX_CFG_SFIMU_ACCEL_FREQUENCY = 0x20060016; // Nominal accelerometer sensor data sampling frequency +const uint32_t UBLOX_CFG_SFIMU_ACCEL_LATENCY = 0x30060017; // Accelerometer sensor data latency due to e.g. CAN bus +const uint32_t UBLOX_CFG_SFIMU_ACCEL_ACCURACY = 0x30060018; // Accelerometer sensor data accuracy +const uint32_t UBLOX_CFG_SFIMU_IMU_EN = 0x1006001d; // IMU enabled +const uint32_t UBLOX_CFG_SFIMU_IMU_I2C_SCL_PIO = 0x2006001e; // SCL PIO of the IMU I2C +const uint32_t UBLOX_CFG_SFIMU_IMU_I2C_SDA_PIO = 0x2006001f; // SDA PIO of the IMU I2C +const uint32_t UBLOX_CFG_SFIMU_AUTO_MNTALG_ENA = 0x10060027; // Enable automatic IMU-mount alignment +const uint32_t UBLOX_CFG_SFIMU_IMU_MNTALG_YAW = 0x4006002d; // User-defined IMU-mount yaw angle [0, 360] +const uint32_t UBLOX_CFG_SFIMU_IMU_MNTALG_PITCH = 0x3006002e; // User-defined IMU-mount pitch angle [-90, 90] +const uint32_t UBLOX_CFG_SFIMU_IMU_MNTALG_ROLL = 0x3006002f; // User-defined IMU-mount roll angle [-180, 180] + +// CFG-SFODO: Sensor fusion (SF) odometer configuration (ZED-F9R) //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_SFODO_COMBINE_TICKS = 0x10070001; // Use combined rear wheel ticks instead of the single tick -const uint32_t UBLOX_CFG_SFODO_USE_SPEED = 0x10070003; // Use speed measurements -const uint32_t UBLOX_CFG_SFODO_DIS_AUTOCOUNTMAX = 0x10070004; // Disable automatic estimation of maximum absolute wheel tick counter +const uint32_t UBLOX_CFG_SFODO_COMBINE_TICKS = 0x10070001; // Use combined rear wheel ticks instead of the single tick +const uint32_t UBLOX_CFG_SFODO_USE_SPEED = 0x10070003; // Use speed measurements +const uint32_t UBLOX_CFG_SFODO_DIS_AUTOCOUNTMAX = 0x10070004; // Disable automatic estimation of maximum absolute wheel tick counter const uint32_t UBLOX_CFG_SFODO_DIS_AUTODIRPINPOL = 0x10070005; // Disable automatic wheel tick direction pin polarity detection -const uint32_t UBLOX_CFG_SFODO_DIS_AUTOSPEED = 0x10070006; // Disable automatic receiver reconfiguration for processing speed data -const uint32_t UBLOX_CFG_SFODO_FACTOR = 0x40070007; // Wheel tick scale factor -const uint32_t UBLOX_CFG_SFODO_QUANT_ERROR = 0x40070008; // Wheel tick quantization -const uint32_t UBLOX_CFG_SFODO_COUNT_MAX = 0x40070009; // Wheel tick counter maximum value -const uint32_t UBLOX_CFG_SFODO_LATENCY = 0x3007000a; // Wheel tick data latency due to e.g. CAN bus -const uint32_t UBLOX_CFG_SFODO_FREQUENCY = 0x2007000b; // Nominal wheel tick data frequency (0 = not set) -const uint32_t UBLOX_CFG_SFODO_CNT_BOTH_EDGES = 0x1007000d; // Count both rising and falling edges on wheel tick signal -const uint32_t UBLOX_CFG_SFODO_SPEED_BAND = 0x3007000e; // Speed sensor dead band (0 = not set) -const uint32_t UBLOX_CFG_SFODO_USE_WT_PIN = 0x1007000f; // Wheel tick signal enabled -const uint32_t UBLOX_CFG_SFODO_DIR_PINPOL = 0x10070010; // Wheel tick direction pin polarity -const uint32_t UBLOX_CFG_SFODO_DIS_AUTOSW = 0x10070011; // Disable automatic use of wheel tick or speed data received over the software interface - -//CFG-SIGNAL: Satellite systems (GNSS) signal configuration +const uint32_t UBLOX_CFG_SFODO_DIS_AUTOSPEED = 0x10070006; // Disable automatic receiver reconfiguration for processing speed data +const uint32_t UBLOX_CFG_SFODO_FACTOR = 0x40070007; // Wheel tick scale factor +const uint32_t UBLOX_CFG_SFODO_QUANT_ERROR = 0x40070008; // Wheel tick quantization +const uint32_t UBLOX_CFG_SFODO_COUNT_MAX = 0x40070009; // Wheel tick counter maximum value +const uint32_t UBLOX_CFG_SFODO_LATENCY = 0x3007000a; // Wheel tick data latency due to e.g. CAN bus +const uint32_t UBLOX_CFG_SFODO_FREQUENCY = 0x2007000b; // Nominal wheel tick data frequency (0 = not set) +const uint32_t UBLOX_CFG_SFODO_CNT_BOTH_EDGES = 0x1007000d; // Count both rising and falling edges on wheel tick signal +const uint32_t UBLOX_CFG_SFODO_SPEED_BAND = 0x3007000e; // Speed sensor dead band (0 = not set) +const uint32_t UBLOX_CFG_SFODO_USE_WT_PIN = 0x1007000f; // Wheel tick signal enabled +const uint32_t UBLOX_CFG_SFODO_DIR_PINPOL = 0x10070010; // Wheel tick direction pin polarity +const uint32_t UBLOX_CFG_SFODO_DIS_AUTOSW = 0x10070011; // Disable automatic use of wheel tick or speed data received over the software interface + +// CFG-SIGNAL: Satellite systems (GNSS) signal configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_SIGNAL_GPS_ENA = 0x1031001f; // GPS enable -const uint32_t UBLOX_CFG_SIGNAL_GPS_L1CA_ENA = 0x10310001; // GPS L1C/A -const uint32_t UBLOX_CFG_SIGNAL_GPS_L5_ENA = 0x10310004; // GPS L5 -const uint32_t UBLOX_CFG_SIGNAL_GPS_L2C_ENA = 0x10310003; // GPS L2C (only on u-blox F9 platform products) -const uint32_t UBLOX_CFG_SIGNAL_SBAS_ENA = 0x10310020; // SBAS enable -const uint32_t UBLOX_CFG_SIGNAL_SBAS_L1CA_ENA = 0x10310005; // SBAS L1C/A -const uint32_t UBLOX_CFG_SIGNAL_GAL_ENA = 0x10310021; // Galileo enable -const uint32_t UBLOX_CFG_SIGNAL_GAL_E1_ENA = 0x10310007; // Galileo E1 -const uint32_t UBLOX_CFG_SIGNAL_GAL_E5A_ENA = 0x10310009; // Galileo E5a -const uint32_t UBLOX_CFG_SIGNAL_GAL_E5B_ENA = 0x1031000a; // Galileo E5b (only on u-blox F9 platform products) -const uint32_t UBLOX_CFG_SIGNAL_BDS_ENA = 0x10310022; // BeiDou Enable -const uint32_t UBLOX_CFG_SIGNAL_BDS_B1_ENA = 0x1031000d; // BeiDou B1I -const uint32_t UBLOX_CFG_SIGNAL_BDS_B1C_ENA = 0x1031000f; // BeiDou B1C -const uint32_t UBLOX_CFG_SIGNAL_BDS_B2A_ENA = 0x10310028; // BeiDou B2a -const uint32_t UBLOX_CFG_SIGNAL_BDS_B2_ENA = 0x1031000e; // BeiDou B2I (only on u-blox F9 platform products) -const uint32_t UBLOX_CFG_SIGNAL_QZSS_ENA = 0x10310024; // QZSS enable -const uint32_t UBLOX_CFG_SIGNAL_QZSS_L1CA_ENA = 0x10310012; // QZSS L1C/A -const uint32_t UBLOX_CFG_SIGNAL_QZSS_L5_ENA = 0x10310017; // QZSS L5 -const uint32_t UBLOX_CFG_SIGNAL_QZSS_L1S_ENA = 0x10310014; // QZSS L1S -const uint32_t UBLOX_CFG_SIGNAL_QZSS_L2C_ENA = 0x10310015; // QZSS L2C (only on u-blox F9 platform products) -const uint32_t UBLOX_CFG_SIGNAL_GLO_ENA = 0x10310025; // GLONASS enable -const uint32_t UBLOX_CFG_SIGNAL_GLO_L1_ENA = 0x10310018; // GLONASS L1 -const uint32_t UBLOX_CFG_SIGNAL_GLO_L2_ENA = 0x1031001a; // GLONASS L2 (only on u-blox F9 platform products) - -//CFG-SPARTN: Configuration of the SPARTN interface +const uint32_t UBLOX_CFG_SIGNAL_GPS_ENA = 0x1031001f; // GPS enable +const uint32_t UBLOX_CFG_SIGNAL_GPS_L1CA_ENA = 0x10310001; // GPS L1C/A +const uint32_t UBLOX_CFG_SIGNAL_GPS_L5_ENA = 0x10310004; // GPS L5 +const uint32_t UBLOX_CFG_SIGNAL_GPS_L2C_ENA = 0x10310003; // GPS L2C (only on u-blox F9 platform products) +const uint32_t UBLOX_CFG_SIGNAL_SBAS_ENA = 0x10310020; // SBAS enable +const uint32_t UBLOX_CFG_SIGNAL_SBAS_L1CA_ENA = 0x10310005; // SBAS L1C/A +const uint32_t UBLOX_CFG_SIGNAL_GAL_ENA = 0x10310021; // Galileo enable +const uint32_t UBLOX_CFG_SIGNAL_GAL_E1_ENA = 0x10310007; // Galileo E1 +const uint32_t UBLOX_CFG_SIGNAL_GAL_E5A_ENA = 0x10310009; // Galileo E5a +const uint32_t UBLOX_CFG_SIGNAL_GAL_E5B_ENA = 0x1031000a; // Galileo E5b (only on u-blox F9 platform products) +const uint32_t UBLOX_CFG_SIGNAL_BDS_ENA = 0x10310022; // BeiDou Enable +const uint32_t UBLOX_CFG_SIGNAL_BDS_B1_ENA = 0x1031000d; // BeiDou B1I +const uint32_t UBLOX_CFG_SIGNAL_BDS_B1C_ENA = 0x1031000f; // BeiDou B1C +const uint32_t UBLOX_CFG_SIGNAL_BDS_B2A_ENA = 0x10310028; // BeiDou B2a +const uint32_t UBLOX_CFG_SIGNAL_BDS_B2_ENA = 0x1031000e; // BeiDou B2I (only on u-blox F9 platform products) +const uint32_t UBLOX_CFG_SIGNAL_QZSS_ENA = 0x10310024; // QZSS enable +const uint32_t UBLOX_CFG_SIGNAL_QZSS_L1CA_ENA = 0x10310012; // QZSS L1C/A +const uint32_t UBLOX_CFG_SIGNAL_QZSS_L5_ENA = 0x10310017; // QZSS L5 +const uint32_t UBLOX_CFG_SIGNAL_QZSS_L1S_ENA = 0x10310014; // QZSS L1S +const uint32_t UBLOX_CFG_SIGNAL_QZSS_L2C_ENA = 0x10310015; // QZSS L2C (only on u-blox F9 platform products) +const uint32_t UBLOX_CFG_SIGNAL_GLO_ENA = 0x10310025; // GLONASS enable +const uint32_t UBLOX_CFG_SIGNAL_GLO_L1_ENA = 0x10310018; // GLONASS L1 +const uint32_t UBLOX_CFG_SIGNAL_GLO_L2_ENA = 0x1031001a; // GLONASS L2 (only on u-blox F9 platform products) + +// CFG-SPARTN: Configuration of the SPARTN interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- const uint32_t UBLOX_CFG_SPARTN_USE_SOURCE = 0x20a70001; -//CFG-SPI: Configuration of the SPI interface +// CFG-SPI: Configuration of the SPI interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_SPI_MAXFF = 0x20640001; // Number of bytes containing 0xFF to receive before switching off reception. Range: 0 (mechanism off) - 63 -const uint32_t UBLOX_CFG_SPI_CPOLARITY = 0x10640002; // Clock polarity select: 0: Active Hight Clock, SCLK idles low, 1: Active Low Clock, SCLK idles high -const uint32_t UBLOX_CFG_SPI_CPHASE = 0x10640003; // Clock phase select: 0: Data captured on first edge of SCLK, 1: Data captured on second edge of SCLK -const uint32_t UBLOX_CFG_SPI_EXTENDEDTIMEOUT = 0x10640005; // Flag to disable timeouting the interface after 1.5s -const uint32_t UBLOX_CFG_SPI_ENABLED = 0x10640006; // Flag to indicate if the SPI interface should be enabled +const uint32_t UBLOX_CFG_SPI_MAXFF = 0x20640001; // Number of bytes containing 0xFF to receive before switching off reception. Range: 0 (mechanism off) - 63 +const uint32_t UBLOX_CFG_SPI_CPOLARITY = 0x10640002; // Clock polarity select: 0: Active Hight Clock, SCLK idles low, 1: Active Low Clock, SCLK idles high +const uint32_t UBLOX_CFG_SPI_CPHASE = 0x10640003; // Clock phase select: 0: Data captured on first edge of SCLK, 1: Data captured on second edge of SCLK +const uint32_t UBLOX_CFG_SPI_EXTENDEDTIMEOUT = 0x10640005; // Flag to disable timeouting the interface after 1.5s +const uint32_t UBLOX_CFG_SPI_ENABLED = 0x10640006; // Flag to indicate if the SPI interface should be enabled -//CFG-SPIINPROT: Input protocol configuration of the SPI interface +// CFG-SPIINPROT: Input protocol configuration of the SPI interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_SPIINPROT_UBX = 0x10790001; // Flag to indicate if UBX should be an input protocol on SPI -const uint32_t UBLOX_CFG_SPIINPROT_NMEA = 0x10790002; // Flag to indicate if NMEA should be an input protocol on SPI -const uint32_t UBLOX_CFG_SPIINPROT_RTCM3X = 0x10790004; // Flag to indicate if RTCM3X should be an input protocol on SPI -const uint32_t UBLOX_CFG_SPIINPROT_SPARTN = 0x10790005; // Flag to indicate if SPARTN should be an input protocol on SPI +const uint32_t UBLOX_CFG_SPIINPROT_UBX = 0x10790001; // Flag to indicate if UBX should be an input protocol on SPI +const uint32_t UBLOX_CFG_SPIINPROT_NMEA = 0x10790002; // Flag to indicate if NMEA should be an input protocol on SPI +const uint32_t UBLOX_CFG_SPIINPROT_RTCM3X = 0x10790004; // Flag to indicate if RTCM3X should be an input protocol on SPI +const uint32_t UBLOX_CFG_SPIINPROT_SPARTN = 0x10790005; // Flag to indicate if SPARTN should be an input protocol on SPI -//CFG-SPIOUTPROT: Output protocol configuration of the SPI interface +// CFG-SPIOUTPROT: Output protocol configuration of the SPI interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_SPIOUTPROT_UBX = 0x107a0001; // Flag to indicate if UBX should be an output protocol on SPI -const uint32_t UBLOX_CFG_SPIOUTPROT_NMEA = 0x107a0002; // Flag to indicate if NMEA should be an output protocol on SPI -const uint32_t UBLOX_CFG_SPIOUTPROT_RTCM3X = 0x107a0004; // Flag to indicate if RTCM3X should be an output protocol on SPI +const uint32_t UBLOX_CFG_SPIOUTPROT_UBX = 0x107a0001; // Flag to indicate if UBX should be an output protocol on SPI +const uint32_t UBLOX_CFG_SPIOUTPROT_NMEA = 0x107a0002; // Flag to indicate if NMEA should be an output protocol on SPI +const uint32_t UBLOX_CFG_SPIOUTPROT_RTCM3X = 0x107a0004; // Flag to indicate if RTCM3X should be an output protocol on SPI -//CFG-TMODE: Time mode configuration +// CFG-TMODE: Time mode configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_TMODE_MODE = 0x20030001; // Receiver mode -const uint32_t UBLOX_CFG_TMODE_POS_TYPE = 0x20030002; // Determines whether the ARP position is given in ECEF or LAT/LON/HEIGHT? -const uint32_t UBLOX_CFG_TMODE_ECEF_X = 0x40030003; // ECEF X coordinate of the ARP position. -const uint32_t UBLOX_CFG_TMODE_ECEF_Y = 0x40030004; // ECEF Y coordinate of the ARP position. -const uint32_t UBLOX_CFG_TMODE_ECEF_Z = 0x40030005; // ECEF Z coordinate of the ARP position. -const uint32_t UBLOX_CFG_TMODE_ECEF_X_HP = 0x20030006; // High-precision ECEF X coordinate of the ARP position. -const uint32_t UBLOX_CFG_TMODE_ECEF_Y_HP = 0x20030007; // High-precision ECEF Y coordinate of the ARP position. -const uint32_t UBLOX_CFG_TMODE_ECEF_Z_HP = 0x20030008; // High-precision ECEF Z coordinate of the ARP position. -const uint32_t UBLOX_CFG_TMODE_LAT = 0x40030009; // Latitude of the ARP position. -const uint32_t UBLOX_CFG_TMODE_LON = 0x4003000a; // Longitude of the ARP position. -const uint32_t UBLOX_CFG_TMODE_HEIGHT = 0x4003000b; // Height of the ARP position. -const uint32_t UBLOX_CFG_TMODE_LAT_HP = 0x2003000c; // High-precision latitude of the ARP position -const uint32_t UBLOX_CFG_TMODE_LON_HP = 0x2003000d; // High-precision longitude of the ARP position. -const uint32_t UBLOX_CFG_TMODE_HEIGHT_HP = 0x2003000e; // High-precision height of the ARP position. -const uint32_t UBLOX_CFG_TMODE_FIXED_POS_ACC = 0x4003000f; // Fixed position 3D accuracy -const uint32_t UBLOX_CFG_TMODE_SVIN_MIN_DUR = 0x40030010; // Survey-in minimum duration -const uint32_t UBLOX_CFG_TMODE_SVIN_ACC_LIMIT = 0x40030011; // Survey-in position accuracy limit - -//CFG-TP: Timepulse configuration +const uint32_t UBLOX_CFG_TMODE_MODE = 0x20030001; // Receiver mode +const uint32_t UBLOX_CFG_TMODE_POS_TYPE = 0x20030002; // Determines whether the ARP position is given in ECEF or LAT/LON/HEIGHT? +const uint32_t UBLOX_CFG_TMODE_ECEF_X = 0x40030003; // ECEF X coordinate of the ARP position. +const uint32_t UBLOX_CFG_TMODE_ECEF_Y = 0x40030004; // ECEF Y coordinate of the ARP position. +const uint32_t UBLOX_CFG_TMODE_ECEF_Z = 0x40030005; // ECEF Z coordinate of the ARP position. +const uint32_t UBLOX_CFG_TMODE_ECEF_X_HP = 0x20030006; // High-precision ECEF X coordinate of the ARP position. +const uint32_t UBLOX_CFG_TMODE_ECEF_Y_HP = 0x20030007; // High-precision ECEF Y coordinate of the ARP position. +const uint32_t UBLOX_CFG_TMODE_ECEF_Z_HP = 0x20030008; // High-precision ECEF Z coordinate of the ARP position. +const uint32_t UBLOX_CFG_TMODE_LAT = 0x40030009; // Latitude of the ARP position. +const uint32_t UBLOX_CFG_TMODE_LON = 0x4003000a; // Longitude of the ARP position. +const uint32_t UBLOX_CFG_TMODE_HEIGHT = 0x4003000b; // Height of the ARP position. +const uint32_t UBLOX_CFG_TMODE_LAT_HP = 0x2003000c; // High-precision latitude of the ARP position +const uint32_t UBLOX_CFG_TMODE_LON_HP = 0x2003000d; // High-precision longitude of the ARP position. +const uint32_t UBLOX_CFG_TMODE_HEIGHT_HP = 0x2003000e; // High-precision height of the ARP position. +const uint32_t UBLOX_CFG_TMODE_FIXED_POS_ACC = 0x4003000f; // Fixed position 3D accuracy +const uint32_t UBLOX_CFG_TMODE_SVIN_MIN_DUR = 0x40030010; // Survey-in minimum duration +const uint32_t UBLOX_CFG_TMODE_SVIN_ACC_LIMIT = 0x40030011; // Survey-in position accuracy limit + +// CFG-TP: Timepulse configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_TP_PULSE_DEF = 0x20050023; // Determines whether the time pulse is interpreted as frequency or period -const uint32_t UBLOX_CFG_TP_PULSE_LENGTH_DEF = 0x20050030; // Determines whether the time pulse length is interpreted as length[us] or pulse ratio[%] -const uint32_t UBLOX_CFG_TP_ANT_CABLEDELAY = 0x30050001; // Antenna cable delay -const uint32_t UBLOX_CFG_TP_PERIOD_TP1 = 0x40050002; // Time pulse period (TP1) -const uint32_t UBLOX_CFG_TP_PERIOD_LOCK_TP1 = 0x40050003; // Time pulse period when locked to GNSS time (TP1) -const uint32_t UBLOX_CFG_TP_FREQ_TP1 = 0x40050024; // Time pulse frequency (TP1) -const uint32_t UBLOX_CFG_TP_FREQ_LOCK_TP1 = 0x40050025; // Time pulse frequency when locked to GNSS time (TP1) -const uint32_t UBLOX_CFG_TP_LEN_TP1 = 0x40050004; // Time pulse length (TP1) -const uint32_t UBLOX_CFG_TP_LEN_LOCK_TP1 = 0x40050005; // Time pulse length when locked to GNSS time (TP1) -const uint32_t UBLOX_CFG_TP_DUTY_TP1 = 0x5005002a; // Time pulse duty cycle (TP1) -const uint32_t UBLOX_CFG_TP_DUTY_LOCK_TP1 = 0x5005002b; // Time pulse duty cycle when locked to GNSS time (TP1) -const uint32_t UBLOX_CFG_TP_USER_DELAY_TP1 = 0x40050006; // User-configurable time pulse delay (TP1) -const uint32_t UBLOX_CFG_TP_TP1_ENA = 0x10050007; // Enable the first timepulse -const uint32_t UBLOX_CFG_TP_SYNC_GNSS_TP1 = 0x10050008; // Sync time pulse to GNSS time or local clock (TP1) -const uint32_t UBLOX_CFG_TP_USE_LOCKED_TP1 = 0x10050009; // Use locked parameters when possible (TP1) -const uint32_t UBLOX_CFG_TP_ALIGN_TO_TOW_TP1 = 0x1005000a; // Align time pulse to top of second (TP1) -const uint32_t UBLOX_CFG_TP_POL_TP1 = 0x1005000b; // Set time pulse polarity (TP1) -const uint32_t UBLOX_CFG_TP_TIMEGRID_TP1 = 0x2005000c; // Time grid to use (TP1) -const uint32_t UBLOX_CFG_TP_PERIOD_TP2 = 0x4005000d; // Time pulse period (TP2) -const uint32_t UBLOX_CFG_TP_PERIOD_LOCK_TP2 = 0x4005000e; // Time pulse period when locked to GNSS time -const uint32_t UBLOX_CFG_TP_FREQ_TP2 = 0x40050026; // Time pulse frequency (TP2) -const uint32_t UBLOX_CFG_TP_FREQ_LOCK_TP2 = 0x40050027; // Time pulse frequency when locked to GNSS time -const uint32_t UBLOX_CFG_TP_LEN_TP2 = 0x4005000f; // Time pulse length (TP2) -const uint32_t UBLOX_CFG_TP_LEN_LOCK_TP2 = 0x40050010; // Time pulse length when locked to GNSS time -const uint32_t UBLOX_CFG_TP_DUTY_TP2 = 0x5005002c; // Time pulse duty cycle (TP2) -const uint32_t UBLOX_CFG_TP_DUTY_LOCK_TP2 = 0x5005002d; // Time pulse duty cycle when locked to GNSS time -const uint32_t UBLOX_CFG_TP_USER_DELAY_TP2 = 0x40050011; // User-configurable time pulse delay (TP2) -const uint32_t UBLOX_CFG_TP_TP2_ENA = 0x10050012; // Enable the second timepulse -const uint32_t UBLOX_CFG_TP_SYNC_GNSS_TP2 = 0x10050013; // Sync time pulse to GNSS time or local clock -const uint32_t UBLOX_CFG_TP_USE_LOCKED_TP2 = 0x10050014; // Use locked parameters when possible (TP2) +const uint32_t UBLOX_CFG_TP_PULSE_DEF = 0x20050023; // Determines whether the time pulse is interpreted as frequency or period +const uint32_t UBLOX_CFG_TP_PULSE_LENGTH_DEF = 0x20050030; // Determines whether the time pulse length is interpreted as length[us] or pulse ratio[%] +const uint32_t UBLOX_CFG_TP_ANT_CABLEDELAY = 0x30050001; // Antenna cable delay +const uint32_t UBLOX_CFG_TP_PERIOD_TP1 = 0x40050002; // Time pulse period (TP1) +const uint32_t UBLOX_CFG_TP_PERIOD_LOCK_TP1 = 0x40050003; // Time pulse period when locked to GNSS time (TP1) +const uint32_t UBLOX_CFG_TP_FREQ_TP1 = 0x40050024; // Time pulse frequency (TP1) +const uint32_t UBLOX_CFG_TP_FREQ_LOCK_TP1 = 0x40050025; // Time pulse frequency when locked to GNSS time (TP1) +const uint32_t UBLOX_CFG_TP_LEN_TP1 = 0x40050004; // Time pulse length (TP1) +const uint32_t UBLOX_CFG_TP_LEN_LOCK_TP1 = 0x40050005; // Time pulse length when locked to GNSS time (TP1) +const uint32_t UBLOX_CFG_TP_DUTY_TP1 = 0x5005002a; // Time pulse duty cycle (TP1) +const uint32_t UBLOX_CFG_TP_DUTY_LOCK_TP1 = 0x5005002b; // Time pulse duty cycle when locked to GNSS time (TP1) +const uint32_t UBLOX_CFG_TP_USER_DELAY_TP1 = 0x40050006; // User-configurable time pulse delay (TP1) +const uint32_t UBLOX_CFG_TP_TP1_ENA = 0x10050007; // Enable the first timepulse +const uint32_t UBLOX_CFG_TP_SYNC_GNSS_TP1 = 0x10050008; // Sync time pulse to GNSS time or local clock (TP1) +const uint32_t UBLOX_CFG_TP_USE_LOCKED_TP1 = 0x10050009; // Use locked parameters when possible (TP1) +const uint32_t UBLOX_CFG_TP_ALIGN_TO_TOW_TP1 = 0x1005000a; // Align time pulse to top of second (TP1) +const uint32_t UBLOX_CFG_TP_POL_TP1 = 0x1005000b; // Set time pulse polarity (TP1) +const uint32_t UBLOX_CFG_TP_TIMEGRID_TP1 = 0x2005000c; // Time grid to use (TP1) +const uint32_t UBLOX_CFG_TP_PERIOD_TP2 = 0x4005000d; // Time pulse period (TP2) +const uint32_t UBLOX_CFG_TP_PERIOD_LOCK_TP2 = 0x4005000e; // Time pulse period when locked to GNSS time +const uint32_t UBLOX_CFG_TP_FREQ_TP2 = 0x40050026; // Time pulse frequency (TP2) +const uint32_t UBLOX_CFG_TP_FREQ_LOCK_TP2 = 0x40050027; // Time pulse frequency when locked to GNSS time +const uint32_t UBLOX_CFG_TP_LEN_TP2 = 0x4005000f; // Time pulse length (TP2) +const uint32_t UBLOX_CFG_TP_LEN_LOCK_TP2 = 0x40050010; // Time pulse length when locked to GNSS time +const uint32_t UBLOX_CFG_TP_DUTY_TP2 = 0x5005002c; // Time pulse duty cycle (TP2) +const uint32_t UBLOX_CFG_TP_DUTY_LOCK_TP2 = 0x5005002d; // Time pulse duty cycle when locked to GNSS time +const uint32_t UBLOX_CFG_TP_USER_DELAY_TP2 = 0x40050011; // User-configurable time pulse delay (TP2) +const uint32_t UBLOX_CFG_TP_TP2_ENA = 0x10050012; // Enable the second timepulse +const uint32_t UBLOX_CFG_TP_SYNC_GNSS_TP2 = 0x10050013; // Sync time pulse to GNSS time or local clock +const uint32_t UBLOX_CFG_TP_USE_LOCKED_TP2 = 0x10050014; // Use locked parameters when possible (TP2) const uint32_t UBLOX_CFG_TP_ALIGN_TO_TOW_TP2 = 0x10050015; // Align time pulse to top of second (TP2) -const uint32_t UBLOX_CFG_TP_POL_TP2 = 0x10050016; // Set time pulse polarity (TP2) -const uint32_t UBLOX_CFG_TP_TIMEGRID_TP2 = 0x20050017; // Time grid to use (TP2) -const uint32_t UBLOX_CFG_TP_DRSTR_TP1 = 0x20050035; // Set drive strength of TP1 -const uint32_t UBLOX_CFG_TP_DRSTR_TP2 = 0x20050036; // Set drive strength of TP2 +const uint32_t UBLOX_CFG_TP_POL_TP2 = 0x10050016; // Set time pulse polarity (TP2) +const uint32_t UBLOX_CFG_TP_TIMEGRID_TP2 = 0x20050017; // Time grid to use (TP2) +const uint32_t UBLOX_CFG_TP_DRSTR_TP1 = 0x20050035; // Set drive strength of TP1 +const uint32_t UBLOX_CFG_TP_DRSTR_TP2 = 0x20050036; // Set drive strength of TP2 -//CFG-TXREADY: TX ready configuration +// CFG-TXREADY: TX ready configuration //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_TXREADY_ENABLED = 0x10a20001; // Flag to indicate if TX ready pin mechanism should be enabled -const uint32_t UBLOX_CFG_TXREADY_POLARITY = 0x10a20002; // The polarity of the TX ready pin: false:high- active, true:low-active -const uint32_t UBLOX_CFG_TXREADY_PIN = 0x20a20003; // Pin number to use for the TX ready functionality -const uint32_t UBLOX_CFG_TXREADY_THRESHOLD = 0x30a20004; // Amount of data that should be ready on the interface before triggering the TX ready pin -const uint32_t UBLOX_CFG_TXREADY_INTERFACE = 0x20a20005; // Interface where the TX ready feature should be linked to +const uint32_t UBLOX_CFG_TXREADY_ENABLED = 0x10a20001; // Flag to indicate if TX ready pin mechanism should be enabled +const uint32_t UBLOX_CFG_TXREADY_POLARITY = 0x10a20002; // The polarity of the TX ready pin: false:high- active, true:low-active +const uint32_t UBLOX_CFG_TXREADY_PIN = 0x20a20003; // Pin number to use for the TX ready functionality +const uint32_t UBLOX_CFG_TXREADY_THRESHOLD = 0x30a20004; // Amount of data that should be ready on the interface before triggering the TX ready pin +const uint32_t UBLOX_CFG_TXREADY_INTERFACE = 0x20a20005; // Interface where the TX ready feature should be linked to -//CFG-UART1: Configuration of the UART1 interface +// CFG-UART1: Configuration of the UART1 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_UART1_BAUDRATE = 0x40520001; // The baud rate that should be configured on the UART1 -const uint32_t UBLOX_CFG_UART1_STOPBITS = 0x20520002; // Number of stopbits that should be used on UART1 -const uint32_t UBLOX_CFG_UART1_DATABITS = 0x20520003; // Number of databits that should be used on UART1 -const uint32_t UBLOX_CFG_UART1_PARITY = 0x20520004; // Parity mode that should be used on UART1 -const uint32_t UBLOX_CFG_UART1_ENABLED = 0x10520005; // Flag to indicate if the UART1 should be enabled +const uint32_t UBLOX_CFG_UART1_BAUDRATE = 0x40520001; // The baud rate that should be configured on the UART1 +const uint32_t UBLOX_CFG_UART1_STOPBITS = 0x20520002; // Number of stopbits that should be used on UART1 +const uint32_t UBLOX_CFG_UART1_DATABITS = 0x20520003; // Number of databits that should be used on UART1 +const uint32_t UBLOX_CFG_UART1_PARITY = 0x20520004; // Parity mode that should be used on UART1 +const uint32_t UBLOX_CFG_UART1_ENABLED = 0x10520005; // Flag to indicate if the UART1 should be enabled -//CFG-UART1INPROT: Input protocol configuration of the UART1 interface +// CFG-UART1INPROT: Input protocol configuration of the UART1 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_UART1INPROT_UBX = 0x10730001; // Flag to indicate if UBX should be an input protocol on UART1 -const uint32_t UBLOX_CFG_UART1INPROT_NMEA = 0x10730002; // Flag to indicate if NMEA should be an input protocol on UART1 -const uint32_t UBLOX_CFG_UART1INPROT_RTCM3X = 0x10730004; // Flag to indicate if RTCM3X should be an input protocol on UART1 -const uint32_t UBLOX_CFG_UART1INPROT_SPARTN = 0x10730005; // Flag to indicate if SPARTN should be an input protocol on UART1 +const uint32_t UBLOX_CFG_UART1INPROT_UBX = 0x10730001; // Flag to indicate if UBX should be an input protocol on UART1 +const uint32_t UBLOX_CFG_UART1INPROT_NMEA = 0x10730002; // Flag to indicate if NMEA should be an input protocol on UART1 +const uint32_t UBLOX_CFG_UART1INPROT_RTCM3X = 0x10730004; // Flag to indicate if RTCM3X should be an input protocol on UART1 +const uint32_t UBLOX_CFG_UART1INPROT_SPARTN = 0x10730005; // Flag to indicate if SPARTN should be an input protocol on UART1 -//CFG-UART1OUTPROT: Output protocol configuration of the UART1 interface +// CFG-UART1OUTPROT: Output protocol configuration of the UART1 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_UART1OUTPROT_UBX = 0x10740001; // Flag to indicate if UBX should be an output protocol on UART1 -const uint32_t UBLOX_CFG_UART1OUTPROT_NMEA = 0x10740002; // Flag to indicate if NMEA should be an output protocol on UART1 -const uint32_t UBLOX_CFG_UART1OUTPROT_RTCM3X = 0x10740004; // Flag to indicate if RTCM3X should be an output protocol on UART1 +const uint32_t UBLOX_CFG_UART1OUTPROT_UBX = 0x10740001; // Flag to indicate if UBX should be an output protocol on UART1 +const uint32_t UBLOX_CFG_UART1OUTPROT_NMEA = 0x10740002; // Flag to indicate if NMEA should be an output protocol on UART1 +const uint32_t UBLOX_CFG_UART1OUTPROT_RTCM3X = 0x10740004; // Flag to indicate if RTCM3X should be an output protocol on UART1 -//CFG-UART2: Configuration of the UART2 interface +// CFG-UART2: Configuration of the UART2 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_UART2_BAUDRATE = 0x40530001; // The baud rate that should be configured on the UART2 -const uint32_t UBLOX_CFG_UART2_STOPBITS = 0x20530002; // Number of stopbits that should be used on UART2 -const uint32_t UBLOX_CFG_UART2_DATABITS = 0x20530003; // Number of databits that should be used on UART2 -const uint32_t UBLOX_CFG_UART2_PARITY = 0x20530004; // Parity mode that should be used on UART2 -const uint32_t UBLOX_CFG_UART2_ENABLED = 0x10530005; // Flag to indicate if the UART2 should be enabled -const uint32_t UBLOX_CFG_UART2_REMAP = 0x10530006; // UART2 Remapping - -//CFG-UART2INPROT: Input protocol configuration of the UART2 interface +const uint32_t UBLOX_CFG_UART2_BAUDRATE = 0x40530001; // The baud rate that should be configured on the UART2 +const uint32_t UBLOX_CFG_UART2_STOPBITS = 0x20530002; // Number of stopbits that should be used on UART2 +const uint32_t UBLOX_CFG_UART2_DATABITS = 0x20530003; // Number of databits that should be used on UART2 +const uint32_t UBLOX_CFG_UART2_PARITY = 0x20530004; // Parity mode that should be used on UART2 +const uint32_t UBLOX_CFG_UART2_ENABLED = 0x10530005; // Flag to indicate if the UART2 should be enabled +const uint32_t UBLOX_CFG_UART2_REMAP = 0x10530006; // UART2 Remapping + +// CFG-UART2INPROT: Input protocol configuration of the UART2 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_UART2INPROT_UBX = 0x10750001; // Flag to indicate if UBX should be an input protocol on UART2 -const uint32_t UBLOX_CFG_UART2INPROT_NMEA = 0x10750002; // Flag to indicate if NMEA should be an input protocol on UART2 -const uint32_t UBLOX_CFG_UART2INPROT_RTCM3X = 0x10750004; // Flag to indicate if RTCM3X should be an input protocol on UART2 -const uint32_t UBLOX_CFG_UART2INPROT_SPARTN = 0x10750005; // Flag to indicate if SPARTN should be an input protocol on UART2 +const uint32_t UBLOX_CFG_UART2INPROT_UBX = 0x10750001; // Flag to indicate if UBX should be an input protocol on UART2 +const uint32_t UBLOX_CFG_UART2INPROT_NMEA = 0x10750002; // Flag to indicate if NMEA should be an input protocol on UART2 +const uint32_t UBLOX_CFG_UART2INPROT_RTCM3X = 0x10750004; // Flag to indicate if RTCM3X should be an input protocol on UART2 +const uint32_t UBLOX_CFG_UART2INPROT_SPARTN = 0x10750005; // Flag to indicate if SPARTN should be an input protocol on UART2 -//CFG-UART2OUTPROT: Output protocol configuration of the UART2 interface +// CFG-UART2OUTPROT: Output protocol configuration of the UART2 interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_UART2OUTPROT_UBX = 0x10760001; // Flag to indicate if UBX should be an output protocol on UART2 -const uint32_t UBLOX_CFG_UART2OUTPROT_NMEA = 0x10760002; // Flag to indicate if NMEA should be an output protocol on UART2 -const uint32_t UBLOX_CFG_UART2OUTPROT_RTCM3X = 0x10760004; // Flag to indicate if RTCM3X should be an output protocol on UART2 +const uint32_t UBLOX_CFG_UART2OUTPROT_UBX = 0x10760001; // Flag to indicate if UBX should be an output protocol on UART2 +const uint32_t UBLOX_CFG_UART2OUTPROT_NMEA = 0x10760002; // Flag to indicate if NMEA should be an output protocol on UART2 +const uint32_t UBLOX_CFG_UART2OUTPROT_RTCM3X = 0x10760004; // Flag to indicate if RTCM3X should be an output protocol on UART2 -//CFG-USB: Configuration of the USB interface +// CFG-USB: Configuration of the USB interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_USB_ENABLED = 0x10650001; // Flag to indicate if the USB interface should be enabled -const uint32_t UBLOX_CFG_USB_SELFPOW = 0x10650002; // Self-powered device -const uint32_t UBLOX_CFG_USB_VENDOR_ID = 0x3065000a; // Vendor ID -const uint32_t UBLOX_CFG_USB_PRODUCT_ID = 0x3065000b; // Vendor ID -const uint32_t UBLOX_CFG_USB_POWER = 0x3065000c; // Power consumption -const uint32_t UBLOX_CFG_USB_VENDOR_STR0 = 0x5065000d; // Vendor string characters 0-7 -const uint32_t UBLOX_CFG_USB_VENDOR_STR1 = 0x5065000e; // Vendor string characters 8-15 -const uint32_t UBLOX_CFG_USB_VENDOR_STR2 = 0x5065000f; // Vendor string characters 16-23 -const uint32_t UBLOX_CFG_USB_VENDOR_STR3 = 0x50650010; // Vendor string characters 24-31 -const uint32_t UBLOX_CFG_USB_PRODUCT_STR0 = 0x50650011; // Product string characters 0-7 -const uint32_t UBLOX_CFG_USB_PRODUCT_STR1 = 0x50650012; // Product string characters 8-15 -const uint32_t UBLOX_CFG_USB_PRODUCT_STR2 = 0x50650013; // Product string characters 16-23 -const uint32_t UBLOX_CFG_USB_PRODUCT_STR3 = 0x50650014; // Product string characters 24-31 -const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR0 = 0x50650015; // Serial number string characters 0-7 -const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR1 = 0x50650016; // Serial number string characters 8-15 -const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR2 = 0x50650017; // Serial number string characters 16-23 -const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR3 = 0x50650018; // Serial number string characters 24-31 - -//CFG-USBINPROT: Input protocol configuration of the USB interface +const uint32_t UBLOX_CFG_USB_ENABLED = 0x10650001; // Flag to indicate if the USB interface should be enabled +const uint32_t UBLOX_CFG_USB_SELFPOW = 0x10650002; // Self-powered device +const uint32_t UBLOX_CFG_USB_VENDOR_ID = 0x3065000a; // Vendor ID +const uint32_t UBLOX_CFG_USB_PRODUCT_ID = 0x3065000b; // Vendor ID +const uint32_t UBLOX_CFG_USB_POWER = 0x3065000c; // Power consumption +const uint32_t UBLOX_CFG_USB_VENDOR_STR0 = 0x5065000d; // Vendor string characters 0-7 +const uint32_t UBLOX_CFG_USB_VENDOR_STR1 = 0x5065000e; // Vendor string characters 8-15 +const uint32_t UBLOX_CFG_USB_VENDOR_STR2 = 0x5065000f; // Vendor string characters 16-23 +const uint32_t UBLOX_CFG_USB_VENDOR_STR3 = 0x50650010; // Vendor string characters 24-31 +const uint32_t UBLOX_CFG_USB_PRODUCT_STR0 = 0x50650011; // Product string characters 0-7 +const uint32_t UBLOX_CFG_USB_PRODUCT_STR1 = 0x50650012; // Product string characters 8-15 +const uint32_t UBLOX_CFG_USB_PRODUCT_STR2 = 0x50650013; // Product string characters 16-23 +const uint32_t UBLOX_CFG_USB_PRODUCT_STR3 = 0x50650014; // Product string characters 24-31 +const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR0 = 0x50650015; // Serial number string characters 0-7 +const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR1 = 0x50650016; // Serial number string characters 8-15 +const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR2 = 0x50650017; // Serial number string characters 16-23 +const uint32_t UBLOX_CFG_USB_SERIAL_NO_STR3 = 0x50650018; // Serial number string characters 24-31 + +// CFG-USBINPROT: Input protocol configuration of the USB interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_USBINPROT_UBX = 0x10770001; // Flag to indicate if UBX should be an input protocol on USB -const uint32_t UBLOX_CFG_USBINPROT_NMEA = 0x10770002; // Flag to indicate if NMEA should be an input protocol on USB -const uint32_t UBLOX_CFG_USBINPROT_RTCM3X = 0x10770004; // Flag to indicate if RTCM3X should be an input protocol on USB -const uint32_t UBLOX_CFG_USBINPROT_SPARTN = 0x10770005; // Flag to indicate if SPARTN should be an input protocol on USB +const uint32_t UBLOX_CFG_USBINPROT_UBX = 0x10770001; // Flag to indicate if UBX should be an input protocol on USB +const uint32_t UBLOX_CFG_USBINPROT_NMEA = 0x10770002; // Flag to indicate if NMEA should be an input protocol on USB +const uint32_t UBLOX_CFG_USBINPROT_RTCM3X = 0x10770004; // Flag to indicate if RTCM3X should be an input protocol on USB +const uint32_t UBLOX_CFG_USBINPROT_SPARTN = 0x10770005; // Flag to indicate if SPARTN should be an input protocol on USB -//CFG-USBOUTPROT: Output protocol configuration of the USB interface +// CFG-USBOUTPROT: Output protocol configuration of the USB interface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const uint32_t UBLOX_CFG_USBOUTPROT_UBX = 0x10780001; // Flag to indicate if UBX should be an output protocol on USB -const uint32_t UBLOX_CFG_USBOUTPROT_NMEA = 0x10780002; // Flag to indicate if NMEA should be an output protocol on USB -const uint32_t UBLOX_CFG_USBOUTPROT_RTCM3X = 0x10780004; // Flag to indicate if RTCM3X should be an output protocol on USB +const uint32_t UBLOX_CFG_USBOUTPROT_UBX = 0x10780001; // Flag to indicate if UBX should be an output protocol on USB +const uint32_t UBLOX_CFG_USBOUTPROT_NMEA = 0x10780002; // Flag to indicate if NMEA should be an output protocol on USB +const uint32_t UBLOX_CFG_USBOUTPROT_RTCM3X = 0x10780004; // Flag to indicate if RTCM3X should be an output protocol on USB #endif diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 216c071..bdc828b 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1,43 +1,43 @@ /* - This is a library written for the u-blox ZED-F9P and NEO-M8P-2 - SparkFun sells these at its website: www.sparkfun.com - Do you like this library? Help support SparkFun. Buy a board! - https://www.sparkfun.com/products/16481 - https://www.sparkfun.com/products/15136 - https://www.sparkfun.com/products/15005 - https://www.sparkfun.com/products/15733 - https://www.sparkfun.com/products/15193 - https://www.sparkfun.com/products/15210 + This is a library written for the u-blox ZED-F9P and NEO-M8P-2 + SparkFun sells these at its website: www.sparkfun.com + Do you like this library? Help support SparkFun. Buy a board! + https://www.sparkfun.com/products/16481 + https://www.sparkfun.com/products/15136 + https://www.sparkfun.com/products/15005 + https://www.sparkfun.com/products/15733 + https://www.sparkfun.com/products/15193 + https://www.sparkfun.com/products/15210 Original version by Nathan Seidle @ SparkFun Electronics, September 6th, 2018 - v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 - - This library handles configuring and handling the responses - from a u-blox GPS module. Works with most modules from u-blox including - the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. - - https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library - - Development environment specifics: - Arduino IDE 1.8.13 - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). - The MIT License (MIT) - Copyright (c) 2016 SparkFun Electronics - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - associated documentation files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the Software is furnished to - do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + v2.0 rework by Paul Clark @ SparkFun Electronics, December 31st, 2020 + + This library handles configuring and handling the responses + from a u-blox GPS module. Works with most modules from u-blox including + the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others. + + https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library + + Development environment specifics: + Arduino IDE 1.8.13 + + SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). + The MIT License (MIT) + Copyright (c) 2016 SparkFun Electronics + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the Software is furnished to + do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __u_blox_structs_h__ @@ -49,7 +49,7 @@ #define DEF_NUM_SENS 7 // The maximum number of ESF sensors #endif -//Additional flags and pointers that need to be stored with each message type +// Additional flags and pointers that need to be stored with each message type struct ubxAutomaticFlags { union @@ -57,9 +57,9 @@ struct ubxAutomaticFlags uint8_t all; struct { - uint8_t automatic : 1; // Will this message be delivered and parsed "automatically" (without polling) - uint8_t implicitUpdate : 1; // Is the update triggered by accessing stale data (=true) or by a call to checkUblox (=false) - uint8_t addToFileBuffer : 1; // Should the raw UBX data be added to the file buffer? + uint8_t automatic : 1; // Will this message be delivered and parsed "automatically" (without polling) + uint8_t implicitUpdate : 1; // Is the update triggered by accessing stale data (=true) or by a call to checkUblox (=false) + uint8_t addToFileBuffer : 1; // Should the raw UBX data be added to the file buffer? uint8_t callbackCopyValid : 1; // Is the copy of the data struct used by the callback valid/fresh? } bits; } flags; @@ -99,12 +99,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_POSECEF_data_t data; UBX_NAV_POSECEF_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_POSECEF_data_t); void (*callbackPointerPtr)(UBX_NAV_POSECEF_data_t *); - UBX_NAV_POSECEF_data_t *callbackData; + UBX_NAV_POSECEF_data_t *callbackData; } UBX_NAV_POSECEF_t; // UBX-NAV-POSLLH (0x01 0x02): Geodetic position solution @@ -112,13 +112,13 @@ const uint16_t UBX_NAV_POSLLH_LEN = 28; typedef struct { - uint32_t iTOW; // GPS time of week of the navigation epoch: ms - int32_t lon; // Longitude: Degrees * 1e-7 - int32_t lat; // Latitude: Degrees * 1e-7 + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + int32_t lon; // Longitude: Degrees * 1e-7 + int32_t lat; // Latitude: Degrees * 1e-7 int32_t height; // Height above ellipsoid: mm - int32_t hMSL; // Height above mean sea level: mm - uint32_t hAcc; // Horizontal Accuracy Estimate: mm - uint32_t vAcc; // Vertical Accuracy Estimate: mm + int32_t hMSL; // Height above mean sea level: mm + uint32_t hAcc; // Horizontal Accuracy Estimate: mm + uint32_t vAcc; // Vertical Accuracy Estimate: mm } UBX_NAV_POSLLH_data_t; typedef struct @@ -143,12 +143,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_POSLLH_data_t data; UBX_NAV_POSLLH_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_POSLLH_data_t); void (*callbackPointerPtr)(UBX_NAV_POSLLH_data_t *); - UBX_NAV_POSLLH_data_t *callbackData; + UBX_NAV_POSLLH_data_t *callbackData; } UBX_NAV_POSLLH_t; // UBX-NAV-STATUS (0x01 0x03): Receiver navigation status @@ -156,7 +156,7 @@ const uint16_t UBX_NAV_STATUS_LEN = 16; typedef struct { - uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint32_t iTOW; // GPS time of week of the navigation epoch: ms uint8_t gpsFix; // GPSfix Type: 0x00 = no fix; 0x01 = dead reckoning only; 0x02 = 2D-fix; 0x03 = 3D-fix // 0x04 = GPS + dead reckoning combined; 0x05 = Time only fix; 0x06..0xff = reserved union @@ -166,8 +166,8 @@ typedef struct { uint8_t gpsFixOk : 1; // 1 = position and velocity valid and within DOP and ACC Masks. uint8_t diffSoln : 1; // 1 = differential corrections were applied - uint8_t wknSet : 1; // 1 = Week Number valid (see Time Validity section for details) - uint8_t towSet : 1; // 1 = Time of Week valid (see Time Validity section for details) + uint8_t wknSet : 1; // 1 = Week Number valid (see Time Validity section for details) + uint8_t towSet : 1; // 1 = Time of Week valid (see Time Validity section for details) } bits; } flags; union @@ -175,7 +175,7 @@ typedef struct uint8_t all; struct { - uint8_t diffCorr : 1; // 1 = differential corrections available + uint8_t diffCorr : 1; // 1 = differential corrections available uint8_t carrSolnValid : 1; // 1 = valid carrSoln uint8_t reserved : 4; uint8_t mapMatching : 2; // map matching status: 00: none @@ -244,12 +244,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_STATUS_data_t data; UBX_NAV_STATUS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_STATUS_data_t); void (*callbackPointerPtr)(UBX_NAV_STATUS_data_t *); - UBX_NAV_STATUS_data_t *callbackData; + UBX_NAV_STATUS_data_t *callbackData; } UBX_NAV_STATUS_t; // UBX-NAV-DOP (0x01 0x04): Dilution of precision @@ -295,7 +295,7 @@ typedef struct UBX_NAV_DOP_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_DOP_data_t); void (*callbackPointerPtr)(UBX_NAV_DOP_data_t *); - UBX_NAV_DOP_data_t *callbackData; + UBX_NAV_DOP_data_t *callbackData; } UBX_NAV_DOP_t; // UBX-NAV-ATT (0x01 0x05): Attitude solution @@ -303,14 +303,14 @@ const uint16_t UBX_NAV_ATT_LEN = 32; typedef struct { - uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint32_t iTOW; // GPS time of week of the navigation epoch: ms uint8_t version; // Message version (0x00 for this version) uint8_t reserved1[3]; - int32_t roll; // Vehicle roll: Degrees * 1e-5 - int32_t pitch; // Vehicle pitch: Degrees * 1e-5 - int32_t heading; // Vehicle heading: Degrees * 1e-5 - uint32_t accRoll; // Vehicle roll accuracy (if null, roll angle is not available): Degrees * 1e-5 - uint32_t accPitch; // Vehicle pitch accuracy (if null, roll angle is not available): Degrees * 1e-5 + int32_t roll; // Vehicle roll: Degrees * 1e-5 + int32_t pitch; // Vehicle pitch: Degrees * 1e-5 + int32_t heading; // Vehicle heading: Degrees * 1e-5 + uint32_t accRoll; // Vehicle roll accuracy (if null, roll angle is not available): Degrees * 1e-5 + uint32_t accPitch; // Vehicle pitch accuracy (if null, roll angle is not available): Degrees * 1e-5 uint32_t accHeading; // Vehicle heading accuracy (if null, roll angle is not available): Degrees * 1e-5 } UBX_NAV_ATT_data_t; @@ -342,7 +342,7 @@ typedef struct UBX_NAV_ATT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_ATT_data_t); void (*callbackPointerPtr)(UBX_NAV_ATT_data_t *); - UBX_NAV_ATT_data_t *callbackData; + UBX_NAV_ATT_data_t *callbackData; } UBX_NAV_ATT_t; // UBX-NAV-PVT (0x01 0x07): Navigation position velocity time solution @@ -353,43 +353,43 @@ typedef struct uint32_t iTOW; // GPS time of week of the navigation epoch: ms uint16_t year; // Year (UTC) uint8_t month; // Month, range 1..12 (UTC) - uint8_t day; // Day of month, range 1..31 (UTC) - uint8_t hour; // Hour of day, range 0..23 (UTC) - uint8_t min; // Minute of hour, range 0..59 (UTC) - uint8_t sec; // Seconds of minute, range 0..60 (UTC) + uint8_t day; // Day of month, range 1..31 (UTC) + uint8_t hour; // Hour of day, range 0..23 (UTC) + uint8_t min; // Minute of hour, range 0..59 (UTC) + uint8_t sec; // Seconds of minute, range 0..60 (UTC) union { uint8_t all; struct { - uint8_t validDate : 1; // 1 = valid UTC Date - uint8_t validTime : 1; // 1 = valid UTC time of day + uint8_t validDate : 1; // 1 = valid UTC Date + uint8_t validTime : 1; // 1 = valid UTC time of day uint8_t fullyResolved : 1; // 1 = UTC time of day has been fully resolved (no seconds uncertainty). - uint8_t validMag : 1; // 1 = valid magnetic declination + uint8_t validMag : 1; // 1 = valid magnetic declination } bits; } valid; - uint32_t tAcc; // Time accuracy estimate (UTC): ns - int32_t nano; // Fraction of second, range -1e9 .. 1e9 (UTC): ns + uint32_t tAcc; // Time accuracy estimate (UTC): ns + int32_t nano; // Fraction of second, range -1e9 .. 1e9 (UTC): ns uint8_t fixType; // GNSSfix Type: - // 0: no fix - // 1: dead reckoning only - // 2: 2D-fix - // 3: 3D-fix - // 4: GNSS + dead reckoning combined - // 5: time only fix + // 0: no fix + // 1: dead reckoning only + // 2: 2D-fix + // 3: 3D-fix + // 4: GNSS + dead reckoning combined + // 5: time only fix union { uint8_t all; struct { uint8_t gnssFixOK : 1; // 1 = valid fix (i.e within DOP & accuracy masks) - uint8_t diffSoln : 1; // 1 = differential corrections were applied + uint8_t diffSoln : 1; // 1 = differential corrections were applied uint8_t psmState : 3; uint8_t headVehValid : 1; // 1 = heading of vehicle is valid, only set if the receiver is in sensor fusion mode - uint8_t carrSoln : 2; // Carrier phase range solution status: - // 0: no carrier phase range solution - // 1: carrier phase range solution with floating ambiguities - // 2: carrier phase range solution with fixed ambiguities + uint8_t carrSoln : 2; // Carrier phase range solution status: + // 0: no carrier phase range solution + // 1: carrier phase range solution with floating ambiguities + // 2: carrier phase range solution with fixed ambiguities } bits; } flags; union @@ -403,21 +403,21 @@ typedef struct uint8_t confirmedTime : 1; // 1 = UTC Time of Day could be confirmed } bits; } flags2; - uint8_t numSV; // Number of satellites used in Nav Solution - int32_t lon; // Longitude: deg * 1e-7 - int32_t lat; // Latitude: deg * 1e-7 - int32_t height; // Height above ellipsoid: mm - int32_t hMSL; // Height above mean sea level: mm - uint32_t hAcc; // Horizontal accuracy estimate: mm - uint32_t vAcc; // Vertical accuracy estimate: mm - int32_t velN; // NED north velocity: mm/s - int32_t velE; // NED east velocity: mm/s - int32_t velD; // NED down velocity: mm/s - int32_t gSpeed; // Ground Speed (2-D): mm/s - int32_t headMot; // Heading of motion (2-D): deg * 1e-5 - uint32_t sAcc; // Speed accuracy estimate: mm/s + uint8_t numSV; // Number of satellites used in Nav Solution + int32_t lon; // Longitude: deg * 1e-7 + int32_t lat; // Latitude: deg * 1e-7 + int32_t height; // Height above ellipsoid: mm + int32_t hMSL; // Height above mean sea level: mm + uint32_t hAcc; // Horizontal accuracy estimate: mm + uint32_t vAcc; // Vertical accuracy estimate: mm + int32_t velN; // NED north velocity: mm/s + int32_t velE; // NED east velocity: mm/s + int32_t velD; // NED down velocity: mm/s + int32_t gSpeed; // Ground Speed (2-D): mm/s + int32_t headMot; // Heading of motion (2-D): deg * 1e-5 + uint32_t sAcc; // Speed accuracy estimate: mm/s uint32_t headAcc; // Heading accuracy estimate (both motion and vehicle): deg * 1e-5 - uint16_t pDOP; // Position DOP * 0.01 + uint16_t pDOP; // Position DOP * 0.01 union { uint8_t all; @@ -428,7 +428,7 @@ typedef struct } flags3; uint8_t reserved1[5]; int32_t headVeh; // Heading of vehicle (2-D): deg * 1e-5 - int16_t magDec; // Magnetic declination: deg * 1e-2 + int16_t magDec; // Magnetic declination: deg * 1e-2 uint16_t magAcc; // Magnetic declination accuracy: deg * 1e-2 } UBX_NAV_PVT_data_t; @@ -477,7 +477,7 @@ typedef struct uint32_t velN : 1; uint32_t velE : 1; } bits; - } moduleQueried1; + } moduleQueried1; union { uint32_t all; @@ -501,12 +501,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_PVT_data_t data; UBX_NAV_PVT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_PVT_data_t); void (*callbackPointerPtr)(UBX_NAV_PVT_data_t *); - UBX_NAV_PVT_data_t *callbackData; + UBX_NAV_PVT_data_t *callbackData; } UBX_NAV_PVT_t; // UBX-NAV-ODO (0x01 0x09): Odometer solution @@ -516,10 +516,10 @@ typedef struct { uint8_t version; // Message version (0x00 for this version) uint8_t reserved1[3]; - uint32_t iTOW; // GPS time of week of the navigation epoch: ms - uint32_t distance; // Ground distance since last reset: m + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint32_t distance; // Ground distance since last reset: m uint32_t totalDistance; // Total cumulative ground distance: m - uint32_t distanceStd; // Ground distance accuracy (1-sigma): m + uint32_t distanceStd; // Ground distance accuracy (1-sigma): m } UBX_NAV_ODO_data_t; typedef struct @@ -542,12 +542,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_ODO_data_t data; UBX_NAV_ODO_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_ODO_data_t); void (*callbackPointerPtr)(UBX_NAV_ODO_data_t *); - UBX_NAV_ODO_data_t *callbackData; + UBX_NAV_ODO_data_t *callbackData; } UBX_NAV_ODO_t; // UBX-NAV-VELECEF (0x01 0x11): Velocity solution in ECEF @@ -555,11 +555,11 @@ const uint16_t UBX_NAV_VELECEF_LEN = 20; typedef struct { - uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint32_t iTOW; // GPS time of week of the navigation epoch: ms int32_t ecefVX; // ECEF X velocity: cm/s int32_t ecefVY; // ECEF Y velocity: cm/s int32_t ecefVZ; // ECEF Z velocity: cm/s - uint32_t sAcc; // Speed accuracy estimate: cm/s + uint32_t sAcc; // Speed accuracy estimate: cm/s } UBX_NAV_VELECEF_data_t; typedef struct @@ -582,12 +582,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_VELECEF_data_t data; UBX_NAV_VELECEF_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_VELECEF_data_t); void (*callbackPointerPtr)(UBX_NAV_VELECEF_data_t *); - UBX_NAV_VELECEF_data_t *callbackData; + UBX_NAV_VELECEF_data_t *callbackData; } UBX_NAV_VELECEF_t; // UBX-NAV-VELNED (0x01 0x12): Velocity solution in NED frame @@ -595,15 +595,15 @@ const uint16_t UBX_NAV_VELNED_LEN = 36; typedef struct { - uint32_t iTOW; // GPS time of week of the navigation epoch: ms - int32_t velN; // North velocity component: cm/s - int32_t velE; // East velocity component: cm/s - int32_t velD; // Down velocity component: cm/s - uint32_t speed; // Speed (3-D): cm/s + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + int32_t velN; // North velocity component: cm/s + int32_t velE; // East velocity component: cm/s + int32_t velD; // Down velocity component: cm/s + uint32_t speed; // Speed (3-D): cm/s uint32_t gSpeed; // Ground Speed (2-D): cm/s int32_t heading; // Heading of motion 2-D: Degrees * 1e-5 - uint32_t sAcc; // Speed accuracy estimate: cm/s - uint32_t cAcc; // Course/Heading accuracy estimate: Degrees * 1e-5 + uint32_t sAcc; // Speed accuracy estimate: cm/s + uint32_t cAcc; // Course/Heading accuracy estimate: Degrees * 1e-5 } UBX_NAV_VELNED_data_t; typedef struct @@ -630,12 +630,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_VELNED_data_t data; UBX_NAV_VELNED_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_VELNED_data_t); void (*callbackPointerPtr)(UBX_NAV_VELNED_data_t *); - UBX_NAV_VELNED_data_t *callbackData; + UBX_NAV_VELNED_data_t *callbackData; } UBX_NAV_VELNED_t; // UBX-NAV-HPPOSECEF (0x01 0x13): High precision position solution in ECEF @@ -645,10 +645,10 @@ typedef struct { uint8_t version; // Message version (0x00 for this version) uint8_t reserved1[3]; - uint32_t iTOW; // GPS time of week of the navigation epoch: ms - int32_t ecefX; // ECEF X coordinate: cm - int32_t ecefY; // ECEF Y coordinate: cm - int32_t ecefZ; // ECEF Z coordinate: cm + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + int32_t ecefX; // ECEF X coordinate: cm + int32_t ecefY; // ECEF Y coordinate: cm + int32_t ecefZ; // ECEF Z coordinate: cm int8_t ecefXHp; // High precision component of ECEF X coordinate: mm * 0.1 int8_t ecefYHp; // High precision component of ECEF Y coordinate: mm * 0.1 int8_t ecefZHp; // High precision component of ECEF Z coordinate: mm * 0.1 @@ -690,12 +690,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_HPPOSECEF_data_t data; UBX_NAV_HPPOSECEF_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_HPPOSECEF_data_t); void (*callbackPointerPtr)(UBX_NAV_HPPOSECEF_data_t *); - UBX_NAV_HPPOSECEF_data_t *callbackData; + UBX_NAV_HPPOSECEF_data_t *callbackData; } UBX_NAV_HPPOSECEF_t; // UBX-NAV-HPPOSLLH (0x01 0x14): High precision geodetic position solution @@ -713,17 +713,17 @@ typedef struct uint8_t invalidLlh : 1; // 1 = Invalid lon, lat, height, hMSL, lonHp, latHp, heightHp and hMSLHp } bits; } flags; - uint32_t iTOW; // GPS time of week of the navigation epoch: ms - int32_t lon; // Longitude: deg * 1e-7 - int32_t lat; // Latitude: deg * 1e-7 - int32_t height; // Height above ellipsoid: mm - int32_t hMSL; // Height above mean sea level: mm - int8_t lonHp; // High precision component of longitude: deg * 1e-9 - int8_t latHp; // High precision component of latitude: deg * 1e-9 + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + int32_t lon; // Longitude: deg * 1e-7 + int32_t lat; // Latitude: deg * 1e-7 + int32_t height; // Height above ellipsoid: mm + int32_t hMSL; // Height above mean sea level: mm + int8_t lonHp; // High precision component of longitude: deg * 1e-9 + int8_t latHp; // High precision component of latitude: deg * 1e-9 int8_t heightHp; // High precision component of height above ellipsoid: mm * 0.1 - int8_t hMSLHp; // High precision component of height above mean sea level: mm * 0.1 - uint32_t hAcc; // Horizontal accuracy estimate: mm * 0.1 - uint32_t vAcc; // Vertical accuracy estimate: mm * 0.1 + int8_t hMSLHp; // High precision component of height above mean sea level: mm * 0.1 + uint32_t hAcc; // Horizontal accuracy estimate: mm * 0.1 + uint32_t vAcc; // Vertical accuracy estimate: mm * 0.1 } UBX_NAV_HPPOSLLH_data_t; typedef struct @@ -756,12 +756,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_HPPOSLLH_data_t data; UBX_NAV_HPPOSLLH_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_HPPOSLLH_data_t); void (*callbackPointerPtr)(UBX_NAV_HPPOSLLH_data_t *); - UBX_NAV_HPPOSLLH_data_t *callbackData; + UBX_NAV_HPPOSLLH_data_t *callbackData; } UBX_NAV_HPPOSLLH_t; // UBX-NAV-PVAT (0x01 0x17): Navigation position velocity attitude time solution @@ -769,51 +769,51 @@ const uint16_t UBX_NAV_PVAT_LEN = 116; typedef struct { - uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint32_t iTOW; // GPS time of week of the navigation epoch: ms uint8_t version; // Message version (0x00 for this version) union { uint8_t all; struct { - uint8_t validDate : 1; // 1 = valid UTC Date - uint8_t validTime : 1; // 1 = valid UTC time of day + uint8_t validDate : 1; // 1 = valid UTC Date + uint8_t validTime : 1; // 1 = valid UTC time of day uint8_t fullyResolved : 1; // 1 = UTC time of day has been fully resolved (no seconds uncertainty). - uint8_t validMag : 1; // 1 = valid magnetic declination + uint8_t validMag : 1; // 1 = valid magnetic declination } bits; } valid; uint16_t year; // Year (UTC) uint8_t month; // Month, range 1..12 (UTC) - uint8_t day; // Day of month, range 1..31 (UTC) - uint8_t hour; // Hour of day, range 0..23 (UTC) - uint8_t min; // Minute of hour, range 0..59 (UTC) - uint8_t sec; // Seconds of minute, range 0..60 (UTC) + uint8_t day; // Day of month, range 1..31 (UTC) + uint8_t hour; // Hour of day, range 0..23 (UTC) + uint8_t min; // Minute of hour, range 0..59 (UTC) + uint8_t sec; // Seconds of minute, range 0..60 (UTC) uint8_t reserved0; uint8_t reserved1[2]; - uint32_t tAcc; // Time accuracy estimate (UTC): ns - int32_t nano; // Fraction of second, range -1e9 .. 1e9 (UTC): ns + uint32_t tAcc; // Time accuracy estimate (UTC): ns + int32_t nano; // Fraction of second, range -1e9 .. 1e9 (UTC): ns uint8_t fixType; // GNSSfix Type: - // 0: no fix - // 1: dead reckoning only - // 2: 2D-fix - // 3: 3D-fix - // 4: GNSS + dead reckoning combined - // 5: time only fix + // 0: no fix + // 1: dead reckoning only + // 2: 2D-fix + // 3: 3D-fix + // 4: GNSS + dead reckoning combined + // 5: time only fix union { uint8_t all; struct { uint8_t gnssFixOK : 1; // 1 = valid fix (i.e within DOP & accuracy masks) - uint8_t diffSoln : 1; // 1 = differential corrections were applied + uint8_t diffSoln : 1; // 1 = differential corrections were applied uint8_t reserved : 1; - uint8_t vehRollValid : 1; // 1 = roll of vehicle is valid, only set if the receiver is in sensor fusion mode - uint8_t vehPitchValid : 1; // 1 = pitch of vehicle is valid, only set if the receiver is in sensor fusion mode + uint8_t vehRollValid : 1; // 1 = roll of vehicle is valid, only set if the receiver is in sensor fusion mode + uint8_t vehPitchValid : 1; // 1 = pitch of vehicle is valid, only set if the receiver is in sensor fusion mode uint8_t vehHeadingValid : 1; // 1 = heading of vehicle is valid, only set if the receiver is in sensor fusion mode - uint8_t carrSoln : 2; // Carrier phase range solution status: - // 0: no carrier phase range solution - // 1: carrier phase range solution with floating ambiguities - // 2: carrier phase range solution with fixed ambiguities + uint8_t carrSoln : 2; // Carrier phase range solution status: + // 0: no carrier phase range solution + // 1: carrier phase range solution with floating ambiguities + // 2: carrier phase range solution with fixed ambiguities } bits; } flags; union @@ -827,30 +827,30 @@ typedef struct uint8_t confirmedTime : 1; // 1 = UTC Time of Day could be confirmed } bits; } flags2; - uint8_t numSV; // Number of satellites used in Nav Solution - int32_t lon; // Longitude: deg * 1e-7 - int32_t lat; // Latitude: deg * 1e-7 - int32_t height; // Height above ellipsoid: mm - int32_t hMSL; // Height above mean sea level: mm - uint32_t hAcc; // Horizontal accuracy estimate: mm - uint32_t vAcc; // Vertical accuracy estimate: mm - int32_t velN; // NED north velocity: mm/s - int32_t velE; // NED east velocity: mm/s - int32_t velD; // NED down velocity: mm/s - int32_t gSpeed; // Ground Speed (2-D): mm/s - uint32_t sAcc; // Speed accuracy estimate: mm/s - int32_t vehRoll; // Vehicle roll: 1e-5 deg - int32_t vehPitch; // Vehicle pitch: 1e-5 deg - int32_t vehHeading; // Vehicle heading: 1e-5 deg - int32_t motHeading; // Motion heading.: 1e-5 deg - uint16_t accRoll; // Vehicle roll accuracy (if null, roll angle is not available): 1e-2 deg - uint16_t accPitch; // Vehicle pitch accuracy (if null, pitch angle is not available): 1e-2 deg - uint16_t accHeading; // Vehicle heading accuracy (if null, heading angle is not available): 1e-2 deg - int16_t magDec; // Magnetic declination: 1e-2 deg - uint16_t magAcc; // Magnetic declination accuracy: 1e-2 deg + uint8_t numSV; // Number of satellites used in Nav Solution + int32_t lon; // Longitude: deg * 1e-7 + int32_t lat; // Latitude: deg * 1e-7 + int32_t height; // Height above ellipsoid: mm + int32_t hMSL; // Height above mean sea level: mm + uint32_t hAcc; // Horizontal accuracy estimate: mm + uint32_t vAcc; // Vertical accuracy estimate: mm + int32_t velN; // NED north velocity: mm/s + int32_t velE; // NED east velocity: mm/s + int32_t velD; // NED down velocity: mm/s + int32_t gSpeed; // Ground Speed (2-D): mm/s + uint32_t sAcc; // Speed accuracy estimate: mm/s + int32_t vehRoll; // Vehicle roll: 1e-5 deg + int32_t vehPitch; // Vehicle pitch: 1e-5 deg + int32_t vehHeading; // Vehicle heading: 1e-5 deg + int32_t motHeading; // Motion heading.: 1e-5 deg + uint16_t accRoll; // Vehicle roll accuracy (if null, roll angle is not available): 1e-2 deg + uint16_t accPitch; // Vehicle pitch accuracy (if null, pitch angle is not available): 1e-2 deg + uint16_t accHeading; // Vehicle heading accuracy (if null, heading angle is not available): 1e-2 deg + int16_t magDec; // Magnetic declination: 1e-2 deg + uint16_t magAcc; // Magnetic declination accuracy: 1e-2 deg uint16_t errEllipseOrient; // Orientation of semi-major axis of error ellipse (degrees from true north): 1e-2 deg - uint32_t errEllipseMajor; // Semi-major axis of error ellipse: mm - uint32_t errEllipseMinor; // Semi-minor axis of error ellipse: mm + uint32_t errEllipseMajor; // Semi-major axis of error ellipse: mm + uint32_t errEllipseMinor; // Semi-minor axis of error ellipse: mm uint8_t reserved2[4]; uint8_t reserved3[4]; } UBX_NAV_PVAT_data_t; @@ -885,7 +885,7 @@ typedef struct uint32_t gnssFixOK : 1; uint32_t diffSoln : 1; - uint32_t vehRollValid : 1; + uint32_t vehRollValid : 1; uint32_t vehPitchValid : 1; uint32_t vehHeadingValid : 1; uint32_t carrSoln : 1; @@ -902,7 +902,7 @@ typedef struct uint32_t hAcc : 1; uint32_t vAcc : 1; } bits; - } moduleQueried1; + } moduleQueried1; union { uint32_t all; @@ -931,12 +931,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_PVAT_data_t data; UBX_NAV_PVAT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_PVAT_data_t); void (*callbackPointerPtr)(UBX_NAV_PVAT_data_t *); - UBX_NAV_PVAT_data_t *callbackData; + UBX_NAV_PVAT_data_t *callbackData; } UBX_NAV_PVAT_t; // UBX-NAV-TIMEUTC (0x01 0x21): UTC time solution @@ -946,13 +946,13 @@ typedef struct { uint32_t iTOW; // GPS time of week of the navigation epoch: ms uint32_t tAcc; // Time accuracy estimate (UTC): ns - int32_t nano; // Fraction of second, range -1e9 .. 1e9 (UTC): ns + int32_t nano; // Fraction of second, range -1e9 .. 1e9 (UTC): ns uint16_t year; // Year (UTC) uint8_t month; // Month, range 1..12 (UTC) - uint8_t day; // Day of month, range 1..31 (UTC) - uint8_t hour; // Hour of day, range 0..23 (UTC) - uint8_t min; // Minute of hour, range 0..59 (UTC) - uint8_t sec; // Seconds of minute, range 0..60 (UTC) + uint8_t day; // Day of month, range 1..31 (UTC) + uint8_t hour; // Hour of day, range 0..23 (UTC) + uint8_t min; // Minute of hour, range 0..59 (UTC) + uint8_t sec; // Seconds of minute, range 0..60 (UTC) union { uint8_t all; @@ -991,17 +991,17 @@ typedef struct uint32_t validUTC : 1; uint32_t utcStandard : 1; } bits; - } moduleQueried; + } moduleQueried; } UBX_NAV_TIMEUTC_moduleQueried_t; typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_TIMEUTC_data_t data; UBX_NAV_TIMEUTC_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_TIMEUTC_data_t); void (*callbackPointerPtr)(UBX_NAV_TIMEUTC_data_t *); - UBX_NAV_TIMEUTC_data_t *callbackData; + UBX_NAV_TIMEUTC_data_t *callbackData; } UBX_NAV_TIMEUTC_t; // UBX-NAV-CLOCK (0x01 0x22): Clock solution @@ -1010,8 +1010,8 @@ const uint16_t UBX_NAV_CLOCK_LEN = 20; typedef struct { uint32_t iTOW; // GPS time of week of the navigation epoch: ms - int32_t clkB; // Clock bias: ns - int32_t clkD; // Clock drift: ns/s + int32_t clkB; // Clock bias: ns + int32_t clkD; // Clock drift: ns/s uint32_t tAcc; // Time accuracy estimate: ns uint32_t fAcc; // Frequency accuracy estimate: ps/s } UBX_NAV_CLOCK_data_t; @@ -1036,12 +1036,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_CLOCK_data_t data; UBX_NAV_CLOCK_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_CLOCK_data_t); void (*callbackPointerPtr)(UBX_NAV_CLOCK_data_t *); - UBX_NAV_CLOCK_data_t *callbackData; + UBX_NAV_CLOCK_data_t *callbackData; } UBX_NAV_CLOCK_t; // UBX-NAV-TIMELS (0x01 0x26): Leap second event information @@ -1049,23 +1049,23 @@ const uint16_t UBX_NAV_TIMELS_LEN = 24; typedef struct { - uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint32_t iTOW; // GPS time of week of the navigation epoch: ms uint8_t version; // Message version (0x00 for this version) uint8_t reserved1[3]; - uint8_t srcOfCurrLs; //Information source for the current number of leap seconds - int8_t currLs; //Current number of leap seconds since start of GPS (Jan 6, 1980), s - uint8_t srcOfLsChange; //Information source for the future leap second event - int8_t lsChange; //Future leap second change if one is scheduled, +1, 0, -1s - int32_t timeToLsEvent; //Num of secs until the next or from the last leap second, s - uint16_t dateOfLsGpsWn; //GPS week num (WN) of the next or the last leap second event - uint16_t dateOfLsGpsDn; //GPS day of week num (DN) for the next or last leap second event + uint8_t srcOfCurrLs; // Information source for the current number of leap seconds + int8_t currLs; // Current number of leap seconds since start of GPS (Jan 6, 1980), s + uint8_t srcOfLsChange; // Information source for the future leap second event + int8_t lsChange; // Future leap second change if one is scheduled, +1, 0, -1s + int32_t timeToLsEvent; // Num of secs until the next or from the last leap second, s + uint16_t dateOfLsGpsWn; // GPS week num (WN) of the next or the last leap second event + uint16_t dateOfLsGpsDn; // GPS day of week num (DN) for the next or last leap second event uint8_t reserved2[3]; union { uint8_t all; struct { - uint8_t validCurrLs : 1; // 1 = Valid current number of leap seconds value + uint8_t validCurrLs : 1; // 1 = Valid current number of leap seconds value uint8_t validTimeToLsEvent : 1; // 1 = Valid time to next leap second event or from the last leap second event if no future event scheduled } bits; } valid; @@ -1097,12 +1097,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_TIMELS_data_t data; UBX_NAV_TIMELS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_TIMELS_data_t); void (*callbackPointerPtr)(UBX_NAV_TIMELS_data_t *); - UBX_NAV_TIMELS_data_t *callbackData; + UBX_NAV_TIMELS_data_t *callbackData; } UBX_NAV_TIMELS_t; // UBX-NAV-SAT (0x01 0x35): Satellite Information @@ -1111,20 +1111,20 @@ const uint16_t UBX_NAV_SAT_MAX_LEN = 8 + (12 * UBX_NAV_SAT_MAX_BLOCKS); typedef struct { - uint32_t iTOW; // GPS time of week + uint32_t iTOW; // GPS time of week uint8_t version; // Message version (0x01 for this version) - uint8_t numSvs; // Number of satellites + uint8_t numSvs; // Number of satellites uint8_t reserved1[2]; } UBX_NAV_SAT_header_t; typedef struct { uint8_t gnssId; // GNSS identifier - uint8_t svId; // Satellite identifier - uint8_t cno; // Carrier-to-noise density ratio: dB-Hz - int8_t elev; // Elevation (range: +/-90): deg - int16_t azim; // Azimuth (range 0-360): deg - int16_t prRes; // Pseudorange residual: m * 0.1 + uint8_t svId; // Satellite identifier + uint8_t cno; // Carrier-to-noise density ratio: dB-Hz + int8_t elev; // Elevation (range: +/-90): deg + int16_t azim; // Azimuth (range 0-360): deg + int16_t prRes; // Pseudorange residual: m * 0.1 union { uint32_t all; @@ -1136,28 +1136,28 @@ typedef struct // 3: signal detected but unusable // 4: code locked and time synchronized // 5, 6, 7: code and carrier locked and time synchronized - uint32_t svUsed : 1; // 1 = Signal in the subset specified in Signal Identifiers is currently being used for navigation - uint32_t health : 2; // Signal health flag: 0: unknown 1: healthy 2: unhealthy - uint32_t diffCorr : 1; // 1 = differential correction data is available for this SV - uint32_t smoothed : 1; // 1 = carrier smoothed pseudorange used + uint32_t svUsed : 1; // 1 = Signal in the subset specified in Signal Identifiers is currently being used for navigation + uint32_t health : 2; // Signal health flag: 0: unknown 1: healthy 2: unhealthy + uint32_t diffCorr : 1; // 1 = differential correction data is available for this SV + uint32_t smoothed : 1; // 1 = carrier smoothed pseudorange used uint32_t orbitSource : 3; // Orbit source: 0: no orbit information is available for this SV // 1: ephemeris is used // 2: almanac is used // 3: AssistNow Offline orbit is used // 4: AssistNow Autonomous orbit is used // 5, 6, 7: other orbit information is used - uint32_t ephAvail : 1; // 1 = ephemeris is available for this SV - uint32_t almAvail : 1; // 1 = almanac is available for this SV - uint32_t anoAvail : 1; // 1 = AssistNow Offline data is available for this SV - uint32_t aopAvail : 1; // 1 = AssistNow Autonomous data is available for this SV + uint32_t ephAvail : 1; // 1 = ephemeris is available for this SV + uint32_t almAvail : 1; // 1 = almanac is available for this SV + uint32_t anoAvail : 1; // 1 = AssistNow Offline data is available for this SV + uint32_t aopAvail : 1; // 1 = AssistNow Autonomous data is available for this SV uint32_t reserved1 : 1; - uint32_t sbasCorrUsed : 1; // 1 = SBAS corrections have been used for a signal in the subset specified in Signal Identifiers - uint32_t rtcmCorrUsed : 1; // 1 = RTCM corrections have been used for a signal in the subset specified in Signal Identifiers - uint32_t slasCorrUsed : 1; // 1 = QZSS SLAS corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t sbasCorrUsed : 1; // 1 = SBAS corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t rtcmCorrUsed : 1; // 1 = RTCM corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t slasCorrUsed : 1; // 1 = QZSS SLAS corrections have been used for a signal in the subset specified in Signal Identifiers uint32_t spartnCorrUsed : 1; // 1 = SPARTN corrections have been used for a signal in the subset specified in Signal Identifiers - uint32_t prCorrUsed : 1; // 1 = Pseudorange corrections have been used for a signal in the subset specified in Signal Identifiers - uint32_t crCorrUsed : 1; // 1 = Carrier range corrections have been used for a signal in the subset specified in Signal Identifiers - uint32_t doCorrUsed : 1; // 1 = Range rate (Doppler) corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t prCorrUsed : 1; // 1 = Pseudorange corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t crCorrUsed : 1; // 1 = Carrier range corrections have been used for a signal in the subset specified in Signal Identifiers + uint32_t doCorrUsed : 1; // 1 = Range rate (Doppler) corrections have been used for a signal in the subset specified in Signal Identifiers uint32_t reserved2 : 9; } bits; } flags; @@ -1171,12 +1171,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_SAT_data_t data; bool moduleQueried; void (*callbackPointer)(UBX_NAV_SAT_data_t); void (*callbackPointerPtr)(UBX_NAV_SAT_data_t *); - UBX_NAV_SAT_data_t *callbackData; + UBX_NAV_SAT_data_t *callbackData; } UBX_NAV_SAT_t; // UBX-NAV-SVIN (0x01 0x3B): Survey-in data @@ -1186,19 +1186,19 @@ typedef struct { uint8_t version; // Message version (0x00 for this version) uint8_t reserved1[3]; - uint32_t iTOW; // GPS time of week of the navigation epoch: ms - uint32_t dur; // Passed survey-in observation time: s - int32_t meanX; // Current survey-in mean position ECEF X coordinate: cm - int32_t meanY; // Current survey-in mean position ECEF Y coordinate: cm - int32_t meanZ; // Current survey-in mean position ECEF Z coordinate: cm + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + uint32_t dur; // Passed survey-in observation time: s + int32_t meanX; // Current survey-in mean position ECEF X coordinate: cm + int32_t meanY; // Current survey-in mean position ECEF Y coordinate: cm + int32_t meanZ; // Current survey-in mean position ECEF Z coordinate: cm int8_t meanXHP; // Current high-precision survey-in mean position ECEF X coordinate: mm * 0.1 int8_t meanYHP; // Current high-precision survey-in mean position ECEF Y coordinate: mm * 0.1 int8_t meanZHP; // Current high-precision survey-in mean position ECEF Z coordinate: mm * 0.1 uint8_t reserved2; uint32_t meanAcc; // Current survey-in mean position accuracy: mm * 0.1 - uint32_t obs; // Number of position observations used during survey-in - int8_t valid; // Survey-in position validity flag, 1 = valid, otherwise 0 - int8_t active; // Survey-in in progress flag, 1 = in-progress, otherwise 0 + uint32_t obs; // Number of position observations used during survey-in + int8_t valid; // Survey-in position validity flag, 1 = valid, otherwise 0 + int8_t active; // Survey-in in progress flag, 1 = in-progress, otherwise 0 uint8_t reserved3[2]; } UBX_NAV_SVIN_data_t; @@ -1230,12 +1230,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + 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_data_t *callbackData; } UBX_NAV_SVIN_t; // UBX-NAV-RELPOSNED (0x01 0x3C): Relative positioning information in NED frame @@ -1250,40 +1250,40 @@ typedef struct uint8_t version; // Message version (0x00 for this version) uint8_t reserved0; uint16_t refStationId; // Reference Station ID - uint32_t iTOW; // GPS time of week of the navigation epoch: ms - int32_t relPosN; // North component of relative position vector: cm - int32_t relPosE; // East component of relative position vector: cm - int32_t relPosD; // Down component of relative position vector: cm - int32_t relPosLength; // Length of the relative position vector: cm + uint32_t iTOW; // GPS time of week of the navigation epoch: ms + int32_t relPosN; // North component of relative position vector: cm + int32_t relPosE; // East component of relative position vector: cm + int32_t relPosD; // Down component of relative position vector: cm + int32_t relPosLength; // Length of the relative position vector: cm int32_t relPosHeading; // Heading of the relative position vector: Degrees * 1e-5 uint8_t reserved1[4]; - int8_t relPosHPN; // High-precision North component of relative position vector: mm * 0.1 - int8_t relPosHPE; // High-precision East component of relative position vector: mm * 0.1 - int8_t relPosHPD; // High-precision Down component of relative position vector: mm * 0.1 + int8_t relPosHPN; // High-precision North component of relative position vector: mm * 0.1 + int8_t relPosHPE; // High-precision East component of relative position vector: mm * 0.1 + int8_t relPosHPD; // High-precision Down component of relative position vector: mm * 0.1 int8_t relPosHPLength; // High-precision component of the length of the relative position vector: mm * 0.1 - uint32_t accN; // Accuracy of relative position North component: mm * 0.1 - uint32_t accE; // Accuracy of relative position East component: mm * 0.1 - uint32_t accD; // Accuracy of relative position Down component: mm * 0.1 - uint32_t accLength; // Accuracy of length of the relative position vector: mm * 0.1 - uint32_t accHeading; // Accuracy of heading of the relative position vector: Degrees * 1e-5 + uint32_t accN; // Accuracy of relative position North component: mm * 0.1 + uint32_t accE; // Accuracy of relative position East component: mm * 0.1 + uint32_t accD; // Accuracy of relative position Down component: mm * 0.1 + uint32_t accLength; // Accuracy of length of the relative position vector: mm * 0.1 + uint32_t accHeading; // Accuracy of heading of the relative position vector: Degrees * 1e-5 uint8_t reserved2[4]; union { uint32_t all; struct { - uint32_t gnssFixOK : 1; // A valid fix (i.e within DOP & accuracy masks) - uint32_t diffSoln : 1; // 1 if differential corrections were applied - uint32_t relPosValid : 1; // 1 if relative position components and accuracies are valid - uint32_t carrSoln : 2; // Carrier phase range solution status: - // 0 = no carrier phase range solution - // 1 = carrier phase range solution with floating ambiguities - // 2 = carrier phase range solution with fixed ambiguities - uint32_t isMoving : 1; // 1 if the receiver is operating in moving baseline mode - uint32_t refPosMiss : 1; // 1 if extrapolated reference position was used to compute moving baseline solution this epoch - uint32_t refObsMiss : 1; // 1 if extrapolated reference observations were used to compute moving baseline solution this epoch + uint32_t gnssFixOK : 1; // A valid fix (i.e within DOP & accuracy masks) + uint32_t diffSoln : 1; // 1 if differential corrections were applied + uint32_t relPosValid : 1; // 1 if relative position components and accuracies are valid + uint32_t carrSoln : 2; // Carrier phase range solution status: + // 0 = no carrier phase range solution + // 1 = carrier phase range solution with floating ambiguities + // 2 = carrier phase range solution with fixed ambiguities + uint32_t isMoving : 1; // 1 if the receiver is operating in moving baseline mode + uint32_t refPosMiss : 1; // 1 if extrapolated reference position was used to compute moving baseline solution this epoch + uint32_t refObsMiss : 1; // 1 if extrapolated reference observations were used to compute moving baseline solution this epoch uint32_t relPosHeadingValid : 1; // 1 if relPosHeading is valid - uint32_t relPosNormalized : 1; // 1 if the components of the relative position vector (including the high-precision parts) are normalized + uint32_t relPosNormalized : 1; // 1 if the components of the relative position vector (including the high-precision parts) are normalized } bits; } flags; } UBX_NAV_RELPOSNED_data_t; @@ -1330,12 +1330,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_NAV_RELPOSNED_data_t data; UBX_NAV_RELPOSNED_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_RELPOSNED_data_t); void (*callbackPointerPtr)(UBX_NAV_RELPOSNED_data_t *); - UBX_NAV_RELPOSNED_data_t *callbackData; + UBX_NAV_RELPOSNED_data_t *callbackData; } UBX_NAV_RELPOSNED_t; // UBX-NAV-AOPSTATUS (0x01 0x60): AssistNow Autonomous status @@ -1351,7 +1351,7 @@ typedef struct { uint8_t useAOP : 1; // AOP enabled flag } bits; - } aopCfg; // AssistNow Autonomous configuration + } aopCfg; // AssistNow Autonomous configuration uint8_t status; // AssistNow Autonomous subsystem is idle (0) or running (not 0) uint8_t reserved1[10]; } UBX_NAV_AOPSTATUS_data_t; @@ -1381,7 +1381,7 @@ typedef struct UBX_NAV_AOPSTATUS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t); void (*callbackPointerPtr)(UBX_NAV_AOPSTATUS_data_t *); - UBX_NAV_AOPSTATUS_data_t *callbackData; + UBX_NAV_AOPSTATUS_data_t *callbackData; } UBX_NAV_AOPSTATUS_t; // RXM-specific structs @@ -1396,24 +1396,24 @@ const uint16_t UBX_RXM_SFRBX_MAX_LEN = 8 + (4 * UBX_RXM_SFRBX_MAX_WORDS); typedef struct { uint8_t gnssId; // GNSS identifier - uint8_t svId; // Satellite identifier + uint8_t svId; // Satellite identifier uint8_t reserved1; - uint8_t freqId; // GLONASS frequency slot + uint8_t freqId; // GLONASS frequency slot uint8_t numWords; // The number of data words contained in this message (0..16) - uint8_t chn; // The tracking channel number the message was received on - uint8_t version; // Message version (0x01 for this version) + uint8_t chn; // The tracking channel number the message was received on + uint8_t version; // Message version (0x01 for this version) uint8_t reserved2; uint32_t dwrd[UBX_RXM_SFRBX_MAX_WORDS]; // The data words } UBX_RXM_SFRBX_data_t; typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_RXM_SFRBX_data_t data; bool moduleQueried; void (*callbackPointer)(UBX_RXM_SFRBX_data_t); void (*callbackPointerPtr)(UBX_RXM_SFRBX_data_t *); - UBX_RXM_SFRBX_data_t *callbackData; + UBX_RXM_SFRBX_data_t *callbackData; } UBX_RXM_SFRBX_t; // UBX-RXM-RAWX (0x02 0x15): Multi-GNSS raw measurement data @@ -1424,15 +1424,15 @@ const uint16_t UBX_RXM_RAWX_MAX_LEN = 16 + (32 * UBX_RXM_RAWX_MAX_BLOCKS); typedef struct { uint8_t rcvTow[8]; // Measurement time of week in receiver local time [64-bit float] - uint16_t week; // GPS week number - int8_t leapS; // GPS leap seconds - uint8_t numMeas; // Number of measurements to follow + uint16_t week; // GPS week number + int8_t leapS; // GPS leap seconds + uint8_t numMeas; // Number of measurements to follow union { uint8_t all; struct { - uint8_t leapSec : 1; // Leap seconds have been determined + uint8_t leapSec : 1; // Leap seconds have been determined uint8_t clkReset : 1; // Clock reset applied } bits; } recStat; @@ -1442,26 +1442,26 @@ typedef struct typedef struct { - uint8_t prMes[8]; // Pseudorange measurement: m [64-bit float] - uint8_t cpMes[8]; // Carrier phase measurement: cycles [64-bit float] - uint8_t doMes[4]; // Doppler measurement: Hz [32-bit float] - uint8_t gnssId; // GNSS identifier - uint8_t svId; // Satellite identifier - uint8_t sigId; // New signal identifier - uint8_t freqId; // GLONASS frequency slot + uint8_t prMes[8]; // Pseudorange measurement: m [64-bit float] + uint8_t cpMes[8]; // Carrier phase measurement: cycles [64-bit float] + uint8_t doMes[4]; // Doppler measurement: Hz [32-bit float] + uint8_t gnssId; // GNSS identifier + uint8_t svId; // Satellite identifier + uint8_t sigId; // New signal identifier + uint8_t freqId; // GLONASS frequency slot uint16_t lockTime; // Carrier phase locktime counter: ms - uint8_t cno; // Carrier-to-noise density ratio: dB-Hz - uint8_t prStdev; // Estimated pseudorange measurement standard deviation: m * 0.01 * 2^n [4-bit] - uint8_t cpStdev; // Estimated carrier phase measurement standard deviation: cycles * 0.004 [4-bit] - uint8_t doStdev; // Estimated Doppler measurement standard deviation: Hz * 0.002 * 2^n [4-bit] + uint8_t cno; // Carrier-to-noise density ratio: dB-Hz + uint8_t prStdev; // Estimated pseudorange measurement standard deviation: m * 0.01 * 2^n [4-bit] + uint8_t cpStdev; // Estimated carrier phase measurement standard deviation: cycles * 0.004 [4-bit] + uint8_t doStdev; // Estimated Doppler measurement standard deviation: Hz * 0.002 * 2^n [4-bit] union { uint8_t all; struct { - uint8_t prValid : 1; // Pseudorange valid - uint8_t cpValid : 1; // Carrier phase valid - uint8_t halfCyc : 1; // Half cycle valid + uint8_t prValid : 1; // Pseudorange valid + uint8_t cpValid : 1; // Carrier phase valid + uint8_t halfCyc : 1; // Half cycle valid uint8_t subHalfCyc : 1; // Half cycle subtracted from phase } bits; } trkStat; @@ -1476,12 +1476,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_RXM_RAWX_data_t data; bool moduleQueried; void (*callbackPointer)(UBX_RXM_RAWX_data_t); void (*callbackPointerPtr)(UBX_RXM_RAWX_data_t *); - UBX_RXM_RAWX_data_t *callbackData; + UBX_RXM_RAWX_data_t *callbackData; } UBX_RXM_RAWX_t; // UBX-RXM-PMP (0x02 0x72): PMP raw data (D9 modules) @@ -1490,31 +1490,31 @@ const uint16_t UBX_RXM_PMP_MAX_LEN = 528; typedef struct { - uint8_t version; // Message version (0x00 / 0x01) - uint8_t reserved0; // Reserved - uint16_t numBytesUserData; // version 0x00: reserved0 ; version 0x01: Number of bytes the userData block has in this frame (0...504) - uint32_t timeTag; // Time since startup when frame started : ms - uint32_t uniqueWord[2]; // Received unique words - uint16_t serviceIdentifier; // Received service identifier - uint8_t spare; // Received spare data + uint8_t version; // Message version (0x00 / 0x01) + uint8_t reserved0; // Reserved + uint16_t numBytesUserData; // version 0x00: reserved0 ; version 0x01: Number of bytes the userData block has in this frame (0...504) + uint32_t timeTag; // Time since startup when frame started : ms + uint32_t uniqueWord[2]; // Received unique words + uint16_t serviceIdentifier; // Received service identifier + uint8_t spare; // Received spare data uint8_t uniqueWordBitErrors; // Number of bit errors in both unique words // The position of fecBits, ebno and reserved1 depends on the message version - uint16_t fecBits; // Number of bits corrected by FEC (forward error correction) - uint8_t ebno; // Energy per bit to noise power spectral density ratio : 2^-3 dB + uint16_t fecBits; // Number of bits corrected by FEC (forward error correction) + uint8_t ebno; // Energy per bit to noise power spectral density ratio : 2^-3 dB uint8_t reserved1; // Reserved uint8_t userData[504]; // Received user data: version 0x00 : starts at byte 20 ; version 0x01 : starts at byte 24 - + } UBX_RXM_PMP_data_t; typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_RXM_PMP_data_t data; bool moduleQueried; void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *); - UBX_RXM_PMP_data_t *callbackData; + UBX_RXM_PMP_data_t *callbackData; } UBX_RXM_PMP_t; // CFG-specific structs @@ -1526,27 +1526,27 @@ const uint16_t UBX_CFG_PRT_LEN = 20; typedef struct { - uint8_t portID; // Port identifier number + uint8_t portID; // Port identifier number uint8_t reserved0; // Reserved union { uint16_t all; struct { - uint16_t en : 1; // Enable TX ready feature for this port - uint16_t pol : 1; // Polarity: 0 High-active; 1 Low-active - uint16_t pin : 5; // PIO to be used (must not be in use by another function) + uint16_t en : 1; // Enable TX ready feature for this port + uint16_t pol : 1; // Polarity: 0 High-active; 1 Low-active + uint16_t pin : 5; // PIO to be used (must not be in use by another function) uint16_t thres : 9; // Threshold } bits; } txReady; - uint32_t mode; // Content changes depending on the port type - uint32_t baudRate ; // Content changes depending on the port type + uint32_t mode; // Content changes depending on the port type + uint32_t baudRate; // Content changes depending on the port type union { uint16_t all; struct { - uint16_t inUbx : 1; // UBX protocol + uint16_t inUbx : 1; // UBX protocol uint16_t inNmea : 1; // NMEA protocol uint16_t inRtcm : 1; // RTCM2 protocol uint16_t reserved : 2; @@ -1559,7 +1559,7 @@ typedef struct uint16_t all; struct { - uint16_t outUbx : 1; // UBX protocol + uint16_t outUbx : 1; // UBX protocol uint16_t outNmea : 1; // NMEA protocol uint16_t reserved : 3; uint16_t outRtcm3 : 1; // RTCM3 protocol (not supported for protocol versions less than 20.00) @@ -1567,7 +1567,7 @@ typedef struct } bits; } outProtoMask; uint16_t flags; // Content changes depending on the port type - uint16_t reserved1; + uint16_t reserved1; } UBX_CFG_PRT_data_t; typedef struct @@ -1582,8 +1582,8 @@ const uint16_t UBX_CFG_RATE_LEN = 6; typedef struct { uint16_t measRate; // The elapsed time between GNSS measurements, which defines the rate: ms - uint16_t navRate; // The ratio between the number of measurements and the number of navigation solutions: cycles - uint16_t timeRef; // The time system to which measurements are aligned: 0: UTC; 1: GPS; 2: GLONASS; 3: BeiDou; 4: Galileo + uint16_t navRate; // The ratio between the number of measurements and the number of navigation solutions: cycles + uint16_t timeRef; // The time system to which measurements are aligned: 0: UTC; 1: GPS; 2: GLONASS; 3: BeiDou; 4: Galileo } UBX_CFG_RATE_data_t; typedef struct @@ -1604,7 +1604,7 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_CFG_RATE_data_t data; UBX_CFG_RATE_moduleQueried_t moduleQueried; } UBX_CFG_RATE_t; @@ -1614,32 +1614,32 @@ const uint16_t UBX_CFG_TP5_LEN = 32; typedef struct { - uint8_t tpIdx; // Time pulse selection (0 = TIMEPULSE, 1 = TIMEPULSE2) + uint8_t tpIdx; // Time pulse selection (0 = TIMEPULSE, 1 = TIMEPULSE2) uint8_t version; // Message version (0x01 for this version) uint8_t reserved1[2]; - int16_t antCableDelay; // Antenna cable delay: ns - int16_t rfGroupDelay; // RF group delay: ns - uint32_t freqPeriod; // Frequency or period time, depending on setting of bit 'isFreq': Hz_or_us - uint32_t freqPeriodLock; // Frequency or period time when locked to GNSS time, only used if 'lockedOtherSet' is set: Hz_or_us - uint32_t pulseLenRatio; // Pulse length or duty cycle, depending on 'isLength': us_or_2^-32 + int16_t antCableDelay; // Antenna cable delay: ns + int16_t rfGroupDelay; // RF group delay: ns + uint32_t freqPeriod; // Frequency or period time, depending on setting of bit 'isFreq': Hz_or_us + uint32_t freqPeriodLock; // Frequency or period time when locked to GNSS time, only used if 'lockedOtherSet' is set: Hz_or_us + uint32_t pulseLenRatio; // Pulse length or duty cycle, depending on 'isLength': us_or_2^-32 uint32_t pulseLenRatioLock; // Pulse length or duty cycle when locked to GNSS time, only used if 'lockedOtherSet' is set: us_or_2^-32 - int32_t userConfigDelay; // User-configurable time pulse delay: ns + int32_t userConfigDelay; // User-configurable time pulse delay: ns union { uint32_t all; struct { - uint32_t active : 1; // If set enable time pulse; if pin assigned to another function, other function takes precedence. - uint32_t lockGnssFreq : 1; // If set, synchronize time pulse to GNSS as soon as GNSS time is valid. If not set, or before GNSS time is valid, use local clock. + uint32_t active : 1; // If set enable time pulse; if pin assigned to another function, other function takes precedence. + uint32_t lockGnssFreq : 1; // If set, synchronize time pulse to GNSS as soon as GNSS time is valid. If not set, or before GNSS time is valid, use local clock. uint32_t lockedOtherSet : 1; // If set the receiver switches between the timepulse settings given by 'freqPeriodLocked' & 'pulseLenLocked' and those given by 'freqPeriod' & 'pulseLen'. - uint32_t isFreq : 1; // If set 'freqPeriodLock' and 'freqPeriod' are interpreted as frequency, otherwise interpreted as period. - uint32_t isLength : 1; // If set 'pulseLenRatioLock' and 'pulseLenRatio' interpreted as pulse length, otherwise interpreted as duty cycle. - uint32_t alignToTow : 1; // Align pulse to top of second (period time must be integer fraction of 1s). Also set 'lockGnssFreq' to use this feature. - uint32_t polarity : 1; // Pulse polarity: 0: falling edge at top of second; 1: rising edge at top of second - uint32_t gridUtcGnss : 4; // Timegrid to use: 0: UTC; 1: GPS; 2: GLONASS; 3: BeiDou; 4: Galileo - uint32_t syncMode : 3; // Sync Manager lock mode to use: - // 0: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, never switch back to 'freqPeriod' and 'pulseLenRatio' - // 1: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, and switch back to 'freqPeriod' and 'pulseLenRatio' as soon as time gets inaccurate + uint32_t isFreq : 1; // If set 'freqPeriodLock' and 'freqPeriod' are interpreted as frequency, otherwise interpreted as period. + uint32_t isLength : 1; // If set 'pulseLenRatioLock' and 'pulseLenRatio' interpreted as pulse length, otherwise interpreted as duty cycle. + uint32_t alignToTow : 1; // Align pulse to top of second (period time must be integer fraction of 1s). Also set 'lockGnssFreq' to use this feature. + uint32_t polarity : 1; // Pulse polarity: 0: falling edge at top of second; 1: rising edge at top of second + uint32_t gridUtcGnss : 4; // Timegrid to use: 0: UTC; 1: GPS; 2: GLONASS; 3: BeiDou; 4: Galileo + uint32_t syncMode : 3; // Sync Manager lock mode to use: + // 0: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, never switch back to 'freqPeriod' and 'pulseLenRatio' + // 1: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, and switch back to 'freqPeriod' and 'pulseLenRatio' as soon as time gets inaccurate } bits; } flags; } UBX_CFG_TP5_data_t; @@ -1657,23 +1657,23 @@ typedef struct uint8_t all; struct { - uint8_t mode : 1; // 0=single; 1=running - uint8_t run : 1; // 0=armed; 1=stopped + uint8_t mode : 1; // 0=single; 1=running + uint8_t run : 1; // 0=armed; 1=stopped uint8_t newFallingEdge : 1; // New falling edge detected - uint8_t timeBase : 2; // 0=Time base is Receiver time; 1=Time base is GNSS time; 2=Time base is UTC - uint8_t utc : 1; // 0=UTC not available; 1=UTC available - uint8_t time : 1; // 0=Time is not valid; 1=Time is valid (Valid GNSS fix) - uint8_t newRisingEdge : 1; // New rising edge detected + uint8_t timeBase : 2; // 0=Time base is Receiver time; 1=Time base is GNSS time; 2=Time base is UTC + uint8_t utc : 1; // 0=UTC not available; 1=UTC available + uint8_t time : 1; // 0=Time is not valid; 1=Time is valid (Valid GNSS fix) + uint8_t newRisingEdge : 1; // New rising edge detected } bits; } flags; - uint16_t count; // Rising edge counter - uint16_t wnR; // Week number of last rising edge - uint16_t wnF; // Week number of last falling edge - uint32_t towMsR; // TOW of rising edge: ms + uint16_t count; // Rising edge counter + uint16_t wnR; // Week number of last rising edge + uint16_t wnF; // Week number of last falling edge + uint32_t towMsR; // TOW of rising edge: ms uint32_t towSubMsR; // Millisecond fraction of tow of rising edge: ns - uint32_t towMsF; // TOW of falling edge: ms + uint32_t towMsF; // TOW of falling edge: ms uint32_t towSubMsF; // Millisecond fraction of tow of falling edge: ns - uint32_t accEst; // Accuracy estimate: ns + uint32_t accEst; // Accuracy estimate: ns } UBX_TIM_TM2_data_t; typedef struct @@ -1708,12 +1708,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_TIM_TM2_data_t data; UBX_TIM_TM2_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_TIM_TM2_data_t); void (*callbackPointerPtr)(UBX_TIM_TM2_data_t *); - UBX_TIM_TM2_data_t *callbackData; + UBX_TIM_TM2_data_t *callbackData; } UBX_TIM_TM2_t; // ESF-specific structs @@ -1723,7 +1723,7 @@ const uint16_t UBX_ESF_ALG_LEN = 16; typedef struct { - uint32_t iTOW; // GPS time of week of the HNR epoch: ms + uint32_t iTOW; // GPS time of week of the HNR epoch: ms uint8_t version; // Message version (0x01 for this version) union { @@ -1731,12 +1731,12 @@ typedef struct struct { uint8_t autoMntAlgOn : 1; // Automatic IMU-mount alignment on/off bit - uint8_t status : 3; // Status of the IMU-mount alignment - // 0: user-defined/fixed angles are used - // 1: IMU-mount roll/pitch angles alignment is ongoing - // 2: IMU-mount roll/pitch/yaw angles alignment is ongoing - // 3: coarse IMU-mount alignment are used - // 4: fine IMU-mount alignment are used + uint8_t status : 3; // Status of the IMU-mount alignment + // 0: user-defined/fixed angles are used + // 1: IMU-mount roll/pitch angles alignment is ongoing + // 2: IMU-mount roll/pitch/yaw angles alignment is ongoing + // 3: coarse IMU-mount alignment are used + // 4: fine IMU-mount alignment are used } bits; } flags; union @@ -1745,14 +1745,14 @@ typedef struct struct { uint8_t tiltAlgError : 1; // IMU-mount tilt (roll and/or pitch) alignment error (0: no error, 1: error) - uint8_t yawAlgError : 1; // IMU-mount yaw alignment error (0: no error, 1: error) - uint8_t angleError : 1; // IMU-mount misalignment Euler angle singularity error (0: no error, 1: error) + uint8_t yawAlgError : 1; // IMU-mount yaw alignment error (0: no error, 1: error) + uint8_t angleError : 1; // IMU-mount misalignment Euler angle singularity error (0: no error, 1: error) } bits; } error; uint8_t reserved1; - uint32_t yaw; // IMU-mount yaw angle [0, 360]: Degrees * 1e-2 + uint32_t yaw; // IMU-mount yaw angle [0, 360]: Degrees * 1e-2 int16_t pitch; // IMU-mount pitch angle [-90, 90]: Degrees * 1e-2 - int16_t roll; // IMU-mount roll angle [-180, 180]: Degrees * 1e-2 + int16_t roll; // IMU-mount roll angle [-180, 180]: Degrees * 1e-2 } UBX_ESF_ALG_data_t; typedef struct @@ -1783,12 +1783,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_ESF_ALG_data_t data; UBX_ESF_ALG_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_ALG_data_t); void (*callbackPointerPtr)(UBX_ESF_ALG_data_t *); - UBX_ESF_ALG_data_t *callbackData; + UBX_ESF_ALG_data_t *callbackData; } UBX_ESF_ALG_t; // UBX-ESF-INS (0x10 0x15): Vehicle dynamics information @@ -1801,23 +1801,23 @@ typedef struct uint32_t all; struct { - uint32_t version : 8; // Message version (0x01 for this version) + uint32_t version : 8; // Message version (0x01 for this version) uint32_t xAngRateValid : 1; // Compensated x-axis angular rate data validity flag (0: not valid, 1: valid) uint32_t yAngRateValid : 1; // Compensated y-axis angular rate data validity flag (0: not valid, 1: valid) uint32_t zAngRateValid : 1; // Compensated z-axis angular rate data validity flag (0: not valid, 1: valid) - uint32_t xAccelValid : 1; // Compensated x-axis acceleration data validity flag (0: not valid, 1: valid) - uint32_t yAccelValid : 1; // Compensated y-axis acceleration data validity flag (0: not valid, 1: valid) - uint32_t zAccelValid : 1; // Compensated z-axis acceleration data validity flag (0: not valid, 1: valid) + uint32_t xAccelValid : 1; // Compensated x-axis acceleration data validity flag (0: not valid, 1: valid) + uint32_t yAccelValid : 1; // Compensated y-axis acceleration data validity flag (0: not valid, 1: valid) + uint32_t zAccelValid : 1; // Compensated z-axis acceleration data validity flag (0: not valid, 1: valid) } bits; } bitfield0; uint8_t reserved1[4]; - uint32_t iTOW; // GPS time of week of the HNR epoch: ms + uint32_t iTOW; // GPS time of week of the HNR epoch: ms int32_t xAngRate; // Compensated x-axis angular rate: Degrees/s * 1e-3 int32_t yAngRate; // Compensated y-axis angular rate: Degrees/s * 1e-3 int32_t zAngRate; // Compensated z-axis angular rate: Degrees/s * 1e-3 - int32_t xAccel; // Compensated x-axis acceleration (gravity-free): m/s^2 * 1e-2 - int32_t yAccel; // Compensated y-axis acceleration (gravity-free): m/s^2 * 1e-2 - int32_t zAccel; // Compensated z-axis acceleration (gravity-free): m/s^2 * 1e-2 + int32_t xAccel; // Compensated x-axis acceleration (gravity-free): m/s^2 * 1e-2 + int32_t yAccel; // Compensated y-axis acceleration (gravity-free): m/s^2 * 1e-2 + int32_t zAccel; // Compensated z-axis acceleration (gravity-free): m/s^2 * 1e-2 } UBX_ESF_INS_data_t; typedef struct @@ -1850,12 +1850,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_ESF_INS_data_t data; UBX_ESF_INS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_INS_data_t); void (*callbackPointerPtr)(UBX_ESF_INS_data_t *); - UBX_ESF_INS_data_t *callbackData; + UBX_ESF_INS_data_t *callbackData; } UBX_ESF_INS_t; // UBX-ESF-MEAS (0x10 0x02): External sensor fusion measurements @@ -1870,7 +1870,7 @@ typedef struct struct { uint32_t dataField : 24; // Data - uint32_t dataType : 6; // Type of data (0 = no data; 1..63 = data type) + uint32_t dataType : 6; // Type of data (0 = no data; 1..63 = data type) } bits; } data; } UBX_ESF_MEAS_sensorData_t; @@ -1883,12 +1883,12 @@ typedef struct uint16_t all; struct { - uint16_t timeMarkSent : 2; // Time mark signal was supplied just prior to sending this message: - // 0 = none, 1 = on Ext0, 2 = on Ext1 - uint16_t timeMarkEdge : 1; // Trigger on rising (0) or falling (1) edge of time mark signal + uint16_t timeMarkSent : 2; // Time mark signal was supplied just prior to sending this message: + // 0 = none, 1 = on Ext0, 2 = on Ext1 + uint16_t timeMarkEdge : 1; // Trigger on rising (0) or falling (1) edge of time mark signal uint16_t calibTtagValid : 1; // Calibration time tag available. Always set to zero. uint16_t reserved : 7; - uint16_t numMeas : 5; // Number of measurements contained in this message (optional, can be obtained from message size) + uint16_t numMeas : 5; // Number of measurements contained in this message (optional, can be obtained from message size) } bits; } flags; uint16_t id; // Identification number of data provider @@ -1921,12 +1921,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_ESF_MEAS_data_t data; UBX_ESF_MEAS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_MEAS_data_t); void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *); - UBX_ESF_MEAS_data_t *callbackData; + UBX_ESF_MEAS_data_t *callbackData; } UBX_ESF_MEAS_t; // UBX-ESF-RAW (0x10 0x03): Raw sensor measurements @@ -1941,7 +1941,7 @@ typedef struct struct { uint32_t dataField : 24; // Data - uint32_t dataType : 8; // Type of data (0 = no data; 1..255 = data type) + uint32_t dataType : 8; // Type of data (0 = no data; 1..255 = data type) } bits; } data; uint32_t sTag; // Sensor time tag @@ -1969,12 +1969,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_ESF_RAW_data_t data; UBX_ESF_RAW_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_RAW_data_t); void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *); - UBX_ESF_RAW_data_t *callbackData; + UBX_ESF_RAW_data_t *callbackData; } UBX_ESF_RAW_t; // UBX-ESF-STATUS (0x10 0x10): External sensor fusion status @@ -1988,8 +1988,8 @@ typedef struct uint8_t all; struct { - uint8_t type : 6; // Sensor data type - uint8_t used : 1; // If set, sensor data is used for the current sensor fusion solution + uint8_t type : 6; // Sensor data type + uint8_t used : 1; // If set, sensor data is used for the current sensor fusion solution uint8_t ready : 1; // If set, sensor is set up (configuration is available or not required) but not used for computing the current sensor fusion solution. } bits; } sensStatus1; @@ -2001,10 +2001,10 @@ typedef struct uint8_t calibStatus : 2; // 00: Sensor is not calibrated // 01: Sensor is calibrating // 10/11: Sensor is calibrated - uint8_t timeStatus : 2; // 00: No data - // 01: Reception of the first byte used to tag the measurement - // 10: Event input used to tag the measurement - // 11: Time tag provided with the data + uint8_t timeStatus : 2; // 00: No data + // 01: Reception of the first byte used to tag the measurement + // 10: Event input used to tag the measurement + // 11: Time tag provided with the data } bits; } sensStatus2; uint8_t freq; // Observation frequency: Hz @@ -2013,17 +2013,17 @@ typedef struct uint8_t all; struct { - uint8_t badMeas : 1; // Bad measurements detected - uint8_t badTTag : 1; // Bad measurement time-tags detected + uint8_t badMeas : 1; // Bad measurements detected + uint8_t badTTag : 1; // Bad measurement time-tags detected uint8_t missingMeas : 1; // Missing or time-misaligned measurements detected - uint8_t noisyMeas : 1; // High measurement noise-level detected + uint8_t noisyMeas : 1; // High measurement noise-level detected } bits; } faults; } UBX_ESF_STATUS_sensorStatus_t; typedef struct { - uint32_t iTOW; // GPS time of week of the HNR epoch: ms + uint32_t iTOW; // GPS time of week of the HNR epoch: ms uint8_t version; // Message version (0x02 for this version) uint8_t reserved1[7]; uint8_t fusionMode; // Fusion mode: @@ -2057,12 +2057,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_ESF_STATUS_data_t data; UBX_ESF_STATUS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_ESF_STATUS_data_t); void (*callbackPointerPtr)(UBX_ESF_STATUS_data_t *); - UBX_ESF_STATUS_data_t *callbackData; + UBX_ESF_STATUS_data_t *callbackData; } UBX_ESF_STATUS_t; // MGA-specific structs @@ -2072,20 +2072,20 @@ const uint16_t UBX_MGA_ACK_DATA0_LEN = 8; typedef struct { - uint8_t type; // Type of acknowledgment: - // 0: The message was not used by the receiver (see infoCode field for an indication of why) - // 1: The message was accepted for use by the receiver (the infoCode field will be 0) - uint8_t version; // Message version - uint8_t infoCode; // Provides greater information on what the receiver chose to do with the message contents - // See sfe_ublox_mga_ack_infocode_e - uint8_t msgId; // UBX message ID of the acknowledged message + uint8_t type; // Type of acknowledgment: + // 0: The message was not used by the receiver (see infoCode field for an indication of why) + // 1: The message was accepted for use by the receiver (the infoCode field will be 0) + uint8_t version; // Message version + uint8_t infoCode; // Provides greater information on what the receiver chose to do with the message contents + // See sfe_ublox_mga_ack_infocode_e + uint8_t msgId; // UBX message ID of the acknowledged message uint8_t msgPayloadStart[4]; // The first 4 bytes of the acknowledged message's payload } UBX_MGA_ACK_DATA0_data_t; #define UBX_MGA_ACK_DATA0_RINGBUFFER_LEN 16 // Provide storage for 16 MGA ACK packets typedef struct { - uint8_t head; + uint8_t head; uint8_t tail; UBX_MGA_ACK_DATA0_data_t data[UBX_MGA_ACK_DATA0_RINGBUFFER_LEN]; // Create a storage array for the MGA ACK packets } UBX_MGA_ACK_DATA0_t; @@ -2114,7 +2114,7 @@ typedef struct typedef struct { - uint8_t head; + uint8_t head; uint8_t tail; UBX_MGA_DBD_data_t data[UBX_MGA_DBD_RINGBUFFER_LEN]; // Create a storage array for the MGA DBD packets } UBX_MGA_DBD_t; @@ -2129,53 +2129,53 @@ typedef struct uint32_t iTOW; // GPS time of week of the HNR epoch: ms uint16_t year; // Year (UTC) uint8_t month; // Month, range 1..12 (UTC) - uint8_t day; // Day of month, range 1..31 (UTC) - uint8_t hour; // Hour of day, range 0..23 (UTC) - uint8_t min; // Minute of hour, range 0..59 (UTC) - uint8_t sec; // Seconds of minute, range 0..60 (UTC) + uint8_t day; // Day of month, range 1..31 (UTC) + uint8_t hour; // Hour of day, range 0..23 (UTC) + uint8_t min; // Minute of hour, range 0..59 (UTC) + uint8_t sec; // Seconds of minute, range 0..60 (UTC) union { uint8_t all; struct { - uint8_t validDate : 1; // 1 = Valid UTC Date - uint8_t validTime : 1; // 1 = Valid UTC Time of Day + uint8_t validDate : 1; // 1 = Valid UTC Date + uint8_t validTime : 1; // 1 = Valid UTC Time of Day uint8_t fullyResolved : 1; // 1 = UTC Time of Day has been fully resolved } bits; } valid; - int32_t nano; // Fraction of second (UTC): ns + int32_t nano; // Fraction of second (UTC): ns uint8_t gpsFix; // GPSfix Type, range 0..5 - // 0x00 = No Fix - // 0x01 = Dead Reckoning only - // 0x02 = 2D-Fix - // 0x03 = 3D-Fix - // 0x04 = GPS + dead reckoning combined - // 0x05 = Time only fix - // 0x06..0xff: reserved + // 0x00 = No Fix + // 0x01 = Dead Reckoning only + // 0x02 = 2D-Fix + // 0x03 = 3D-Fix + // 0x04 = GPS + dead reckoning combined + // 0x05 = Time only fix + // 0x06..0xff: reserved union { uint8_t all; struct { - uint8_t gpsFixOK : 1; // >1 = Fix within limits (e.g. DOP & accuracy) - uint8_t diffSoln : 1; // 1 = DGPS used - uint8_t WKNSET : 1; // 1 = Valid GPS week number - uint8_t TOWSET : 1; // 1 = Valid GPS time of week (iTOW & fTOW) + uint8_t gpsFixOK : 1; // >1 = Fix within limits (e.g. DOP & accuracy) + uint8_t diffSoln : 1; // 1 = DGPS used + uint8_t WKNSET : 1; // 1 = Valid GPS week number + uint8_t TOWSET : 1; // 1 = Valid GPS time of week (iTOW & fTOW) uint8_t headVehValid : 1; // 1= Heading of vehicle is valid } bits; } flags; uint8_t reserved1[2]; - int32_t lon; // Longitude: Degrees * 1e-7 - int32_t lat; // Latitude: Degrees * 1e-7 - int32_t height; // Height above ellipsoid: mm - int32_t hMSL; // Height above MSL: mm - int32_t gSpeed; // Ground Speed (2-D): mm/s - int32_t speed; // Speed (3-D): mm/s - int32_t headMot; // Heading of motion (2-D): Degrees * 1e-5 - int32_t headVeh; // Heading of vehicle (2-D): Degrees * 1e-5 - uint32_t hAcc; // Horizontal accuracy: mm - uint32_t vAcc; // Vertical accuracy: mm - uint32_t sAcc; // Speed accuracy: mm/s + int32_t lon; // Longitude: Degrees * 1e-7 + int32_t lat; // Latitude: Degrees * 1e-7 + int32_t height; // Height above ellipsoid: mm + int32_t hMSL; // Height above MSL: mm + int32_t gSpeed; // Ground Speed (2-D): mm/s + int32_t speed; // Speed (3-D): mm/s + int32_t headMot; // Heading of motion (2-D): Degrees * 1e-5 + int32_t headVeh; // Heading of vehicle (2-D): Degrees * 1e-5 + uint32_t hAcc; // Horizontal accuracy: mm + uint32_t vAcc; // Vertical accuracy: mm + uint32_t sAcc; // Speed accuracy: mm/s uint32_t headAcc; // Heading accuracy: Degrees * 1e-5 uint8_t reserved2[4]; } UBX_HNR_PVT_data_t; @@ -2228,12 +2228,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_HNR_PVT_data_t data; UBX_HNR_PVT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_HNR_PVT_data_t); void (*callbackPointerPtr)(UBX_HNR_PVT_data_t *); - UBX_HNR_PVT_data_t *callbackData; + UBX_HNR_PVT_data_t *callbackData; } UBX_HNR_PVT_t; // UBX-HNR-ATT (0x28 0x01): Attitude solution @@ -2244,11 +2244,11 @@ typedef struct uint32_t iTOW; // GPS time of week of the navigation epoch: ms uint8_t version; uint8_t reserved1[3]; - int32_t roll; // Vehicle roll: Degrees * 1e-5 - int32_t pitch; // Vehicle pitch: Degrees * 1e-5 - int32_t heading; // Vehicle heading: Degrees * 1e-5 - uint32_t accRoll; // Vehicle roll accuracy: Degrees * 1e-5 - uint32_t accPitch; // Vehicle pitch accuracy: Degrees * 1e-5 + int32_t roll; // Vehicle roll: Degrees * 1e-5 + int32_t pitch; // Vehicle pitch: Degrees * 1e-5 + int32_t heading; // Vehicle heading: Degrees * 1e-5 + uint32_t accRoll; // Vehicle roll accuracy: Degrees * 1e-5 + uint32_t accPitch; // Vehicle pitch accuracy: Degrees * 1e-5 uint32_t accHeading; // Vehicle heading accuracy: Degrees * 1e-5 } UBX_HNR_ATT_data_t; @@ -2275,12 +2275,12 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_HNR_ATT_data_t data; UBX_HNR_ATT_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_HNR_ATT_data_t); void (*callbackPointerPtr)(UBX_HNR_ATT_data_t *); - UBX_HNR_ATT_data_t *callbackData; + UBX_HNR_ATT_data_t *callbackData; } UBX_HNR_ATT_t; // UBX-HNR-INS (0x28 0x02): Vehicle dynamics information @@ -2293,23 +2293,23 @@ typedef struct uint32_t all; struct { - uint32_t version : 8; // Message version (0x00 for this version) + uint32_t version : 8; // Message version (0x00 for this version) uint32_t xAngRateValid : 1; // Compensated x-axis angular rate data validity flag (0: not valid, 1: valid) uint32_t yAngRateValid : 1; // Compensated y-axis angular rate data validity flag (0: not valid, 1: valid) uint32_t zAngRateValid : 1; // Compensated z-axis angular rate data validity flag (0: not valid, 1: valid) - uint32_t xAccelValid : 1; // Compensated x-axis acceleration data validity flag (0: not valid, 1: valid) - uint32_t yAccelValid : 1; // Compensated y-axis acceleration data validity flag (0: not valid, 1: valid) - uint32_t zAccelValid : 1; // Compensated z-axis acceleration data validity flag (0: not valid, 1: valid) + uint32_t xAccelValid : 1; // Compensated x-axis acceleration data validity flag (0: not valid, 1: valid) + uint32_t yAccelValid : 1; // Compensated y-axis acceleration data validity flag (0: not valid, 1: valid) + uint32_t zAccelValid : 1; // Compensated z-axis acceleration data validity flag (0: not valid, 1: valid) } bits; } bitfield0; uint8_t reserved1[4]; - uint32_t iTOW; // GPS time of week of the HNR epoch: ms + uint32_t iTOW; // GPS time of week of the HNR epoch: ms int32_t xAngRate; // Compensated x-axis angular rate: Degrees/s * 1e-3 int32_t yAngRate; // Compensated y-axis angular rate: Degrees/s * 1e-3 int32_t zAngRate; // Compensated z-axis angular rate: Degrees/s * 1e-3 - int32_t xAccel; // Compensated x-axis acceleration (with gravity): m/s^2 * 1e-2 - int32_t yAccel; // Compensated y-axis acceleration (with gravity): m/s^2 * 1e-2 - int32_t zAccel; // Compensated z-axis acceleration (with gravity): m/s^2 * 1e-2 + int32_t xAccel; // Compensated x-axis acceleration (with gravity): m/s^2 * 1e-2 + int32_t yAccel; // Compensated y-axis acceleration (with gravity): m/s^2 * 1e-2 + int32_t zAccel; // Compensated z-axis acceleration (with gravity): m/s^2 * 1e-2 } UBX_HNR_INS_data_t; typedef struct @@ -2342,17 +2342,17 @@ typedef struct typedef struct { - ubxAutomaticFlags automaticFlags; + ubxAutomaticFlags automaticFlags; UBX_HNR_INS_data_t data; UBX_HNR_INS_moduleQueried_t moduleQueried; void (*callbackPointer)(UBX_HNR_INS_data_t); void (*callbackPointerPtr)(UBX_HNR_INS_data_t *); - UBX_HNR_INS_data_t *callbackData; + UBX_HNR_INS_data_t *callbackData; } UBX_HNR_INS_t; // NMEA-specific structs -//Additional flags and pointers that need to be stored with each message type +// Additional flags and pointers that need to be stored with each message type struct nmeaAutomaticFlags { union @@ -2361,7 +2361,7 @@ struct nmeaAutomaticFlags struct { uint8_t completeCopyValid : 1; // Is the copy of the data struct used by the get function valid/fresh? 0 = invalid, 1 = valid - uint8_t completeCopyRead : 1; // Has the complete copy been read? 0 = unread, 1 = read + uint8_t completeCopyRead : 1; // Has the complete copy been read? 0 = unread, 1 = read uint8_t callbackCopyValid : 1; // Is the copy of the data struct used by the callback valid/fresh? 0 = invalid/stale, 1 = valid/fresh } bits; } flags; @@ -2382,8 +2382,8 @@ typedef struct typedef struct { - nmeaAutomaticFlags automaticFlags; - NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy + nmeaAutomaticFlags automaticFlags; + NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy NMEA_GGA_data_t completeCopy; // The working copy is copied into the complete copy when all data has been received and the checksum is valid void (*callbackPointer)(NMEA_GGA_data_t); void (*callbackPointerPtr)(NMEA_GGA_data_t *); @@ -2392,8 +2392,8 @@ typedef struct typedef struct { - nmeaAutomaticFlags automaticFlags; - NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy + nmeaAutomaticFlags automaticFlags; + NMEA_GGA_data_t workingCopy; // Incoming data is added to the working copy NMEA_GGA_data_t completeCopy; // The working copy is copied into the complete copy when all data has been received and the checksum is valid void (*callbackPointer)(NMEA_GGA_data_t); void (*callbackPointerPtr)(NMEA_GGA_data_t *); From 213d29cafe8fea66dc481dadb3efcb5abba68a83 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 11 Feb 2022 15:01:41 +0000 Subject: [PATCH 113/122] Add setDynamicSPARTNKeys. Update Example19 --- ...ample19_LBand_Corrections_with_NEO-D9S.ino | 31 ++- .../secrets.h | 24 +++ src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 193 ++++++++++++++++-- 3 files changed, 220 insertions(+), 28 deletions(-) create mode 100644 examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h diff --git a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino index 72453b3..5fb0a4a 100644 --- a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino +++ b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino @@ -10,6 +10,9 @@ This is a proof of concept to show how the UBX-RXM-PMP corrections control the accuracy. + You will need a Thingstream PointPerfect account to be able to access the SPARTN Credentials (IP Dynamic Keys). + Copy and paste the Current Key and Next Key into secrets.h. + Feel like supporting open source hardware? Buy a board from SparkFun! ZED-F9P RTK2: https://www.sparkfun.com/products/16481 @@ -21,6 +24,8 @@ Open the serial monitor at 115200 baud to see the output */ +#include "secrets.h" // <- Copy and paste the Current Key and Next Key into secrets.h + #include //http://librarymanager/All#SparkFun_u-blox_GNSS SFE_UBLOX_GNSS myGNSS; // ZED-F9x SFE_UBLOX_GNSS myLBand; // NEO-D9S @@ -141,16 +146,27 @@ void setup() } Serial.println(F("u-blox GNSS module connected")); - myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise - myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN); //Be sure SPARTN input is enabled + uint8_t ok = myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + if (ok) ok = myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN); //Be sure SPARTN input is enabled - myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible + if (ok) ok = myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible - myGNSS.setNavigationFrequency(1); //Set output in Hz. + if (ok) ok = myGNSS.setNavigationFrequency(1); //Set output in Hz. - myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed + //Configure the SPARTN IP Dynamic Keys + //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. + //"Every time the 'current' key is expired, 'next' takes its place." + //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. + // The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. + if (ok) ok = myGNSS.setDynamicSPARTNKeys(currentKeyLengthBytes, currentKeyGPSWeek, currentKeyGPSToW, currentDynamicKey, + nextKeyLengthBytes, nextKeyGPSWeek, nextKeyGPSToW, nextDynamicKey); - //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM + //if (ok) ok = myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM + + Serial.print(F("GNSS: configuration ")); + Serial.println(OK(ok)); + + myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Begin and configure the NEO-D9S L-Band receiver @@ -164,7 +180,7 @@ void setup() } Serial.println(F("u-blox NEO-D9S connected")); - uint8_t ok = myLBand.setVal32(UBLOX_CFG_PMP_CENTER_FREQUENCY, myLBandFreq); // Default 1539812500 Hz + ok = myLBand.setVal32(UBLOX_CFG_PMP_CENTER_FREQUENCY, myLBandFreq); // Default 1539812500 Hz if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SEARCH_WINDOW, 2200); // Default 2200 Hz if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_SERVICE_ID, 0); // Default 1 if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SERVICE_ID, 21845); // Default 50821 @@ -178,6 +194,7 @@ void setup() if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2, 1); // Output UBX-RXM-PMP on UART2 if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART1_BAUDRATE, 38400); // match baudrate with ZED default if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART2_BAUDRATE, 38400); // match baudrate with ZED default + Serial.print(F("L-Band: configuration ")); Serial.println(OK(ok)); diff --git a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h new file mode 100644 index 0000000..b205c9a --- /dev/null +++ b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h @@ -0,0 +1,24 @@ +// You can set the information below after signing up with the u-blox Thingstream portal +// and adding a new New PointPerfect Thing +// https://portal.thingstream.io/app/location-services/things +// In the new PointPerfect Thing, you go to the credentials tab and copy and paste the IP Dynamic Keys here. +// +// The keys are valid from a particular GPS Week Number and Time of Week. +// Looking at the credentials tab, the current key expires 23:59 Feb 11th 2022. +// This means the next key is valid _from_ Midnight Feb 12th 2022. +// That is GPS Week 2196. The GPS Time of Week in seconds is 518418. +// Working backwards, the current key became valid exactly 4 weeks earlier (Midnight Jan 15th 2022). +// +// See: https://www.labsat.co.uk/index.php/en/gps-time-calculator +// +// The keys are given as: 32 hexadecimal digits = 128 bits = 16 Bytes + +const uint8_t currentKeyLengthBytes = 16; +const uint8_t currentDynamicKey[] = "f742bd6b7248043177dd649141d8fb0b"; +const uint16_t currentKeyGPSWeek = 2192; +const uint32_t currentKeyGPSToW = 518418; + +const uint8_t nextKeyLengthBytes = 16; +const uint8_t nextDynamicKey[] = "8206........................29f4"; +const uint16_t nextKeyGPSWeek = 2196; +const uint32_t nextKeyGPSToW = 518418; diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 6789cc3..0bfa29a 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -7585,27 +7585,6 @@ bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t m // The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait) { - // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F - bool isASCIIHex = true; - uint16_t i = 0; - while ((i < (uint16_t)keyLengthBytes) && (isASCIIHex == true)) - { - if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary - } - if (isASCIIHex) // Check the second half of the ASCII Hex key - { - while ((i < ((uint16_t)keyLengthBytes * 2) && (isASCIIHex == true))) - { - if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary - } - } - // Check if there is room for the key in packetCfg. Resize the buffer if not. size_t payloadLength = (size_t)keyLengthBytes + 12; if (packetCfgPayloadSize < payloadLength) @@ -7635,6 +7614,27 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validF payloadCfg[10] = (validFromTow >> 16) & 0xFF; payloadCfg[11] = (validFromTow >> 24) & 0xFF; + // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F + bool isASCIIHex = true; + uint16_t i = 0; + while ((i < (uint16_t)keyLengthBytes) && (isASCIIHex == true)) + { + if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + if (isASCIIHex) // Check the second half of the ASCII Hex key + { + while ((i < ((uint16_t)keyLengthBytes * 2) && (isASCIIHex == true))) + { + if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + } + if (isASCIIHex) // Convert ASCII Hex key to binary { for (i = 0; i < ((uint16_t)keyLengthBytes * 2); i += 2) @@ -7677,6 +7677,157 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validF bool SFE_UBLOX_GNSS::setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const uint8_t *key1, uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2, uint16_t maxWait) { + // Check if there is room for the key in packetCfg. Resize the buffer if not. + size_t payloadLength = (size_t)keyLengthBytes1 + (size_t)keyLengthBytes2 + 20; + if (packetCfgPayloadSize < payloadLength) + { + if (!setPacketCfgPayloadSize(payloadLength)) // Check if the resize was successful + { + return (false); + } + } + + // Copy the key etc. into packetCfg + packetCfg.cls = UBX_CLASS_RXM; + packetCfg.id = UBX_RXM_SPARTNKEY; + packetCfg.len = payloadLength; + packetCfg.startingSpot = 0; + + payloadCfg[0] = 0x01; // version + payloadCfg[1] = 0x02; // numKeys + payloadCfg[2] = 0x00; // reserved0 + payloadCfg[3] = 0x00; // reserved0 + payloadCfg[4] = 0x00; // reserved1 + payloadCfg[5] = keyLengthBytes1; + payloadCfg[6] = validFromWno1 & 0xFF; // validFromWno little-endian + payloadCfg[7] = validFromWno1 >> 8; + payloadCfg[8] = validFromTow1 & 0xFF; // validFromTow little-endian + payloadCfg[9] = (validFromTow1 >> 8) & 0xFF; + payloadCfg[10] = (validFromTow1 >> 16) & 0xFF; + payloadCfg[11] = (validFromTow1 >> 24) & 0xFF; + payloadCfg[12] = 0x00; // reserved1 + payloadCfg[13] = keyLengthBytes2; + payloadCfg[14] = validFromWno2 & 0xFF; // validFromWno little-endian + payloadCfg[15] = validFromWno2 >> 8; + payloadCfg[16] = validFromTow2 & 0xFF; // validFromTow little-endian + payloadCfg[17] = (validFromTow2 >> 8) & 0xFF; + payloadCfg[18] = (validFromTow2 >> 16) & 0xFF; + payloadCfg[19] = (validFromTow2 >> 24) & 0xFF; + + // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F + bool isASCIIHex = true; + uint16_t i = 0; + while ((i < (uint16_t)keyLengthBytes1) && (isASCIIHex == true)) + { + if (((key1[i] >= '0') && (key1[i] <= '9')) || ((key1[i] >= 'a') && (key1[i] <= 'f')) || ((key1[i] >= 'A') && (key1[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + if (isASCIIHex) // Check the second half of the ASCII Hex key + { + while ((i < ((uint16_t)keyLengthBytes1 * 2) && (isASCIIHex == true))) + { + if (((key1[i] >= '0') && (key1[i] <= '9')) || ((key1[i] >= 'a') && (key1[i] <= 'f')) || ((key1[i] >= 'A') && (key1[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + } + + if (isASCIIHex) // Convert ASCII Hex key to binary + { + for (i = 0; i < ((uint16_t)keyLengthBytes1 * 2); i += 2) + { + if ((key1[i] >= '0') && (key1[i] <= '9')) + { + payloadCfg[20 + (i >> 1)] = (key1[i] - '0') << 4; + } + else if ((key1[i] >= 'a') && (key1[i] <= 'f')) + { + payloadCfg[20 + (i >> 1)] = (key1[i] + 10 - 'a') << 4; + } + else // if ((key1[i] >= 'A') && (key1[i] <= 'F')) + { + payloadCfg[20 + (i >> 1)] = (key1[i] + 10 - 'A') << 4; + } + + if ((key1[i + 1] >= '0') && (key1[i + 1] <= '9')) + { + payloadCfg[20 + (i >> 1)] |= key1[i + 1] - '0'; + } + else if ((key1[i + 1] >= 'a') && (key1[i + 1] <= 'f')) + { + payloadCfg[20 + (i >> 1)] |= key1[i + 1] + 10 - 'a'; + } + else // if ((key1[i + 1] >= 'A') && (key1[i + 1] <= 'F')) + { + payloadCfg[20 + (i >> 1)] |= key1[i + 1] + 10 - 'A'; + } + } + } + else // Binary key + { + memcpy(&payloadCfg[20], key1, keyLengthBytes1); + } + + // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F + isASCIIHex = true; + i = 0; + while ((i < (uint16_t)keyLengthBytes2) && (isASCIIHex == true)) + { + if (((key2[i] >= '0') && (key2[i] <= '9')) || ((key2[i] >= 'a') && (key2[i] <= 'f')) || ((key2[i] >= 'A') && (key2[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + if (isASCIIHex) // Check the second half of the ASCII Hex key + { + while ((i < ((uint16_t)keyLengthBytes2 * 2) && (isASCIIHex == true))) + { + if (((key2[i] >= '0') && (key2[i] <= '9')) || ((key2[i] >= 'a') && (key2[i] <= 'f')) || ((key2[i] >= 'A') && (key2[i] <= 'F'))) + i++; // Keep checking if data is all ASCII Hex + else + isASCIIHex = false; // Data is binary + } + } + + if (isASCIIHex) // Convert ASCII Hex key to binary + { + for (i = 0; i < ((uint16_t)keyLengthBytes2 * 2); i += 2) + { + if ((key2[i] >= '0') && (key2[i] <= '9')) + { + payloadCfg[20 + keyLengthBytes1 + (i >> 1)] = (key2[i] - '0') << 4; + } + else if ((key2[i] >= 'a') && (key2[i] <= 'f')) + { + payloadCfg[20 + keyLengthBytes1 + (i >> 1)] = (key2[i] + 10 - 'a') << 4; + } + else // if ((key2[i] >= 'A') && (key2[i] <= 'F')) + { + payloadCfg[20 + keyLengthBytes1 + (i >> 1)] = (key2[i] + 10 - 'A') << 4; + } + + if ((key2[i + 1] >= '0') && (key2[i + 1] <= '9')) + { + payloadCfg[20 + keyLengthBytes1 + (i >> 1)] |= key2[i + 1] - '0'; + } + else if ((key2[i + 1] >= 'a') && (key2[i + 1] <= 'f')) + { + payloadCfg[20 + keyLengthBytes1 + (i >> 1)] |= key2[i + 1] + 10 - 'a'; + } + else // if ((key2[i + 1] >= 'A') && (key2[i + 1] <= 'F')) + { + payloadCfg[20 + keyLengthBytes1 + (i >> 1)] |= key2[i + 1] + 10 - 'A'; + } + } + } + else // Binary key + { + memcpy(&payloadCfg[20 + keyLengthBytes1], key2, keyLengthBytes2); + } + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } From 1aa043cef5a93970b8e6d7cf02d0f6f1aa6d5bc3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 14 Feb 2022 12:09:13 +0000 Subject: [PATCH 114/122] Update Example19. Add setRXMPMPmessageCallbackPtr. Add const char versions of setDynamicSPARTNKey + setDynamicSPARTNKeys --- ...xample17_NTRIPClient_With_GGA_Callback.ino | 20 +- ...ample19_LBand_Corrections_with_NEO-D9S.ino | 48 +- .../secrets.h | 4 +- keywords.txt | 10 +- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 474 ++++++++++-------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 86 ++-- src/u-blox_structs.h | 31 +- 7 files changed, 388 insertions(+), 285 deletions(-) diff --git a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino index 4741b49..9206681 100644 --- a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino +++ b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino @@ -93,22 +93,17 @@ void pushGPGGA(NMEA_GGA_data_t *nmeaData) // | | | void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) { - long latitude = ubxDataStruct->lat; // Print the latitude + double latitude = ubxDataStruct->lat; // Print the latitude Serial.print(F("Lat: ")); - Serial.print(latitude / 10000000L); - Serial.print(F(".")); - Serial.print(abs(latitude % 10000000L)); + Serial.print(latitude / 10000000.0, 7); - long longitude = ubxDataStruct->lon; // Print the longitude + double longitude = ubxDataStruct->lon; // Print the longitude Serial.print(F(" Long: ")); - Serial.print(longitude / 10000000L); - Serial.print(F(".")); - Serial.print(abs(longitude % 10000000L)); + Serial.print(longitude / 10000000.0, 7); - long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level + double altitude = ubxDataStruct->hMSL; // Print the height above mean sea level Serial.print(F(" Height: ")); - Serial.print(altitude); - Serial.print(F(" (mm)")); + Serial.print(altitude / 1000.0, 3); uint8_t fixType = ubxDataStruct->fixType; // Print the fix type Serial.print(F(" Fix: ")); @@ -159,9 +154,8 @@ void setup() while (myGNSS.begin() == false) //Connect to the Ublox module using Wire port { - Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring.")); delay(2000); - //while (1); } Serial.println(F("u-blox module connected")); diff --git a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino index 5fb0a4a..ae9de84 100644 --- a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino +++ b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino @@ -38,25 +38,24 @@ const uint32_t myLBandFreq = 1556290000; // Uncomment this line to use the US SP //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Callback: pushRXMPMP will be called when new PMP data arrives -// See u-blox_structs.h for the full definition of UBX_RXM_PMP_data_t -// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMPMPcallbackPtr -// / _____ This _must_ be UBX_RXM_PMP_data_t +// See u-blox_structs.h for the full definition of UBX_RXM_PMP_message_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setRXMPMPmessageCallbackPtr +// / _____ This _must_ be UBX_RXM_PMP_message_data_t // | / _____ You can use any name you like for the struct // | | / // | | | -void pushRXMPMP(UBX_RXM_PMP_data_t *pmpData) +void pushRXMPMP(UBX_RXM_PMP_message_data_t *pmpData) { + //Extract the raw message payload length + uint16_t payloadLen = ((uint16_t)pmpData->lengthMSB << 8) | (uint16_t)pmpData->lengthLSB; + Serial.print(F("New RXM-PMP data received. Message payload length is ")); + Serial.print(payloadLen); + Serial.println(F(" Bytes. Pushing it to the GNSS...")); + //Push the PMP data to the GNSS - Serial.print(F("New RXM-PMP data received. Message version is 0x0")); - Serial.print(pmpData->version, HEX); - Serial.print(F(". numBytesUserData is ")); - size_t numDataBytes = 504; // Version 0x00 messages always contain 504 bytes of userData - if (pmpData->version == 0x01) - numDataBytes = pmpData->numBytesUserData; - Serial.print(numDataBytes); - Serial.println(F(". Pushing them to the GNSS...")); - - myGNSS.pushRawData(pmpData->userData, numDataBytes); + //The payload length could be variable, so we need to push the header and payload, then checksum + myGNSS.pushRawData(&pmpData->sync1, (size_t)payloadLen + 6); // Push the sync chars, class, ID, length and payload + myGNSS.pushRawData(&pmpData->checksumA, (size_t)2); // Push the checksum bytes } //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -70,22 +69,17 @@ void pushRXMPMP(UBX_RXM_PMP_data_t *pmpData) // | | | void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) { - long latitude = ubxDataStruct->lat; // Print the latitude + double latitude = ubxDataStruct->lat; // Print the latitude Serial.print(F("Lat: ")); - Serial.print(latitude / 10000000L); - Serial.print(F(".")); - Serial.print(abs(latitude % 10000000L)); + Serial.print(latitude / 10000000.0, 7); - long longitude = ubxDataStruct->lon; // Print the longitude + double longitude = ubxDataStruct->lon; // Print the longitude Serial.print(F(" Long: ")); - Serial.print(longitude / 10000000L); - Serial.print(F(".")); - Serial.print(abs(longitude % 10000000L)); + Serial.print(longitude / 10000000.0, 7); - long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level + double altitude = ubxDataStruct->hMSL; // Print the height above mean sea level Serial.print(F(" Height: ")); - Serial.print(altitude); - Serial.print(F(" (mm)")); + Serial.print(altitude / 1000.0, 3); uint8_t fixType = ubxDataStruct->fixType; // Print the fix type Serial.print(F(" Fix: ")); @@ -157,7 +151,7 @@ void setup() //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. //"Every time the 'current' key is expired, 'next' takes its place." //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. - // The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. + // The key can be provided in binary (uint8_t) format or in ASCII Hex (char) format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. if (ok) ok = myGNSS.setDynamicSPARTNKeys(currentKeyLengthBytes, currentKeyGPSWeek, currentKeyGPSToW, currentDynamicKey, nextKeyLengthBytes, nextKeyGPSWeek, nextKeyGPSToW, nextDynamicKey); @@ -200,7 +194,7 @@ void setup() myLBand.softwareResetGNSSOnly(); // Do a restart - myLBand.setAutoRXMPMPcallbackPtr(&pushRXMPMP); // Call pushRXMPMP when new PMP data arrives. Push it to the GNSS + myLBand.setRXMPMPmessageCallbackPtr(&pushRXMPMP); // Call pushRXMPMP when new PMP data arrives. Push it to the GNSS } diff --git a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h index b205c9a..158e11c 100644 --- a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h +++ b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/secrets.h @@ -14,11 +14,11 @@ // The keys are given as: 32 hexadecimal digits = 128 bits = 16 Bytes const uint8_t currentKeyLengthBytes = 16; -const uint8_t currentDynamicKey[] = "f742bd6b7248043177dd649141d8fb0b"; +const char currentDynamicKey[] = "f742bd6b7248043177dd649141d8fb0b"; const uint16_t currentKeyGPSWeek = 2192; const uint32_t currentKeyGPSToW = 518418; const uint8_t nextKeyLengthBytes = 16; -const uint8_t nextDynamicKey[] = "8206........................29f4"; +const char nextDynamicKey[] = "8206........................29f4"; const uint16_t nextKeyGPSWeek = 2196; const uint32_t nextKeyGPSToW = 518418; diff --git a/keywords.txt b/keywords.txt index bba5c7f..6111314 100644 --- a/keywords.txt +++ b/keywords.txt @@ -26,10 +26,15 @@ UBX_NAV_VELECEF_data_t KEYWORD1 UBX_NAV_VELNED_data_t KEYWORD1 UBX_NAV_HPPOSECEF_data_t KEYWORD1 UBX_NAV_HPPOSLLH_data_t KEYWORD1 +UBX_NAV_PVAT_data_t KEYWORD1 UBX_NAV_CLOCK_data_t KEYWORD1 +UBX_NAV_SAT_data_t KEYWORD1 UBX_NAV_RELPOSNED_data_t KEYWORD1 UBX_NAV_TIMELS_data_t KEYWORD1 +UBX_NAV_AOPSTATUS_data_t KEYWORD1 +UBX_RXM_PMP_data_t KEYWORD1 +UBX_RXM_PMP_message_data_t KEYWORD1 UBX_RXM_SFRBX_data_t KEYWORD1 UBX_RXM_RAWX_data_t KEYWORD1 @@ -45,6 +50,8 @@ UBX_HNR_PVT_data_t KEYWORD1 UBX_HNR_ATT_data_t KEYWORD1 UBX_HNR_INS_data_t KEYWORD1 +NMEA_GGA_data_t KEYWORD1 + ####################################### # Methods and Functions (KEYWORD2) ####################################### @@ -364,7 +371,8 @@ initPacketUBXAOPSTATUS KEYWORD2 flushAOPSTATUS KEYWORD2 logAOPSTATUS KEYWORD2 -setAutoRXMPMPcallbackPtr KEYWORD2 +setRXMPMPcallbackPtr KEYWORD2 +setRXMPMPmessageCallbackPtr KEYWORD2 getRXMSFRBX KEYWORD2 setAutoRXMSFRBX KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 0bfa29a..7ae4f32 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -284,6 +284,16 @@ void SFE_UBLOX_GNSS::end(void) packetUBXRXMPMP = NULL; // Redundant? } + if (packetUBXRXMPMPmessage != NULL) + { + if (packetUBXRXMPMPmessage->callbackData != NULL) + { + delete packetUBXRXMPMPmessage->callbackData; + } + delete packetUBXRXMPMPmessage; + packetUBXRXMPMPmessage = NULL; // Redundant? + } + if (packetUBXRXMSFRBX != NULL) { if (packetUBXRXMSFRBX->callbackData != NULL) @@ -1258,7 +1268,7 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) result = true; break; case UBX_RXM_PMP: - if (packetUBXRXMPMP != NULL) + if ((packetUBXRXMPMP != NULL) || (packetUBXRXMPMPmessage != NULL)) result = true; break; } @@ -3254,45 +3264,52 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // Note: the field positions depend on the version { // Parse various byte fields into storage - but only if we have memory allocated for it - if (packetUBXRXMPMP != NULL) + if ((packetUBXRXMPMP != NULL) && (packetUBXRXMPMP->callbackData != NULL)) { - packetUBXRXMPMP->data.version = extractByte(msg, 0); - packetUBXRXMPMP->data.numBytesUserData = extractInt(msg, 2); - packetUBXRXMPMP->data.timeTag = extractLong(msg, 4); - packetUBXRXMPMP->data.uniqueWord[0] = extractLong(msg, 8); - packetUBXRXMPMP->data.uniqueWord[1] = extractLong(msg, 12); - packetUBXRXMPMP->data.serviceIdentifier = extractInt(msg, 16); - packetUBXRXMPMP->data.spare = extractByte(msg, 18); - packetUBXRXMPMP->data.uniqueWordBitErrors = extractByte(msg, 19); - - if (packetUBXRXMPMP->data.version == 0x00) + packetUBXRXMPMP->callbackData->version = extractByte(msg, 0); + packetUBXRXMPMP->callbackData->numBytesUserData = extractInt(msg, 2); + packetUBXRXMPMP->callbackData->timeTag = extractLong(msg, 4); + packetUBXRXMPMP->callbackData->uniqueWord[0] = extractLong(msg, 8); + packetUBXRXMPMP->callbackData->uniqueWord[1] = extractLong(msg, 12); + packetUBXRXMPMP->callbackData->serviceIdentifier = extractInt(msg, 16); + packetUBXRXMPMP->callbackData->spare = extractByte(msg, 18); + packetUBXRXMPMP->callbackData->uniqueWordBitErrors = extractByte(msg, 19); + + if (packetUBXRXMPMP->callbackData->version == 0x00) { - packetUBXRXMPMP->data.fecBits = extractInt(msg, 524); - packetUBXRXMPMP->data.ebno = extractByte(msg, 526); + packetUBXRXMPMP->callbackData->fecBits = extractInt(msg, 524); + packetUBXRXMPMP->callbackData->ebno = extractByte(msg, 526); } else // if (packetUBXRXMPMP->data.version == 0x01) { - packetUBXRXMPMP->data.fecBits = extractInt(msg, 20); - packetUBXRXMPMP->data.ebno = extractByte(msg, 22); + packetUBXRXMPMP->callbackData->fecBits = extractInt(msg, 20); + packetUBXRXMPMP->callbackData->ebno = extractByte(msg, 22); } - uint16_t userDataStart = (packetUBXRXMPMP->data.version == 0x00) ? 20 : 24; - uint16_t userDataLength = (packetUBXRXMPMP->data.version == 0x00) ? 504 : (packetUBXRXMPMP->data.numBytesUserData); + uint16_t userDataStart = (packetUBXRXMPMP->callbackData->version == 0x00) ? 20 : 24; + uint16_t userDataLength = (packetUBXRXMPMP->callbackData->version == 0x00) ? 504 : (packetUBXRXMPMP->callbackData->numBytesUserData); for (uint16_t i = 0; (i < userDataLength) && (i < 504); i++) { - packetUBXRXMPMP->data.userData[i] = extractByte(msg, i + userDataStart); + packetUBXRXMPMP->callbackData->userData[i] = extractByte(msg, i + userDataStart); } - // Mark all datums as fresh (not read before) - packetUBXRXMPMP->moduleQueried = true; + packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid + } - // Check if we need to copy the data for the callbacks - if ((packetUBXRXMPMP->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale - { - memcpy(&packetUBXRXMPMP->callbackData->version, &packetUBXRXMPMP->data.version, sizeof(UBX_RXM_PMP_data_t)); - packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = true; - } + // Full PMP message + if ((packetUBXRXMPMPmessage != NULL) && (packetUBXRXMPMPmessage->callbackData != NULL)) + { + packetUBXRXMPMPmessage->callbackData->sync1 = UBX_SYNCH_1; + packetUBXRXMPMPmessage->callbackData->sync2 = UBX_SYNCH_2; + packetUBXRXMPMPmessage->callbackData->cls = UBX_CLASS_RXM; + packetUBXRXMPMPmessage->callbackData->ID = UBX_RXM_PMP; + packetUBXRXMPMPmessage->callbackData->lengthLSB = msg->len & 0xFF; + packetUBXRXMPMPmessage->callbackData->lengthMSB = msg->len >> 8; + + memcpy(packetUBXRXMPMPmessage->callbackData->payload, msg->payload, msg->len); + + packetUBXRXMPMPmessage->callbackData->checksumA = msg->checksumA; + packetUBXRXMPMPmessage->callbackData->checksumB = msg->checksumB; } } else if (msg->id == UBX_RXM_SFRBX) @@ -4862,17 +4879,26 @@ 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->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid { - if (packetUBXRXMPMP->callbackPointerPtr != NULL) // If the pointer to the callback has been defined - { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM PMP")); - packetUBXRXMPMP->callbackPointerPtr(packetUBXRXMPMP->callbackData); // Call the callback - } + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM PMP")); + 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->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 + } + if ((packetUBXRXMSFRBX != NULL) // If RAM has been allocated for message storage && (packetUBXRXMSFRBX->callbackData != NULL) // If RAM has been allocated for the copy of the data && (packetUBXRXMSFRBX->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid @@ -7582,8 +7608,69 @@ bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t m //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. //"Every time the 'current' key is expired, 'next' takes its place." //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. -// The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. -bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait) +// The key can be provided in binary (uint8_t) format or in ASCII Hex (char) format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. +bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const char *key) +{ + uint8_t *binaryKey = new uint8_t[keyLengthBytes]; // Allocate memory to store the binaryKey + + if (binaryKey == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + _debugSerial->println(F("setDynamicSPARTNKey: binaryKey RAM allocation failed!")); +#endif + return (false); + } + + bool ok = true; + + // Convert the ASCII Hex const char to binary uint8_t + for (uint16_t i = 0; i < ((uint16_t)keyLengthBytes * 2); i += 2) + { + if ((key[i] >= '0') && (key[i] <= '9')) + { + binaryKey[i >> 1] = (key[i] - '0') << 4; + } + else if ((key[i] >= 'a') && (key[i] <= 'f')) + { + binaryKey[i >> 1] = (key[i] + 10 - 'a') << 4; + } + else if ((key[i] >= 'A') && (key[i] <= 'F')) + { + binaryKey[i >> 1] = (key[i] + 10 - 'A') << 4; + } + else + { + ok = false; + } + + if ((key[i + 1] >= '0') && (key[i + 1] <= '9')) + { + binaryKey[i >> 1] |= key[i + 1] - '0'; + } + else if ((key[i + 1] >= 'a') && (key[i + 1] <= 'f')) + { + binaryKey[i >> 1] |= key[i + 1] + 10 - 'a'; + } + else if ((key[i + 1] >= 'A') && (key[i + 1] <= 'F')) + { + binaryKey[i >> 1] |= key[i + 1] + 10 - 'A'; + } + else + { + ok = false; + } + } + + if (ok) + ok = setDynamicSPARTNKey(keyLengthBytes, validFromWno, validFromTow, (const uint8_t *)binaryKey); + + delete[] binaryKey; // Free the memory allocated for binaryKey + + return (ok); +} + +bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key) { // Check if there is room for the key in packetCfg. Resize the buffer if not. size_t payloadLength = (size_t)keyLengthBytes + 12; @@ -7614,68 +7701,127 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validF payloadCfg[10] = (validFromTow >> 16) & 0xFF; payloadCfg[11] = (validFromTow >> 24) & 0xFF; - // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F - bool isASCIIHex = true; - uint16_t i = 0; - while ((i < (uint16_t)keyLengthBytes) && (isASCIIHex == true)) + memcpy(&payloadCfg[12], key, keyLengthBytes); + + return (sendCommand(&packetCfg, 0) == SFE_UBLOX_STATUS_SUCCESS); // UBX-RXM-SPARTNKEY is silent. It does not ACK (or NACK) +} + +bool SFE_UBLOX_GNSS::setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const char *key1, + uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const char *key2) +{ + uint8_t *binaryKey1 = new uint8_t[keyLengthBytes1]; // Allocate memory to store binaryKey1 + + if (binaryKey1 == NULL) { - if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + _debugSerial->println(F("setDynamicSPARTNKeys: binaryKey1 RAM allocation failed!")); +#endif + return (false); } - if (isASCIIHex) // Check the second half of the ASCII Hex key + + uint8_t *binaryKey2 = new uint8_t[keyLengthBytes2]; // Allocate memory to store binaryKey2 + + if (binaryKey2 == NULL) { - while ((i < ((uint16_t)keyLengthBytes * 2) && (isASCIIHex == true))) - { - if (((key[i] >= '0') && (key[i] <= '9')) || ((key[i] >= 'a') && (key[i] <= 'f')) || ((key[i] >= 'A') && (key[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary - } +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + _debugSerial->println(F("setDynamicSPARTNKeys: binaryKey2 RAM allocation failed!")); +#endif + delete[] binaryKey1; + return (false); } - if (isASCIIHex) // Convert ASCII Hex key to binary + bool ok = true; + + // Convert the ASCII Hex const char to binary uint8_t + for (uint16_t i = 0; i < ((uint16_t)keyLengthBytes1 * 2); i += 2) { - for (i = 0; i < ((uint16_t)keyLengthBytes * 2); i += 2) + if ((key1[i] >= '0') && (key1[i] <= '9')) { - if ((key[i] >= '0') && (key[i] <= '9')) - { - payloadCfg[12 + (i >> 1)] = (key[i] - '0') << 4; - } - else if ((key[i] >= 'a') && (key[i] <= 'f')) - { - payloadCfg[12 + (i >> 1)] = (key[i] + 10 - 'a') << 4; - } - else // if ((key[i] >= 'A') && (key[i] <= 'F')) - { - payloadCfg[12 + (i >> 1)] = (key[i] + 10 - 'A') << 4; - } + binaryKey1[i >> 1] = (key1[i] - '0') << 4; + } + else if ((key1[i] >= 'a') && (key1[i] <= 'f')) + { + binaryKey1[i >> 1] = (key1[i] + 10 - 'a') << 4; + } + else if ((key1[i] >= 'A') && (key1[i] <= 'F')) + { + binaryKey1[i >> 1] = (key1[i] + 10 - 'A') << 4; + } + else + { + ok = false; + } - if ((key[i + 1] >= '0') && (key[i + 1] <= '9')) - { - payloadCfg[12 + (i >> 1)] |= key[i + 1] - '0'; - } - else if ((key[i + 1] >= 'a') && (key[i + 1] <= 'f')) - { - payloadCfg[12 + (i >> 1)] |= key[i + 1] + 10 - 'a'; - } - else // if ((key[i + 1] >= 'A') && (key[i + 1] <= 'F')) - { - payloadCfg[12 + (i >> 1)] |= key[i + 1] + 10 - 'A'; - } + if ((key1[i + 1] >= '0') && (key1[i + 1] <= '9')) + { + binaryKey1[i >> 1] |= key1[i + 1] - '0'; + } + else if ((key1[i + 1] >= 'a') && (key1[i + 1] <= 'f')) + { + binaryKey1[i >> 1] |= key1[i + 1] + 10 - 'a'; + } + else if ((key1[i + 1] >= 'A') && (key1[i + 1] <= 'F')) + { + binaryKey1[i >> 1] |= key1[i + 1] + 10 - 'A'; + } + else + { + ok = false; } } - else // Binary key + + // Convert the ASCII Hex const char to binary uint8_t + for (uint16_t i = 0; i < ((uint16_t)keyLengthBytes2 * 2); i += 2) { - memcpy(&payloadCfg[12], key, keyLengthBytes); + if ((key2[i] >= '0') && (key2[i] <= '9')) + { + binaryKey2[i >> 1] = (key2[i] - '0') << 4; + } + else if ((key2[i] >= 'a') && (key2[i] <= 'f')) + { + binaryKey2[i >> 1] = (key2[i] + 10 - 'a') << 4; + } + else if ((key2[i] >= 'A') && (key2[i] <= 'F')) + { + binaryKey2[i >> 1] = (key2[i] + 10 - 'A') << 4; + } + else + { + ok = false; + } + + if ((key2[i + 1] >= '0') && (key2[i + 1] <= '9')) + { + binaryKey2[i >> 1] |= key2[i + 1] - '0'; + } + else if ((key2[i + 1] >= 'a') && (key2[i + 1] <= 'f')) + { + binaryKey2[i >> 1] |= key2[i + 1] + 10 - 'a'; + } + else if ((key2[i + 1] >= 'A') && (key2[i + 1] <= 'F')) + { + binaryKey2[i >> 1] |= key2[i + 1] + 10 - 'A'; + } + else + { + ok = false; + } } - return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK + if (ok) + ok = setDynamicSPARTNKeys(keyLengthBytes1, validFromWno1, validFromTow1, (const uint8_t *)binaryKey1, + keyLengthBytes2, validFromWno2, validFromTow2, (const uint8_t *)binaryKey2); + + delete[] binaryKey1; // Free the memory allocated for binaryKey1 + delete[] binaryKey2; // Free the memory allocated for binaryKey2 + + return (ok); } bool SFE_UBLOX_GNSS::setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const uint8_t *key1, - uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2, uint16_t maxWait) + uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2) { // Check if there is room for the key in packetCfg. Resize the buffer if not. size_t payloadLength = (size_t)keyLengthBytes1 + (size_t)keyLengthBytes2 + 20; @@ -7714,121 +7860,10 @@ bool SFE_UBLOX_GNSS::setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t vali payloadCfg[18] = (validFromTow2 >> 16) & 0xFF; payloadCfg[19] = (validFromTow2 >> 24) & 0xFF; - // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F - bool isASCIIHex = true; - uint16_t i = 0; - while ((i < (uint16_t)keyLengthBytes1) && (isASCIIHex == true)) - { - if (((key1[i] >= '0') && (key1[i] <= '9')) || ((key1[i] >= 'a') && (key1[i] <= 'f')) || ((key1[i] >= 'A') && (key1[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary - } - if (isASCIIHex) // Check the second half of the ASCII Hex key - { - while ((i < ((uint16_t)keyLengthBytes1 * 2) && (isASCIIHex == true))) - { - if (((key1[i] >= '0') && (key1[i] <= '9')) || ((key1[i] >= 'a') && (key1[i] <= 'f')) || ((key1[i] >= 'A') && (key1[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary - } - } - - if (isASCIIHex) // Convert ASCII Hex key to binary - { - for (i = 0; i < ((uint16_t)keyLengthBytes1 * 2); i += 2) - { - if ((key1[i] >= '0') && (key1[i] <= '9')) - { - payloadCfg[20 + (i >> 1)] = (key1[i] - '0') << 4; - } - else if ((key1[i] >= 'a') && (key1[i] <= 'f')) - { - payloadCfg[20 + (i >> 1)] = (key1[i] + 10 - 'a') << 4; - } - else // if ((key1[i] >= 'A') && (key1[i] <= 'F')) - { - payloadCfg[20 + (i >> 1)] = (key1[i] + 10 - 'A') << 4; - } + memcpy(&payloadCfg[20], key1, keyLengthBytes1); + memcpy(&payloadCfg[20 + keyLengthBytes1], key2, keyLengthBytes2); - if ((key1[i + 1] >= '0') && (key1[i + 1] <= '9')) - { - payloadCfg[20 + (i >> 1)] |= key1[i + 1] - '0'; - } - else if ((key1[i + 1] >= 'a') && (key1[i + 1] <= 'f')) - { - payloadCfg[20 + (i >> 1)] |= key1[i + 1] + 10 - 'a'; - } - else // if ((key1[i + 1] >= 'A') && (key1[i + 1] <= 'F')) - { - payloadCfg[20 + (i >> 1)] |= key1[i + 1] + 10 - 'A'; - } - } - } - else // Binary key - { - memcpy(&payloadCfg[20], key1, keyLengthBytes1); - } - - // Check if all keyLengthBytes are ASCII Hex 0-9, a-f, A-F - isASCIIHex = true; - i = 0; - while ((i < (uint16_t)keyLengthBytes2) && (isASCIIHex == true)) - { - if (((key2[i] >= '0') && (key2[i] <= '9')) || ((key2[i] >= 'a') && (key2[i] <= 'f')) || ((key2[i] >= 'A') && (key2[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary - } - if (isASCIIHex) // Check the second half of the ASCII Hex key - { - while ((i < ((uint16_t)keyLengthBytes2 * 2) && (isASCIIHex == true))) - { - if (((key2[i] >= '0') && (key2[i] <= '9')) || ((key2[i] >= 'a') && (key2[i] <= 'f')) || ((key2[i] >= 'A') && (key2[i] <= 'F'))) - i++; // Keep checking if data is all ASCII Hex - else - isASCIIHex = false; // Data is binary - } - } - - if (isASCIIHex) // Convert ASCII Hex key to binary - { - for (i = 0; i < ((uint16_t)keyLengthBytes2 * 2); i += 2) - { - if ((key2[i] >= '0') && (key2[i] <= '9')) - { - payloadCfg[20 + keyLengthBytes1 + (i >> 1)] = (key2[i] - '0') << 4; - } - else if ((key2[i] >= 'a') && (key2[i] <= 'f')) - { - payloadCfg[20 + keyLengthBytes1 + (i >> 1)] = (key2[i] + 10 - 'a') << 4; - } - else // if ((key2[i] >= 'A') && (key2[i] <= 'F')) - { - payloadCfg[20 + keyLengthBytes1 + (i >> 1)] = (key2[i] + 10 - 'A') << 4; - } - - if ((key2[i + 1] >= '0') && (key2[i + 1] <= '9')) - { - payloadCfg[20 + keyLengthBytes1 + (i >> 1)] |= key2[i + 1] - '0'; - } - else if ((key2[i + 1] >= 'a') && (key2[i + 1] <= 'f')) - { - payloadCfg[20 + keyLengthBytes1 + (i >> 1)] |= key2[i + 1] + 10 - 'a'; - } - else // if ((key2[i + 1] >= 'A') && (key2[i + 1] <= 'F')) - { - payloadCfg[20 + keyLengthBytes1 + (i >> 1)] |= key2[i + 1] + 10 - 'A'; - } - } - } - else // Binary key - { - memcpy(&payloadCfg[20 + keyLengthBytes1], key2, keyLengthBytes2); - } - - return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK + return (sendCommand(&packetCfg, 0) == SFE_UBLOX_STATUS_SUCCESS); // UBX-RXM-SPARTNKEY is silent. It does not ACK (or NACK) } // CONFIGURATION INTERFACE (protocol v27 and above) @@ -11460,7 +11495,7 @@ void SFE_UBLOX_GNSS::logAOPSTATUS(bool enabled) // ***** RXM PMP automatic support // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! -bool SFE_UBLOX_GNSS::setAutoRXMPMPcallbackPtr(void (*callbackPointer)(UBX_RXM_PMP_data_t *)) +bool SFE_UBLOX_GNSS::setRXMPMPcallbackPtr(void (*callbackPointer)(UBX_RXM_PMP_data_t *)) { if (packetUBXRXMPMP == NULL) initPacketUBXRXMPMP(); // Check that RAM has been allocated for the data @@ -11500,7 +11535,50 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMPMP() packetUBXRXMPMP->automaticFlags.flags.all = 0; packetUBXRXMPMP->callbackPointerPtr = NULL; packetUBXRXMPMP->callbackData = NULL; - packetUBXRXMPMP->moduleQueried = false; + return (true); +} + +// Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! +bool SFE_UBLOX_GNSS::setRXMPMPmessageCallbackPtr(void (*callbackPointer)(UBX_RXM_PMP_message_data_t *)) +{ + if (packetUBXRXMPMPmessage == NULL) + initPacketUBXRXMPMPmessage(); // Check that RAM has been allocated for the data + if (packetUBXRXMPMPmessage == NULL) // Only attempt this if RAM allocation was successful + return false; + + if (packetUBXRXMPMPmessage->callbackData == NULL) // Check if RAM has been allocated for the callback copy + { + packetUBXRXMPMPmessage->callbackData = new UBX_RXM_PMP_message_data_t; // Allocate RAM for the main struct + } + + if (packetUBXRXMPMPmessage->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("setAutoRXMPMPmessagecallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXRXMPMPmessage->callbackPointerPtr = callbackPointer; + return (true); +} + +// PRIVATE: Allocate RAM for packetUBXRXMPMPmessage and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXRXMPMPmessage() +{ + packetUBXRXMPMPmessage = new UBX_RXM_PMP_message_t; // Allocate RAM for the main struct + if (packetUBXRXMPMPmessage == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXRXMPMPmessage: RAM alloc failed!")); +#endif + return (false); + } + packetUBXRXMPMPmessage->automaticFlags.flags.all = 0; + packetUBXRXMPMPmessage->callbackPointerPtr = NULL; + packetUBXRXMPMPmessage->callbackData = NULL; return (true); } diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index d587362..b1d3bb5 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -901,10 +901,13 @@ class SFE_UBLOX_GNSS //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. //"Every time the 'current' key is expired, 'next' takes its place." //"Therefore the host should then retrieve the new 'next' key and send only that." - Use setDynamicSPARTNKey for this. - // The key can be provided in binary format or in ASCII Hex format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. - bool setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key, uint16_t maxWait = defaultMaxWait); + // The key can be provided in binary (uint8_t) format or in ASCII Hex (char) format, but in both cases keyLengthBytes _must_ represent the binary key length in bytes. + bool setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const char *key); + bool setDynamicSPARTNKey(uint8_t keyLengthBytes, uint16_t validFromWno, uint32_t validFromTow, const uint8_t *key); + bool setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const char *key1, + uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const char *key2); bool setDynamicSPARTNKeys(uint8_t keyLengthBytes1, uint16_t validFromWno1, uint32_t validFromTow1, const uint8_t *key1, - uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2, uint16_t maxWait = defaultMaxWait); + uint8_t keyLengthBytes2, uint16_t validFromWno2, uint32_t validFromTow2, const uint8_t *key2); // General configuration (used only on protocol v27 and higher - ie, ZED-F9P) @@ -1110,7 +1113,8 @@ class SFE_UBLOX_GNSS // Note: on the NEO-D9S, the UBX-RXM-PMP messages are enabled by default on all ports. // You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 0) // The NEO-D9S does not support UBX-CFG-MSG - bool setAutoRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! + bool setRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! + bool setRXMPMPmessageCallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_message_data_t *)); // Use this if you want all of the PMP message (including sync chars, checksum, etc.) to push to a GNSS bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX bool setAutoRXMSFRBX(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic RXM SFRBX reports at the navigation frequency @@ -1442,9 +1446,10 @@ class SFE_UBLOX_GNSS UBX_NAV_RELPOSNED_t *packetUBXNAVRELPOSNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_NAV_AOPSTATUS_t *packetUBXNAVAOPSTATUS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_RXM_PMP_t *packetUBXRXMPMP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_RXM_PMP_t *packetUBXRXMPMP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_RXM_PMP_message_t *packetUBXRXMPMPmessage = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_CFG_PRT_t *packetUBXCFGPRT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_CFG_RATE_t *packetUBXCFGRATE = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1514,39 +1519,40 @@ class SFE_UBLOX_GNSS // The initPacket functions need to be private as they don't check if memory has already been allocated. // Functions like setAutoNAVPOSECEF will check that memory has not been allocated before calling initPacket. - bool initPacketUBXNAVPOSECEF(); // Allocate RAM for packetUBXNAVPOSECEF and initialize it - bool initPacketUBXNAVSTATUS(); // Allocate RAM for packetUBXNAVSTATUS and initialize it - bool initPacketUBXNAVDOP(); // Allocate RAM for packetUBXNAVDOP and initialize it - bool initPacketUBXNAVATT(); // Allocate RAM for packetUBXNAVATT and initialize it - bool initPacketUBXNAVPVT(); // Allocate RAM for packetUBXNAVPVT and initialize it - bool initPacketUBXNAVODO(); // Allocate RAM for packetUBXNAVODO and initialize it - bool initPacketUBXNAVVELECEF(); // Allocate RAM for packetUBXNAVVELECEF and initialize it - bool initPacketUBXNAVVELNED(); // Allocate RAM for packetUBXNAVVELNED and initialize it - bool initPacketUBXNAVHPPOSECEF(); // Allocate RAM for packetUBXNAVHPPOSECEF and initialize it - bool initPacketUBXNAVHPPOSLLH(); // Allocate RAM for packetUBXNAVHPPOSLLH and initialize it - bool initPacketUBXNAVPVAT(); // Allocate RAM for packetUBXNAVPVAT and initialize it - bool initPacketUBXNAVCLOCK(); // Allocate RAM for packetUBXNAVCLOCK and initialize it - bool initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it - bool initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it - bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it - bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it - bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it - bool initPacketUBXRXMPMP(); // Allocate RAM for packetUBXRXMPMP and initialize it - bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it - bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it - bool initPacketUBXCFGPRT(); // Allocate RAM for packetUBXCFGPRT and initialize it - bool initPacketUBXCFGRATE(); // Allocate RAM for packetUBXCFGRATE and initialize it - bool initPacketUBXTIMTM2(); // Allocate RAM for packetUBXTIMTM2 and initialize it - bool initPacketUBXESFALG(); // Allocate RAM for packetUBXESFALG and initialize it - bool initPacketUBXESFSTATUS(); // Allocate RAM for packetUBXESFSTATUS and initialize it - bool initPacketUBXESFINS(); // Allocate RAM for packetUBXESFINS and initialize it - bool initPacketUBXESFMEAS(); // Allocate RAM for packetUBXESFMEAS and initialize it - bool initPacketUBXESFRAW(); // Allocate RAM for packetUBXESFRAW and initialize it - bool initPacketUBXHNRATT(); // Allocate RAM for packetUBXHNRATT and initialize it - bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it - bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it - bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it - bool initPacketUBXMGADBD(); // Allocate RAM for packetUBXMGADBD and initialize it + bool initPacketUBXNAVPOSECEF(); // Allocate RAM for packetUBXNAVPOSECEF and initialize it + bool initPacketUBXNAVSTATUS(); // Allocate RAM for packetUBXNAVSTATUS and initialize it + bool initPacketUBXNAVDOP(); // Allocate RAM for packetUBXNAVDOP and initialize it + bool initPacketUBXNAVATT(); // Allocate RAM for packetUBXNAVATT and initialize it + bool initPacketUBXNAVPVT(); // Allocate RAM for packetUBXNAVPVT and initialize it + bool initPacketUBXNAVODO(); // Allocate RAM for packetUBXNAVODO and initialize it + bool initPacketUBXNAVVELECEF(); // Allocate RAM for packetUBXNAVVELECEF and initialize it + bool initPacketUBXNAVVELNED(); // Allocate RAM for packetUBXNAVVELNED and initialize it + bool initPacketUBXNAVHPPOSECEF(); // Allocate RAM for packetUBXNAVHPPOSECEF and initialize it + bool initPacketUBXNAVHPPOSLLH(); // Allocate RAM for packetUBXNAVHPPOSLLH and initialize it + bool initPacketUBXNAVPVAT(); // Allocate RAM for packetUBXNAVPVAT and initialize it + bool initPacketUBXNAVCLOCK(); // Allocate RAM for packetUBXNAVCLOCK and initialize it + bool initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it + bool initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it + bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it + bool initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it + bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it + bool initPacketUBXRXMPMP(); // Allocate RAM for packetUBXRXMPMP and initialize it + bool initPacketUBXRXMPMPmessage(); // Allocate RAM for packetUBXRXMPMPRaw and initialize it + bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it + bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it + bool initPacketUBXCFGPRT(); // Allocate RAM for packetUBXCFGPRT and initialize it + bool initPacketUBXCFGRATE(); // Allocate RAM for packetUBXCFGRATE and initialize it + bool initPacketUBXTIMTM2(); // Allocate RAM for packetUBXTIMTM2 and initialize it + bool initPacketUBXESFALG(); // Allocate RAM for packetUBXESFALG and initialize it + bool initPacketUBXESFSTATUS(); // Allocate RAM for packetUBXESFSTATUS and initialize it + bool initPacketUBXESFINS(); // Allocate RAM for packetUBXESFINS and initialize it + bool initPacketUBXESFMEAS(); // Allocate RAM for packetUBXESFMEAS and initialize it + bool initPacketUBXESFRAW(); // Allocate RAM for packetUBXESFRAW and initialize it + bool initPacketUBXHNRATT(); // Allocate RAM for packetUBXHNRATT and initialize it + bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it + bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it + bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it + bool initPacketUBXMGADBD(); // Allocate RAM for packetUBXMGADBD and initialize it bool initStorageNMEAGPGGA(); // Allocate RAM for incoming NMEA GPGGA messages and initialize it bool initStorageNMEAGNGGA(); // Allocate RAM for incoming NMEA GNGGA messages and initialize it diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index bdc828b..2d0ce24 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1486,7 +1486,8 @@ typedef struct // UBX-RXM-PMP (0x02 0x72): PMP raw data (D9 modules) // There are two versions of this message but, fortunately, both have a max len of 528 -const uint16_t UBX_RXM_PMP_MAX_LEN = 528; +const uint16_t UBX_RXM_PMP_MAX_USER_DATA = 504; +const uint16_t UBX_RXM_PMP_MAX_LEN = UBX_RXM_PMP_MAX_USER_DATA + 24; typedef struct { @@ -1504,19 +1505,41 @@ typedef struct uint8_t ebno; // Energy per bit to noise power spectral density ratio : 2^-3 dB uint8_t reserved1; // Reserved - uint8_t userData[504]; // Received user data: version 0x00 : starts at byte 20 ; version 0x01 : starts at byte 24 + uint8_t userData[UBX_RXM_PMP_MAX_USER_DATA]; // Received user data: version 0x00 : starts at byte 20 ; version 0x01 : starts at byte 24 } UBX_RXM_PMP_data_t; +// The PMP data can only be accessed via a callback. PMP cannot be polled. typedef struct { ubxAutomaticFlags automaticFlags; - UBX_RXM_PMP_data_t data; - bool moduleQueried; void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *); UBX_RXM_PMP_data_t *callbackData; } UBX_RXM_PMP_t; +// Define a struct to hold the entire PMP message so the whole thing can be pushed to a GNSS. +// Remember that the length of the payload could be variable (with version 1 messages). +typedef struct +{ + uint8_t sync1; // 0xB5 + uint8_t sync2; // 0x62 + uint8_t cls; + uint8_t ID; + uint8_t lengthLSB; + uint8_t lengthMSB; + uint8_t payload[UBX_RXM_PMP_MAX_LEN]; + uint8_t checksumA; + uint8_t checksumB; +} UBX_RXM_PMP_message_data_t; + +// The PMP data can only be accessed via a callback. PMP cannot be polled. +typedef struct +{ + ubxAutomaticFlags automaticFlags; + void (*callbackPointerPtr)(UBX_RXM_PMP_message_data_t *); + UBX_RXM_PMP_message_data_t *callbackData; +} UBX_RXM_PMP_message_t; + // CFG-specific structs // UBX-CFG-PRT (0x06 0x00): Port configuration From 286670c7945bf0308d7ad85994faaa16f7ee14dd Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 14 Feb 2022 13:54:22 +0100 Subject: [PATCH 115/122] Update SparkFun_u-blox_GNSS_Arduino_Library.h --- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index b1d3bb5..9608593 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -809,6 +809,7 @@ class SFE_UBLOX_GNSS bool setUSBOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure USB port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof bool setSPIOutput(uint8_t comSettings, uint16_t maxWait = defaultMaxWait); // Configure SPI port to output UBX, NMEA, RTCM3, SPARTN or a combination thereof void setNMEAOutputPort(Stream &nmeaOutputPort); // Sets the internal variable for the port to direct NMEA characters to + void setOutputPort(Stream &outputPort); // Sets the internal variable for the port to direct ALL characters to // Reset to defaults @@ -1562,7 +1563,7 @@ class SFE_UBLOX_GNSS Stream *_serialPort; // The generic connection to user's chosen Serial hardware Stream *_nmeaOutputPort = NULL; // The user can assign an output port to print NMEA sentences if they wish Stream *_debugSerial; // The stream to send debug messages to if enabled - + Stream *_outputPort = NULL; SPIClass *_spiPort; // The instance of SPIClass uint8_t _csPin; // The chip select pin uint32_t _spiSpeed; // The speed to use for SPI (Hz) From 505bffd53264a866693c7c36228853bf438e5b69 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 14 Feb 2022 13:57:07 +0100 Subject: [PATCH 116/122] Update SparkFun_u-blox_GNSS_Arduino_Library.cpp --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 7ae4f32..5b32b87 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1527,6 +1527,8 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) // Take a given byte and file it into the proper array void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID) { + if (_outputPort != NULL) + _outputPort->write(incoming); // Echo this byte to the serial port if ((currentSentence == NONE) || (currentSentence == NMEA)) { if (incoming == UBX_SYNCH_1) // UBX binary frames start with 0xB5, aka μ @@ -6449,6 +6451,11 @@ void SFE_UBLOX_GNSS::setNMEAOutputPort(Stream &nmeaOutputPort) _nmeaOutputPort = &nmeaOutputPort; // Store the port from user } +void SFE_UBLOX_GNSS::setOutputPort(Stream &outputPort) +{ + _outputPort = &outputPort; // Store the port from user +} + // Reset to defaults void SFE_UBLOX_GNSS::factoryReset() From 3000efbb918c8c926c6d102f3354c171a95fbf7b Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 14 Feb 2022 13:58:32 +0100 Subject: [PATCH 117/122] Update Example19_LBand_Corrections_with_NEO-D9S.ino --- .../Example19_LBand_Corrections_with_NEO-D9S.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino index ae9de84..d012a16 100644 --- a/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino +++ b/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino @@ -146,7 +146,9 @@ void setup() if (ok) ok = myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible if (ok) ok = myGNSS.setNavigationFrequency(1); //Set output in Hz. - + + if (ok) ok = myGNSS.setVal8(UBLOX_CFG_SPARTN_USE_SOURCE, 1); // use LBAND PMP message + //Configure the SPARTN IP Dynamic Keys //"When the receiver boots, the host should send 'current' and 'next' keys in one message." - Use setDynamicSPARTNKeys for this. //"Every time the 'current' key is expired, 'next' takes its place." From 6ea673060eabd4b8a4a497497a9716447ad9ba2d Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 14 Feb 2022 14:53:57 +0100 Subject: [PATCH 118/122] Update SparkFun_u-blox_GNSS_Arduino_Library.cpp --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 5b32b87..20df53c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3312,6 +3312,8 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMPMPmessage->callbackData->checksumA = msg->checksumA; packetUBXRXMPMPmessage->callbackData->checksumB = msg->checksumB; + + packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid } } else if (msg->id == UBX_RXM_SFRBX) From b4e251c5b0acb8a82a5b869a445a3b96a3bbdcbf Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 14 Feb 2022 14:08:43 +0000 Subject: [PATCH 119/122] Set packetUBXRXMPMPmessage callbackCopyValid to true --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 7ae4f32..d6d7db3 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3310,6 +3310,8 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMPMPmessage->callbackData->checksumA = msg->checksumA; packetUBXRXMPMPmessage->callbackData->checksumB = msg->checksumB; + + packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid } } else if (msg->id == UBX_RXM_SFRBX) From 29c0f0c5e9b55275eee3d7836c2b1434fa9c75e7 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 14 Feb 2022 14:44:02 +0000 Subject: [PATCH 120/122] Add setNMEAOutputPort to keywords.txt --- keywords.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/keywords.txt b/keywords.txt index 6111314..afb36a6 100644 --- a/keywords.txt +++ b/keywords.txt @@ -125,6 +125,7 @@ setUART2Output KEYWORD2 setUSBOutput KEYWORD2 setSPIOutput KEYWORD2 setNMEAOutputPort KEYWORD2 +setOutputPort KEYWORD2 factoryReset KEYWORD2 hardReset KEYWORD2 From daf38964f4f3ea7eba81a412eab40933f63af662 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 20 Feb 2022 17:24:11 +0000 Subject: [PATCH 121/122] v2.2.1 --- library.properties | 2 +- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/library.properties b/library.properties index 0a5a6a5..cef0eb9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.2.0 +version=2.2.1 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 5eb04af..952f79f 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -3265,8 +3265,12 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) // Note: length is variable with version 0x01 // Note: the field positions depend on the version { - // Parse various byte fields into storage - but only if we have memory allocated for it - if ((packetUBXRXMPMP != NULL) && (packetUBXRXMPMP->callbackData != NULL)) + // Parse various byte fields into storage - but only if we have memory allocated for it. + // By default, new PMP data will always overwrite 'old' data (data which is valid but which has not yet been read by the callback). + // 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); @@ -3298,8 +3302,12 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMPMP->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid } - // Full PMP message - if ((packetUBXRXMPMPmessage != NULL) && (packetUBXRXMPMPmessage->callbackData != NULL)) + // Full PMP message, including Class, ID and checksum + // By default, new PMP data will always overwrite 'old' data (data which is valid but which has not yet been read by the callback). + // 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; From 48c38ff0204a423fcb3c3fd8a09095e5b774acb6 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Sun, 20 Feb 2022 19:06:12 +0000 Subject: [PATCH 122/122] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b6e577..f0630f3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ This library can be installed via the Arduino Library manager. Search for **Spar u-blox's PointPerfect GNSS augmentation service uses the secure MQTT protocol to download SPARTN format correction data, providing "3-6 cm accuracy and convergence within seconds". Please see the new [PointPerfect Client example](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/tree/main/examples/ZED-F9P/Example18_PointPerfectClient) for more details. -v2.3 also supports L-band correction services using the new u-blox NEO-D9S correction data receiver. Please see the new [L-band Corrections example](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/tree/main/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S) for more details. +v2.2.1 also supports L-band correction services using the new u-blox NEO-D9S correction data receiver. Please see the new [L-band Corrections example](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/tree/main/examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S) for more details. Other RTK NTRIP corrections services often require you to send them your location in NMEA GPGGA format. v2.2 of the library makes this easy by providing get functions and automatic callbacks for both GPGGA and GNGGA messages. You can now instruct your module to output GPGGA (e.g.) every 10 seconds and then push it to the correction server directly from the callback. No more polling, no more parsing!