From c351fb5b76788b37e3e2dc23047ed9bc6a1e3121 Mon Sep 17 00:00:00 2001 From: UT2UH Date: Wed, 14 Apr 2021 19:33:31 +0300 Subject: [PATCH 1/3] UBX-NAV-TIMELS support added for leap second event --- .../Example28_GetLeapSecondInfo.ino | 143 ++++++++++++++++++ keywords.txt | 7 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 112 ++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 24 +++ src/u-blox_structs.h | 51 +++++++ 5 files changed, 337 insertions(+) create mode 100644 examples/Example28_GetLeapSecondInfo/Example28_GetLeapSecondInfo.ino diff --git a/examples/Example28_GetLeapSecondInfo/Example28_GetLeapSecondInfo.ino b/examples/Example28_GetLeapSecondInfo/Example28_GetLeapSecondInfo.ino new file mode 100644 index 0000000..a96f27c --- /dev/null +++ b/examples/Example28_GetLeapSecondInfo/Example28_GetLeapSecondInfo.ino @@ -0,0 +1,143 @@ +/* + Getting leap second event info as SNTP Leap Indicator, time to a leap second event and the number of leap seconds since GPS epoch + By: UT2UH + Date: April 14th, 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 query a u-blox module for the leap second event info to cast to SNTP Leap Indicator enumeration. + We also turn off the NMEA output on the I2C port. This decreases the amount of I2C traffic dramatically. + + Leave NMEA parsing behind. Now you can simply ask the module for the datums you want! + + 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 BlackBoard + If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425) + Open the serial monitor at 115200 baud to see the output +*/ + +#include //Needed for I2C to GNSS + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +typedef enum { + LI_NO_WARNING, //Time leaping not scheduled + LI_LAST_MINUTE_61_SEC, //Last minute has 61 seconds + LI_LAST_MINUTE_59_SEC, //Last minute has 59 seconds + LI_ALARM_CONDITION //The NTP server's clock not synchronized +} ntp_LI_e; + + +long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module. + +void setup() +{ + Serial.begin(115200); + while (!Serial) + ; //Wait for user to open terminal + Serial.println("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) + ; + } + + // Uncomment the next line if you need to completely reset your module + //myGNSS.factoryDefault(); delay(5000); // Reset everything and wait while the module restarts + + myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) + myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR + + Serial.println("Compare Unix Epoch given with reference one from https://www.epochconverter.com/"); + +} + +void loop() +{ + //Query module only every second. Doing it more often will just cause I2C traffic. + //The module only responds when a new position is available + if (millis() - lastTime > 1000) + { + lastTime = millis(); //Update the timer + + // getUnixEpoch marks the PVT data as stale so you will get Unix time and PVT time on alternate seconds + + uint32_t us; //microseconds returned by getUnixEpoch() + uint32_t epoch = myGNSS.getUnixEpoch(); + Serial.print("Unix Epoch rounded: "); + Serial.print(epoch, DEC); + epoch = myGNSS.getUnixEpoch(us); + Serial.print(" Exact Unix Epoch: "); + Serial.print(epoch, DEC); + Serial.print(" micros: "); + Serial.println(us, DEC); + int32_t timeToLeapSecEvent; + ntp_LI_e leapIndicator = (ntp_LI_e)myGNSS.getLeapIndicator(timeToLeapSecEvent); + Serial.print("NTP LI: "); + Serial.print(leapIndicator, DEC); + switch (leapIndicator){ + case LI_NO_WARNING: + Serial.print(" - No event scheduled"); + break; + case LI_LAST_MINUTE_61_SEC: + Serial.print(" - last minute will end at 23:60"); + break; + case LI_LAST_MINUTE_59_SEC: + Serial.print(" - last minute will end at 23:58"); + break; + case LI_ALARM_CONDITION: + default: + Serial.print(" - Unknown (clock not synchronized)"); + break; + } + Serial.print(". Time to the next leap second event: "); + Serial.println(timeToLeapSecEvent, DEC); + + sfe_ublox_ls_src_e leapSecSource; + Serial.print("Leap seconds since GPS Epoch (Jan 6th, 1980): "); + Serial.print(myGNSS.getCurrentLeapSeconds(leapSecSource), DEC); + switch (leapSecSource){ + case SFE_UBLOX_LS_SRC_DEFAULT: + Serial.print(" - hardcoded"); + break; + case SFE_UBLOX_LS_SRC_GLONASS: + Serial.print(" - derived from GPS and GLONASS time difference"); + break; + case SFE_UBLOX_LS_SRC_GPS: + Serial.print(" - according to GPS"); + break; + case SFE_UBLOX_LS_SRC_SBAS: + Serial.print(" - according to SBAS"); + break; + case SFE_UBLOX_LS_SRC_BEIDOU: + Serial.print(" - according to BeiDou"); + break; + case SFE_UBLOX_LS_SRC_GALILEO: + Serial.print(" - according to Galileo"); + break; + case SFE_UBLOX_LS_SRC_AIDED: + Serial.print(" - last minute will end at 23:58"); + break; + case SFE_UBLOX_LS_SRC_CONFIGURED: + Serial.print(" - as configured)"); + break; + case SFE_UBLOX_LS_SRC_UNKNOWN: + default: + Serial.print(" - source unknown"); + break; + } + Serial.println(); + } + Serial.println(); +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index f4ba8e0..cd258e0 100644 --- a/keywords.txt +++ b/keywords.txt @@ -28,6 +28,7 @@ UBX_NAV_HPPOSECEF_data_t KEYWORD1 UBX_NAV_HPPOSLLH_data_t KEYWORD1 UBX_NAV_CLOCK_data_t KEYWORD1 UBX_NAV_RELPOSNED_data_t KEYWORD1 +UBX_NAV_TIMELS_data_t KEYWORD1 UBX_RXM_SFRBX_data_t KEYWORD1 UBX_RXM_RAWX_data_t KEYWORD1 @@ -264,6 +265,11 @@ initPacketUBXNAVCLOCK KEYWORD2 flushNAVCLOCK KEYWORD2 logNAVCLOCK KEYWORD2 +getLeapSecondEvent KEYWORD2 +getLeapIndicator KEYWORD2 +getCurrentLeapSeconds KEYWORD2 +initPacketUBXNAVTIMELS KEYWORD2 + getSurveyStatus KEYWORD2 initPacketUBXNAVSVIN KEYWORD2 @@ -569,6 +575,7 @@ UBX_NAV_RELPOSNED LITERAL1 UBX_NAV_RESETODO LITERAL1 UBX_NAV_STATUS LITERAL1 UBX_NAV_SVIN LITERAL1 +UBX_NAV_TIMELS LITERAL1 UBX_NAV_VELECEF LITERAL1 UBX_NAV_VELNED LITERAL1 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index cfba10d..22f97ac 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -789,6 +789,9 @@ boolean SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) 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; @@ -916,6 +919,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) 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; @@ -1949,6 +1955,26 @@ 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 + if (packetUBXNAVTIMELS != NULL) + { + packetUBXNAVTIMELS->data.iTOW = extractLong(msg, 0); + packetUBXNAVTIMELS->data.version = extractByte(msg, 4); + packetUBXNAVTIMELS->data.srcOfCurrLs = extractByte(msg, 8); + packetUBXNAVTIMELS->data.currLs = extractSignedChar(msg, 9); + packetUBXNAVTIMELS->data.srcOfLsChange = extractByte(msg, 10); + packetUBXNAVTIMELS->data.lsChange = extractSignedChar(msg, 11); + packetUBXNAVTIMELS->data.timeToLsEvent = extractSignedLong(msg, 12); + packetUBXNAVTIMELS->data.dateOfLsGpsWn = extractInt(msg, 16); + packetUBXNAVTIMELS->data.dateOfLsGpsDn = extractInt(msg, 18); + packetUBXNAVTIMELS->data.valid = extractSignedChar(msg, 23); + + //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 @@ -6862,6 +6888,53 @@ void SFE_UBLOX_GNSS::logNAVCLOCK(boolean enabled) 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 +boolean SFE_UBLOX_GNSS::getLeapSecondEvent(uint16_t maxWait) +{ + 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); + + packetCfg.cls = UBX_CLASS_NAV; + packetCfg.id = UBX_NAV_TIMELS; + 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); +} + +// PRIVATE: Allocate RAM for packetUBXNAVTIMELS and initialize it +boolean SFE_UBLOX_GNSS::initPacketUBXNAVTIMELS() +{ + packetUBXNAVTIMELS = new UBX_NAV_TIMELS_t; //Allocate RAM for the main struct + if (packetUBXNAVTIMELS == NULL) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXNAVTIMELS: PANIC! RAM allocation failed!")); + return (false); + } + packetUBXNAVTIMELS->automaticFlags.flags.all = 0; + packetUBXNAVTIMELS->callbackPointer = NULL; + packetUBXNAVTIMELS->callbackData = NULL; + packetUBXNAVTIMELS->moduleQueried.moduleQueried.all = 0; + return (true); +} + // ***** NAV SVIN automatic support //Reads survey in status and sets the global variables @@ -10178,6 +10251,45 @@ float SFE_UBLOX_GNSS::getSurveyInMeanAccuracy(uint16_t maxWait) // Returned as 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) +{ + 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.valid == false) + getLeapSecondEvent(maxWait); + packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.valid = 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; + timeToLsEvent = packetUBXNAVTIMELS->data.timeToLsEvent; + // returns NTP Leap Indicator + // 0 -no warning + // 1 -last minute of the day has 61 seconds + // 2 -last minute of the day has 59 seconds + // 3 -unknown (clock unsynchronized) + return ((boolean)packetUBXNAVTIMELS->data.valid ? (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) +{ + 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.valid == false) + getLeapSecondEvent(maxWait); + packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.valid = 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; + source = ((sfe_ublox_ls_src_e)packetUBXNAVTIMELS->data.srcOfCurrLs); + return ((int8_t)packetUBXNAVTIMELS->data.currLs); +} + // ***** RELPOSNED Helper Functions and automatic support float SFE_UBLOX_GNSS::getRelPosN(uint16_t maxWait) // Returned as m diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 06ea72c..69970fd 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -407,6 +407,20 @@ enum sfe_ublox_gnss_ids_e 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 +}; + #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 @@ -800,6 +814,9 @@ class SFE_UBLOX_GNSS // Add "auto" support for NAV SVIN - to avoid needing 'global' storage boolean getSurveyStatus(uint16_t maxWait); //Reads survey in status + // Add "auto" support for NAV TIMELS - to avoid needing 'global' storage + boolean getLeapSecondEvent(uint16_t maxWait); //Reads leap second event info + boolean getRELPOSNED(uint16_t maxWait = defaultMaxWait); //Get Relative Positioning Information of the NED frame boolean setAutoRELPOSNED(boolean enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic RELPOSNED reports boolean setAutoRELPOSNED(boolean enabled, boolean 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 @@ -1032,6 +1049,11 @@ class SFE_UBLOX_GNSS 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 @@ -1084,6 +1106,7 @@ class SFE_UBLOX_GNSS 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_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_RELPOSNED_t *packetUBXNAVRELPOSNED = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1157,6 +1180,7 @@ class SFE_UBLOX_GNSS boolean initPacketUBXNAVHPPOSECEF(); // Allocate RAM for packetUBXNAVHPPOSECEF and initialize it boolean initPacketUBXNAVHPPOSLLH(); // Allocate RAM for packetUBXNAVHPPOSLLH and initialize it boolean initPacketUBXNAVCLOCK(); // Allocate RAM for packetUBXNAVCLOCK and initialize it + boolean initPacketUBXNAVTIMELS(); // Allocate RAM for packetUBXNAVTIMELS and initialize it boolean initPacketUBXNAVSVIN(); // Allocate RAM for packetUBXNAVSVIN and initialize it boolean initPacketUBXNAVRELPOSNED(); // Allocate RAM for packetUBXNAVRELPOSNED and initialize it boolean initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 50611bf..574baa2 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -854,6 +854,57 @@ typedef struct UBX_NAV_CLOCK_data_t *callbackData; } UBX_NAV_CLOCK_t; +// UBX-NAV-TIMELS (0x01 0x26): Leap second event information +const uint16_t UBX_NAV_TIMELS_LEN = 24; + +typedef struct +{ + 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 reserved2[3]; + int8_t valid; // Validity flag, 1 = valid, otherwise 0 +} UBX_NAV_TIMELS_data_t; + +typedef struct +{ + union + { + uint32_t all; + struct + { + uint32_t all : 1; + + uint32_t iTOW : 1; + uint32_t version : 1; + uint32_t srcOfCurrLs : 1; + uint32_t currLs : 1; + uint32_t srcOfLsChange : 1; + uint32_t lsChange : 1; + uint32_t timeToLsEvent : 1; + uint32_t dateOfLsGpsWn : 1; + uint32_t dateOfLsGpsDn : 1; + uint32_t valid : 1; + } bits; + } moduleQueried; +} UBX_NAV_TIMELS_moduleQueried_t; + +typedef struct +{ + ubxAutomaticFlags automaticFlags; + UBX_NAV_TIMELS_data_t data; + UBX_NAV_TIMELS_moduleQueried_t moduleQueried; + void (*callbackPointer)(UBX_NAV_TIMELS_data_t); + UBX_NAV_TIMELS_data_t *callbackData; +} UBX_NAV_TIMELS_t; + // UBX-NAV-SVIN (0x01 0x3B): Survey-in data const uint16_t UBX_NAV_SVIN_LEN = 40; From 103d7b5412aaea46ba34dd4c936934b816f0bcde Mon Sep 17 00:00:00 2001 From: UT2UH Date: Wed, 14 Apr 2021 21:44:36 +0300 Subject: [PATCH 2/3] TIMELS RAM deleted on 'end' --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index c9f2cb8..1d2bc91 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -85,6 +85,12 @@ void SFE_UBLOX_GNSS::end(void) delete[] currentGeofenceParams; currentGeofenceParams = NULL; // Redundant? } + + if (packetUBXNAVTIMELS != NULL) + { + delete[] packetUBXNAVTIMELS; + packetUBXNAVTIMELS = NULL; // Redundant? + } if (packetUBXNAVPOSECEF != NULL) { From 5c7298c37de8d006ead9e1772e0e2d7ea6814001 Mon Sep 17 00:00:00 2001 From: UT2UH Date: Thu, 15 Apr 2021 12:28:54 +0300 Subject: [PATCH 3/3] UBX-NAV-TIMELS validity bits fixes --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 12 ++++++------ src/u-blox_structs.h | 13 +++++++++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 1d2bc91..fcd8cfb 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2086,7 +2086,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXNAVTIMELS->data.timeToLsEvent = extractSignedLong(msg, 12); packetUBXNAVTIMELS->data.dateOfLsGpsWn = extractInt(msg, 16); packetUBXNAVTIMELS->data.dateOfLsGpsDn = extractInt(msg, 18); - packetUBXNAVTIMELS->data.valid = extractSignedChar(msg, 23); + packetUBXNAVTIMELS->data.valid.all = extractSignedChar(msg, 23); //Mark all datums as fresh (not read before) packetUBXNAVTIMELS->moduleQueried.moduleQueried.all = 0xFFFFFFFF; @@ -10391,9 +10391,9 @@ uint8_t SFE_UBLOX_GNSS::getLeapIndicator(int32_t& timeToLsEvent, uint16_t maxWai if (packetUBXNAVTIMELS == NULL) //Bail if the RAM allocation failed return 3; - if (packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.valid == false) + if (packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validTimeToLsEvent == false) getLeapSecondEvent(maxWait); - packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.valid = 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; @@ -10403,7 +10403,7 @@ uint8_t SFE_UBLOX_GNSS::getLeapIndicator(int32_t& timeToLsEvent, uint16_t maxWai // 1 -last minute of the day has 61 seconds // 2 -last minute of the day has 59 seconds // 3 -unknown (clock unsynchronized) - return ((boolean)packetUBXNAVTIMELS->data.valid ? (uint8_t)(packetUBXNAVTIMELS->data.lsChange == -1 ? 2 : packetUBXNAVTIMELS->data.lsChange) : 3); + return ((boolean)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) @@ -10412,9 +10412,9 @@ int8_t SFE_UBLOX_GNSS::getCurrentLeapSeconds(sfe_ublox_ls_src_e& source, uint16_ if (packetUBXNAVTIMELS == NULL) //Bail if the RAM allocation failed return false; - if (packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.valid == false) + if (packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.validCurrLs == false) getLeapSecondEvent(maxWait); - packetUBXNAVTIMELS->moduleQueried.moduleQueried.bits.valid = 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; diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 574baa2..a8a8300 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -870,7 +870,15 @@ typedef struct 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]; - int8_t valid; // Validity flag, 1 = valid, otherwise 0 + union + { + uint8_t all; + struct + { + 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; } UBX_NAV_TIMELS_data_t; typedef struct @@ -891,7 +899,8 @@ typedef struct uint32_t timeToLsEvent : 1; uint32_t dateOfLsGpsWn : 1; uint32_t dateOfLsGpsDn : 1; - uint32_t valid : 1; + uint32_t validCurrLs : 1; + uint32_t validTimeToLsEvent : 1; } bits; } moduleQueried; } UBX_NAV_TIMELS_moduleQueried_t;