diff --git a/examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino b/examples/NEO-F10N/Example1_NAV_SIG/Example1_NAV_SIG.ino similarity index 90% rename from examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino rename to examples/NEO-F10N/Example1_NAV_SIG/Example1_NAV_SIG.ino index aab7381..dfacc1a 100644 --- a/examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino +++ b/examples/NEO-F10N/Example1_NAV_SIG/Example1_NAV_SIG.ino @@ -1,19 +1,17 @@ /* - Configuring the NEO-F10N GNSS to send RXM RAWX reports over Serial and display them using a callback + Configuring the NEO-F10N GNSS to send NAV SIG reports over Serial and display them using a callback By: Paul Clark SparkFun Electronics - Date: November 24th, 2023 + Date: February 29th, 2024 License: MIT. See license file for more information. - This example shows how to configure the u-blox NEO-F10N GNSS to send RXM RAWX reports automatically + This example shows how to configure the u-blox NEO-F10N GNSS to send NAV SIG reports automatically and access the data via a callback. It also demonstrates how to mark the L5 signals as healthy. Note: the NEO-F10N only supports UART1. It does not support I2C, SPI or built-in USB. To run this example on the SparkFun NEO-F10N breakout, you need to open the USB-TX and USB-RX jumpers to isolate the on-board CH340 USB interface chip. See Hardware Connections below. - Note: the engineering sample of the NEO-F10N-00B supports RXM-RAWX. Production firmware may not. - Feel like supporting open source hardware? Buy a board from SparkFun! NEO-F10N: https://www.sparkfun.com/products/24114 @@ -32,22 +30,22 @@ #include //http://librarymanager/All#SparkFun_u-blox_GNSS_v3 SFE_UBLOX_GNSS_SERIAL myGNSS; -// Callback: newRAWX will be called when new RXM RAWX data arrives -// See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t -// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMRAWXcallback -// / _____ This _must_ be UBX_RXM_RAWX_data_t +// Callback: newSIG will be called when new NAV SIG data arrives +// See u-blox_structs.h for the full definition of UBX_NAV_SIG_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSIGcallback +// / _____ This _must_ be UBX_NAV_SIG_data_t // | / _____ You can use any name you like for the struct // | | / // | | | -void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct) +void newSIG(UBX_NAV_SIG_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(F("New NAV SIG data received. It contains ")); + Serial.print(ubxDataStruct->header.numSigs); // Print numSigs (Number of signals / 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.numSigs; block++) // For each block { char SV[14 + 4 + 4 + 256 + 1]; // Allocate space for sigId plus svId plus cno plus bars plus NULL switch (ubxDataStruct->blocks[block].gnssId) @@ -274,7 +272,7 @@ void setup() myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART1 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.setMeasurementRate(5000); //Produce one solution every five seconds (RAWX produces a _lot_ of data!) + myGNSS.setMeasurementRate(5000); //Produce one solution every five seconds (NAV SIG produces a _lot_ of data!) myGNSS.setVal8(UBLOX_CFG_SIGNAL_GPS_L5_ENA, 1); // Make sure the GPS L5 band is enabled (needed on the NEO-F9P) @@ -284,7 +282,7 @@ void setup() myGNSS.softwareResetGNSSOnly(); // Restart the GNSS to apply the L5 health override - myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX + myGNSS.setAutoNAVSIGcallbackPtr(&newSIG); // Enable automatic NAV SIG messages with callback to newSIG } void loop() diff --git a/keywords.txt b/keywords.txt index 6930897..6d665a3 100644 --- a/keywords.txt +++ b/keywords.txt @@ -45,6 +45,7 @@ UBX_NAV_PVAT_data_t KEYWORD1 UBX_NAV_TIMEUTC_data_t KEYWORD1 UBX_NAV_CLOCK_data_t KEYWORD1 UBX_NAV_SAT_data_t KEYWORD1 +UBX_NAV_SIG_data_t KEYWORD1 UBX_NAV_SVIN_data_t KEYWORD1 UBX_NAV_RELPOSNED_data_t KEYWORD1 UBX_NAV_TIMELS_data_t KEYWORD1 @@ -441,6 +442,15 @@ assumeAutoNAVSAT KEYWORD2 flushNAVSAT KEYWORD2 logNAVSAT KEYWORD2 +getNAVSIG KEYWORD2 +setAutoNAVSIG KEYWORD2 +setAutoNAVSIGrate KEYWORD2 +setAutoNAVSIGcallback KEYWORD2 +setAutoNAVSIGcallbackPtr KEYWORD2 +assumeAutoNAVSIG KEYWORD2 +flushNAVSIG KEYWORD2 +logNAVSIG KEYWORD2 + getRELPOSNED KEYWORD2 setAutoRELPOSNED KEYWORD2 setAutoRELPOSNEDrate KEYWORD2 @@ -923,6 +933,7 @@ UBX_NAV_PVAT LITERAL1 UBX_NAV_RELPOSNED LITERAL1 UBX_NAV_RESETODO LITERAL1 UBX_NAV_SAT LITERAL1 +UBX_NAV_SIG LITERAL1 UBX_NAV_SBAS LITERAL1 UBX_NAV_SIG LITERAL1 UBX_NAV_SLAS LITERAL1 diff --git a/library.properties b/library.properties index fb378ca..0495426 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS v3 -version=3.1.2 +version=3.1.3 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules

diff --git a/src/u-blox_GNSS.cpp b/src/u-blox_GNSS.cpp index f5c12b3..cbd21c6 100644 --- a/src/u-blox_GNSS.cpp +++ b/src/u-blox_GNSS.cpp @@ -329,6 +329,16 @@ void DevUBLOXGNSS::end(void) packetUBXNAVSAT = nullptr; } + if (packetUBXNAVSIG != nullptr) + { + if (packetUBXNAVSIG->callbackData != nullptr) + { + delete packetUBXNAVSIG->callbackData; + } + delete packetUBXNAVSIG; + packetUBXNAVSIG = nullptr; + } + if (packetUBXRXMPMP != nullptr) { if (packetUBXRXMPMP->callbackData != nullptr) @@ -1409,6 +1419,12 @@ bool DevUBLOXGNSS::autoLookup(uint8_t Class, uint8_t ID, uint16_t *maxSize) *maxSize = UBX_NAV_SAT_MAX_LEN; return (packetUBXNAVSAT != nullptr); } + else if (ID == UBX_NAV_SIG) + { + if (maxSize != nullptr) + *maxSize = UBX_NAV_SIG_MAX_LEN; + return (packetUBXNAVSIG != nullptr); + } #endif break; case UBX_CLASS_RXM: @@ -3868,6 +3884,49 @@ void DevUBLOXGNSS::processUBXpacket(ubxPacket *msg) } } } + else if (msg->id == UBX_NAV_SIG) // Note: length is variable + { + // Parse various byte fields into storage - but only if we have memory allocated for it + if (packetUBXNAVSIG != nullptr) + { + packetUBXNAVSIG->data.header.iTOW = extractLong(msg, 0); + packetUBXNAVSIG->data.header.version = extractByte(msg, 4); + packetUBXNAVSIG->data.header.numSigs = extractByte(msg, 5); + + // The NAV SIG message could potentially contain data for 255 signals. (numSigs is uint8_t. UBX_NAV_SIG_MAX_BLOCKS is 92) + for (uint16_t i = 0; (i < UBX_NAV_SIG_MAX_BLOCKS) && (i < ((uint16_t)packetUBXNAVSIG->data.header.numSigs)) && ((i * 16) < (msg->len - 8)); i++) + { + uint16_t offset = (i * 16) + 8; + packetUBXNAVSIG->data.blocks[i].gnssId = extractByte(msg, offset + 0); + packetUBXNAVSIG->data.blocks[i].svId = extractByte(msg, offset + 1); + packetUBXNAVSIG->data.blocks[i].sigId = extractByte(msg, offset + 2); + packetUBXNAVSIG->data.blocks[i].freqId = extractByte(msg, offset + 3); + packetUBXNAVSIG->data.blocks[i].prRes = extractSignedInt(msg, offset + 4); + packetUBXNAVSIG->data.blocks[i].cno = extractByte(msg, offset + 6); + packetUBXNAVSIG->data.blocks[i].qualityInd = extractByte(msg, offset + 7); + packetUBXNAVSIG->data.blocks[i].corrSource = extractByte(msg, offset + 8); + packetUBXNAVSIG->data.blocks[i].ionoModel = extractByte(msg, offset + 9); + packetUBXNAVSIG->data.blocks[i].sigFlags.all = extractInt(msg, offset + 10); + } + + // Mark all datums as fresh (not read before) + packetUBXNAVSIG->moduleQueried = true; + + // Check if we need to copy the data for the callback + if ((packetUBXNAVSIG->callbackData != nullptr) // If RAM has been allocated for the copy of the data + && (packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale + { + memcpy(&packetUBXNAVSIG->callbackData->header.iTOW, &packetUBXNAVSIG->data.header.iTOW, sizeof(UBX_NAV_SIG_data_t)); + packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid = true; + } + + // Check if we need to copy the data into the file buffer + if (packetUBXNAVSIG->automaticFlags.flags.bits.addToFileBuffer) + { + addedToFileBuffer = storePacket(msg); + } + } + } #endif else if (msg->id == UBX_NAV_RELPOSNED && ((msg->len == UBX_NAV_RELPOSNED_LEN) || (msg->len == UBX_NAV_RELPOSNED_LEN_F9))) { @@ -5747,6 +5806,17 @@ void DevUBLOXGNSS::checkCallbacks(void) } packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } + + if (packetUBXNAVSIG != nullptr) // If RAM has been allocated for message storage + if (packetUBXNAVSIG->callbackData != nullptr) // If RAM has been allocated for the copy of the data + if (packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid == true) // If the copy of the data is valid + { + if (packetUBXNAVSIG->callbackPointerPtr != nullptr) // If the pointer to the callback has been defined + { + packetUBXNAVSIG->callbackPointerPtr(packetUBXNAVSIG->callbackData); // Call the callback + } + packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + } #endif if (packetUBXNAVRELPOSNED != nullptr) // If RAM has been allocated for message storage @@ -12958,6 +13028,177 @@ void DevUBLOXGNSS::logNAVSAT(bool enabled) return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) packetUBXNAVSAT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; } + +// ***** NAV SIG automatic support + +// Signal information +// Returns true if commands was successful +bool DevUBLOXGNSS::getNAVSIG(uint16_t maxWait) +{ + if (packetUBXNAVSIG == nullptr) + initPacketUBXNAVSIG(); // Check that RAM has been allocated for the NAVSIG data + if (packetUBXNAVSIG == nullptr) // Bail if the RAM allocation failed + return (false); + + if (packetUBXNAVSIG->automaticFlags.flags.bits.automatic && packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate) + { + // The GPS is automatically reporting, we just check whether we got unread data + checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Don't overwrite the requested Class and ID + return packetUBXNAVSIG->moduleQueried; + } + else if (packetUBXNAVSIG->automaticFlags.flags.bits.automatic && !packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate) + { + // Someone else has to call checkUblox for us... + return (false); + } + else + { + // The GPS is not automatically reporting NAVSIG so we have to poll explicitly + packetCfg.cls = UBX_CLASS_NAV; + packetCfg.id = UBX_NAV_SIG; + 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 NAVSIG message generation by the GNSS. This changes the way getNAVSIG +// works. +bool DevUBLOXGNSS::setAutoNAVSIG(bool enable, uint8_t layer, uint16_t maxWait) +{ + return setAutoNAVSIGrate(enable ? 1 : 0, true, layer, maxWait); +} + +// Enable or disable automatic NAVSIG message generation by the GNSS. This changes the way getNAVSIG +// works. +bool DevUBLOXGNSS::setAutoNAVSIG(bool enable, bool implicitUpdate, uint8_t layer, uint16_t maxWait) +{ + return setAutoNAVSIGrate(enable ? 1 : 0, implicitUpdate, layer, maxWait); +} + +// Enable or disable automatic NAV SAT message generation by the GNSS. This changes the way getNAVSIG +// works. +bool DevUBLOXGNSS::setAutoNAVSIGrate(uint8_t rate, bool implicitUpdate, uint8_t layer, uint16_t maxWait) +{ + if (packetUBXNAVSIG == nullptr) + initPacketUBXNAVSIG(); // Check that RAM has been allocated for the data + if (packetUBXNAVSIG == nullptr) // Only attempt this if RAM allocation was successful + return false; + + if (rate > 127) + rate = 127; + + uint32_t key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_I2C; + if (_commType == COMM_TYPE_SPI) + key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_SPI; + else if (_commType == COMM_TYPE_SERIAL) + { + if (!_UART2) + key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART1; + else + key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART2; + } + + bool ok = setVal8(key, rate, layer, maxWait); + if (ok) + { + packetUBXNAVSIG->automaticFlags.flags.bits.automatic = (rate > 0); + packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + packetUBXNAVSIG->moduleQueried = false; // Mark data as stale + return ok; +} + +// Enable automatic navigation message generation by the GNSS. +bool DevUBLOXGNSS::setAutoNAVSIGcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SIG_data_t *), uint8_t layer, uint16_t maxWait) +{ + // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually. + bool result = setAutoNAVSIG(true, false, layer, maxWait); + if (!result) + return (result); // Bail if setAuto failed + + if (packetUBXNAVSIG->callbackData == nullptr) // Check if RAM has been allocated for the callback copy + { + packetUBXNAVSIG->callbackData = new UBX_NAV_SIG_data_t; // Allocate RAM for the main struct + } + + if (packetUBXNAVSIG->callbackData == nullptr) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial.println(F("setAutoNAVSIGcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXNAVSIG->callbackPointerPtr = callbackPointerPtr; + return (true); +} + +// In case no config access to the GNSS is possible and NAV SAT is send cyclically already +// set config to suitable parameters +bool DevUBLOXGNSS::assumeAutoNAVSIG(bool enabled, bool implicitUpdate) +{ + if (packetUBXNAVSIG == nullptr) + initPacketUBXNAVSIG(); // Check that RAM has been allocated for the NAVSIG data + if (packetUBXNAVSIG == nullptr) // Bail if the RAM allocation failed + return (false); + + bool changes = packetUBXNAVSIG->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate != implicitUpdate; + if (changes) + { + packetUBXNAVSIG->automaticFlags.flags.bits.automatic = enabled; + packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; + } + return changes; +} + +// PRIVATE: Allocate RAM for packetUBXNAVSIG and initialize it +bool DevUBLOXGNSS::initPacketUBXNAVSIG() +{ + packetUBXNAVSIG = new UBX_NAV_SIG_t; // Allocate RAM for the main struct + if (packetUBXNAVSIG == nullptr) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial.println(F("initPacketUBXNAVSIG: RAM alloc failed!")); +#endif + return (false); + } + packetUBXNAVSIG->automaticFlags.flags.all = 0; + packetUBXNAVSIG->callbackPointerPtr = nullptr; + packetUBXNAVSIG->callbackData = nullptr; + packetUBXNAVSIG->moduleQueried = false; + return (true); +} + +// Mark all the data as read/stale +void DevUBLOXGNSS::flushNAVSIG() +{ + if (packetUBXNAVSIG == nullptr) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSIG->moduleQueried = false; // Mark all datums as stale (read before) +} + +// Log this data in file buffer +void DevUBLOXGNSS::logNAVSIG(bool enabled) +{ + if (packetUBXNAVSIG == nullptr) + return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!) + packetUBXNAVSIG->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled; +} #endif // ***** NAV RELPOSNED automatic support diff --git a/src/u-blox_GNSS.h b/src/u-blox_GNSS.h index 1e5e3a4..83a9ead 100644 --- a/src/u-blox_GNSS.h +++ b/src/u-blox_GNSS.h @@ -898,6 +898,15 @@ class DevUBLOXGNSS 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 getNAVSIG(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Query module for latest AssistNow Autonomous status and load global vars:. If autoNAVSIG is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new NAVSIG is available. + bool setAutoNAVSIG(bool enabled, uint8_t layer = VAL_LAYER_RAM_BBR, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Enable/disable automatic NAVSIG reports at the navigation frequency + bool setAutoNAVSIG(bool enabled, bool implicitUpdate, uint8_t layer = VAL_LAYER_RAM_BBR, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Enable/disable automatic NAVSIG 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 setAutoNAVSIGrate(uint8_t rate, bool implicitUpdate = true, uint8_t layer = VAL_LAYER_RAM_BBR, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Set the rate for automatic NAVSIG reports + bool setAutoNAVSIGcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SIG_data_t *), uint8_t layer = VAL_LAYER_RAM_BBR, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Enable automatic NAVSIG reports at the navigation frequency. Data is accessed from the callback. + bool assumeAutoNAVSIG(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and NAVSIG is send cyclically already + void flushNAVSIG(); // Mark all the NAVSIG data as read/stale + void logNAVSIG(bool enabled = true); // Log data to file buffer #endif bool getRELPOSNED(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Get Relative Positioning Information of the NED frame @@ -1364,6 +1373,7 @@ class DevUBLOXGNSS #ifndef SFE_UBLOX_DISABLE_RAWX_SFRBX_PMP_QZSS_SAT UBX_NAV_SAT_t *packetUBXNAVSAT = nullptr; // Pointer to struct. RAM will be allocated for this if/when necessary + UBX_NAV_SIG_t *packetUBXNAVSIG = nullptr; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_PMP_t *packetUBXRXMPMP = nullptr; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_PMP_message_t *packetUBXRXMPMPmessage = nullptr; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_QZSSL6_message_t *packetUBXRXMQZSSL6message = nullptr; // Pointer to struct. RAM will be allocated for this if/when necessary @@ -1479,6 +1489,7 @@ class DevUBLOXGNSS bool initPacketUBXNAVAOPSTATUS(); // Allocate RAM for packetUBXNAVAOPSTATUS and initialize it bool initPacketUBXNAVEOE(); // Allocate RAM for packetUBXNAVEOE and initialize it bool initPacketUBXNAVSAT(); // Allocate RAM for packetUBXNAVSAT and initialize it + bool initPacketUBXNAVSIG(); // Allocate RAM for packetUBXNAVSIG and initialize it bool initPacketUBXRXMPMP(); // Allocate RAM for packetUBXRXMPMP and initialize it bool initPacketUBXRXMPMPmessage(); // Allocate RAM for packetUBXRXMPMPRaw and initialize it bool initPacketUBXRXMQZSSL6message(); // Allocate RAM for packetUBXRXMQZSSL6raw and initialize it diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 0a7264f..1664e88 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1190,6 +1190,84 @@ typedef struct UBX_NAV_SAT_data_t *callbackData; } UBX_NAV_SAT_t; +// UBX-NAV-SIG (0x01 0x43): Signal information +// Note: length is variable +const uint8_t UBX_NAV_SIG_MAX_BLOCKS = 92; +const uint16_t UBX_NAV_SIG_MAX_LEN = 8 + (16 * UBX_NAV_SIG_MAX_BLOCKS); + +typedef struct +{ + uint32_t iTOW; // GPS time of week + uint8_t version; // Message version (0x00 for this version) + uint8_t numSigs; // Number of signals + uint8_t reserved0[2]; +} UBX_NAV_SIG_header_t; + +typedef struct +{ + uint8_t gnssId; // GNSS identifier + uint8_t svId; // Satellite identifier + uint8_t sigId; // New signal identifier + uint8_t freqId; // GLONASS frequency slot + int16_t prRes; // Pseudorange residual: m * 0.1 + uint8_t cno; // Carrier-to-noise density ratio: dB-Hz + uint8_t qualityInd; // 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 timesynchronized + uint8_t corrSource; // Correction source: + // 0 = no corrections + // 1 = SBAS corrections + // 2 = BeiDou corrections + // 3 = RTCM2 corrections + // 4 = RTCM3 OSR corrections + // 5 = RTCM3 SSR corrections + // 6 = QZSS SLAS corrections + // 7 = SPARTN corrections + // 8 = CLAS corrections + uint8_t ionoModel; // Ionospheric model used: + // 0 = no model + // 1 = Klobuchar model transmitted by GPS + // 2 = SBAS model + // 3 = Klobuchar model transmitted by BeiDou + // 8 = Iono delay derived from dual frequency observations + union + { + uint16_t all; + struct + { + uint16_t health : 1; // Signal health flag: 0 = unknown; 1 = healthy; 2 = unhealthy + uint16_t prSmoothed : 1; // 1 = Pseudorange has been smoothed + uint16_t prUsed : 1; // 1 = Pseudorange has been used for this signal + uint16_t crUsed : 1; // 1 = Carrier range has been used for this signal + uint16_t doUsed : 1; // 1 = Range rate (Doppler) has been used for this signal + uint16_t prCorrUsed : 1; // 1 = Pseudorange corrections have been used for this signal + uint16_t crCorrUsed : 1; // 1 = Carrier range corrections have been used for this signal + uint16_t doCorrUsed : 1; // 1 = Range rate (Doppler) corrections have been usedfor this signal + uint16_t authStatus : 1; // Authentication status of the navigation data: 0 = Unknown; 1 = Authenticated + } bits; + } sigFlags; + uint8_t reserved1[4]; +} UBX_NAV_SIG_block_t; + +typedef struct +{ + UBX_NAV_SIG_header_t header; + UBX_NAV_SIG_block_t blocks[UBX_NAV_SIG_MAX_BLOCKS]; +} UBX_NAV_SIG_data_t; + +typedef struct +{ + ubxAutomaticFlags automaticFlags; + UBX_NAV_SIG_data_t data; + bool moduleQueried; + void (*callbackPointerPtr)(UBX_NAV_SIG_data_t *); + UBX_NAV_SIG_data_t *callbackData; +} UBX_NAV_SIG_t; + // UBX-NAV-SVIN (0x01 0x3B): Survey-in data const uint16_t UBX_NAV_SVIN_LEN = 40;