diff --git a/.github/workflows/build-for-release.yml b/.github/workflows/build-for-release.yml index fa0e70e..23caa6f 100644 --- a/.github/workflows/build-for-release.yml +++ b/.github/workflows/build-for-release.yml @@ -6,7 +6,7 @@ on: env: FILENAME_PREFIX: RTK_mosaic-T_Firmware FIRMWARE_VERSION_MAJOR: 1 - FIRMWARE_VERSION_MINOR: 0 + FIRMWARE_VERSION_MINOR: 1 CORE_VERSION: 3.0.1 jobs: diff --git a/Firmware/RTK_mosaic-T_Firmware/Begin.ino b/Firmware/RTK_mosaic-T_Firmware/Begin.ino index 5bde0b2..0484069 100644 --- a/Firmware/RTK_mosaic-T_Firmware/Begin.ino +++ b/Firmware/RTK_mosaic-T_Firmware/Begin.ino @@ -110,6 +110,8 @@ void beginBoard() pin_errorLED = 32; pin_lockLED = 33; + pin_serial0TX_Alt = 23; + pin_serial0RX_Alt = 34; pin_serial1TX = 14; pin_serial1RX = 13; pin_serial1CTS = 26; @@ -174,6 +176,32 @@ void beginBoard() } } +void beginConsole(uint32_t baud, bool allowAlt) +{ + // Don't try to print here. serialConsole may not have been initialized + + if ((!allowAlt) || (!settings.enableTCPServer)) + { + serialConsole.begin(baud, SERIAL_8N1, pin_serial0RX, pin_serial0TX); + } + else + { + if ((pin_serial0RX_Alt < 0) || (pin_serial0TX_Alt < 0)) + { + reportFatalError("No Serial0 Alt pins"); + } + else + { + serialConsole.begin(baud, SERIAL_8N1, pin_serial0RX_Alt, pin_serial0TX_Alt); + } + } + + delay(10); + + while (serialConsole.available()) + serialConsole.read(); +} + // We want the UART1 interrupts to be pinned to core 0 to avoid competing with I2C interrupts // We do not start the UART1 here because the interrupts would be pinned to core 1 // We instead start a task that runs on core 0, that then begins serial diff --git a/Firmware/RTK_mosaic-T_Firmware/Display.ino b/Firmware/RTK_mosaic-T_Firmware/Display.ino index cc3ff6f..a5e4344 100644 --- a/Firmware/RTK_mosaic-T_Firmware/Display.ino +++ b/Firmware/RTK_mosaic-T_Firmware/Display.ino @@ -125,8 +125,16 @@ void updateDisplay() oled->print(textLine); yPos += 8; - snprintf(textLine, sizeof(textLine), "IP %s", - gnssIP.toString().c_str()); + if ((settings.enableTCPServer) && ((gnssSecond % 4) > 1)) // Print TCP Port for two seconds + { + snprintf(textLine, sizeof(textLine), "IP TCP Port %d", + settings.tcpServerPort); + } + else + { + snprintf(textLine, sizeof(textLine), "IP %s", + gnssIP.toString().c_str()); + } oled->setCursor(0, yPos); oled->print(textLine); yPos += 8; diff --git a/Firmware/RTK_mosaic-T_Firmware/GNSS.ino b/Firmware/RTK_mosaic-T_Firmware/GNSS.ino index ccf873b..c987e5d 100644 --- a/Firmware/RTK_mosaic-T_Firmware/GNSS.ino +++ b/Firmware/RTK_mosaic-T_Firmware/GNSS.ino @@ -189,6 +189,13 @@ bool initializeGNSS() return false; } + // Configure COM3 for daisy chain to IPS1 + if (!sendWithResponse("sdio, COM3, DC1, DC2\n\r", "DataInOut")) + { + systemPrintln("GNSS FAIL (DataInOut COM3)"); + return false; + } + if (!sendWithResponse("sso, Stream1, COM1, Group1, sec1\n\r", "SBFOutput")) { systemPrintln("GNSS FAIL (SBFOutput Stream1)"); @@ -218,7 +225,7 @@ bool configureGNSSPPS() systemPrintln("Configuring GNSS PPS"); - String ppsParams = String("setPPSParameters, "); + String ppsParams = String("spps, "); ppsParams += String(mosaicPPSParametersInterval[settings.ppsInterval]) + String(", "); ppsParams += String(mosaicPPSParametersPolarity[settings.ppsPolarity]) + String(", "); ppsParams += String(settings.ppsDelay_ns) + String(", "); @@ -246,3 +253,57 @@ bool configureGNSSPPS() return true; } +bool configureGNSSTCPServer() +{ + if (!online.gnss) + return false; + + systemPrintln("Configuring GNSS TCP Server"); + + String tcpParams = String("siss, IPS1, "); + + if (settings.enableTCPServer) + { + tcpParams += String(settings.tcpServerPort) + String(", TCP2Way\n\r"); + } + else + { + tcpParams += String("0\n\r"); + } + + int retries = 3; + + while (!sendWithResponse(tcpParams, "IPServerSettings") && (retries > 0)) + { + systemPrintln("No response from mosaic. Retrying - with escape sequence..."); + sendWithResponse("SSSSSSSSSSSSSSSSSSSS\n\r", "COM4>"); // Send escape sequence + retries--; + } + + if (retries == 0) + { + systemPrintln("GNSS FAIL (IPServerSettings)"); + return false; + } + + // Configure IPS1 + if (settings.enableTCPServer) + { + if (!sendWithResponse("sdio, IPS1, DC2, DC1\n\r", "DataInOut")) + { + systemPrintln("GNSS FAIL (DataInOut IPS1)"); + return false; + } + } + else + { + if (!sendWithResponse("sdio, IPS1, none, none\n\r", "DataInOut")) + { + systemPrintln("GNSS FAIL (DataInOut IPS1)"); + return false; + } + } + + systemPrintln("GNSS TCP Server configured"); + return true; +} \ No newline at end of file diff --git a/Firmware/RTK_mosaic-T_Firmware/NVM.ino b/Firmware/RTK_mosaic-T_Firmware/NVM.ino index 1fefcb6..99eaf41 100644 --- a/Firmware/RTK_mosaic-T_Firmware/NVM.ino +++ b/Firmware/RTK_mosaic-T_Firmware/NVM.ino @@ -98,6 +98,9 @@ void recordSystemSettingsToFile(File *settingsFile) settingsFile->printf("%s=%0.3e\r\n", "Ik", settings.Ik); settingsFile->printf("%s=%d\r\n", "preferNonCompositeGPSBias", settings.preferNonCompositeGPSBias); settingsFile->printf("%s=%d\r\n", "preferNonCompositeGalileoBias", settings.preferNonCompositeGalileoBias); + settingsFile->printf("%s=%d\r\n", "enableTCPServer", settings.enableTCPServer); + settingsFile->printf("%s=%d\r\n", "tcpServerPort", settings.tcpServerPort); + //settingsFile->printf("%s=%d\r\n", "", settings.); @@ -366,6 +369,10 @@ bool parseLine(char *str, Settings *settings) settings->preferNonCompositeGPSBias = d; else if (strcmp(settingName, "preferNonCompositeGalileoBias") == 0) settings->preferNonCompositeGalileoBias = d; + else if (strcmp(settingName, "enableTCPServer") == 0) + settings->enableTCPServer = d; + else if (strcmp(settingName, "tcpServerPort") == 0) + settings->tcpServerPort = d; //else if (strcmp(settingName, "") == 0) // settings-> = d; diff --git a/Firmware/RTK_mosaic-T_Firmware/RTK_mosaic-T_Firmware.ino b/Firmware/RTK_mosaic-T_Firmware/RTK_mosaic-T_Firmware.ino index 59f9ef4..d42f896 100644 --- a/Firmware/RTK_mosaic-T_Firmware/RTK_mosaic-T_Firmware.ino +++ b/Firmware/RTK_mosaic-T_Firmware/RTK_mosaic-T_Firmware.ino @@ -11,6 +11,14 @@ Set the board to "ESP32 Wrover Module" Settings are pulled from ESP32's file system LittleFS. + + Version history: + 1.0: Initial release + 1.1: Add TCP support + The console can be accessed via TCP (COM3 is daisy chained to IPS1) + On the v1.0 PCB, link: + mosaic COM3 TX (TX3) to ESP32 GPIO 34 + mosaic COM3 RX (RX3) to ESP32 GPIO 23 */ // This is passed in from compiler extra flags @@ -49,6 +57,12 @@ int pin_errorLED = -1; int pin_lockLED = -1; +const int pin_serial0TX = 1; +const int pin_serial0RX = 3; + +int pin_serial0TX_Alt = -1; +int pin_serial0RX_Alt = -1; + int pin_serial1TX = -1; int pin_serial1RX = -1; int pin_serial1CTS = -1; @@ -142,6 +156,7 @@ GPS_PARSE_TABLE; //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include // Required for uart_set_rx_full_threshold() on cores 1000) + if (millis() - lastHeapReport >= settings.periodicPrintInterval_ms) { reportHeapNow(false); } diff --git a/Firmware/RTK_mosaic-T_Firmware/Tasks.ino b/Firmware/RTK_mosaic-T_Firmware/Tasks.ino index 8597da1..d03214c 100644 --- a/Firmware/RTK_mosaic-T_Firmware/Tasks.ino +++ b/Firmware/RTK_mosaic-T_Firmware/Tasks.ino @@ -115,7 +115,14 @@ void gnssReadTask(void *e) while (true) { if ((settings.enableTaskReports == true) && !inMainMenu) - systemPrintf("SerialReadTask High watermark: %d\r\n", uxTaskGetStackHighWaterMark(nullptr)); + { + static unsigned long lastPrint = 0; + if (millis() > (lastPrint + settings.periodicPrintInterval_ms)) + { + systemPrintf("SerialReadTask High watermark: %d\r\n", uxTaskGetStackHighWaterMark(nullptr)); + lastPrint = millis(); + } + } while (serialGNSS.available()) { @@ -710,11 +717,11 @@ void ButtonCheckTask(void *e) { setupBtn->read(); - if (setupBtn->isPressed()) // Switch is set to base mode + if (setupBtn->isPressed()) { // Do stuff... Maybe change the display? } - else if (setupBtn->wasReleased()) // Switch is set to Rover + else if (setupBtn->wasReleased()) { // Do stuff... Maybe change the display? } diff --git a/Firmware/RTK_mosaic-T_Firmware/menuMain.ino b/Firmware/RTK_mosaic-T_Firmware/menuMain.ino index a4a47f6..361ea76 100644 --- a/Firmware/RTK_mosaic-T_Firmware/menuMain.ino +++ b/Firmware/RTK_mosaic-T_Firmware/menuMain.ino @@ -91,6 +91,13 @@ void menuMain() printUnknown(incoming); } + configureGNSSTCPServer(); // Configure TCP + + if (settings.enableTCPServer) + systemPrintf("TCP Server is enabled. Please connect on port %d to view the console\r\n", settings.tcpServerPort); + + beginConsole(115200, true); // Swap to Alt pins if TCP is enabled + recordSystemSettings(); // Once all menus have exited, record the new settings to LittleFS and config file clearBuffer(); // Empty buffer of any newline chars diff --git a/Firmware/RTK_mosaic-T_Firmware/menuSystem.ino b/Firmware/RTK_mosaic-T_Firmware/menuSystem.ino index 5946c91..b833ebd 100644 --- a/Firmware/RTK_mosaic-T_Firmware/menuSystem.ino +++ b/Firmware/RTK_mosaic-T_Firmware/menuSystem.ino @@ -398,6 +398,12 @@ void menuOperation() systemPrint("13) Pulse-Per-Second Pulse Width (ms): "); systemPrintln(settings.ppsPulseWidth_ms); + systemPrint("14) TCP Server (IPS1): "); + systemPrintf("%s\r\n", settings.enableTCPServer ? "Enabled" : "Disabled"); + + systemPrint("15) TCP Server Port: "); + systemPrintln(settings.tcpServerPort); + systemPrintln("\r\nx) Exit"); byte incoming = getCharacterNumber(); @@ -534,6 +540,25 @@ void menuOperation() ppsStarted = false; // Restart PPS afterwards } } + else if (incoming == 14) + { + settings.enableTCPServer ^= 1; + } + else if (incoming == 15) + { + systemPrint("Enter the TCP Server Port: "); + int port = getNumber(); // Returns EXIT, TIMEOUT, or long + if ((port != INPUT_RESPONSE_GETNUMBER_EXIT) && + (port != INPUT_RESPONSE_GETNUMBER_TIMEOUT)) + { + if (port < 1 || port > 65534) + systemPrintln("Error: Port is out of range"); + else + { + settings.tcpServerPort = port; + } + } + } // Menu exit control else if (incoming == 'x') break; @@ -563,12 +588,13 @@ void printCurrentConditions(bool CSV) firstTime = false; } - systemPrintf("%04d/%02d/%02d,%02d:%02d:%02d", - gnssYear, gnssMonth, gnssDay, gnssHour, gnssMinute, gnssSecond); - uint32_t epochSecs; uint32_t epochMillis; convertGnssTimeToEpoch(&epochSecs, &epochMillis); + + systemPrintf("%04d/%02d/%02d,%02d:%02d:%02d", + gnssYear, gnssMonth, gnssDay, gnssHour, gnssMinute, gnssSecond); + systemPrintf(",%lu.%03lu", epochSecs, epochMillis); systemPrint(","); diff --git a/Firmware/RTK_mosaic-T_Firmware/settings.h b/Firmware/RTK_mosaic-T_Firmware/settings.h index 3e6192b..59882b0 100644 --- a/Firmware/RTK_mosaic-T_Firmware/settings.h +++ b/Firmware/RTK_mosaic-T_Firmware/settings.h @@ -273,6 +273,8 @@ typedef struct double Ik = 0.151; // PI I term bool preferNonCompositeGPSBias = false; // Prefer non-composite GPS bias - if available. Mutex with preferNonCompositeGalileoBias bool preferNonCompositeGalileoBias = false; // Prefer non-composite Galileo bias - if available. Mutex with preferNonCompositeGPSBias + bool enableTCPServer = false; // Enable and configure mosaic-T IPS1 for TCP2way for the ESP32 console + uint16_t tcpServerPort = 28785; // Add new settings above <------------------------------------------------------------> diff --git a/Firmware/RTK_mosaic-T_Firmware/support.ino b/Firmware/RTK_mosaic-T_Firmware/support.ino index d8547c6..1fa081e 100644 --- a/Firmware/RTK_mosaic-T_Firmware/support.ino +++ b/Firmware/RTK_mosaic-T_Firmware/support.ino @@ -1,27 +1,25 @@ // Helper functions to support printing to eiter the serial port or bluetooth connection -// If we are printing to all endpoints, BT gets priority int systemAvailable() { - return (Serial.available()); + return (serialConsole.available()); } -// If we are printing to all endpoints, BT gets priority int systemRead() { - return (Serial.read()); + return (serialConsole.read()); } // Output a buffer of the specified length to the serial port void systemWrite(const uint8_t *buffer, uint16_t length) { - Serial.write(buffer, length); + serialConsole.write(buffer, length); } // Ensure all serial output has been transmitted, FIFOs are empty void systemFlush() { - Serial.flush(); + serialConsole.flush(); } // Output a byte to the serial port @@ -747,7 +745,7 @@ void formatFirmwareVersion(char prefix, uint8_t major, uint8_t minor, char *buff // The buffer is too small for the version number else { - Serial.printf("ERROR: Buffer too small for version number!\r\n"); + serialConsole.printf("ERROR: Buffer too small for version number!\r\n"); if (bufferLength > 0) *buffer = 0; } diff --git a/Firmware/Utils/ESP32_FLASH_ERASE.bat b/Firmware/Utils/ESP32_FLASH_ERASE.bat new file mode 100644 index 0000000..f706b39 --- /dev/null +++ b/Firmware/Utils/ESP32_FLASH_ERASE.bat @@ -0,0 +1,20 @@ +@echo off + +if [%1]==[] goto findPort + +set COMPORT=%1 +goto erase + +:findPort + +for /f "tokens=2 delims=(" %%a in ('wmic path win32_pnpentity get caption /format:list ^| find "COM" ^| find "CH340"') do ( + for /f "tokens=1 delims=)" %%b in ("%%a") do ( + set COMPORT=%%b + ) +) + +:erase + +set ESPTOOL="esptool.exe" + +call %ESPTOOL% --chip esp32 -p %COMPORT% -b 460800 erase_flash \ No newline at end of file diff --git a/Firmware/Utils/esptool.exe b/Firmware/Utils/esptool.exe new file mode 100644 index 0000000..318b67e Binary files /dev/null and b/Firmware/Utils/esptool.exe differ