@@ -622,6 +622,16 @@ void DevUBLOXGNSS::end(void)
622622 }
623623#endif
624624
625+ if (storageRTCM1005 != nullptr)
626+ {
627+ if (storageRTCM1005->callbackData != nullptr)
628+ {
629+ delete storageRTCM1005->callbackData;
630+ }
631+ delete storageRTCM1005;
632+ storageRTCM1005 = nullptr;
633+ }
634+
625635 if (sfe_ublox_ubx_logging_list_head != nullptr)
626636 {
627637 while (sfe_ublox_ubx_logging_list_head->next != nullptr)
@@ -2168,6 +2178,35 @@ void DevUBLOXGNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t req
21682178 // If there is space in the RTCM buffer, store the data there too
21692179 if (rtcmBufferSpaceAvailable() >= _storageRTCM->messageLength + 6)
21702180 storeRTCMBytes(_storageRTCM->dataMessage, _storageRTCM->messageLength + 6);
2181+
2182+ // Check "Auto" RTCM
2183+ if ((messageType == 1005) && (_storageRTCM->messageLength == RTCM_1005_MSG_LEN_BYTES) && (storageRTCM1005 != nullptr))
2184+ {
2185+ storageRTCM1005->data.MessageNumber = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 0, 12);
2186+ storageRTCM1005->data.ReferenceStationID = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 12, 12);
2187+ storageRTCM1005->data.ITRFRealizationYear = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 24, 6);
2188+ storageRTCM1005->data.GPSIndicator = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 30, 1);
2189+ storageRTCM1005->data.GLONASSIndicator = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 31, 1);
2190+ storageRTCM1005->data.GalileoIndicator = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 32, 1);
2191+ storageRTCM1005->data.ReferenceStationIndicator = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 33, 1);
2192+ storageRTCM1005->data.AntennaReferencePointECEFX = extractSignedBits64(&_storageRTCM->dataMessage[3], 34, 38);
2193+ storageRTCM1005->data.SingleReceiverOscillatorIndicator = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 72, 1);
2194+ storageRTCM1005->data.Reserved = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 73, 1);
2195+ storageRTCM1005->data.AntennaReferencePointECEFY = extractSignedBits64(&_storageRTCM->dataMessage[3], 74, 38);
2196+ storageRTCM1005->data.QuarterCycleIndicator = extractUnsignedBits16(&_storageRTCM->dataMessage[3], 112, 2);
2197+ storageRTCM1005->data.AntennaReferencePointECEFY = extractSignedBits64(&_storageRTCM->dataMessage[3], 114, 38);
2198+
2199+ storageRTCM1005->automaticFlags.flags.bits.dataValid = 1; // Mark the data as valid and unread
2200+ storageRTCM1005->automaticFlags.flags.bits.dataRead = 0;
2201+
2202+ if (storageRTCM1005->callbackData != nullptr) // Should we copy the data for the callback?
2203+ if (storageRTCM1005->callbackPointerPtr != nullptr) // Has the callback been defined?
2204+ if (storageRTCM1005->automaticFlags.flags.bits.callbackDataValid == 0) // Only overwrite the callback copy if it has been read
2205+ {
2206+ memcpy(storageRTCM1005->callbackData, &_storageRTCM->dataMessage[3], RTCM_1005_MSG_LEN_BYTES);
2207+ storageRTCM1005->automaticFlags.flags.bits.callbackDataValid = 1;
2208+ }
2209+ }
21712210 }
21722211 else
21732212 {
@@ -15706,6 +15745,83 @@ void DevUBLOXGNSS::crc24q(uint8_t incoming, uint32_t *checksum)
1570615745
1570715746#endif
1570815747
15748+ // Return the most recent RTCM 1005: 0 = no data, 1 = stale data, 2 = fresh data
15749+ uint8_t DevUBLOXGNSS::getLatestRTCM1005(RTCM_1005_data_t *data)
15750+ {
15751+ if (!initStorageRTCM())
15752+ return 0;
15753+ if (storageRTCM1005 == nullptr)
15754+ initStorageRTCM1005(); // Check that RAM has been allocated for the message
15755+ if (storageRTCM1005 == nullptr) // Bail if the RAM allocation failed
15756+ return 0;
15757+
15758+ checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Don't overwrite the requested Class and ID
15759+
15760+ uint8_t result = 0;
15761+ if (storageRTCM1005->automaticFlags.flags.bits.dataValid == 1) // Is the copy valid?
15762+ {
15763+ result = 1;
15764+ if (storageRTCM1005->automaticFlags.flags.bits.dataRead == 0) // Has the data already been read?
15765+ {
15766+ result = 2;
15767+ storageRTCM1005->automaticFlags.flags.bits.dataRead = 1; // Mark the data as read
15768+ }
15769+ }
15770+
15771+ return (result);
15772+ }
15773+
15774+ bool DevUBLOXGNSS::setRTCM1005callbackPtr(void (*callbackPointerPtr)(RTCM_1005_data_t *))
15775+ {
15776+ if (!initStorageRTCM())
15777+ return false;
15778+ if (storageRTCM1005 == nullptr)
15779+ initStorageRTCM1005(); // Check that RAM has been allocated for the message
15780+ if (storageRTCM1005 == nullptr) // Bail if the RAM allocation failed
15781+ return (false);
15782+
15783+ if (storageRTCM1005->callbackData == nullptr) // Check if RAM has been allocated for the callback copy
15784+ {
15785+ storageRTCM1005->callbackData = new RTCM_1005_data_t;
15786+ }
15787+
15788+ if (storageRTCM1005->callbackData == nullptr)
15789+ {
15790+ #ifndef SFE_UBLOX_REDUCED_PROG_MEM
15791+ if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
15792+ _debugSerial.println(F("setRTCM1005callbackPtr: RAM alloc failed!"));
15793+ #endif
15794+ return (false);
15795+ }
15796+
15797+ storageRTCM1005->callbackPointerPtr = callbackPointerPtr;
15798+ return (true);
15799+ }
15800+
15801+ // Private: allocate RAM for incoming RTCM 1005 messages and initialize it
15802+ bool DevUBLOXGNSS::initStorageRTCM1005()
15803+ {
15804+ if (storageRTCM1005 != nullptr) // Check if storage already exists
15805+ return true;
15806+
15807+ storageRTCM1005 = new RTCM_1005_t; // Allocate RAM for the main struct
15808+ if (storageRTCM1005 == nullptr)
15809+ {
15810+ #ifndef SFE_UBLOX_REDUCED_PROG_MEM
15811+ if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
15812+ _debugSerial.println(F("initStorageRTCM1005: RAM alloc failed!"));
15813+ #endif
15814+ return (false);
15815+ }
15816+
15817+ storageRTCM1005->callbackPointerPtr = nullptr; // Clear the callback pointers
15818+ storageRTCM1005->callbackData = nullptr;
15819+
15820+ storageRTCM1005->automaticFlags.flags.all = 0; // Mark the data as invalid/stale and unread
15821+
15822+ return (true);
15823+ }
15824+
1570915825// ***** CFG RATE Helper Functions
1571015826
1571115827// Set the rate at which the module will give us an updated navigation solution
@@ -17560,3 +17676,104 @@ double DevUBLOXGNSS::extractDouble(ubxPacket *msg, uint16_t spotToStart)
1756017676 converter.unsigned64 = extractLongLong(msg, spotToStart);
1756117677 return (converter.dbl);
1756217678}
17679+
17680+ // Given a pointer, extract an unsigned integer, starting at bit start with width
17681+ uint16_t DevUBLOXGNSS::extractUnsignedBits16(uint8_t *ptr, uint16_t start, uint16_t width)
17682+ {
17683+ uint16_t result = 0;
17684+ uint16_t count = 0;
17685+ uint8_t bitMask = 0x80;
17686+
17687+ // Loop until we reach the start bit
17688+ while (count < start)
17689+ {
17690+ bitMask >> 1; // Shift the bit mask
17691+ count++; // Increment the count
17692+ if (bitMask == 0) // Have we counted 8 bits?
17693+ {
17694+ ptr++; // Point to the next byte
17695+ bitMask = 0x80; // Reset the bit mask
17696+ }
17697+ }
17698+
17699+ // We have reached the start bit and ptr is pointing at the correct byte
17700+ // Now extract width bytes, incrementing ptr and shifting bitMask as we go
17701+ while (count < (start + width))
17702+ {
17703+ if (*ptr & bitMask) // Is the bit set?
17704+ result |= 1; // Set the corresponding bit in result
17705+
17706+ bitMask >> 1; // Shift the bit mask
17707+ count++; // Increment the count
17708+
17709+ if (bitMask == 0) // Have we counted 8 bits?
17710+ {
17711+ ptr++; // Point to the next byte
17712+ bitMask = 0x80; // Reset the bit mask
17713+ }
17714+
17715+ if (count < (start + width)) // Do we need to shift result?
17716+ result <<= 1; // Shift the result
17717+ }
17718+
17719+ return result;
17720+ }
17721+
17722+ // Given a pointer, extract a signed integer, starting at bit start with width
17723+ int64_t DevUBLOXGNSS::extractSignedBits64(uint8_t *ptr, uint16_t start, uint16_t width)
17724+ {
17725+
17726+ unsignedSigned64 result;
17727+ result.unsigned64 = 0;
17728+
17729+ unsignedSigned64 twosComplement;
17730+ twosComplement.unsigned64 = 0xFFFFFFFFFFFFFFFF;
17731+
17732+ bool isNegative;
17733+
17734+ uint16_t count = 0;
17735+ uint8_t bitMask = 0x80;
17736+
17737+ // Loop until we reach the start bit
17738+ while (count < start)
17739+ {
17740+ bitMask >> 1; // Shift the bit mask
17741+ count++; // Increment the count
17742+ if (bitMask == 0) // Have we counted 8 bits?
17743+ {
17744+ ptr++; // Point to the next byte
17745+ bitMask = 0x80; // Reset the bit mask
17746+ }
17747+ }
17748+
17749+ isNegative = *ptr & bitMask; // Record the first bit - indicates in the number is negative
17750+
17751+ // We have reached the start bit and ptr is pointing at the correct byte
17752+ // Now extract width bytes, incrementing ptr and shifting bitMask as we go
17753+ while (count < (start + width))
17754+ {
17755+ if (*ptr & bitMask) // Is the bit set?
17756+ result.unsigned64 |= 1; // Set the corresponding bit in result
17757+
17758+ bitMask >> 1; // Shift the bit mask
17759+ count++; // Increment the count
17760+ twosComplement.unsigned64 <<= 1; // Shift the two's complement mask
17761+
17762+ if (bitMask == 0) // Have we counted 8 bits?
17763+ {
17764+ ptr++; // Point to the next byte
17765+ bitMask = 0x80; // Reset the bit mask
17766+ }
17767+
17768+ if (count < (start + width)) // Do we need to shift result?
17769+ result.unsigned64 <<= 1; // Shift the result
17770+ }
17771+
17772+ // Handle negative number
17773+ if (isNegative)
17774+ result.unsigned64 |= twosComplement.unsigned64; // OR in the two's complement mask
17775+
17776+ return result.signed64;
17777+ }
17778+
17779+
0 commit comments