diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html
index f520bd565..cda88f9cf 100644
--- a/Firmware/RTK_Everywhere/AP-Config/index.html
+++ b/Firmware/RTK_Everywhere/AP-Config/index.html
@@ -362,6 +362,18 @@
+
diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js
index 79d45dc1c..ace0abb77 100644
--- a/Firmware/RTK_Everywhere/AP-Config/src/main.js
+++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js
@@ -876,7 +876,9 @@ function validateFields() {
if (isElementShown("lg290pGnssSettings") == true) {
checkElementValue("rtcmMinElev", -90, 90, "Must be between -90 and 90", "collapseGNSSConfig");
}
-
+ if (ge("enableGalileoHas").checked == true) {
+ checkElementStringSpacesNoCommas("configurePPP", 1, 30, "Must be 1 to 30 characters. Separated by spaces. Commas not allowed", "collapseGNSSConfig");
+ }
if (ge("enableNtripClient").checked == true) {
checkElementString("ntripClientCasterHost", 1, 45, "Must be 1 to 45 characters", "collapseGNSSConfig");
checkElementValue("ntripClientCasterPort", 1, 99999, "Must be 1 to 99999", "collapseGNSSConfig");
@@ -1379,6 +1381,19 @@ function checkElementString(id, min, max, errorText, collapseID) {
clearError(id);
}
+function checkElementStringSpacesNoCommas(id, min, max, errorText, collapseID) {
+ value = ge(id).value;
+ var commas = value.split(',');
+ var spaces = value.split(' ');
+ if ((value.length < min) || (value.length > max) || (commas.length > 1) || (spaces.length == 1)) {
+ ge(id + 'Error').innerHTML = 'Error: ' + errorText;
+ ge(collapseID).classList.add('show');
+ errorCount++;
+ }
+ else
+ clearError(id);
+}
+
function checkElementIPAddress(id, errorText, collapseID) {
value = ge(id).value;
var data = value.split('.');
diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.h b/Firmware/RTK_Everywhere/GNSS_LG290P.h
index c28a278dc..541f1435b 100644
--- a/Firmware/RTK_Everywhere/GNSS_LG290P.h
+++ b/Firmware/RTK_Everywhere/GNSS_LG290P.h
@@ -450,7 +450,7 @@ class GNSS_LG290P : GNSS
// elevationDegrees: The elevation value in degrees
bool setElevation(uint8_t elevationDegrees);
- bool setHighAccuracyService(bool enableGalileoHas);
+ bool setHighAccuracyService(bool enableGalileoHas, const char *configurePPP);
// Enable all the valid messages for this platform
bool setMessages(int maxRetries);
diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino
index 91ce2f286..4c44e68ae 100644
--- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino
+++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino
@@ -412,7 +412,7 @@ bool GNSS_LG290P::configureRover()
if (settings.debugGnss && response == false)
systemPrintln("configureRover: Set rate failed");
- response &= setHighAccuracyService(settings.enableGalileoHas);
+ response &= setHighAccuracyService(settings.enableGalileoHas, (const char *)settings.configurePPP);
response &= enableRTCMRover();
if (settings.debugGnss && response == false)
@@ -528,7 +528,7 @@ bool GNSS_LG290P::configureBase()
response &= setMinCnoRadio(settings.minCNO);
- response &= setHighAccuracyService(settings.enableGalileoHas);
+ response &= setHighAccuracyService(settings.enableGalileoHas, (const char *)settings.configurePPP);
response &= enableRTCMBase(); // Set RTCM messages
if (settings.debugGnss && response == false)
@@ -1912,6 +1912,9 @@ void GNSS_LG290P::menuConstellations()
{
systemPrintf("%d) Galileo E6 Corrections: %s\r\n", MAX_LG290P_CONSTELLATIONS + 1,
settings.enableGalileoHas ? "Enabled" : "Disabled");
+ if (settings.enableGalileoHas)
+ systemPrintf("%d) PPP Configuration: \"%s\"\r\n", MAX_LG290P_CONSTELLATIONS + 2,
+ settings.configurePPP);
}
systemPrintln("x) Exit");
@@ -1928,6 +1931,31 @@ void GNSS_LG290P::menuConstellations()
{
settings.enableGalileoHas ^= 1;
}
+ else if ((incoming == MAX_LG290P_CONSTELLATIONS + 2) && present.galileoHasCapable && settings.enableGalileoHas)
+ {
+ systemPrintln("Enter the PPP configuration separated by spaces, not commas:");
+ char newConfig[sizeof(settings.configurePPP)];
+ getUserInputString(newConfig, sizeof(newConfig));
+ bool isValid = true;
+ int spacesSeen = 0;
+ for (size_t i = 0; i < strlen(newConfig); i++)
+ {
+ if ((isValid) && (newConfig[i] == ',')) // Check for no commas
+ {
+ systemPrintln("Comma detected. Please try again");
+ isValid = false;
+ }
+ if (newConfig[i] == ' ')
+ spacesSeen++;
+ }
+ if ((isValid) && (spacesSeen < 4)) // Check for at least 4 spaces
+ {
+ systemPrintln("Configuration should contain at least 4 spaces");
+ isValid = false;
+ }
+ if (isValid)
+ snprintf(settings.configurePPP, sizeof(settings.configurePPP), "%s", newConfig);
+ }
else if (incoming == INPUT_RESPONSE_GETNUMBER_EXIT)
break;
else if (incoming == INPUT_RESPONSE_GETNUMBER_TIMEOUT)
@@ -1939,7 +1967,7 @@ void GNSS_LG290P::menuConstellations()
// Apply current settings to module
gnss->setConstellations();
- setHighAccuracyService(settings.enableGalileoHas);
+ setHighAccuracyService(settings.enableGalileoHas, (const char *)settings.configurePPP);
clearBuffer(); // Empty buffer of any newline chars
}
@@ -2415,7 +2443,7 @@ bool GNSS_LG290P::setElevation(uint8_t elevationDegrees)
}
//----------------------------------------
-bool GNSS_LG290P::setHighAccuracyService(bool enableGalileoHas)
+bool GNSS_LG290P::setHighAccuracyService(bool enableGalileoHas, const char *configurePPP)
{
bool result = true;
@@ -2429,7 +2457,9 @@ bool GNSS_LG290P::setHighAccuracyService(bool enableGalileoHas)
{
// $PQTMCFGPPP,W,2,1,120,0.10,0.15*68
// Enable E6 HAS, WGS84, 120 timeout, 0.10m Horizontal convergence accuracy threshold, 0.15m Vertical threshold
- if (_lg290p->sendOkCommand("$PQTMCFGPPP", ",W,2,1,120,0.10,0.15") == true)
+ char paramConfigurePPP[sizeof(settings.configurePPP) + 4];
+ snprintf(paramConfigurePPP, sizeof(paramConfigurePPP), ",W,%s", configPppSpacesToCommas(configurePPP));
+ if (_lg290p->sendOkCommand("$PQTMCFGPPP", paramConfigurePPP) == true)
{
systemPrintln("Galileo E6 HAS service enabled");
}
diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h
index 8c0f58ff5..4c62263ee 100644
--- a/Firmware/RTK_Everywhere/settings.h
+++ b/Firmware/RTK_Everywhere/settings.h
@@ -1111,6 +1111,7 @@ struct Settings
254}; // Mark first record with key so defaults will be applied. Int value for each supported message - Report
// rates for RTCM Base. Default to Quectel recommended rates.
int lg290pMessageRatesPQTM[MAX_LG290P_PQTM_MSG] = {254}; // Mark first record with key so defaults will be applied.
+ char configurePPP[30] = "2 1 120 0.10 0.15"; // PQTMCFGPPP: 2,1,120,0.10,0.15 ** Use spaces, not commas! **
#endif // COMPILE_LG290P
bool debugSettings = false;
@@ -1849,6 +1850,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] =
{ 0, 1, 1, 0, 0, 0, 0, 0, 1, L29, 1, tLgMRBaRT, MAX_LG290P_RTCM_MSG, & settings.lg290pMessageRatesRTCMBase, "messageRateRTCMBase_", gnssCmdUpdateMessageRates, },
{ 0, 1, 1, 0, 0, 0, 0, 0, 1, L29, 1, tLgMRRvRT, MAX_LG290P_RTCM_MSG, & settings.lg290pMessageRatesRTCMRover, "messageRateRTCMRover_", gnssCmdUpdateMessageRates, },
{ 0, 1, 1, 0, 0, 0, 0, 0, 1, L29, 1, tLgMRPqtm, MAX_LG290P_PQTM_MSG, & settings.lg290pMessageRatesPQTM, "messageRatePQTM_", gnssCmdUpdateMessageRates, },
+ { 1, 1, 0, 0, 0, 0, 0, 0, 1, L29, 1, tCharArry, sizeof(settings.configurePPP), & settings.configurePPP, "configurePPP", nullptr, },
#endif // COMPILE_LG290P
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, ALL, 1, _bool, 0, & settings.debugSettings, "debugSettings", nullptr, },
diff --git a/Firmware/RTK_Everywhere/support.ino b/Firmware/RTK_Everywhere/support.ino
index afda7931e..5240641bb 100644
--- a/Firmware/RTK_Everywhere/support.ino
+++ b/Firmware/RTK_Everywhere/support.ino
@@ -1208,3 +1208,13 @@ void WeekToWToUnixEpoch(uint64_t *unixEpoch, uint16_t GPSWeek, uint32_t GPSToW)
*unixEpoch += GPSToW; // 518400
*unixEpoch += 315964800;
}
+
+const char *configPppSpacesToCommas(const char *config)
+{
+ static char commas[sizeof(settings.configurePPP)];
+ snprintf(commas, sizeof(commas), "%s", config);
+ for (size_t i = 0; i < strlen(commas); i++)
+ if (commas[i] == ' ')
+ commas[i] = ',';
+ return (const char *)commas;
+}