@@ -399,6 +399,16 @@ void DevUBLOXGNSS::end(void)
399
399
packetUBXTIMTM2 = nullptr;
400
400
}
401
401
402
+ if (packetUBXTIMTP != nullptr)
403
+ {
404
+ if (packetUBXTIMTP->callbackData != nullptr)
405
+ {
406
+ delete packetUBXTIMTP->callbackData;
407
+ }
408
+ delete packetUBXTIMTP;
409
+ packetUBXTIMTP = nullptr;
410
+ }
411
+
402
412
#ifndef SFE_UBLOX_DISABLE_ESF
403
413
if (packetUBXESFALG != nullptr)
404
414
{
@@ -1397,6 +1407,12 @@ bool DevUBLOXGNSS::autoLookup(uint8_t Class, uint8_t ID, uint16_t *maxSize)
1397
1407
*maxSize = UBX_TIM_TM2_LEN;
1398
1408
return (packetUBXTIMTM2 != nullptr);
1399
1409
}
1410
+ else if (ID == UBX_TIM_TP)
1411
+ {
1412
+ if (maxSize != nullptr)
1413
+ *maxSize = UBX_TIM_TP_LEN;
1414
+ return (packetUBXTIMTP != nullptr);
1415
+ }
1400
1416
break;
1401
1417
case UBX_CLASS_ESF:
1402
1418
#ifndef SFE_UBLOX_DISABLE_ESF
@@ -4158,6 +4174,36 @@ void DevUBLOXGNSS::processUBXpacket(ubxPacket *msg)
4158
4174
}
4159
4175
}
4160
4176
}
4177
+ else if (msg->id == UBX_TIM_TP && msg->len == UBX_TIM_TP_LEN)
4178
+ {
4179
+ // Parse various byte fields into storage - but only if we have memory allocated for it
4180
+ if (packetUBXTIMTP != nullptr)
4181
+ {
4182
+ packetUBXTIMTP->data.towMS = extractLong(msg, 0);
4183
+ packetUBXTIMTP->data.towSubMS = extractLong(msg, 4);
4184
+ packetUBXTIMTP->data.qErr = extractSignedLong(msg, 8);
4185
+ packetUBXTIMTP->data.week = extractInt(msg, 12);
4186
+ packetUBXTIMTP->data.flags.all = extractByte(msg, 14);
4187
+ packetUBXTIMTP->data.refInfo.all = extractByte(msg, 15);
4188
+
4189
+ // Mark all datums as fresh (not read before)
4190
+ packetUBXTIMTP->moduleQueried.moduleQueried.all = 0xFFFFFFFF;
4191
+
4192
+ // Check if we need to copy the data for the callback
4193
+ if ((packetUBXTIMTP->callbackData != nullptr) // If RAM has been allocated for the copy of the data
4194
+ && (packetUBXTIMTP->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale
4195
+ {
4196
+ memcpy(&packetUBXTIMTP->callbackData->towMS, &packetUBXTIMTP->data.towMS, sizeof(UBX_TIM_TP_data_t));
4197
+ packetUBXTIMTP->automaticFlags.flags.bits.callbackCopyValid = true;
4198
+ }
4199
+
4200
+ // Check if we need to copy the data into the file buffer
4201
+ if (packetUBXTIMTP->automaticFlags.flags.bits.addToFileBuffer)
4202
+ {
4203
+ addedToFileBuffer = storePacket(msg);
4204
+ }
4205
+ }
4206
+ }
4161
4207
break;
4162
4208
#ifndef SFE_UBLOX_DISABLE_ESF
4163
4209
case UBX_CLASS_ESF:
@@ -5642,6 +5688,17 @@ void DevUBLOXGNSS::checkCallbacks(void)
5642
5688
packetUBXTIMTM2->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale
5643
5689
}
5644
5690
5691
+ if (packetUBXTIMTP != nullptr) // If RAM has been allocated for message storage
5692
+ if (packetUBXTIMTP->callbackData != nullptr) // If RAM has been allocated for the copy of the data
5693
+ if (packetUBXTIMTP->automaticFlags.flags.bits.callbackCopyValid == true) // If the copy of the data is valid
5694
+ {
5695
+ if (packetUBXTIMTP->callbackPointerPtr != nullptr) // If the pointer to the callback has been defined
5696
+ {
5697
+ packetUBXTIMTP->callbackPointerPtr(packetUBXTIMTP->callbackData); // Call the callback
5698
+ }
5699
+ packetUBXTIMTP->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale
5700
+ }
5701
+
5645
5702
#ifndef SFE_UBLOX_DISABLE_ESF
5646
5703
if (packetUBXESFALG != nullptr) // If RAM has been allocated for message storage
5647
5704
if (packetUBXESFALG->callbackData != nullptr) // If RAM has been allocated for the copy of the data
@@ -13010,6 +13067,172 @@ void DevUBLOXGNSS::logTIMTM2(bool enabled)
13010
13067
packetUBXTIMTM2->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled;
13011
13068
}
13012
13069
13070
+ // ***** TIM TP automatic support
13071
+
13072
+ bool DevUBLOXGNSS::getTIMTP(uint16_t maxWait)
13073
+ {
13074
+ if (packetUBXTIMTP == nullptr)
13075
+ initPacketUBXTIMTP(); // Check that RAM has been allocated for the TP data
13076
+ if (packetUBXTIMTP == nullptr) // Bail if the RAM allocation failed
13077
+ return (false);
13078
+
13079
+ if (packetUBXTIMTP->automaticFlags.flags.bits.automatic && packetUBXTIMTP->automaticFlags.flags.bits.implicitUpdate)
13080
+ {
13081
+ // The GPS is automatically reporting, we just check whether we got unread data
13082
+ checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Don't overwrite the requested Class and ID
13083
+ return packetUBXTIMTP->moduleQueried.moduleQueried.bits.all;
13084
+ }
13085
+ else if (packetUBXTIMTP->automaticFlags.flags.bits.automatic && !packetUBXTIMTP->automaticFlags.flags.bits.implicitUpdate)
13086
+ {
13087
+ // Someone else has to call checkUblox for us...
13088
+ return (false);
13089
+ }
13090
+ else
13091
+ {
13092
+ // The GPS is not automatically reporting navigation position so we have to poll explicitly
13093
+ packetCfg.cls = UBX_CLASS_TIM;
13094
+ packetCfg.id = UBX_TIM_TP;
13095
+ packetCfg.len = 0;
13096
+ packetCfg.startingSpot = 0;
13097
+
13098
+ // The data is parsed as part of processing the response
13099
+ sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait);
13100
+
13101
+ if (retVal == SFE_UBLOX_STATUS_DATA_RECEIVED)
13102
+ return (true);
13103
+
13104
+ if (retVal == SFE_UBLOX_STATUS_DATA_OVERWRITTEN)
13105
+ {
13106
+ return (true);
13107
+ }
13108
+
13109
+ return (false);
13110
+ }
13111
+ }
13112
+
13113
+ // Enable or disable automatic message generation by the GNSS. This changes the way getTIMTP works.
13114
+ bool DevUBLOXGNSS::setAutoTIMTP(bool enable, uint8_t layer, uint16_t maxWait)
13115
+ {
13116
+ return setAutoTIMTPrate(enable ? 1 : 0, true, layer, maxWait);
13117
+ }
13118
+
13119
+ // Enable or disable automatic message generation by the GNSS. This changes the way getTIMTP works.
13120
+ bool DevUBLOXGNSS::setAutoTIMTP(bool enable, bool implicitUpdate, uint8_t layer, uint16_t maxWait)
13121
+ {
13122
+ return setAutoTIMTPrate(enable ? 1 : 0, implicitUpdate, layer, maxWait);
13123
+ }
13124
+
13125
+ // Enable or disable automatic message generation by the GNSS. This changes the way getTIMTP works.
13126
+ bool DevUBLOXGNSS::setAutoTIMTPrate(uint8_t rate, bool implicitUpdate, uint8_t layer, uint16_t maxWait)
13127
+ {
13128
+ if (packetUBXTIMTP == nullptr)
13129
+ initPacketUBXTIMTP(); // Check that RAM has been allocated for the data
13130
+ if (packetUBXTIMTP == nullptr) // Only attempt this if RAM allocation was successful
13131
+ return false;
13132
+
13133
+ if (rate > 127)
13134
+ rate = 127;
13135
+
13136
+ uint32_t key = UBLOX_CFG_MSGOUT_UBX_TIM_TP_I2C;
13137
+ if (_commType == COMM_TYPE_SPI)
13138
+ key = UBLOX_CFG_MSGOUT_UBX_TIM_TP_SPI;
13139
+ else if (_commType == COMM_TYPE_SERIAL)
13140
+ {
13141
+ if (!_UART2)
13142
+ key = UBLOX_CFG_MSGOUT_UBX_TIM_TP_UART1;
13143
+ else
13144
+ key = UBLOX_CFG_MSGOUT_UBX_TIM_TP_UART2;
13145
+ }
13146
+
13147
+ bool ok = setVal8(key, rate, layer, maxWait);
13148
+ if (ok)
13149
+ {
13150
+ packetUBXTIMTP->automaticFlags.flags.bits.automatic = (rate > 0);
13151
+ packetUBXTIMTP->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
13152
+ }
13153
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.all = false;
13154
+ return ok;
13155
+ }
13156
+
13157
+ // Enable automatic message generation by the GNSS.
13158
+ bool DevUBLOXGNSS::setAutoTIMTPcallbackPtr(void (*callbackPointerPtr)(UBX_TIM_TP_data_t *), uint8_t layer, uint16_t maxWait)
13159
+ {
13160
+ // Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually.
13161
+ bool result = setAutoTIMTP(true, false, layer, maxWait);
13162
+ if (!result)
13163
+ return (result); // Bail if setAuto failed
13164
+
13165
+ if (packetUBXTIMTP->callbackData == nullptr) // Check if RAM has been allocated for the callback copy
13166
+ {
13167
+ packetUBXTIMTP->callbackData = new UBX_TIM_TP_data_t; // Allocate RAM for the main struct
13168
+ }
13169
+
13170
+ if (packetUBXTIMTP->callbackData == nullptr)
13171
+ {
13172
+ #ifndef SFE_UBLOX_REDUCED_PROG_MEM
13173
+ if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
13174
+ _debugSerial.println(F("setAutoTIMTPcallbackPtr: RAM alloc failed!"));
13175
+ #endif
13176
+ return (false);
13177
+ }
13178
+
13179
+ packetUBXTIMTP->callbackPointerPtr = callbackPointerPtr;
13180
+ return (true);
13181
+ }
13182
+
13183
+ // In case no config access to the GNSS is possible and TIM TP is send cyclically already
13184
+ // set config to suitable parameters
13185
+ bool DevUBLOXGNSS::assumeAutoTIMTP(bool enabled, bool implicitUpdate)
13186
+ {
13187
+ if (packetUBXTIMTP == nullptr)
13188
+ initPacketUBXTIMTP(); // Check that RAM has been allocated for the data
13189
+ if (packetUBXTIMTP == nullptr) // Only attempt this if RAM allocation was successful
13190
+ return false;
13191
+
13192
+ bool changes = packetUBXTIMTP->automaticFlags.flags.bits.automatic != enabled || packetUBXTIMTP->automaticFlags.flags.bits.implicitUpdate != implicitUpdate;
13193
+ if (changes)
13194
+ {
13195
+ packetUBXTIMTP->automaticFlags.flags.bits.automatic = enabled;
13196
+ packetUBXTIMTP->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
13197
+ }
13198
+ return changes;
13199
+ }
13200
+
13201
+ // PRIVATE: Allocate RAM for packetUBXTIMTP and initialize it
13202
+ bool DevUBLOXGNSS::initPacketUBXTIMTP()
13203
+ {
13204
+ packetUBXTIMTP = new UBX_TIM_TP_t; // Allocate RAM for the main struct
13205
+ if (packetUBXTIMTP == nullptr)
13206
+ {
13207
+ #ifndef SFE_UBLOX_REDUCED_PROG_MEM
13208
+ if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
13209
+ _debugSerial.println(F("initPacketUBXTIMTP: RAM alloc failed!"));
13210
+ #endif
13211
+ return (false);
13212
+ }
13213
+ packetUBXTIMTP->automaticFlags.flags.all = 0;
13214
+ packetUBXTIMTP->callbackPointerPtr = nullptr;
13215
+ packetUBXTIMTP->callbackData = nullptr;
13216
+ packetUBXTIMTP->moduleQueried.moduleQueried.all = 0;
13217
+ return (true);
13218
+ }
13219
+
13220
+ // Mark all the data as read/stale
13221
+ void DevUBLOXGNSS::flushTIMTP()
13222
+ {
13223
+ if (packetUBXTIMTP == nullptr)
13224
+ return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
13225
+ packetUBXTIMTP->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before)
13226
+ }
13227
+
13228
+ // Log this data in file buffer
13229
+ void DevUBLOXGNSS::logTIMTP(bool enabled)
13230
+ {
13231
+ if (packetUBXTIMTP == nullptr)
13232
+ return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
13233
+ packetUBXTIMTP->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled;
13234
+ }
13235
+
13013
13236
#ifndef SFE_UBLOX_DISABLE_ESF
13014
13237
// ***** ESF ALG automatic support
13015
13238
@@ -16545,6 +16768,84 @@ uint8_t DevUBLOXGNSS::getAOPSTATUSstatus(uint16_t maxWait)
16545
16768
return (packetUBXNAVAOPSTATUS->data.status);
16546
16769
}
16547
16770
16771
+ // ***** TIM TP Helper Functions
16772
+
16773
+ uint32_t DevUBLOXGNSS::getTIMTPtowMS(uint16_t maxWait)
16774
+ {
16775
+ if (packetUBXTIMTP == nullptr)
16776
+ initPacketUBXTIMTP(); // Check that RAM has been allocated for the TP data
16777
+ if (packetUBXTIMTP == nullptr) // Bail if the RAM allocation failed
16778
+ return 0;
16779
+
16780
+ if (packetUBXTIMTP->moduleQueried.moduleQueried.bits.towMS == false)
16781
+ getTIMTP(maxWait);
16782
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.towMS = false; // Since we are about to give this to user, mark this data as stale
16783
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.all = false;
16784
+ return (packetUBXTIMTP->data.towMS);
16785
+ }
16786
+
16787
+ uint32_t DevUBLOXGNSS::getTIMTPtowSubMS(uint16_t maxWait)
16788
+ {
16789
+ if (packetUBXTIMTP == nullptr)
16790
+ initPacketUBXTIMTP(); // Check that RAM has been allocated for the TP data
16791
+ if (packetUBXTIMTP == nullptr) // Bail if the RAM allocation failed
16792
+ return 0;
16793
+
16794
+ if (packetUBXTIMTP->moduleQueried.moduleQueried.bits.towSubMS == false)
16795
+ getTIMTP(maxWait);
16796
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.towSubMS = false; // Since we are about to give this to user, mark this data as stale
16797
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.all = false;
16798
+ return (packetUBXTIMTP->data.towSubMS);
16799
+ }
16800
+
16801
+ uint16_t DevUBLOXGNSS::getTIMTPweek(uint16_t maxWait)
16802
+ {
16803
+ if (packetUBXTIMTP == nullptr)
16804
+ initPacketUBXTIMTP(); // Check that RAM has been allocated for the TP data
16805
+ if (packetUBXTIMTP == nullptr) // Bail if the RAM allocation failed
16806
+ return 0;
16807
+
16808
+ if (packetUBXTIMTP->moduleQueried.moduleQueried.bits.week == false)
16809
+ getTIMTP(maxWait);
16810
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.week = false; // Since we are about to give this to user, mark this data as stale
16811
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.all = false;
16812
+ return (packetUBXTIMTP->data.week);
16813
+ }
16814
+
16815
+ // Convert TIM TP to Unix epoch including microseconds
16816
+ // CAUTION! Assumes the time base is UTC and the week number is GPS
16817
+ uint32_t DevUBLOXGNSS::getTIMTPAsEpoch(uint32_t µsecond, uint16_t maxWait)
16818
+ {
16819
+ if (packetUBXNAVPVT == nullptr)
16820
+ initPacketUBXNAVPVT(); // Check that RAM has been allocated for the PVT data
16821
+ if (packetUBXNAVPVT == nullptr) // Bail if the RAM allocation failed
16822
+ return 0;
16823
+
16824
+ if (packetUBXTIMTP->moduleQueried.moduleQueried.bits.week == false)
16825
+ getTIMTP(maxWait);
16826
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.week = false; // Since we are about to give this to user, mark this data as stale
16827
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.towMS = false;
16828
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.towSubMS = false;
16829
+ packetUBXTIMTP->moduleQueried.moduleQueried.bits.all = false;
16830
+
16831
+ uint32_t tow = packetUBXTIMTP->data.week - SFE_UBLOX_JAN_1ST_2020_WEEK; // Calculate the number of weeks since Jan 1st 2020
16832
+ tow *= SFE_UBLOX_SECS_PER_WEEK; // Convert weeks to seconds
16833
+ tow += SFE_UBLOX_EPOCH_WEEK_2086; // Add the TOW for Jan 1st 2020
16834
+ tow += packetUBXTIMTP->data.towMS / 1000; // Add the TOW for the next TP
16835
+
16836
+ uint32_t us = packetUBXTIMTP->data.towMS % 1000; // Extract the milliseconds
16837
+ us *= 1000; // Convert to microseconds
16838
+
16839
+ double subMS = packetUBXTIMTP->data.towSubMS; // Get towSubMS (ms * 2^-32)
16840
+ subMS *= pow(2.0, -32.0); // Convert to milliseconds
16841
+ subMS *= 1000; // Convert to microseconds
16842
+
16843
+ us += (int32_t)subMS; // Add subMS
16844
+
16845
+ microsecond = us;
16846
+ return tow;
16847
+ }
16848
+
16548
16849
#ifndef SFE_UBLOX_DISABLE_ESF
16549
16850
// ***** ESF Helper Functions
16550
16851
0 commit comments