Skip to content

Commit 0e8d3d2

Browse files
committed
Initial support for Flex LoRa and GNSS updates over UART
1 parent 668a945 commit 0e8d3d2

File tree

10 files changed

+395
-135
lines changed

10 files changed

+395
-135
lines changed

Firmware/RTK_Everywhere/Begin.ino

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ void identifyBoard()
161161
productVariant = RTK_POSTCARD;
162162

163163
#ifndef NOT_FACET_FLEX
164+
systemPrintln("<<<<<<<<<< !!!!!!!!!! FLEX FORCED !!!!!!!!!! >>>>>>>>>>");
164165
productVariant = RTK_FLEX; // TODO remove once v1.1 Flex has ID resistors
165166
#endif
166167
}
@@ -1129,27 +1130,8 @@ void beginGnssUart()
11291130
}
11301131
}
11311132

1132-
// Assign GNSS UART interrupts to the core that started the task. See:
1133-
// https://github.com/espressif/arduino-esp32/issues/3386
1134-
void pinGnssUartTask(void *pvParameters)
1133+
void forceGnssCommunicationRate(uint32_t &platformGnssCommunicationRate)
11351134
{
1136-
// Start notification
1137-
if (settings.printTaskStartStop)
1138-
systemPrintln("Task pinGnssUartTask started");
1139-
1140-
if (serialGNSS == nullptr)
1141-
serialGNSS = new HardwareSerial(2); // Use UART2 on the ESP32 for communication with the GNSS module
1142-
1143-
serialGNSS->setRxBufferSize(settings.uartReceiveBufferSize);
1144-
serialGNSS->setTimeout(settings.serialTimeoutGNSS); // Requires serial traffic on the UART pins for detection
1145-
1146-
if (pin_GnssUart_RX == -1 || pin_GnssUart_TX == -1)
1147-
reportFatalError("Illegal UART pin assignment.");
1148-
1149-
uint32_t platformGnssCommunicationRate =
1150-
settings.dataPortBaud; // Default to 230400bps for ZED. This limits GNSS fixes at 4Hz but allows SD buffer to be
1151-
// reduced to 6k.
1152-
11531135
if (productVariant == RTK_TORCH)
11541136
{
11551137
// Override user setting. Required because beginGnssUart() is called before beginBoard().
@@ -1178,6 +1160,29 @@ void pinGnssUartTask(void *pvParameters)
11781160
platformGnssCommunicationRate = 115200;
11791161
}
11801162
}
1163+
}
1164+
// Assign GNSS UART interrupts to the core that started the task. See:
1165+
// https://github.com/espressif/arduino-esp32/issues/3386
1166+
void pinGnssUartTask(void *pvParameters)
1167+
{
1168+
// Start notification
1169+
if (settings.printTaskStartStop)
1170+
systemPrintln("Task pinGnssUartTask started");
1171+
1172+
if (serialGNSS == nullptr)
1173+
serialGNSS = new HardwareSerial(2); // Use UART2 on the ESP32 for communication with the GNSS module
1174+
1175+
serialGNSS->setRxBufferSize(settings.uartReceiveBufferSize);
1176+
serialGNSS->setTimeout(settings.serialTimeoutGNSS); // Requires serial traffic on the UART pins for detection
1177+
1178+
if (pin_GnssUart_RX == -1 || pin_GnssUart_TX == -1)
1179+
reportFatalError("Illegal UART pin assignment.");
1180+
1181+
uint32_t platformGnssCommunicationRate =
1182+
settings.dataPortBaud; // Default to 230400bps for ZED. This limits GNSS fixes at 4Hz but allows SD buffer to be
1183+
// reduced to 6k.
1184+
1185+
forceGnssCommunicationRate(platformGnssCommunicationRate);
11811186

11821187
serialGNSS->begin(platformGnssCommunicationRate, SERIAL_8N1, pin_GnssUart_RX,
11831188
pin_GnssUart_TX); // Start UART on platform dependent pins for SPP. The GNSS will be

Firmware/RTK_Everywhere/Display.ino

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3288,3 +3288,30 @@ void displayWebConfig(std::vector<iconPropertyBlinking> &iconPropertyList)
32883288

32893289
printTextCenter(myIP, yPos, QW_FONT_5X7, 1, false);
32903290
}
3291+
3292+
// Show GNSS update - button exit
3293+
void paintGnssUpdate()
3294+
{
3295+
paintGenericUpdate("GNSS");
3296+
}
3297+
void paintLoRaUpdate()
3298+
{
3299+
paintGenericUpdate("LoRa");
3300+
}
3301+
void paintGenericUpdate(const char *device)
3302+
{
3303+
if (online.display)
3304+
{
3305+
oled->erase(); // Clear the display's internal buffer
3306+
int yPos = (oled->getHeight() - 38) / 2;
3307+
uint8_t fontHeight = 8;
3308+
printTextCenter(device, yPos, QW_FONT_5X7, 1, false); // text, y, font type, kerning, inverted
3309+
yPos = yPos + fontHeight + 1;
3310+
printTextCenter("Update", yPos, QW_FONT_5X7, 1, false);
3311+
yPos = yPos + fontHeight + 3;
3312+
printTextCenter("Button", yPos, QW_FONT_5X7, 1, true); // text, y, font type, kerning, inverted
3313+
yPos = yPos + fontHeight + 1;
3314+
printTextCenter("To Exit", yPos, QW_FONT_5X7, 1, true);
3315+
oled->display(); // Push internal buffer to display
3316+
}
3317+
}

Firmware/RTK_Everywhere/GNSS.ino

Lines changed: 180 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,10 @@ void gnssDetectReceiverType()
142142

143143
// TODO remove after testing, force retest on each boot
144144
// Note: with this in place, the X5 detection will take a lot longer due to the baud rate change
145-
settings.detectedGnssReceiver = GNSS_RECEIVER_UNKNOWN;
145+
#ifndef NOT_FACET_FLEX
146+
systemPrintln("<<<<<<<<<< !!!!!!!!!! FLEX FORCED !!!!!!!!!! >>>>>>>>>>");
147+
//settings.detectedGnssReceiver = GNSS_RECEIVER_UNKNOWN; // This may be causing weirdness on the LG290P. Commenting for now
148+
#endif
146149

147150
// Start auto-detect if NVM is not yet set
148151
if (settings.detectedGnssReceiver == GNSS_RECEIVER_UNKNOWN)
@@ -243,4 +246,179 @@ void gnssReset()
243246
{
244247
digitalWrite(pin_GNSS_Reset, LOW); // Tell LG290P to reset
245248
}
246-
}
249+
}
250+
251+
//----------------------------------------
252+
// Force UART connection to GNSS for firmware update on the next boot by special file in
253+
// LittleFS
254+
//----------------------------------------
255+
bool createGNSSPassthrough()
256+
{
257+
return createPassthrough("/updateGnssFirmware.txt");
258+
}
259+
bool createPassthrough(const char *filename)
260+
{
261+
if (online.fs == false)
262+
return false;
263+
264+
if (LittleFS.exists(filename))
265+
{
266+
if (settings.debugGnss)
267+
systemPrintf("LittleFS %s already exists\r\n", filename);
268+
return true;
269+
}
270+
271+
File updateUm980Firmware = LittleFS.open(filename, FILE_WRITE);
272+
updateUm980Firmware.close();
273+
274+
if (LittleFS.exists(filename))
275+
return true;
276+
277+
if (settings.debugGnss)
278+
systemPrintf("Unable to create %s on LittleFS\r\n", filename);
279+
return false;
280+
}
281+
282+
//----------------------------------------
283+
void gnssFirmwareBeginUpdate()
284+
{
285+
// Note: UM980 needs its own dedicated update function, due to the T@ and bootloader trigger
286+
287+
// Note: gnssFirmwareBeginUpdate is called during setup, after identify board. I2C, gpio expanders, buttons
288+
// and display have all been initialized. But, importantly, the UARTs have not yet been started.
289+
// This makes our job much easier...
290+
291+
// NOTE: X20P may expect a baud rate change during the update. We may need to force 9600 baud. TODO
292+
293+
// Flag that we are in direct connect mode. Button task will gnssFirmwareRemoveUpdate and exit
294+
inDirectConnectMode = true;
295+
296+
// Note: we can't call gnssFirmwareRemoveUpdate() here as closing Tera Term will reset the ESP32,
297+
// returning the firmware to normal operation...
298+
299+
// Paint GNSS Update
300+
paintGnssUpdate();
301+
302+
// Stop all UART tasks. Redundant
303+
tasksStopGnssUart();
304+
305+
uint32_t serialBaud = 115200;
306+
307+
forceGnssCommunicationRate(serialBaud); // On Flex, must be called after gnssDetectReceiverType
308+
309+
systemPrintln();
310+
systemPrintf("Entering GNSS direct connect for firmware update and configuration. Disconnect this terminal "
311+
"connection. Use the GNSS manufacturer software "
312+
"to update the firmware. Baudrate: %dbps. Press the %s button to return "
313+
"to normal operation.\r\n", serialBaud, present.button_mode ? "mode" : "power");
314+
systemFlush();
315+
316+
Serial.end(); // We must end before we begin otherwise the UART settings are corrupted
317+
Serial.begin(serialBaud);
318+
319+
if (serialGNSS == nullptr)
320+
serialGNSS = new HardwareSerial(2); // Use UART2 on the ESP32 for communication with the GNSS module
321+
322+
serialGNSS->setRxBufferSize(settings.uartReceiveBufferSize);
323+
serialGNSS->setTimeout(settings.serialTimeoutGNSS); // Requires serial traffic on the UART pins for detection
324+
325+
// This is OK for Flex too. We're using the main GNSS pins.
326+
serialGNSS->begin(serialBaud, SERIAL_8N1, pin_GnssUart_RX, pin_GnssUart_TX);
327+
328+
// // On Flex with the LG290P, it may be wise to disable message output on UART1 first?
329+
// if ((productVariant == RTK_FLEX) && present.gnss_lg290p)
330+
// {
331+
// // GNSS has not been begun, so we need to send the command manually
332+
// serialGNSS->println("$PQTMCFGPROT,W,1,1,00000000,00000000*38");
333+
// delay(100);
334+
// serialGNSS->println("$PQTMCFGPROT,W,1,1,00000000,00000000*38");
335+
// delay(100);
336+
// while (serialGNSS->available())
337+
// serialGNSS->read(); // Soak up any residual messages
338+
// }
339+
340+
// Echo everything to/from GNSS
341+
while (1)
342+
{
343+
static unsigned long lastSerial = millis(); // Temporary fix for buttonless Flex
344+
345+
if (Serial.available()) // Note: use if, not while
346+
{
347+
serialGNSS->write(Serial.read());
348+
lastSerial = millis();
349+
}
350+
351+
if (serialGNSS->available()) // Note: use if, not while
352+
Serial.write(serialGNSS->read());
353+
354+
// Button task will gnssFirmwareRemoveUpdate and restart
355+
356+
// Temporary fix for buttonless Flex. TODO - remove
357+
if ((productVariant == RTK_FLEX) && (millis() > (lastSerial + 30000)))
358+
{
359+
// Beep to indicate exit
360+
beepOn();
361+
delay(300);
362+
beepOff();
363+
delay(100);
364+
beepOn();
365+
delay(300);
366+
beepOff();
367+
368+
gnssFirmwareRemoveUpdate();
369+
370+
systemPrintln("Exiting direct connection (passthrough) mode");
371+
systemFlush(); // Complete prints
372+
373+
ESP.restart();
374+
}
375+
}
376+
}
377+
378+
//----------------------------------------
379+
// Check if direct connection file exists
380+
//----------------------------------------
381+
bool gnssFirmwareCheckUpdate()
382+
{
383+
return gnssFirmwareCheckUpdateFile("/updateGnssFirmware.txt");
384+
}
385+
bool gnssFirmwareCheckUpdateFile(const char *filename)
386+
{
387+
if (online.fs == false)
388+
return false;
389+
390+
if (LittleFS.exists(filename))
391+
{
392+
if (settings.debugGnss)
393+
systemPrintf("LittleFS %s exists\r\n", filename);
394+
395+
// We do not remove the file here. See removeupdateUm980Firmware().
396+
397+
return true;
398+
}
399+
400+
return false;
401+
}
402+
403+
//----------------------------------------
404+
// Remove direct connection file
405+
//----------------------------------------
406+
void gnssFirmwareRemoveUpdate()
407+
{
408+
return gnssFirmwareRemoveUpdateFile("/updateGnssFirmware.txt");
409+
}
410+
void gnssFirmwareRemoveUpdateFile(const char *filename)
411+
{
412+
if (online.fs == false)
413+
return;
414+
415+
if (LittleFS.exists(filename))
416+
{
417+
if (settings.debugGnss)
418+
systemPrintf("Removing %s\r\n", filename);
419+
420+
LittleFS.remove(filename);
421+
}
422+
}
423+
424+
//----------------------------------------

0 commit comments

Comments
 (0)