From e35376f2e6f39b91627038d216438c7b8b38a92b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 17 Mar 2022 18:25:12 +0000 Subject: [PATCH] Add support for UBX-RXM-COR --- keywords.txt | 5 + src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 87 ++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 4 + src/u-blox_structs.h | 104 +++++++++++++++---- 4 files changed, 178 insertions(+), 22 deletions(-) diff --git a/keywords.txt b/keywords.txt index 9e34ac0..5e187b2 100644 --- a/keywords.txt +++ b/keywords.txt @@ -40,6 +40,7 @@ UBX_NAV_AOPSTATUS_data_t KEYWORD1 UBX_RXM_PMP_data_t KEYWORD1 UBX_RXM_PMP_message_data_t KEYWORD1 +UBX_RXM_COR_data_t KEYWORD1 UBX_RXM_SFRBX_data_t KEYWORD1 UBX_RXM_RAWX_data_t KEYWORD1 @@ -393,6 +394,8 @@ logAOPSTATUS KEYWORD2 setRXMPMPcallbackPtr KEYWORD2 setRXMPMPmessageCallbackPtr KEYWORD2 +setRXMCORcallbackPtr KEYWORD2 + getRXMSFRBX KEYWORD2 setAutoRXMSFRBX KEYWORD2 setAutoRXMSFRBXrate KEYWORD2 @@ -772,6 +775,8 @@ UBX_NAV_TIMELS LITERAL1 UBX_NAV_VELECEF LITERAL1 UBX_NAV_VELNED LITERAL1 +UBX_RXM_PMP LITERAL1 +UBX_RXM_COR LITERAL1 UBX_RXM_RAWX LITERAL1 UBX_RXM_SFRBX LITERAL1 UBX_RXM_SPARTN LITERAL1 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index dd36b24..1c42dad 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -294,6 +294,16 @@ void SFE_UBLOX_GNSS::end(void) packetUBXRXMPMPmessage = NULL; // Redundant? } + if (packetUBXRXMCOR != NULL) + { + if (packetUBXRXMCOR->callbackData != NULL) + { + delete packetUBXRXMCOR->callbackData; + } + delete packetUBXRXMCOR; + packetUBXRXMCOR = NULL; // Redundant? + } + if (packetUBXRXMSFRBX != NULL) { if (packetUBXRXMSFRBX->callbackData != NULL) @@ -1333,6 +1343,10 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) if ((packetUBXRXMPMP != NULL) || (packetUBXRXMPMPmessage != NULL)) result = true; break; + case UBX_RXM_COR: + if (packetUBXRXMCOR != NULL) + result = true; + break; } } break; @@ -1504,6 +1518,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID) case UBX_RXM_PMP: maxSize = UBX_RXM_PMP_MAX_LEN; break; + case UBX_RXM_COR: + maxSize = UBX_RXM_COR_LEN; + break; } } break; @@ -3772,6 +3789,22 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid } } + else if (msg->id == UBX_RXM_COR) + { + // Parse various byte fields into storage - but only if we have memory allocated for it + if ((packetUBXRXMCOR != NULL) && (packetUBXRXMCOR->callbackData != NULL) + //&& (packetUBXRXMCOR->automaticFlags.flags.bits.callbackCopyValid == false) // <=== Uncomment this line to prevent new data from overwriting 'old' + ) + { + packetUBXRXMCOR->callbackData->version = extractByte(msg, 0); + packetUBXRXMCOR->callbackData->ebno = extractByte(msg, 1); + packetUBXRXMCOR->callbackData->statusInfo.all = extractLong(msg, 4); + packetUBXRXMCOR->callbackData->msgType = extractInt(msg, 8); + packetUBXRXMCOR->callbackData->msgSubType = extractInt(msg, 10); + + packetUBXRXMCOR->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid + } + } else if (msg->id == UBX_RXM_SFRBX) // Note: length is variable // Note: on protocol version 17: numWords is (0..16) @@ -5359,6 +5392,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } + if ((packetUBXRXMCOR != NULL) // If RAM has been allocated for message storage + && (packetUBXRXMCOR->callbackData != NULL) // If RAM has been allocated for the copy of the data + && (packetUBXRXMCOR->callbackPointerPtr != NULL) // If the pointer to the callback has been defined + && (packetUBXRXMCOR->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + { + // if (_printDebug == true) + // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM COR")); + packetUBXRXMCOR->callbackPointerPtr(packetUBXRXMCOR->callbackData); // Call the callback + packetUBXRXMCOR->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 @@ -12316,6 +12360,49 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMPMPmessage() return (true); } +bool SFE_UBLOX_GNSS::setRXMCORcallbackPtr(void (*callbackPointer)(UBX_RXM_COR_data_t *)) +{ + if (packetUBXRXMCOR == NULL) + initPacketUBXRXMCOR(); // Check that RAM has been allocated for the data + if (packetUBXRXMCOR == NULL) // Only attempt this if RAM allocation was successful + return false; + + if (packetUBXRXMCOR->callbackData == NULL) // Check if RAM has been allocated for the callback copy + { + packetUBXRXMCOR->callbackData = new UBX_RXM_COR_data_t; // Allocate RAM for the main struct + } + + if (packetUBXRXMCOR->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("setAutoRXMCORcallbackPtr: RAM alloc failed!")); +#endif + return (false); + } + + packetUBXRXMCOR->callbackPointerPtr = callbackPointer; + return (true); +} + +// PRIVATE: Allocate RAM for packetUBXRXMCOR and initialize it +bool SFE_UBLOX_GNSS::initPacketUBXRXMCOR() +{ + packetUBXRXMCOR = new UBX_RXM_COR_t; // Allocate RAM for the main struct + if (packetUBXRXMCOR == NULL) + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + _debugSerial->println(F("initPacketUBXRXMCOR: RAM alloc failed!")); +#endif + return (false); + } + packetUBXRXMCOR->automaticFlags.flags.all = 0; + packetUBXRXMCOR->callbackPointerPtr = NULL; + packetUBXRXMCOR->callbackData = NULL; + return (true); +} + // ***** RXM SFRBX automatic support bool SFE_UBLOX_GNSS::getRXMSFRBX(uint16_t maxWait) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 45c4594..7797409 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1159,6 +1159,8 @@ public: 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 setRXMCORcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_COR_data_t *)); // RXM COR + 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 @@ -1512,6 +1514,7 @@ public: 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_COR_t *packetUBXRXMCOR = 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 @@ -1610,6 +1613,7 @@ private: 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 initPacketUBXRXMCOR(); // Allocate RAM for packetUBXRXMCOR 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 diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 3bef638..321bf53 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1484,6 +1484,66 @@ typedef struct UBX_RXM_RAWX_data_t *callbackData; } UBX_RXM_RAWX_t; +// UBX-RXM-COR (0x02 0x34): Differential correction input status +const uint16_t UBX_RXM_COR_LEN = 12; + +typedef struct +{ + uint8_t version; // Message version (0x01 for this version) + uint8_t ebno; // Energy per bit to noise power spectral density ratio (Eb/N0): 2^-3 dB + // 0: unknown. Reported only for protocol UBX-RXM-PMP (SPARTN) to monitor signal quality. + uint8_t reserved0[2]; // Reserved + union + { + uint32_t all; + struct + { + uint32_t protocol : 5; // Input correction data protocol: + // 0: Unknown + // 1: RTCM3 + // 2: SPARTN (Secure Position Augmentation for Real Time Navigation) + // 29: UBX-RXM-PMP (SPARTN) + // 30: UBX-RXM-QZSSL6 + uint32_t errStatus : 2; // Error status of the received correction message content based on possibly available error codes or checksums: + // 0: Unknown + // 1: Error-free + // 2: Erroneous + uint32_t msgUsed : 2; // Status of receiver using the input message: + // 0: Unknown + // 1: Not used + // 2: Used + uint32_t correctionId : 16; // Identifier for the correction stream: + // For RTCM 3: Reference station ID (DF003) of the received RTCM input message. + // Valid range 0-4095. + // For all other messages, reports 0xFFFF. + // For other correction protocols 0xFFFF. + uint32_t msgTypeValid : 1; // Validity of the msgType field. Set to False e.g. if the protocol does not define msgType. + uint32_t msgSubTypeValid : 1; // Validity of the msgSubType field. Set to False e.g. if the protocol does not define subtype for the msgType. + uint32_t msgInputHandle : 1; // Input handling support of the input message: + // 0: Receiver does not have input handling support for this message + // 1: Receiver has input handling support for this message + uint32_t msgEncrypted : 2; // Encryption status of the input message: + // 0: Unknown + // 1: Not encrypted + // 2: Encrypted + uint32_t msgDecrypted : 2; // Decryption status of the input message: + // 0: Unknown + // 1: Not decrypted + // 2: Successfully decrypted + } bits; + } statusInfo; + uint16_t msgType; // Message type + uint16_t msgSubType; // Message subtype +} UBX_RXM_COR_data_t; + +// The COR data can only be accessed via a callback. COR cannot be polled. +typedef struct +{ + ubxAutomaticFlags automaticFlags; + void (*callbackPointerPtr)(UBX_RXM_COR_data_t *); + UBX_RXM_COR_data_t *callbackData; +} UBX_RXM_COR_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_USER_DATA = 504; @@ -1702,36 +1762,36 @@ const uint16_t UBX_MON_HW_LEN = 60; typedef struct { - uint32_t pinSel; // Mask of pins set as peripheral/PIO - uint32_t pinBank; // Mask of pins set as bank A/B - uint32_t pinDir; // Mask of pins set as input/output - uint32_t pinVal; // Mask of pins value low/high + uint32_t pinSel; // Mask of pins set as peripheral/PIO + uint32_t pinBank; // Mask of pins set as bank A/B + uint32_t pinDir; // Mask of pins set as input/output + uint32_t pinVal; // Mask of pins value low/high uint16_t noisePerMS; // Noise level as measured by the GPS core - uint16_t agcCnt; // AGC monitor (counts SIGHI xor SIGLO, range 0 to 8191) - uint8_t aStatus; // Status of the antenna supervisor state machine (0=INIT, 1=DONTKNOW, 2=OK, 3=SHORT, 4=OPEN) - uint8_t aPower; // Current power status of antenna (0=OFF, 1=ON, 2=DONTKNOW) + uint16_t agcCnt; // AGC monitor (counts SIGHI xor SIGLO, range 0 to 8191) + uint8_t aStatus; // Status of the antenna supervisor state machine (0=INIT, 1=DONTKNOW, 2=OK, 3=SHORT, 4=OPEN) + uint8_t aPower; // Current power status of antenna (0=OFF, 1=ON, 2=DONTKNOW) union { uint8_t all; struct { - uint8_t rtcCalib : 1; // RTC is calibrated - uint8_t safeBoot : 1; // Safeboot mode (0 = inactive, 1 = active) + uint8_t rtcCalib : 1; // RTC is calibrated + uint8_t safeBoot : 1; // Safeboot mode (0 = inactive, 1 = active) uint8_t jammingState : 2; // Output from jamming/interference monitor (0 = unknown or feature disabled, // 1 = ok - no significant jamming, // 2 = warning - interference visible but fix OK, // 3 = critical - interference visible and no fix) - uint8_t xtalAbsent : 1; // RTC xtal has been determined to be absent + uint8_t xtalAbsent : 1; // RTC xtal has been determined to be absent } bits; } flags; - uint8_t reserved1; // Reserved - uint32_t usedMask; // Mask of pins that are used by the virtual pin manager - uint8_t VP[17]; // Array of pin mappings for each of the 17 physical pins - uint8_t jamInd; // CW jamming indicator, scaled (0 = no CW jamming, 255 = strong CW jamming) + uint8_t reserved1; // Reserved + uint32_t usedMask; // Mask of pins that are used by the virtual pin manager + uint8_t VP[17]; // Array of pin mappings for each of the 17 physical pins + uint8_t jamInd; // CW jamming indicator, scaled (0 = no CW jamming, 255 = strong CW jamming) uint8_t reserved2[2]; // Reserved - uint32_t pinIrq; // Mask of pins value using the PIO Irq - uint32_t pullH; // Mask of pins value using the PIO pull high resistor - uint8_t pullL; // Mask of pins value using the PIO pull low resistor + uint32_t pinIrq; // Mask of pins value using the PIO Irq + uint32_t pullH; // Mask of pins value using the PIO pull high resistor + uint8_t pullL; // Mask of pins value using the PIO pull low resistor } UBX_MON_HW_data_t; // UBX-MON-HW2 (0x0A 0x0B): Extended hardware status @@ -1739,15 +1799,15 @@ const uint16_t UBX_MON_HW2_LEN = 28; typedef struct { - int8_t ofsI; // Imbalance of I-part of complex signal, scaled (-128 = max. negative imbalance, 127 = max. positive imbalance) - uint8_t magI; // Magnitude of I-part of complex signal, scaled (0 = no signal, 255 = max. magnitude) - int8_t ofsQ; // Imbalance of Q-part of complex signal, scaled (-128 = max. negative imbalance, 127 = max. positive imbalance) - uint8_t magQ; // Magnitude of Q-part of complex signal, scaled (0 = no signal, 255 = max. magnitude) + int8_t ofsI; // Imbalance of I-part of complex signal, scaled (-128 = max. negative imbalance, 127 = max. positive imbalance) + uint8_t magI; // Magnitude of I-part of complex signal, scaled (0 = no signal, 255 = max. magnitude) + int8_t ofsQ; // Imbalance of Q-part of complex signal, scaled (-128 = max. negative imbalance, 127 = max. positive imbalance) + uint8_t magQ; // Magnitude of Q-part of complex signal, scaled (0 = no signal, 255 = max. magnitude) uint8_t cfgSource; // Source of low-level configuration (114 = ROM, 111 = OTP, 112 = config pins, 102 = flash image) uint8_t reserved0[3]; uint32_t lowLevCfg; // Low-level configuration (obsolete for protocol versions greater than 15.00) uint8_t reserved1[8]; - uint32_t postStatus; // POST status word + uint32_t postStatus; // POST status word uint8_t reserved2[4]; // Reserved } UBX_MON_HW2_data_t;