@@ -1080,7 +1080,6 @@ uint8_t GNSS_LG290P::getFixType()
1080
1080
// ----------------------------------------
1081
1081
float GNSS_LG290P::getHorizontalAccuracy ()
1082
1082
{
1083
- // Coming soon from EPE
1084
1083
if (online.gnss )
1085
1084
return (_lg290p->get2DError ());
1086
1085
return 0 ;
@@ -1574,6 +1573,7 @@ void GNSS_LG290P::menuMessages()
1574
1573
systemPrintln (" 1) Set NMEA Messages" );
1575
1574
systemPrintln (" 2) Set Rover RTCM Messages" );
1576
1575
systemPrintln (" 3) Set Base RTCM Messages" );
1576
+ systemPrintln (" 4) Set PQTM Messages" );
1577
1577
1578
1578
systemPrintln (" 10) Reset to Defaults" );
1579
1579
@@ -1587,6 +1587,8 @@ void GNSS_LG290P::menuMessages()
1587
1587
menuMessagesSubtype (settings.lg290pMessageRatesRTCMRover , " RTCMRover" );
1588
1588
else if (incoming == 3 )
1589
1589
menuMessagesSubtype (settings.lg290pMessageRatesRTCMBase , " RTCMBase" );
1590
+ else if (incoming == 4 )
1591
+ menuMessagesSubtype (settings.lg290pMessageRatesPQTM , " PQTM" );
1590
1592
else if (incoming == 10 )
1591
1593
{
1592
1594
// Reset rates to defaults
@@ -1601,6 +1603,10 @@ void GNSS_LG290P::menuMessages()
1601
1603
for (int x = 0 ; x < MAX_LG290P_RTCM_MSG; x++)
1602
1604
settings.lg290pMessageRatesRTCMBase [x] = lgMessagesRTCM[x].msgDefaultRate ;
1603
1605
1606
+ // Reset PQTM rates to defaults
1607
+ for (int x = 0 ; x < MAX_LG290P_PQTM_MSG; x++)
1608
+ settings.lg290pMessageRatesPQTM [x] = lgMessagesPQTM[x].msgDefaultRate ;
1609
+
1604
1610
systemPrintln (" Reset to Defaults" );
1605
1611
}
1606
1612
@@ -1638,7 +1644,7 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message
1638
1644
{
1639
1645
endOfBlock = MAX_LG290P_NMEA_MSG;
1640
1646
1641
- for (int x = 0 ; x < MAX_LG290P_NMEA_MSG ; x++)
1647
+ for (int x = 0 ; x < endOfBlock ; x++)
1642
1648
{
1643
1649
if (lg290pFirmwareVersion <= lgMessagesNMEA[x].firmwareVersionSupported )
1644
1650
systemPrintf (" %d) Message %s: %d - Requires firmware update\r\n " , x + 1 ,
@@ -1652,7 +1658,7 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message
1652
1658
{
1653
1659
endOfBlock = MAX_LG290P_RTCM_MSG;
1654
1660
1655
- for (int x = 0 ; x < MAX_LG290P_RTCM_MSG ; x++)
1661
+ for (int x = 0 ; x < endOfBlock ; x++)
1656
1662
{
1657
1663
if (lg290pFirmwareVersion <= lgMessagesRTCM[x].firmwareVersionSupported )
1658
1664
systemPrintf (" %d) Message %s: %d - Requires firmware update\r\n " , x + 1 ,
@@ -1666,16 +1672,30 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message
1666
1672
{
1667
1673
endOfBlock = MAX_LG290P_RTCM_MSG;
1668
1674
1669
- for (int x = 0 ; x < MAX_LG290P_RTCM_MSG ; x++)
1675
+ for (int x = 0 ; x < endOfBlock ; x++)
1670
1676
{
1671
1677
if (lg290pFirmwareVersion <= lgMessagesRTCM[x].firmwareVersionSupported )
1672
- systemPrintf (" %d) Message %s: %d - Requires firmware update\r\n " , x + 1 , lgMessagesRTCM[x]. msgTextName ,
1673
- settings.lg290pMessageRatesRTCMBase [x]);
1678
+ systemPrintf (" %d) Message %s: %d - Requires firmware update\r\n " , x + 1 ,
1679
+ lgMessagesRTCM[x]. msgTextName , settings.lg290pMessageRatesRTCMBase [x]);
1674
1680
else
1675
1681
systemPrintf (" %d) Message %s: %d\r\n " , x + 1 , lgMessagesRTCM[x].msgTextName ,
1676
1682
settings.lg290pMessageRatesRTCMBase [x]);
1677
1683
}
1678
1684
}
1685
+ else if (strcmp (messageType, " PQTM" ) == 0 )
1686
+ {
1687
+ endOfBlock = MAX_LG290P_PQTM_MSG;
1688
+
1689
+ for (int x = 0 ; x < endOfBlock; x++)
1690
+ {
1691
+ if (lg290pFirmwareVersion <= lgMessagesPQTM[x].firmwareVersionSupported )
1692
+ systemPrintf (" %d) Message %s: %d - Requires firmware update\r\n " , x + 1 ,
1693
+ lgMessagesPQTM[x].msgTextName , settings.lg290pMessageRatesPQTM [x]);
1694
+ else
1695
+ systemPrintf (" %d) Message %s: %d\r\n " , x + 1 , lgMessagesPQTM[x].msgTextName ,
1696
+ settings.lg290pMessageRatesPQTM [x]);
1697
+ }
1698
+ }
1679
1699
1680
1700
systemPrintln (" x) Exit" );
1681
1701
@@ -1698,6 +1718,11 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message
1698
1718
sprintf (messageString, " Enter number of fixes required before %s is reported (0 to disable)" ,
1699
1719
lgMessagesRTCM[incoming].msgTextName );
1700
1720
}
1721
+ else if (strcmp (messageType, " PQTM" ) == 0 )
1722
+ {
1723
+ sprintf (messageString, " Enter number of fixes required before %s is reported (0 to disable)" ,
1724
+ lgMessagesPQTM[incoming].msgTextName );
1725
+ }
1701
1726
1702
1727
int newSetting = 0 ;
1703
1728
@@ -1718,6 +1743,11 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message
1718
1743
if (getNewSetting (messageString, 0 , 1200 , &newSetting) == INPUT_RESPONSE_VALID)
1719
1744
settings.lg290pMessageRatesRTCMBase [incoming] = newSetting;
1720
1745
}
1746
+ if (strcmp (messageType, " PQTM" ) == 0 )
1747
+ {
1748
+ if (getNewSetting (messageString, 0 , 1 , &newSetting) == INPUT_RESPONSE_VALID)
1749
+ settings.lg290pMessageRatesPQTM [incoming] = newSetting;
1750
+ }
1721
1751
}
1722
1752
else if (incoming == INPUT_RESPONSE_GETNUMBER_EXIT)
1723
1753
break ;
@@ -2134,3 +2164,190 @@ void lg290pReset()
2134
2164
{
2135
2165
digitalWrite (pin_GNSS_Reset, LOW);
2136
2166
}
2167
+
2168
+ // Given a NMEA or PQTM sentence, determine if it is enabled in settings
2169
+ // This is used to signal to the processUart1Message() task to remove messages that are needed
2170
+ // by the library to function (ie, PQTMEPE, PQTMPVT, GNGSV) but should not be logged or passed to other consumers
2171
+ // If unknown, allow messages through. Filtering and suppression should be selectively added in.
2172
+ bool lg290pMessageEnabled (char *nmeaSentence, int sentenceLength)
2173
+ {
2174
+ // Identify message type: PQTM or NMEA
2175
+ char messageType[strlen (" PQTM" ) + 1 ] = {0 };
2176
+ strncpy (messageType, &nmeaSentence[1 ],
2177
+ 4 ); // Copy four letters, starting in spot 1. Null terminated from array initializer.
2178
+
2179
+ if (strncmp (messageType, " PQTM" , sizeof (messageType)) == 0 )
2180
+ {
2181
+ // Identify sentence type
2182
+ char sentenceType[strlen (" EPE" ) + 1 ] = {0 };
2183
+ strncpy (sentenceType, &nmeaSentence[5 ],
2184
+ 3 ); // Copy three letters, starting in spot 5. Null terminated from array initializer.
2185
+
2186
+ // Find this sentence type in the settings array
2187
+ for (int messageNumber = 0 ; messageNumber < MAX_LG290P_PQTM_MSG; messageNumber++)
2188
+ {
2189
+ if (strncmp (lgMessagesPQTM[messageNumber].msgTextName , sentenceType, sizeof (sentenceType)) == 0 )
2190
+ {
2191
+ if (settings.lg290pMessageRatesPQTM [messageNumber] > 0 )
2192
+ return (true );
2193
+ return (false );
2194
+ }
2195
+ }
2196
+ }
2197
+
2198
+ else // We have to assume $G????
2199
+ {
2200
+ // Identify sentence type
2201
+ char sentenceType[strlen (" GSV" ) + 1 ] = {0 };
2202
+ strncpy (sentenceType, &nmeaSentence[3 ],
2203
+ 3 ); // Copy three letters, starting in spot 3. Null terminated from array initializer.
2204
+
2205
+ // Find this sentence type in the settings array
2206
+ for (int messageNumber = 0 ; messageNumber < MAX_LG290P_NMEA_MSG; messageNumber++)
2207
+ {
2208
+ if (strncmp (lgMessagesNMEA[messageNumber].msgTextName , sentenceType, sizeof (sentenceType)) == 0 )
2209
+ {
2210
+ if (settings.lg290pMessageRatesNMEA [messageNumber] > 0 )
2211
+ return (true );
2212
+ return (false );
2213
+ }
2214
+ }
2215
+ }
2216
+
2217
+ // If we can't ID this message, allow it by default. The device configuration should control most message flow.
2218
+ return (true );
2219
+ }
2220
+
2221
+ // Re-create the GST sentence to increase the horizontal and vertical precision number of decimals
2222
+ // ie, 0.0 becomes 0.009
2223
+ // See issue: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/513
2224
+ // $GNGST,223954.500,1.7,1.5,1.0,109.3,1.412,1.055,2.4*7E
2225
+ // Modifies the sentence length with new length
2226
+ void lg290pModifyGst (char *nmeaSentence, uint16_t *sentenceLength)
2227
+ {
2228
+ // This issue currently only applies to LG290P firmware version 4
2229
+ // Version 3 does not support GST messages. Version 5 should fix the issue.
2230
+ if (lg290pFirmwareVersion != 4 )
2231
+ return ;
2232
+
2233
+ if (online.gnss == false )
2234
+ return ;
2235
+
2236
+ // Only apply the GST patch if our HPA is very small (<0.1m), ie RTK Float or Fix.
2237
+ if (gnss->isRTKFix () == false && gnss->isRTKFloat () == false )
2238
+ return ;
2239
+
2240
+ GNSS_LG290P *lg290p = (GNSS_LG290P *)gnss;
2241
+
2242
+ // Identify sentence type
2243
+ char sentenceType[strlen (" GST" ) + 1 ] = {0 };
2244
+ strncpy (sentenceType, &nmeaSentence[3 ],
2245
+ 3 ); // Copy three letters, starting in spot 3. Null terminated from array initializer.
2246
+
2247
+ // We only care about GST sentences
2248
+ if (strncmp (sentenceType, " GST" , sizeof (sentenceType)) != 0 )
2249
+ return ;
2250
+
2251
+ const int latitudeErrorComma = 6 ;
2252
+ const int longitudeErrorComma = 7 ;
2253
+ const int altitudeErrorComma = 8 ;
2254
+
2255
+ uint8_t latitudeStart = 0 ;
2256
+ uint8_t latitudeStop = 0 ;
2257
+ uint8_t longitudeStart = 0 ;
2258
+ uint8_t longitudeStop = 0 ;
2259
+ uint8_t altitudeStart = 0 ;
2260
+ uint8_t checksumStart = 0 ;
2261
+
2262
+ if (settings.enableImuCompensationDebug == true && !inMainMenu)
2263
+ systemPrintf (" Original GNGST:\r\n %s\r\n " , nmeaSentence);
2264
+
2265
+ int commaCount = 0 ;
2266
+ for (int x = 0 ; x < strnlen (nmeaSentence, *sentenceLength); x++) // Assumes sentence is null terminated
2267
+ {
2268
+ if (nmeaSentence[x] == ' ,' )
2269
+ {
2270
+ commaCount++;
2271
+ if (commaCount == latitudeErrorComma)
2272
+ latitudeStart = x + 1 ;
2273
+ if (commaCount == latitudeErrorComma + 1 )
2274
+ latitudeStop = x;
2275
+ if (commaCount == longitudeErrorComma)
2276
+ longitudeStart = x + 1 ;
2277
+ if (commaCount == longitudeErrorComma + 1 )
2278
+ longitudeStop = x;
2279
+ if (commaCount == altitudeErrorComma)
2280
+ altitudeStart = x + 1 ;
2281
+ }
2282
+ if (nmeaSentence[x] == ' *' )
2283
+ {
2284
+ checksumStart = x;
2285
+ break ;
2286
+ }
2287
+ }
2288
+
2289
+ if (latitudeStart == 0 || latitudeStop == 0 || longitudeStart == 0 || longitudeStop == 0 || altitudeStart == 0 ||
2290
+ checksumStart == 0 )
2291
+ {
2292
+ systemPrintln (" Delineator not found" );
2293
+ return ;
2294
+ }
2295
+
2296
+ char newSentence[150 ] = {0 };
2297
+
2298
+ if (sizeof (newSentence) < *sentenceLength)
2299
+ {
2300
+ systemPrintln (" newSentence not big enough!" );
2301
+ return ;
2302
+ }
2303
+
2304
+ char errorString[strlen (" 0.000" ) + 1 ] = {0 };
2305
+
2306
+ // strncat terminates
2307
+
2308
+ // Add start of message up to latitude
2309
+ strncat (newSentence, nmeaSentence, latitudeStart);
2310
+
2311
+ // Convert error from EPE message to string. We don't have pure lat error, only 2D and 3D.
2312
+ snprintf (errorString, sizeof (errorString), " %0.3f" , lg290p->getHorizontalAccuracy ());
2313
+
2314
+ // Add latitude error
2315
+ strncat (newSentence, errorString, sizeof (newSentence) - 1 );
2316
+
2317
+ // Add interstitial between end of lat and beginning of lon
2318
+ strncat (newSentence, nmeaSentence + latitudeStop, longitudeStart - latitudeStop);
2319
+
2320
+ // Add same error for longitude error
2321
+ strncat (newSentence, errorString, sizeof (newSentence) - 1 );
2322
+
2323
+ // Add interstitial between end of lon and beginning of alt
2324
+ strncat (newSentence, nmeaSentence + longitudeStop, altitudeStart - longitudeStop);
2325
+
2326
+ // Convert error from EPE message to string. We don't have pure altitude error, use double 2D error as stand-in.
2327
+ snprintf (errorString, sizeof (errorString), " %0.3f" , lg290p->getHorizontalAccuracy () * 2 );
2328
+
2329
+ // Add altitude error. We don't really have altitude so use 3D error in its place.
2330
+ strncat (newSentence, errorString, sizeof (newSentence) - 1 );
2331
+
2332
+ // From: http://engineeringnotes.blogspot.com/2015/02/generate-crc-for-nmea-strings-arduino.html
2333
+ byte CRC = 0 ; // XOR chars between '$' and '*'
2334
+ for (byte x = 1 ; x < strlen (newSentence); x++)
2335
+ CRC = CRC ^ newSentence[x];
2336
+
2337
+ // Convert CRC to string, add * and CR LF
2338
+ snprintf (errorString, sizeof (errorString), " *%02X\r\n " , CRC);
2339
+
2340
+ // Add CRC
2341
+ strncat (newSentence, errorString, sizeof (newSentence) - 1 );
2342
+
2343
+ // Increase length of sentence
2344
+ *sentenceLength = strlen (newSentence);
2345
+
2346
+ // Overwrite the original NMEA
2347
+ strncpy (nmeaSentence, newSentence, *sentenceLength);
2348
+
2349
+ nmeaSentence[*sentenceLength] = ' \0 ' ; // Terminate string
2350
+
2351
+ if (settings.enableImuCompensationDebug == true && !inMainMenu)
2352
+ systemPrintf (" Corrected GNGST:\r\n %s\r\n " , nmeaSentence);
2353
+ }
0 commit comments