diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index df68993..1bd117c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -321,21 +321,11 @@ void SFE_UBLOX_GNSS::end(void) packetUBXRXMPMPmessage = NULL; // Redundant? } - if (packetUBXRXMQZSSL6 != NULL) - { - if (packetUBXRXMQZSSL6->callbackData != NULL) - { - delete packetUBXRXMQZSSL6->callbackData; - } - delete packetUBXRXMQZSSL6; - packetUBXRXMQZSSL6 = NULL; // Redundant? - } - if (packetUBXRXMQZSSL6message != NULL) { if (packetUBXRXMQZSSL6message->callbackData != NULL) { - delete packetUBXRXMQZSSL6message->callbackData; + delete [] packetUBXRXMQZSSL6message->callbackData; } delete packetUBXRXMQZSSL6message; packetUBXRXMQZSSL6message = NULL; // Redundant? @@ -1391,7 +1381,7 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID) result = true; break; case UBX_RXM_QZSSL6: - if ((packetUBXRXMQZSSL6 != NULL) || (packetUBXRXMQZSSL6message != NULL)) + if (packetUBXRXMQZSSL6message != NULL) result = true; break; case UBX_RXM_COR: @@ -3861,50 +3851,26 @@ 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. - // By default, new QZSSL6 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 ((packetUBXRXMQZSSL6 != NULL) && (packetUBXRXMQZSSL6->callbackData != NULL) - //&& (packetUBXRXMQZSSL6->automaticFlags.flags.bits.callbackCopyValid == false) // <=== Uncomment this line to prevent new data from overwriting 'old' - ) - { - packetUBXRXMQZSSL6->callbackData->version = extractByte(msg, 0); - packetUBXRXMQZSSL6->callbackData->svId = extractByte(msg, 1); - packetUBXRXMQZSSL6->callbackData->cno = extractInt(msg, 2); - packetUBXRXMQZSSL6->callbackData->timeTag = extractLong(msg, 4); - packetUBXRXMQZSSL6->callbackData->groupDelay = extractByte(msg, 8); - packetUBXRXMQZSSL6->callbackData->bitErrCorr = extractByte(msg, 9); - packetUBXRXMQZSSL6->callbackData->chInfo = extractInt(msg, 10); - packetUBXRXMQZSSL6->callbackData->reserved0[0] = extractByte(msg, 12); - packetUBXRXMQZSSL6->callbackData->reserved0[0] = extractByte(msg, 13); - for (uint16_t i = 0; (i < UBX_RXM_QZSSL6_DATALEN); i++) - { - packetUBXRXMQZSSL6->callbackData->msgBytes[i] = extractByte(msg, i + 14); + // Full QZSSL6 message, including Class, ID and checksum + for (int ch = 0; ch < UBX_RXM_QZSSL6_NUM_CHANNELS; ch ++) { + if (0 == (packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid & (1<callbackData[ch].sync1 = UBX_SYNCH_1; + packetUBXRXMQZSSL6message->callbackData[ch].sync2 = UBX_SYNCH_2; + packetUBXRXMQZSSL6message->callbackData[ch].cls = UBX_CLASS_RXM; + packetUBXRXMQZSSL6message->callbackData[ch].ID = UBX_RXM_QZSSL6; + packetUBXRXMQZSSL6message->callbackData[ch].lengthLSB = msg->len & 0xFF; + packetUBXRXMQZSSL6message->callbackData[ch].lengthMSB = msg->len >> 8; + + memcpy(packetUBXRXMQZSSL6message->callbackData[ch].payload, msg->payload, msg->len); + + packetUBXRXMQZSSL6message->callbackData[ch].checksumA = msg->checksumA; + packetUBXRXMQZSSL6message->callbackData[ch].checksumB = msg->checksumB; + + packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid |= (1 << ch); + break; // abort when added } - packetUBXRXMQZSSL6->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid - } - - // Full QZSSL6 message, including Class, ID and checksum - // By default, new QZSSL6 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 ((packetUBXRXMQZSSL6message != NULL) && (packetUBXRXMQZSSL6message->callbackData != NULL) - //&& (packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid == false) // <=== Uncomment this line to prevent new data from overwriting 'old' - ) - { - packetUBXRXMQZSSL6message->callbackData->sync1 = UBX_SYNCH_1; - packetUBXRXMQZSSL6message->callbackData->sync2 = UBX_SYNCH_2; - packetUBXRXMQZSSL6message->callbackData->cls = UBX_CLASS_RXM; - packetUBXRXMQZSSL6message->callbackData->ID = UBX_RXM_QZSSL6; - packetUBXRXMQZSSL6message->callbackData->lengthLSB = msg->len & 0xFF; - packetUBXRXMQZSSL6message->callbackData->lengthMSB = msg->len >> 8; - - memcpy(packetUBXRXMQZSSL6message->callbackData->payload, msg->payload, msg->len); - - packetUBXRXMQZSSL6message->callbackData->checksumA = msg->checksumA; - packetUBXRXMQZSSL6message->callbackData->checksumB = msg->checksumB; - - packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid - } + } } else if (msg->id == UBX_RXM_COR) { @@ -5521,26 +5487,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void) packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale } - if ((packetUBXRXMQZSSL6 != NULL) // If RAM has been allocated for message storage - && (packetUBXRXMQZSSL6->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMQZSSL6->callbackPointerPtr != NULL) // If the pointer to the callback has been defined - && (packetUBXRXMQZSSL6->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid + if ((packetUBXRXMQZSSL6message != NULL) && // If RAM has been allocated for message storage + (packetUBXRXMQZSSL6message->callbackData != NULL) && // If RAM has been allocated for the copy of the data + (packetUBXRXMQZSSL6message->callbackPointerPtr != NULL)) // If the pointer to the callback has been defined { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM QZSSL6")); - packetUBXRXMQZSSL6->callbackPointerPtr(packetUBXRXMQZSSL6->callbackData); // Call the callback - packetUBXRXMQZSSL6->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale - } - - if ((packetUBXRXMQZSSL6message != NULL) // If RAM has been allocated for message storage - && (packetUBXRXMQZSSL6message->callbackData != NULL) // If RAM has been allocated for the copy of the data - && (packetUBXRXMQZSSL6message->callbackPointerPtr != NULL) // If the pointer to the callback has been defined - && (packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid - { - // if (_printDebug == true) - // _debugSerial->println(F("checkCallbacks: calling callbackPtr for RXM QZSSL6 message")); - packetUBXRXMQZSSL6message->callbackPointerPtr(packetUBXRXMQZSSL6message->callbackData); // Call the callback - packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale + for (int ch = 0; ch < UBX_RXM_QZSSL6_NUM_CHANNELS; ch ++) { + if (packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid & (1 << ch)) // If the copy of the data is valid + { + packetUBXRXMQZSSL6message->callbackPointerPtr( &packetUBXRXMQZSSL6message->callbackData[ch] ); // Call the callback + } + } + packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale } if ((packetUBXRXMCOR != NULL) // If RAM has been allocated for message storage @@ -12661,50 +12618,6 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMPMPmessage() // ***** RXM QZSSL6 automatic support -// Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! -bool SFE_UBLOX_GNSS::setRXMQZSSL6callbackPtr(void (*callbackPointer)(UBX_RXM_QZSSL6_data_t *)) -{ - if (packetUBXRXMQZSSL6 == NULL) - initPacketUBXRXMQZSSL6(); // Check that RAM has been allocated for the data - if (packetUBXRXMQZSSL6 == NULL) // Only attempt this if RAM allocation was successful - return false; - - if (packetUBXRXMQZSSL6->callbackData == NULL) // Check if RAM has been allocated for the callback copy - { - packetUBXRXMQZSSL6->callbackData = new UBX_RXM_QZSSL6_data_t; // Allocate RAM for the main struct - } - - if (packetUBXRXMQZSSL6->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("setAutoRXMQZSSL6callbackPtr: RAM alloc failed!")); -#endif - return (false); - } - - packetUBXRXMQZSSL6->callbackPointerPtr = callbackPointer; - return (true); -} - -// PRIVATE: Allocate RAM for packetUBXRXMQZSSL6 and initialize it -bool SFE_UBLOX_GNSS::initPacketUBXRXMQZSSL6() -{ - packetUBXRXMQZSSL6 = new UBX_RXM_QZSSL6_t; // Allocate RAM for the main struct - if (packetUBXRXMQZSSL6 == NULL) - { -#ifndef SFE_UBLOX_REDUCED_PROG_MEM - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - _debugSerial->println(F("initPacketUBXRXMQZSSL6: RAM alloc failed!")); -#endif - return (false); - } - packetUBXRXMQZSSL6->automaticFlags.flags.all = 0; - packetUBXRXMQZSSL6->callbackPointerPtr = NULL; - packetUBXRXMQZSSL6->callbackData = NULL; - return (true); -} - // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! bool SFE_UBLOX_GNSS::setRXMQZSSL6messageCallbackPtr(void (*callbackPointer)(UBX_RXM_QZSSL6_message_data_t *)) { @@ -12715,7 +12628,7 @@ bool SFE_UBLOX_GNSS::setRXMQZSSL6messageCallbackPtr(void (*callbackPointer)(UBX_ if (packetUBXRXMQZSSL6message->callbackData == NULL) // Check if RAM has been allocated for the callback copy { - packetUBXRXMQZSSL6message->callbackData = new UBX_RXM_QZSSL6_message_data_t; // Allocate RAM for the main struct + packetUBXRXMQZSSL6message->callbackData = new UBX_RXM_QZSSL6_message_data_t[UBX_RXM_QZSSL6_NUM_CHANNELS]; // Allocate RAM for the main struct } if (packetUBXRXMQZSSL6message->callbackData == NULL) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index bad937c..d3ff385 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1168,7 +1168,6 @@ public: // Note: on the NEO-D9C, the UBX-RXM-QZSSL6 messages are enabled by default on all ports. // You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_I2C, 0) // The NEO-D9C does not support UBX-CFG-MSG - bool setRXMQZSSL6callbackPtr(void (*callbackPointerPtr)(UBX_RXM_QZSSL6_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack! bool setRXMQZSSL6messageCallbackPtr(void (*callbackPointerPtr)(UBX_RXM_QZSSL6_message_data_t *)); // Use this if you want all of the QZSSL6 message (including sync chars, checksum, etc.) to push to a GNSS bool setRXMCORcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_COR_data_t *)); // RXM COR @@ -1526,7 +1525,6 @@ 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_QZSSL6_t *packetUBXRXMQZSSL6 = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_RXM_QZSSL6_message_t *packetUBXRXMQZSSL6message = 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 diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index d9e4a3c..d427611 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1600,7 +1600,8 @@ typedef struct } UBX_RXM_PMP_message_t; // UBX-RXM-QZSSL6 (0x02 0x73): QZSS L6 raw data (D9C modules) -#define UBX_RXM_QZSSL6_DATALEN 250 +#define UBX_RXM_QZSSL6_NUM_CHANNELS 2 +const uint16_t UBX_RXM_QZSSL6_DATALEN = 250; const uint16_t UBX_RXM_QZSSL6_MAX_LEN = UBX_RXM_QZSSL6_DATALEN + 14; typedef struct @@ -1616,13 +1617,20 @@ typedef struct uint8_t msgBytes[UBX_RXM_QZSSL6_DATALEN]; // Bytes in a QZSS L6 message } UBX_RXM_QZSSL6_data_t; -// The QZSSL6 data can only be accessed via a callback. QZSSL6 cannot be polled. -typedef struct +struct ubxQZSSL6AutomaticFlags { - ubxAutomaticFlags automaticFlags; - void (*callbackPointerPtr)(UBX_RXM_QZSSL6_data_t *); - UBX_RXM_QZSSL6_data_t *callbackData; -} UBX_RXM_QZSSL6_t; + union + { + 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 callbackCopyValid : UBX_RXM_QZSSL6_NUM_CHANNELS; // Is the copies of the data structs used by the callback valid/fresh? + } bits; + } flags; +}; // Define a struct to hold the entire QZSSL6 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).