diff --git a/README.md b/README.md index 56c7411..e03d1a9 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ for details on supported boards, and additional setup instructions. Manufacturer | Model | Position | Temperature | Humidity | Pressure -------------|-------|----------|-------------|----------|---------- -Vaisala | RS92-SGP/NGP | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: +Vaisala | RS92-SGP | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: Vaisala | RS41-SG/SGP/SGM | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: (for -SGP) Graw | DFM06/09/17 | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: Meteomodem | M10 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | Not Sent @@ -45,7 +45,7 @@ course be considered for inclusion :-). You can download the latest binary automated build for the development and testing branches [here](http://rdzsonde.mooo.com/download.html), the binary includes everything including configuration files so any existing settings will be reset. -To update an existing installatiom to the latest development or master version you can use the [OTA](https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/Other-features#over-the-air-updates) update feature. +To update an existing installation to the latest development or master version you can use the [OTA](https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/Other-features#over-the-air-updates) update feature. The downloaded .bin file can be flashed to your ESP32 board using [esptool](https://github.com/espressif/esptool) or [ESP32 Download Tool](https://www.espressif.com/en/support/download/other-tools) diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 14f2949..de921bf 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -43,7 +43,8 @@ AsyncWebServer server(80); AXP20X_Class axp; #define PMU_IRQ 35 SemaphoreHandle_t axpSemaphore; -bool pmu_irq = false; +// 0: cleared; 1: set; 2: do not check, also query state of axp via i2c on each loop +uint8_t pmu_irq = 0; const char *updateHost = "rdzsonde.mooo.com"; int updatePort = 80; @@ -75,7 +76,12 @@ const char *dfmSubtypeStrSH[16] = { NULL, NULL, NULL, NULL, NULL, NULL, "DFM17", // 0x0D NULL, NULL }; - + +// Times in ms, i.e. station: 10 minutes, mobile: 20 seconds +#define APRS_STATION_UPDATE_TIME (10*60*1000) +#define APRS_MOBILE_STATION_UPDATE_TIME (20*1000) +unsigned long time_last_aprs_update = -APRS_STATION_UPDATE_TIME; + #if FEATURE_SONDEHUB #define SONDEHUB_STATION_UPDATE_TIME (60*60*1000) // 60 min #define SONDEHUB_MOBILE_STATION_UPDATE_TIME (30*1000) // 30 sec @@ -83,18 +89,19 @@ WiFiClient shclient; // Sondehub v2 int shImportInterval = 0; char shImport = 0; unsigned long time_last_update = 0; +#endif /* SH_LOC_OFF: never send position information to SondeHub SH_LOC_FIXED: send fixed position (if specified in config) to sondehub SH_LOC_CHASE: always activate chase mode and send GPS position (if available) SH_LOC_AUTO: if there is no valid GPS position, or GPS position < MIN_LOC_AUTO_DIST away from known fixed position: use FIXED mode otherwise, i.e. if there is a valid GPS position and (either no fixed position in config, or GPS position is far away from fixed position), use CHASE mode. */ +// same constants used for SondeHub and APRS enum { SH_LOC_OFF, SH_LOC_FIXED, SH_LOC_CHASE, SH_LOC_AUTO }; /* auto mode is chase if valid GPS position and (no fixed location entered OR valid GPS position and distance in lat/lon deg to fixed location > threshold) */ #define MIN_LOC_AUTO_DIST 200 /* meter */ #define SH_LOC_AUTO_IS_CHASE ( gpsPos.valid && ( (isnan(sonde.config.rxlat) || isnan(sonde.config.rxlon) ) || \ calcLatLonDist( gpsPos.lat, gpsPos.lon, sonde.config.rxlat, sonde.config.rxlon ) > MIN_LOC_AUTO_DIST ) ) -#endif extern float calcLatLonDist(float lat1, float lon1, float lat2, float lon2); // KISS over TCP for communicating with APRSdroid @@ -317,25 +324,6 @@ const char *createQRGForm() { strcat(ptr, "\n"); strcat(ptr, "
"); strcat(ptr, "\n"); -#if 0 - strcat(ptr, ""); - for (int i = 0; i < sonde.config.maxsonde; i++) { - //String s = sondeTypeSelect(i >= sonde.nSonde ? 2 : sonde.sondeList[i].type); - String site = sonde.sondeList[i].launchsite; - sprintf(ptr + strlen(ptr), "" - "" - "" - //"", - "
IDActiveFreqLaunchsiteMode
%d", - i + 1, - i + 1, (i < sonde.nSonde && sonde.sondeList[i].active) ? "checked" : "", - i + 1, i >= sonde.nSonde ? 400.000 : sonde.sondeList[i].freq, - i + 1, i >= sonde.nSonde ? " " : sonde.sondeList[i].launchsite, - i + 1, i >= sonde.nSonde ? 2 : sondeTypeChar[sonde.sondeList[i].type] ); - //i + 1, s.c_str()); - } - strcat(ptr, "
"); -#endif //
"); HTMLSAVEBUTTON(ptr); HTMLBODYEND(ptr); @@ -611,110 +599,6 @@ void setupConfigData() { } -#if 0 -struct st_configitems config_list[] = { - /* General config settings */ - {"", "Software configuration", -5, NULL}, - {"wifi", "Wifi mode (0-Off/1-Client/2-Access Point/3-Debug)", 0, &sonde.config.wifi}, - {"debug", "Debug mode (0/1)", 0, &sonde.config.debug}, - {"maxsonde", "Maxsonde (max # QRG entries)", 0, &sonde.config.maxsonde}, - {"screenfile", "Screen config (0=automatic; 1-5=predefined; other=custom)", 0, &sonde.config.screenfile}, - {"display", "Display screens (scan,default,...)", -6, sonde.config.display}, - /* Spectrum display settings */ - {"spectrum", "Show spectrum (-1=no, 0=forever, >0=seconds)", 0, &sonde.config.spectrum}, - {"startfreq", "Startfreq (MHz)", 0, &sonde.config.startfreq}, - {"channelbw", "Bandwidth (kHz)", 0, &sonde.config.channelbw}, - {"marker", "Spectrum MHz marker", 0, &sonde.config.marker}, - {"noisefloor", "Spectrum noisefloor", 0, &sonde.config.noisefloor}, - /* decoder settings */ - {"", "Receiver configuration", -5, NULL}, - {"freqofs", "RX frequency offset (Hz)", 0, &sonde.config.freqofs}, - {"rs41.agcbw", "RS41 AGC bandwidth", 0, &sonde.config.rs41.agcbw}, - {"rs41.rxbw", "RS41 RX bandwidth", 0, &sonde.config.rs41.rxbw}, - {"rs92.rxbw", "RS92 RX (and AGC) bandwidth", 0, &sonde.config.rs92.rxbw}, - {"rs92.alt2d", "RS92 2D fix default altitude", 0, &sonde.config.rs92.alt2d}, - {"dfm.agcbw", "DFM AGC bandwidth", 0, &sonde.config.dfm.agcbw}, - {"dfm.rxbw", "DFM RX bandwidth", 0, &sonde.config.dfm.rxbw}, - {"m10m20.agcbw", "M10/M20 AGC bandwidth", 0, &sonde.config.m10m20.agcbw}, - {"m10m20.rxbw", "M10/M20 RX bandwidth", 0, &sonde.config.m10m20.rxbw}, - {"mp3h.agcbw", "MP3H AGC bandwidth", 0, &sonde.config.mp3h.agcbw}, - {"mp3h.rxbw", "MP3H RX bandwidth", 0, &sonde.config.mp3h.rxbw}, - {"ephftp", "FTP for eph (RS92)", 39, &sonde.config.ephftp}, - {"", "Data feed configuration", -5, NULL}, - /* APRS settings */ - {"call", "Call", 8, sonde.config.call}, - {"passcode", "Passcode", 0, &sonde.config.passcode}, - /* KISS tnc settings */ - {"kisstnc.active", "KISS TNC (port 14590) (needs reboot)", 0, &sonde.config.kisstnc.active}, - {"kisstnc.idformat", "KISS TNC ID Format", -2, &sonde.config.kisstnc.idformat}, - /* AXUDP settings */ - {"axudp.active", "AXUDP active", -3, &sonde.config.udpfeed.active}, - {"axudp.host", "AXUDP Host", 63, sonde.config.udpfeed.host}, - {"axudp.port", "AXUDP Port", 0, &sonde.config.udpfeed.port}, - {"axudp.idformat", "DFM ID Format", -2, &sonde.config.udpfeed.idformat}, - {"axudp.highrate", "Rate limit", 0, &sonde.config.udpfeed.highrate}, - /* APRS TCP settings, current not used */ - {"tcp.active", "APRS TCP active", -3, &sonde.config.tcpfeed.active}, - {"tcp.host", "ARPS TCP Host", 63, sonde.config.tcpfeed.host}, - {"tcp.port", "APRS TCP Port", 0, &sonde.config.tcpfeed.port}, - {"tcp.idformat", "DFM ID Format", -2, &sonde.config.tcpfeed.idformat}, - {"tcp.highrate", "Rate limit", 0, &sonde.config.tcpfeed.highrate}, - -#if FEATURE_MQTT - /* MQTT */ - {"mqtt.active", "MQTT Active (needs reboot)", 0, &sonde.config.mqtt.active}, - {"mqtt.id", "MQTT client ID", 63, &sonde.config.mqtt.id}, - {"mqtt.host", "MQTT server hostname", 63, &sonde.config.mqtt.host}, - {"mqtt.port", "MQTT Port", 0, &sonde.config.mqtt.port}, - {"mqtt.username", "MQTT Username", 63, &sonde.config.mqtt.username}, - {"mqtt.password", "MQTT Password", 63, &sonde.config.mqtt.password}, - {"mqtt.prefix", "MQTT Prefix", 63, &sonde.config.mqtt.prefix}, -#endif - - /* Hardware dependeing settings */ - {"", "Hardware configuration (requires reboot)", -5, NULL}, - {"disptype", "Display type (0=OLED/SSD1306, 1=ILI9225, 2=OLED/SH1106, 3=ILI9341, 4=ILI9342)", 0, &sonde.config.disptype}, - {"norx_timeout", "No-RX-Timeout in seconds (-1=disabled)", 0, &sonde.config.norx_timeout}, - {"oled_sda", "OLED SDA/TFT SDA", 0, &sonde.config.oled_sda}, - {"oled_scl", "OLED SCL/TFT CLK", 0, &sonde.config.oled_scl}, - {"oled_rst", "OLED RST/TFT RST (needs reboot)", 0, &sonde.config.oled_rst}, - {"tft_rs", "TFT RS", 0, &sonde.config.tft_rs}, - {"tft_cs", "TFT CS", 0, &sonde.config.tft_cs}, - {"tft_orient", "TFT orientation (0/1/2/3), OLED flip: 3", 0, &sonde.config.tft_orient}, - {"tft_spifreq", "TFT SPI speed", 0, &sonde.config.tft_spifreq}, - {"button_pin", "Button input port", -4, &sonde.config.button_pin}, - {"button2_pin", "Button 2 input port", -4, &sonde.config.button2_pin}, - {"button2_axp", "Use AXP192 PWR as Button 2", 0, &sonde.config.button2_axp}, - {"touch_thresh", "Touch button threshold
(0 for calib mode)", 0, &sonde.config.touch_thresh}, - {"power_pout", "Power control port", 0, &sonde.config.power_pout}, - {"led_pout", "LED output port", 0, &sonde.config.led_pout}, - {"gps_rxd", "GPS RXD pin (-1 to disable)", 0, &sonde.config.gps_rxd}, - {"gps_txd", "GPS TXD pin (not really needed)", 0, &sonde.config.gps_txd}, - {"batt_adc", "Battery measurement pin", 0, &sonde.config.batt_adc}, -#if 1 - {"sx1278_ss", "SX1278 SS", 0, &sonde.config.sx1278_ss}, - {"sx1278_miso", "SX1278 MISO", 0, &sonde.config.sx1278_miso}, - {"sx1278_mosi", "SX1278 MOSI", 0, &sonde.config.sx1278_mosi}, - {"sx1278_sck", "SX1278 SCK", 0, &sonde.config.sx1278_sck}, -#endif - {"mdnsname", "mDNS name", 14, &sonde.config.mdnsname}, - -#if FEATURE_SONDEHUB - /* SondeHub settings */ - {"", "SondeHub settings", -5, NULL}, - {"sondehub.active", "SondeHub reporting (0=disabled, 1=active)", 0, &sonde.config.sondehub.active}, - {"sondehub.chase", "SondeHub location reporting (0=off, 1=fixed, 2=chase/GPS, 3=auto)", 0, &sonde.config.sondehub.chase}, - {"sondehub.host", "SondeHub host (DO NOT CHANGE)", 63, &sonde.config.sondehub.host}, - {"sondehub.callsign", "Callsign", 63, &sonde.config.sondehub.callsign}, - {"sondehub.lat", "Latitude (optional, required to show station on SondeHub Tracker)", -7, &sonde.config.sondehub.lat}, - {"sondehub.lon", "Longitude (optional, required to show station on SondeHub Tracker)", -7, &sonde.config.sondehub.lon}, - {"sondehub.alt", "Altitude (optional, visible on SondeHub tracker)", 19, &sonde.config.sondehub.alt}, - {"sondehub.antenna", "Antenna (optional, visisble on SondeHub tracker)", 63, &sonde.config.sondehub.antenna}, - {"sondehub.email", "SondeHub email (optional, only used to contact in case of upload errors)", 63, &sonde.config.sondehub.email}, - {"sondehub.fimport", "SondeHub freq import (interval/maxdist/maxage [min/km/min])", 18, &sonde.config.sondehub.fimport}, -}; -#endif -#else struct st_configitems config_list[] = { /* General config settings */ {"wifi", 0, &sonde.config.wifi}, @@ -745,22 +629,23 @@ struct st_configitems config_list[] = { {"mp3h.rxbw", 0, &sonde.config.mp3h.rxbw}, {"ephftp", 39, &sonde.config.ephftp}, /* APRS settings */ - {"call", 8, sonde.config.call}, + {"call", 9, sonde.config.call}, {"passcode", 0, &sonde.config.passcode}, /* KISS tnc settings */ {"kisstnc.active", 0, &sonde.config.kisstnc.active}, - {"kisstnc.idformat", -2, &sonde.config.kisstnc.idformat}, /* AXUDP settings */ {"axudp.active", -3, &sonde.config.udpfeed.active}, {"axudp.host", 63, sonde.config.udpfeed.host}, {"axudp.port", 0, &sonde.config.udpfeed.port}, - {"axudp.idformat", -2, &sonde.config.udpfeed.idformat}, {"axudp.highrate", 0, &sonde.config.udpfeed.highrate}, /* APRS TCP settings, current not used */ {"tcp.active", -3, &sonde.config.tcpfeed.active}, {"tcp.host", 63, sonde.config.tcpfeed.host}, {"tcp.port", 0, &sonde.config.tcpfeed.port}, - {"tcp.idformat", -2, &sonde.config.tcpfeed.idformat}, + {"tcp.chase", 0, &sonde.config.chase}, + {"tcp.comment", 30, sonde.config.comment}, + {"tcp.objcall", 9, sonde.config.objcall}, + {"tcp.beaconsym", 4, sonde.config.beaconsym}, {"tcp.highrate", 0, &sonde.config.tcpfeed.highrate}, #if FEATURE_CHASEMAPPER /* Chasemapper settings */ @@ -817,75 +702,12 @@ struct st_configitems config_list[] = { {"sondehub.fiactive", 0, &sonde.config.sondehub.fiactive}, {"sondehub.fiinterval", 0, &sonde.config.sondehub.fiinterval}, {"sondehub.fimaxdist", 0, &sonde.config.sondehub.fimaxdist}, - {"sondehub.fimaxage", 0, &sonde.config.sondehub.fimaxage}, + {"sondehub.fimaxage", -7, &sonde.config.sondehub.fimaxage}, #endif }; -#endif const int N_CONFIG = (sizeof(config_list) / sizeof(struct st_configitems)); -#if 0 -// old code, no longer needed (in js now) - -void addConfigStringEntry(char *ptr, int idx, const char *label, int len, char *field) { - sprintf(ptr + strlen(ptr), "%s\n", - label, idx, field); -} -void addConfigNumEntry(char *ptr, int idx, const char *label, int *value) { - sprintf(ptr + strlen(ptr), "%s\n", - label, idx, *value); -} -void addConfigDblEntry(char *ptr, int idx, const char *label, double * value) { - sprintf(ptr + strlen(ptr), "%s\n", - label, idx, *value); -} -void addConfigButtonEntry(char *ptr, int idx, const char *label, int *value) { - int v = *value, ck = 0; - if (v == 255) v = -1; - if (v != -1) { - if (v & 128) ck = 1; - v = v & 127; - } - - sprintf(ptr + strlen(ptr), "%s", - label, idx, v); - sprintf(ptr + strlen(ptr), " Touch \n", idx, ck ? " checked" : ""); -} -void addConfigTypeEntry(char *ptr, int idx, const char *label, int *value) { - // TODO -} -void addConfigOnOffEntry(char *ptr, int idx, const char *label, int *value) { - // TODO -} -void addConfigSeparatorEntry(char *ptr) { - strcat(ptr, "
\n"); -} -void addConfigHeading(char *ptr, const char *label) { - strcat(ptr, ""); - strcat(ptr, label); - strcat(ptr, "\n"); -} -void addConfigInt8List(char *ptr, int idx, const char *label, int8_t *list) { - sprintf(ptr + strlen(ptr), "%s using /screens%d.txt", label, Display::getScreenIndex(sonde.config.screenfile)); - for (int i = 0; i < disp.nLayouts; i++) { - sprintf(ptr + strlen(ptr), "
%d=%s", i, disp.layouts[i].label); - } - sprintf(ptr + strlen(ptr), "\n"); -} -#endif - const char *createConfigForm() { char *ptr = message; strcpy(ptr, HTMLHEAD); strcat(ptr, ""); @@ -932,43 +754,6 @@ const char *createConfigForm() { strcat(ptr, "\");\n"); } strcat(ptr, "configTable();\n "); -#if 0 - strcat(ptr, ""); - for (int i = 0; i < N_CONFIG; i++) { - Serial.printf("%d: %s -- %d\n", i, config_list[i].label, strlen(ptr)); - switch (config_list[i].type) { - case -5: // Heading - addConfigHeading(ptr, config_list[i].label); - break; - case -6: // List of int8 values - addConfigInt8List(ptr, i, config_list[i].label, (int8_t *)config_list[i].data); - break; - case -3: // on/off - addConfigOnOffEntry(ptr, i, config_list[i].label, (int *)config_list[i].data); - break; - case -2: // DFM format - addConfigTypeEntry(ptr, i, config_list[i].label, (int *)config_list[i].data); - break; - case -1: - addConfigSeparatorEntry(ptr); - break; - case 0: - addConfigNumEntry(ptr, i, config_list[i].label, (int *)config_list[i].data); - break; - case -4: - addConfigButtonEntry(ptr, i, config_list[i].label, (int *)config_list[i].data); - break; - case -7: /* double for lat/lon */ - addConfigDblEntry(ptr, i, config_list[i].label, (double *)config_list[i].data); - break; - default: - addConfigStringEntry(ptr, i, config_list[i].label, config_list[i].type, (char *)config_list[i].data); - break; - } - } - strcat(ptr, "
OptionValue
"); - //
"); -#endif HTMLSAVEBUTTON(ptr); HTMLBODYEND(ptr); Serial.printf("Config form: size=%d bytes\n", strlen(message)); @@ -998,12 +783,6 @@ const char *handleConfigPost(AsyncWebServerRequest * request) { String strlabel = request->getParam(i)->name(); const char *label = strlabel.c_str(); if (label[strlen(label) - 1] == '#') continue; -#if 0 - if (strncmp(label, "CFG", 3) != 0) continue; - int idx = atoi(label + 3); - Serial.printf("idx is %d\n", idx); - if (config_list[idx].type == -1) continue; // skip separator entries, should not happen -#endif AsyncWebParameter *value = request->getParam(label, true); if (!value) continue; String strvalue = value->value(); @@ -1016,19 +795,6 @@ const char *handleConfigPost(AsyncWebServerRequest * request) { strvalue = String(i); } } -#if 0 - if (config_list[idx].type == -4) { // input button port with "touch" checkbox - char tmp[10]; - snprintf(tmp, 10, "TO%d", idx); - AsyncWebParameter *touch = request->getParam(tmp, true); - if (touch) { - int i = atoi(strvalue.c_str()); - if (i != -1 && i != 255) i += 128; - strvalue = String(i); - } - } - Serial.printf("Processing %s=%s\n", config_list[idx].name, strvalue.c_str()); -#endif Serial.printf("Processing %s=%s\n", label, strvalue.c_str()); //int wlen = f.printf("%s=%s\n", config_list[idx].name, strvalue.c_str()); int wlen = f.printf("%s=%s\n", label, strvalue.c_str()); @@ -1370,21 +1136,6 @@ const char *sendGPX(AsyncWebServerRequest * request) { return message; } -#if 0 -// no longer supported -// tcp socket / json for android app is used now -void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { - if (type == WS_EVT_CONNECT) { - Serial.println("Websocket client connection received"); - client->text("Hello from ESP32 Server"); - //globalClient = client; - } else if (type == WS_EVT_DISCONNECT) { - Serial.println("Client disconnected"); - globalClient = NULL; - } -} -#endif - const char* PARAM_MESSAGE = "message"; void SetupAsyncServer() { @@ -1757,21 +1508,21 @@ void initGPS() { if (testfile && !testfile.isDirectory()) { testfile.close(); Serial.println("GPS resetting baud to 9k6..."); - /* TODO: debug: - * Sometimes I have seen the Serial2.begin to cause a reset - * Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) - * Backtrace: 0x40081d2f:0x3ffc11b0 0x40087969:0x3ffc11e0 0x4000bfed:0x3ffb1db0 0x4008b7dd:0x3ffb1dc0 0x4017afee:0x3ffb1de0 0x4017b04b:0x3ffb1e20 0x4010722b:0x3ffb1e50 0x40107303:0x3ffb1e70 0x4010782d:0x3ffb1e90 0x40103814:0x3ffb1ed0 0x400d8772:0x3ffb1f10 0x400d9057:0x3ffb1f60 0x40107aca:0x3ffb1fb0 0x4008a63e:0x3ffb1fd0 - * #0 0x40081d2f:0x3ffc11b0 in _uart_isr at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 - * #1 0x40087969:0x3ffc11e0 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154 - * #2 0x4000bfed:0x3ffb1db0 in ?? ??:0 - * #3 0x4008b7dd:0x3ffb1dc0 in vTaskExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c:3507 - * #4 0x4017afee:0x3ffb1de0 in esp_intr_alloc_intrstatus at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c:784 - * #5 0x4017b04b:0x3ffb1e20 in esp_intr_alloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c:784 - * #6 0x4010722b:0x3ffb1e50 in uartEnableInterrupt at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 - * #7 0x40107303:0x3ffb1e70 in uartAttachRx at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 - * #8 0x4010782d:0x3ffb1e90 in uartBegin at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 - * #9 0x40103814:0x3ffb1ed0 in HardwareSerial::begin(unsigned long, unsigned int, signed char, signed char, bool, unsigned long) at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/HardwareSerial.cpp:190 - */ + /* TODO: debug: + Sometimes I have seen the Serial2.begin to cause a reset + Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) + Backtrace: 0x40081d2f:0x3ffc11b0 0x40087969:0x3ffc11e0 0x4000bfed:0x3ffb1db0 0x4008b7dd:0x3ffb1dc0 0x4017afee:0x3ffb1de0 0x4017b04b:0x3ffb1e20 0x4010722b:0x3ffb1e50 0x40107303:0x3ffb1e70 0x4010782d:0x3ffb1e90 0x40103814:0x3ffb1ed0 0x400d8772:0x3ffb1f10 0x400d9057:0x3ffb1f60 0x40107aca:0x3ffb1fb0 0x4008a63e:0x3ffb1fd0 + #0 0x40081d2f:0x3ffc11b0 in _uart_isr at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 + #1 0x40087969:0x3ffc11e0 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154 + #2 0x4000bfed:0x3ffb1db0 in ?? ??:0 + #3 0x4008b7dd:0x3ffb1dc0 in vTaskExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c:3507 + #4 0x4017afee:0x3ffb1de0 in esp_intr_alloc_intrstatus at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c:784 + #5 0x4017b04b:0x3ffb1e20 in esp_intr_alloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c:784 + #6 0x4010722b:0x3ffb1e50 in uartEnableInterrupt at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 + #7 0x40107303:0x3ffb1e70 in uartAttachRx at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 + #8 0x4010782d:0x3ffb1e90 in uartBegin at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464 + #9 0x40103814:0x3ffb1ed0 in HardwareSerial::begin(unsigned long, unsigned int, signed char, signed char, bool, unsigned long) at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/HardwareSerial.cpp:190 + */ Serial2.begin(115200, SERIAL_8N1, sonde.config.gps_rxd, sonde.config.gps_txd); Serial2.write(ubx_set9k6, sizeof(ubx_set9k6)); delay(200); @@ -1927,7 +1678,7 @@ void IRAM_ATTR buttonISR() { button1.numberKeyPresses += 1; button1.keydownTime = now; } else { //Button up - if(!b1wasdown) return; + if (!b1wasdown) return; b1wasdown = false; unsigned long now = my_millis(); if (button1.doublepress == -1) return; // key was never pressed before, ignore button up @@ -2008,13 +1759,15 @@ void handlePMUirq() { button2.pressed = KP_MID; button2.keydownTime = my_millis(); } - pmu_irq = false; + if (pmu_irq != 2) { + pmu_irq = 0; + } axp.clearIRQ(); xSemaphoreGive( axpSemaphore ); } } else { Serial.println("handlePMIirq() called. THIS SHOULD NOT HAPPEN w/o button2_axp set"); - pmu_irq = false; // prevent main loop blocking + pmu_irq = 0; // prevent main loop blocking } } @@ -2171,22 +1924,54 @@ void setup() // Display backlight on M5 Core2 axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON); axp.setDCDC3Voltage(3300); + // SetBusPowerMode(0): + // #define AXP192_GPIO0_CTL (0x90) + // #define AXP192_GPIO0_VOL (0x91) + // #define AXP202_LDO234_DC23_CTL (0x12) + + // The axp class lacks a functino to set GPIO0 VDO to 3.3V (as is done by original M5Stack software) + // so do this manually (default value 2.8V did not have the expected effect :)) + // data = Read8bit(0x91); + // write1Byte(0x91, (data & 0X0F) | 0XF0); + uint8_t reg; + Wire.beginTransmission((uint8_t)AXP192_SLAVE_ADDRESS); + Wire.write(AXP192_GPIO0_VOL); + Wire.endTransmission(); + Wire.requestFrom(AXP192_SLAVE_ADDRESS, 1); + reg = Wire.read(); + reg = (reg&0x0F) | 0xF0; + Wire.beginTransmission((uint8_t)AXP192_SLAVE_ADDRESS); + Wire.write(AXP192_GPIO0_VOL); + Wire.write(reg); + Wire.endTransmission(); + // data = Read8bit(0x90); + // Write1Byte(0x90, (data & 0XF8) | 0X02) + axp.setGPIOMode(AXP_GPIO_0, AXP_IO_LDO_MODE); // disable AXP supply from VBUS + pmu_irq = 2; // IRQ pin is not connected on Core2 + // data = Read8bit(0x12); //read reg 0x12 + // Write1Byte(0x12, data | 0x40); // enable 3,3V => 5V booster + // this is done below anyway: axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + + axp.adc1Enable(AXP202_ACIN_VOL_ADC1, 1); + axp.adc1Enable(AXP202_ACIN_CUR_ADC1, 1); } else { // GPS on T-Beam, buzzer on M5 Core2 axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); + axp.adc1Enable(AXP202_VBUS_VOL_ADC1, 1); + axp.adc1Enable(AXP202_VBUS_CUR_ADC1, 1); } axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); axp.setDCDC1Voltage(3300); - axp.adc1Enable(AXP202_VBUS_VOL_ADC1, 1); - axp.adc1Enable(AXP202_VBUS_CUR_ADC1, 1); axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); - if (sonde.config.button2_axp) { - pinMode(PMU_IRQ, INPUT_PULLUP); - attachInterrupt(PMU_IRQ, [] { - pmu_irq = true; - }, FALLING); + if (sonde.config.button2_axp ) { + if (pmu_irq != 2) { + pinMode(PMU_IRQ, INPUT_PULLUP); + attachInterrupt(PMU_IRQ, [] { + pmu_irq = 1; + }, FALLING); + } //axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1); axp.enableIRQ( AXP202_PEK_LONGPRESS_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1 ); axp.clearIRQ(); @@ -2545,7 +2330,7 @@ void loopDecoder() { // first check if ID and position lat+lonis ok if (s->d.validID && ((s->d.validPos & 0x03) == 0x03)) { - char *str = aprs_senddata(s, sonde.config.call, sonde.config.udpfeed.symbol); + char *str = aprs_senddata(s, sonde.config.call, sonde.config.objcall, sonde.config.udpfeed.symbol); if (connected) { char raw[201]; int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN); @@ -2569,6 +2354,7 @@ void loopDecoder() { } else if ( tcpclient.connected() ) { unsigned long now = millis(); + Serial.printf("aprs: now-last = %ld\n", (now-lasttcp)); if ( (now - lasttcp) > sonde.config.tcpfeed.highrate * 1000L ) { strcat(str, "\r\n"); Serial.print(str); @@ -2601,6 +2387,10 @@ void loopDecoder() { sondehub_finish_data(&shclient, s, &sonde.config.sondehub); #endif } + // Send own position periodically + if (sonde.config.tcpfeed.active) { + aprs_station_update(); + } // always send data, even if not valid.... if (rdzclient.connected()) { Serial.println("Sending position via TCP as rdzJSON"); @@ -2620,12 +2410,12 @@ void loopDecoder() { *gps = 0; } //maintain backwords compatibility - float lat = isnan(s->d.lat)?0:s->d.lat; - float lon = isnan(s->d.lon)?0:s->d.lon; - float alt = isnan(s->d.alt)?-1:s->d.alt; - float vs = isnan(s->d.vs)?0:s->d.vs; - float hs = isnan(s->d.hs)?0:s->d.hs; - float dir = isnan(s->d.dir)?0:s->d.dir; + float lat = isnan(s->d.lat) ? 0 : s->d.lat; + float lon = isnan(s->d.lon) ? 0 : s->d.lon; + float alt = isnan(s->d.alt) ? -1 : s->d.alt; + float vs = isnan(s->d.vs) ? 0 : s->d.vs; + float hs = isnan(s->d.hs) ? 0 : s->d.hs; + float dir = isnan(s->d.dir) ? 0 : s->d.dir; // int len = snprintf(raw, 1024, "{" @@ -3445,6 +3235,47 @@ void loop() { } +void aprs_station_update() { + int chase = sonde.config.chase; + // automatically decided if CHASE or FIXED mode is used (for config AUTO) + if (chase == SH_LOC_AUTO) { + if (SH_LOC_AUTO_IS_CHASE) chase = SH_LOC_CHASE; else chase = SH_LOC_FIXED; + } + unsigned long time_now = millis(); + unsigned long time_delta = time_now - time_last_aprs_update; + unsigned long update_time = (chase == SH_LOC_CHASE) ? APRS_MOBILE_STATION_UPDATE_TIME : APRS_STATION_UPDATE_TIME; + Serial.printf("aprs_station_update: delta: %ld, update in %ld\n", time_delta, update_time); + if (time_delta < update_time) return; + Serial.println("Update is due!!"); + + float lat, lon; + if (chase == SH_LOC_FIXED) { + // fixed location + lat = sonde.config.rxlat; + lon = sonde.config.rxlon; + if (isnan(lat) || isnan(lon)) return; + } else { + if (gpsPos.valid && gpsPos.lat != 0 && gpsPos.lon != 0) { + lat = gpsPos.lat; + lon = gpsPos.lon; + } else { + return; + } + } + Serial.printf("Really updating!! (objcall is %s)", sonde.config.objcall); + char *bcn = aprs_send_beacon(sonde.config.call, lat, lon, sonde.config.beaconsym + ((chase==SH_LOC_CHASE)?2:0), sonde.config.comment); + if ( tcpclient.disconnected()) { + tcpclient.connect(sonde.config.tcpfeed.host, sonde.config.tcpfeed.port); + } + if ( tcpclient.connected() ) { + strcat(bcn, "\r\n"); + Serial.println("****BEACON****"); + Serial.print(bcn); + tcpclient.write(bcn, strlen(bcn)); + time_last_aprs_update = time_now; + } +} + #if FEATURE_SONDEHUB // Sondehub v2 DB related codes /* @@ -3555,7 +3386,7 @@ void sondehub_station_update(WiFiClient * client, struct st_sondehub * conf) { // At least, do this safely. See Notes-on-Using-WiFiClient.txt for details // If any of the client->print failed before (remote end closed connection), // then calling client->read will cause a LoadProhibited exception - if(client->connected()) { + if (client->connected()) { String response = client->readString(); Serial.println(response); Serial.println("Response done..."); @@ -3641,9 +3472,11 @@ void sondehub_reply_handler(WiFiClient * client) { // also handle periodic station updates here... // interval check moved to sondehub_station_update to avoid having to calculate distance in auto mode twice - if (shState == SH_CONN_IDLE || shState == SH_DISCONNECTED ) { - // (do not set station update while a telemetry report is being sent - sondehub_station_update(&shclient, &sonde.config.sondehub); + if (sonde.config.sondehub.active) { + if (shState == SH_CONN_IDLE || shState == SH_DISCONNECTED ) { + // (do not set station update while a telemetry report is being sent + sondehub_station_update(&shclient, &sonde.config.sondehub); + } } } diff --git a/RX_FSK/data/cfg.js b/RX_FSK/data/cfg.js index ddc6231..9ef3bc5 100644 --- a/RX_FSK/data/cfg.js +++ b/RX_FSK/data/cfg.js @@ -35,17 +35,18 @@ var cfgs = [ [ "call", "Call"], [ "passcode", "Passcode"], [ "kisstnc.active", "KISS TNC (port 14590) (needs reboot)"], -[ "kisstnc.idformat", "KISS TNC ID format"], [ "axudp.active", "AXUDP active"], [ "axudp.host", "AXUDP host"], [ "axudp.port", "AXUDP port"], -[ "axudp.idformat", "DFM ID format"], [ "axudp.highrate", "Rate limit"], [ "tcp.active", "APRS TCP active"], -[ "tcp.host", "ARPS TCP host"], +[ "tcp.host", "APRS TCP host"], [ "tcp.port", "APRS TCP port"], -[ "tcp.idformat", "DFM ID format"], [ "tcp.highrate", "Rate limit"], +[ "tcp.objcall", "APRS object call"], +[ "tcp.beaconsym", "APRS tracker symbol"], +[ "tcp.chase", "APRS location reporting (0=off, 1=fixed, 2=chase/GPS, 3=auto)"], +[ "tcp.comment", "APRS location comment"], [ "", "MQTT data feed configuration", "https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/MQTT-configuration"], [ "mqtt.active", "MQTT active (needs reboot)"], [ "mqtt.id", "MQTT client ID"], diff --git a/RX_FSK/data/config.txt b/RX_FSK/data/config.txt index 73f7250..aca7559 100644 --- a/RX_FSK/data/config.txt +++ b/RX_FSK/data/config.txt @@ -97,17 +97,19 @@ axudp.host=192.168.42.20 axudp.port=9002 axudp.symbol=/O axudp.highrate=1 -axudp.idformat=0 #-------------------------------# -# maybe some time in the future +# connect to some aprs server #-------------------------------# -# currently simply not implemented, no need to put anything here anyway tcp.active=0 tcp.host=radiosondy.info tcp.port=14590 tcp.symbol=/O tcp.highrate=20 -tcp.idformat=0 +# send beacon (possibly with different call or SSID) +tcp.chase=0 +tcp.objcall= +tcp.beaconsym=/`/( +tcp.comment= #-------------------------------# # mqtt settings #-------------------------------# diff --git a/RX_FSK/data/livemap.js b/RX_FSK/data/livemap.js index 75c2614..9d425cf 100644 --- a/RX_FSK/data/livemap.js +++ b/RX_FSK/data/livemap.js @@ -14,11 +14,20 @@ $(document).ready(function(){ L.control.scale().addTo(map); L.control.attribution({prefix:false}).addTo(map); - var osm = L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', { - attribution: '
Leaflet · Map: OpenStreetMap
', - minZoom: 1, - maxZoom: 19 - }); + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + var osm = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors © CARTO', + minZoom: 1, + maxZoom: 19 + }); + } else { + var osm = L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', { + attribution: '
Leaflet · Map: OpenStreetMap
', + minZoom: 1, + maxZoom: 19 + }); + } + var esri = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { attribution: '
Leaflet · Map: Esri · Earthstar Geographics
', minZoom: 1, diff --git a/RX_FSK/data/qrg.txt b/RX_FSK/data/qrg.txt index 43f2bb2..6b3cc96 100644 --- a/RX_FSK/data/qrg.txt +++ b/RX_FSK/data/qrg.txt @@ -14,10 +14,4 @@ 405.900 4 + Bergen_2 405.100 4 + Meppen_2 405.300 4 - Essen -403.330 9 - TrUebPl -403.450 9 - TrUebPl -403.470 9 - TrUebPl -403.850 9 - TrUebPl -403.870 9 - TrUebPl -403.890 9 - TrUebPl # end diff --git a/RX_FSK/data/screens1.txt b/RX_FSK/data/screens1.txt index baa0fd5..52bd823 100644 --- a/RX_FSK/data/screens1.txt +++ b/RX_FSK/data/screens1.txt @@ -115,7 +115,7 @@ timeaction=#,D,+ 0,5=S#: 0,9=T 3,0=F MHz -5,0=S +5,0,16=S 7,5=n ############ diff --git a/RX_FSK/data/screens5.txt b/RX_FSK/data/screens5.txt index 857b5cc..ba3fa18 100644 --- a/RX_FSK/data/screens5.txt +++ b/RX_FSK/data/screens5.txt @@ -111,217 +111,220 @@ ########### @ScannerTFT-D timer=-1,0,0 -key1action=D,#,F,W -key2action=#,#,#,# +key1action=F,#,#,W +key2action=>,#,#,# timeaction=#,D,+ scale=11,10 fonts=0,2 -color=B0B0B0 -0,0=Xsuche.. -color=6C757D -3,0=xStartort -color=B0B0B0 -4,0=S -color=6C757D -3,15=xFreq. Platz -color=B0B0B0 -4,15,23=S# -color=6C757D -6,0=xTyp -color=B0B0B0 -7,0,5=T -color=6C757D -6,15=xFrequenz -color=B0B0B0 -7,15=F -color=6C757D -28,0=Scanner +color=FFFFFF +0,0.3=XSuche... +color=79CDCD +3,0.3=xFreq. Platz +color=FFFFFF +4,0.3,3=S# +color=79CDCD,0 +6,0.3=xStartort +color=FFFFFF +7,0.3,20=S +color=79CDCD,0 +9,0.3=xTyp +color=FFFFFF +10,0.33,5=T +color=79CDCD +9,15=xFrequenz +color=FFFFFF +10,15=F +color=79CDCD +28,0.3=xScanner 28,9=n 28,21=bVV + ############ @MainTFT-D timer=-1,-1,-1 -key1action=>,0,F,W +key1action=0,#,F,W key2action=+,#,#,# timeaction=#,#,0 scale=11,10 fonts=0,2 -color=6C757D -0,0=xSerial -0,6=t -color=B0B0B0 -1,0=Is -color=6C757D +color=79CDCD +0,0.3=xSerial +0,6,10=t +color=FFFFFF +1,0.3=Is +color=79CDCD 0,14=xFreq. 0,17.5=s -color=B0B0B0 +color=FFFFFF 1,14=F -color=6C757D -3,0=xLatitude -color=B0B0B0 -4,0,10=L -color=6C757D +color=79CDCD +3,0.3=xLatitude +color=FFFFFF +4,0.3,10=L +color=79CDCD 3,14=xLongitude -color=B0B0B0 +color=FFFFFF 4,14,23=O -color=6C757D -6,0=xHoriz. Geschw. -color=B0B0B0 -7,0,10=Hkkm/h -color=6C757D +color=79CDCD +6,0.3=xHoriz. Geschw. +color=FFFFFF +7,0.3,10=Hkkm/h +color=79CDCD 6,14=xVert. Geschw. -color=B0B0B0 -7,13.5,23=Vm/s -color=6C757D +color=FFFFFF +7,14,23=Vm/s +color=79CDCD 9.5,14=xHoehe Sonde color=ffff00 -10.5,13.5,23=A +10.7,14,23=A color=ffff00,000033 9,1=g0CCS,45,ffff00,000044,4,55ff55,4,eeaa00 color=bbbbbb,000000 -color=6C757D +color=79CDCD 12.5,14=xHoehe RX color=ffff00 -13.5,14=GH -color=6C757D -15.5,14=xEntfernung +13.5,14,23=GH +color=79CDCD +15.5,14=xTimer color=ffff00 -16.5,14,23=GD -color=6C757D -19,0=xTimer -color=B0B0B0 -20,0,10=Kc4 -color=6C757D +16.5,14,23=Kc4 +fonts=0,8 +color=FFFFFF +18.7,0,-12.3=GD +fonts=0,2 +color=79CDCD 19,14=xRSSI -color=B0B0B0 +color=FFFFFF 20,14,23=R -color=6C757D -22,0=xLufttemperatur -color=B0B0B0 -23,0,10=Mt°C -color=6C757D +color=79CDCD +22,0.3=xLufttemperatur +color=FFFFFF +23,0.3,10=Mt°C +color=79CDCD 22,14=xLuftfeuchtigkeit -color=B0B0B0 +color=FFFFFF 23,14,23=Mh%rH -color=6C757D -25,0=xLuftdruck -color=B0B0B0 -26,0,10=MphPa -color=6C757D +color=79CDCD +25,0.3=xLuftdruck +color=FFFFFF +26,0.3,10=MphPa +color=79CDCD 25,14=xZellenspannung -color=B0B0B0 +color=FFFFFF 26,14,23=MbV -color=6C757D -28,0=Q +color=FFFFFF +28,0.3=Q +color=79CDCD 28,13=c 28,21=bVV ########### @ScannerTFT-E timer=-1,0,0 -key1action=D,#,F,W -key2action=#,#,#,# +key1action=F,#,#,W +key2action=>,#,#,# timeaction=#,D,+ scale=11,10 fonts=0,2 -color=B0B0B0 -0,0=XScan... -color=6C757D -3,0=xLaunchsize -color=B0B0B0 -4,0=S -color=6C757D -3,15=xFreq.index -color=B0B0B0 -4,15,23=S# -color=6C757D -6,0=xType -color=B0B0B0 -7,0,5=T -color=6C757D +color=FFFFFF +0,0.3=XScan... +color=79CDCD +3,0.3=xFreq. index +color=FFFFFF +4,0.3,3=S# +color=79CDCD,0 +6,0.3=xLaunchsize +color=FFFFFF +7,0.3,20=S +color=79CDCD,0 +9,0.3=xType +color=FFFFFF +10,0.33,5=T +color=79CDCD 6,15=xFrequency -color=B0B0B0 +color=FFFFFF 7,15=F -color=6C757D -28,0=Scanner +color=79CDCD +28,0.3=xScanner 28,9=n 28,21=bVV ############ @MainTFT timer=-1,-1,-1 -key1action=>,0,F,W +key1action=0,#,F,W key2action=+,#,#,# timeaction=#,#,0 scale=11,10 fonts=0,2 -color=6C757D -0,0=xSerial -0,6=t -color=B0B0B0 -1,0=Is -color=6C757D +color=79CDCD +0,0.3=xSerial +0,6,10=t +color=FFFFFF +1,0.3=Is +color=79CDCD 0,14=xFreq. 0,17.5=s -color=B0B0B0 +color=FFFFFF 1,14=F -color=6C757D -3,0=xLatitude -color=B0B0B0 -4,0,10=L -color=6C757D +color=79CDCD +3,0.3=xLatitude +color=FFFFFF +4,0.3,10=L +color=79CDCD 3,14=xLongitude -color=B0B0B0 +color=FFFFFF 4,14,23=O -color=6C757D -6,0=xHor.Velocity -color=B0B0B0 -7,0,10=Hkkm/h -color=6C757D +color=79CDCD +6,0.3=xHor.Velocity +color=FFFFFF +7,0.3,10=Hkkm/h +color=79CDCD 6,14=xVert.Velocity -color=B0B0B0 -7,13.5,23=Vm/s -color=6C757D +color=FFFFFF +7,14,23=Vm/s +color=79CDCD 9.5,14=xAltitude color=ffff00 -10.5,13.5,23=A +10.7,14,23=A color=ffff00,000033 9,1=g0CCS,45,ffff00,000044,4,55ff55,4,eeaa00 color=bbbbbb,000000 -color=6C757D +color=79CDCD 12.5,14=xRX Altitude color=ffff00 -13.5,14=GH -color=6C757D -15.5,14=xDistance +13.5,14,23=GH +color=79CDCD +15.5,14=xTimer color=ffff00 -16.5,14,23=GD -color=6C757D -19,0=xTimer -color=B0B0B0 -20,0,10=Kc4 -color=6C757D +16.5,14,23=Kc4 +fonts=0,8 +color=FFFFFF +18.7,0,-12.3=GD +fonts=0,2 +color=79CDCD 19,14=xRSSI -color=B0B0B0 +color=FFFFFF 20,14,23=R -color=6C757D -22,0=xTemperature -color=B0B0B0 -23,0,10=Mt°C -color=6C757D +color=79CDCD +22,0.3=xTemperature +color=FFFFFF +23,0.3,10=Mt°C +color=79CDCD 22,14=xHumidity -color=B0B0B0 +color=FFFFFF 23,14,23=Mh%rH -color=6C757D -25,0=xPressure -color=B0B0B0 -26,0,10=MphPa -color=6C757D +color=79CDCD +25,0.3=xPressure +color=FFFFFF +26,0.3,10=MphPa +color=79CDCD 25,14=xSonde Battery -color=B0B0B0 +color=FFFFFF 26,14,23=MbV -color=6C757D -28,0=Q +color=FFFFFF +28,0.3=Q +color=79CDCD 28,13=c 28,21=bVV diff --git a/RX_FSK/data/style.css b/RX_FSK/data/style.css index 2a32214..8d93559 100755 --- a/RX_FSK/data/style.css +++ b/RX_FSK/data/style.css @@ -72,7 +72,6 @@ td#sfreq { display: none; flex: 1; padding: 6px 12px; - border: 1px solid #ccc; border-top: none; flex-direction: column; overflow: auto; @@ -340,11 +339,11 @@ p{ @media (prefers-color-scheme: dark) { body { background-color: #333; - } + } h2{ color: white; } - table, th, td, .save, .topnav a.active { + table, th, td, .save, a.active { color: white; border: 1px solid grey; border-collapse: collapse; @@ -354,4 +353,28 @@ p{ color: white; background-color: #333; } -} \ No newline at end of file + a:link, a:visited { + color: #D3D3D3; + } + .topnav, td#sfreq { + background-color: grey; + } + .topnav a:visited { + color: white; + } + .ctlbtn { + color: white; + background-color: grey; + } + .leaflet-center { + color: white; + background-color: grey; + } + .leaflet-bar a { + background-color: grey !important; + } + .leaflet-popup-content-wrapper, .leaflet-popup-tip { + color: white !important; + background: grey !important; + } +} diff --git a/RX_FSK/src/DFM.cpp b/RX_FSK/src/DFM.cpp index 49a0642..1b0cad3 100644 --- a/RX_FSK/src/DFM.cpp +++ b/RX_FSK/src/DFM.cpp @@ -14,6 +14,7 @@ #define DFM_FRAMELEN 33 +#define MAXIDAGE 1800 /* * observed DAT patterns for DFM-9: @@ -217,6 +218,12 @@ const char* typestr[16]={ "", "" }; +void DFM::killid() { + SondeData *sd = &(sonde.si()->d); + sd->validID = false; + memset((void *)&dfmstate, 0, sizeof(dfmstate)); +} + #define DFMIDTHRESHOLD 2 /* inspired by oe5dxl's finddnmae in sondeudp.c of dxlaprs */ void DFM::finddfname(uint8_t *b) @@ -432,6 +439,9 @@ void DFM::decodeDAT(uint8_t *dat) int tt = (y-1970)*365 + (y-1969)/4; // days since 1970 if(m<=12) { tt += MON[m]; if((y%4)==0 && m>2) tt++; } tt = (tt+d-1)*(60*60*24) + h*3600 + mi*60; + // If we get a time stamp much different to the previously received one, kill the ID. + // most likely, we have a new sonde now, so wait for the new ID. + if(tt-dfmstate.datesec > MAXIDAGE) killid(); dfmstate.datesec = tt; dfmstate.good |= 0x100; } @@ -486,7 +496,9 @@ void DFM::decodeDAT(uint8_t *dat) vh = ((uint16_t)dat[4]<<8) + dat[5]; Serial.print("GPS-lat: "); Serial.print(lat*0.0000001); Serial.print(", hor-V: "); Serial.print(vh*0.01); - si->lat = lat*0.0000001; + lat = lat*0.0000001; + if( lat!=0 && si->lat!=0 && abs(lat-si->lat)>.25 ) killid(); + si->lat = lat; si->hs = vh*0.01; if(lat!=0 || vh!=0) si->validPos |= 0x11; else si->validPos &= ~0x11; } @@ -496,7 +508,9 @@ void DFM::decodeDAT(uint8_t *dat) float lon, dir; lon = (int32_t)(((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + (uint32_t)dat[3]); dir = ((uint16_t)dat[4]<<8) + dat[5]; - si->lon = lon*0.0000001; + lon = lon*0.0000001; + if( lon!=0 && si->lon!=0 && abs(lon-si->lon)>.25 ) killid(); + si->lon = lon; si->dir = dir*0.01; Serial.print("GPS-lon: "); Serial.print(si->lon); Serial.print(", dir: "); Serial.print(si->dir); diff --git a/RX_FSK/src/DFM.h b/RX_FSK/src/DFM.h index baf5ea1..db7564f 100644 --- a/RX_FSK/src/DFM.h +++ b/RX_FSK/src/DFM.h @@ -37,8 +37,7 @@ private: void bitsToBytes(uint8_t *bits, uint8_t *bytes, int len); int processDFMdata(uint8_t dt); int decodeFrameDFM(uint8_t *data); - int receiveOld(); - int receiveNew(); + void killid(); #define B 8 diff --git a/RX_FSK/src/Display.cpp b/RX_FSK/src/Display.cpp index 66d063f..706e8f0 100644 --- a/RX_FSK/src/Display.cpp +++ b/RX_FSK/src/Display.cpp @@ -305,6 +305,17 @@ void U8x8Display::getDispSize(uint8_t *height, uint8_t *width, uint8_t *lineskip void U8x8Display::drawString(uint16_t x, uint16_t y, const char *s, int16_t width, uint16_t fg, uint16_t bg) { char buf[50]; utf2latin15(s, buf, 50); + if(width!=WIDTH_AUTO && width>0) { + for(int l = strlen(buf); ldrawString(x, y, buf); } @@ -1333,7 +1344,7 @@ void Display::drawSite(DispEntry *de) { case '#': // currentSonde is index in array starting with 0; // but we draw "1" for the first entry and so on... - snprintf(buf, 3, "%2d", sonde.currentSonde+1); + snprintf(buf, 3, "%d ", sonde.currentSonde+1); buf[2]=0; break; case 't': @@ -1355,8 +1366,13 @@ void Display::drawSite(DispEntry *de) { buf[5]=0; break; case 0: case 'l': default: // launch site - drawString(de, sonde.si()->launchsite); - return; + // TODO: This is a workaround to be compatible with older screens1.txt + // This does not work correctly with non-ascii utf8 characters. + // For this reason, this workaround will likely be removed in the future + // Instead, all screens?.txt should always indicate the max. length of the displayed string. + snprintf(buf, 17, "%-16s", sonde.si()->launchsite); + //drawString(de, sonde.si()->launchsite); + //return; } if(de->extra[0]) strcat(buf, de->extra+1); drawString(de, buf); @@ -1677,11 +1693,19 @@ void Display::drawBatt(DispEntry *de) { snprintf(buf, 30, "%.2f%s", val, de->extra+1); break; case 'U': - val = axp.getVbusVoltage(); + if(sonde.config.type == TYPE_M5_CORE2) { + val = axp.getAcinVoltage(); + } else { + val = axp.getVbusVoltage(); + } snprintf(buf, 30, "%.2f%s", val/1000, de->extra+1); break; case 'I': - val = axp.getVbusCurrent(); + if(sonde.config.type == TYPE_M5_CORE2) { + val = axp.getAcinCurrent(); + } else { + val = axp.getVbusCurrent(); + } snprintf(buf, 30, "%.2f%s", val, de->extra+1); break; case 'T': diff --git a/RX_FSK/src/M10M20.cpp b/RX_FSK/src/M10M20.cpp index 81315da..b6e2c0f 100644 --- a/RX_FSK/src/M10M20.cpp +++ b/RX_FSK/src/M10M20.cpp @@ -575,6 +575,7 @@ int M10M20::decodeframeM20(uint8_t *data) { ids[6] = (char)((id/100)%10+48); ids[7] = (char)((id/10)%10+48); ids[8] = (char)(id%10+48); + ids[9] = 0; strncpy(si->id, ids, 10); // Serial: AAB-C-DDEEE char *ser = si->ser; diff --git a/RX_FSK/src/Scanner.cpp b/RX_FSK/src/Scanner.cpp index 4f548df..64039f9 100644 --- a/RX_FSK/src/Scanner.cpp +++ b/RX_FSK/src/Scanner.cpp @@ -20,12 +20,13 @@ struct scancfg { int NCHAN; // number of channels to scan, PLOT_W * SMPL_PIX int SMOOTH; int ADDWAIT; + int VSCALE; }; //struct scancfg scanLCD={ 121, 7, 120/6, 120/6/4, 6000.0/120.0/20.0, 20, 120*20, 1 }; -struct scancfg scanLCD={ 121, 7, 120/6, 120/6/4, 6000.0/120.0/10.0, 10, 120*10, 2, 40 }; -struct scancfg scanTFT={ 210, 16, 210/6, 210/6/5, 6000.0/210.0/10.0, 10, 210*10, 1, 0 }; -struct scancfg scan9341={ 210, 16, 210/6, 210/6/5, 6000.0/210.0/10.0, 10, 210*10, 1, 0 }; +struct scancfg scanLCD={ 121, 7, 120/6, 120/6/4, 6000.0/120.0/10.0, 10, 120*10, 2, 40, 1 }; +struct scancfg scanTFT={ 210, 16, 210/6, 210/6/5, 6000.0/210.0/10.0, 10, 210*10, 1, 0, 1 }; +struct scancfg scan934x={ 300, 22, 300/6, 300/6/5, 6000.0/300.0/7.0, 7, 300*5, 1, 10, 2 }; struct scancfg &scanconfig = scanTFT; @@ -35,9 +36,12 @@ struct scancfg &scanconfig = scanTFT; // max of 120*5 and 210*3 //#define MAXN 210*10 -#define MAXN 120*20 -// max of 120 and 210 (ceil(210/8)*8)) -#define MAXDISP 216 +//#define MAXN 120*20 +#define MAXN 300*10 + +// max of 120 and 210 (ceil(210/8)*8)) -- now ceil(300/8)*8 +//#define MAXDISP 216 +#define MAXDISP 304 int scanresult[MAXN]; int scandisp[MAXDISP]; @@ -50,7 +54,7 @@ double peakf=0; const byte tilepatterns[9]={0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF}; void Scanner::fillTiles(uint8_t *row, int value) { for(int y=0; y=8) { row[8*y]=255; continue; } row[8*y] = tilepatterns[nbits]; @@ -66,8 +70,8 @@ void Scanner::fillTiles(uint8_t *row, int value) { */ ///// unused???? uint8_t tiles[16] = { 0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0, 1, 3, 7, 15, 31, 63, 127, 255}; -// type 0: lcd, 1: tft, 2: lcd(sh1106) -#define ISTFT (sonde.config.disptype==1 || sonde.config.disptype==3) +// type 0: lcd, 1: tft(ILI9225), 2: lcd(sh1106) 3:TFT(ili9341), 4: TFT(ili9342) +#define ISTFT (sonde.config.disptype!=0 && sonde.config.disptype!=2) void Scanner::plotResult() { int yofs = 0; @@ -77,9 +81,9 @@ void Scanner::plotResult() if (sonde.config.marker != 0) { itoa((sonde.config.startfreq), buf, 10); disp.rdis->drawString(0, 1, buf); - disp.rdis->drawString(95, 1, "MHz"); + disp.rdis->drawString(scanconfig.PLOT_W/2-10, 1, "MHz"); itoa((sonde.config.startfreq + 6), buf, 10); - disp.rdis->drawString(195, 1, buf); + disp.rdis->drawString(scanconfig.PLOT_W-15, 1, buf); } } else { @@ -120,8 +124,10 @@ void Scanner::scan() { if(!ISTFT) { // LCD small scanconfig = scanLCD; - } else { + } else if (sonde.config.disptype==1) { scanconfig = scanTFT; + } else { + scanconfig = scan934x; } // Configure STARTF = (sonde.config.startfreq * 1000000); diff --git a/RX_FSK/src/ShFreqImport.cpp b/RX_FSK/src/ShFreqImport.cpp index ff0e93e..407b7aa 100644 --- a/RX_FSK/src/ShFreqImport.cpp +++ b/RX_FSK/src/ShFreqImport.cpp @@ -48,7 +48,8 @@ void ShFreqImport::setLabel(int idx, char *id, float lat, float lon) { void ShFreqImport::usekeyvalue() { if(strcmp(keyword,"lat")==0) lat = atof(value); if(strcmp(keyword,"lon")==0) lon = atof(value); - if(strcmp(keyword,"frequency")==0) freq = atof(value); + if(strcmp(keyword,"frequency")==0) { if(isnan(freq)) freq = atof(value); } // prefer tx_frequency if available + if(strcmp(keyword,"tx_frequency")==0) freq = atof(value); if(strcmp(keyword,"type")==0) strcpy(type, value); } @@ -123,13 +124,12 @@ int ShFreqImport::handleChar(char c) { // wait for initial '{' if(c=='{') { Serial.println("{ found"); - lat = NAN; lon = NAN; freq = NAN; *type = 0; importState++; } break; case BEFOREID: // what for first '"' in { "A1234567" : { ... } }; or detect end - if(c=='"') { idpos = 0; importState++; } + if(c=='"') { idpos = 0; lat = NAN; lon = NAN; freq = NAN; *type = 0; importState++; } if(c=='}') { importState = ENDREACHED; cleanup(); @@ -156,7 +156,7 @@ int ShFreqImport::handleChar(char c) { if(c==':') { valuepos = 0; quotes = 0; - if(strcmp(keyword,"lat")==0 || strcmp(keyword, "lon")==0 || strcmp(keyword, "frequency")==0 ) + if(strcmp(keyword,"lat")==0 || strcmp(keyword, "lon")==0 || strcmp(keyword, "frequency")==0 || strcmp(keyword, "tx_frequency")==0) importState = BEFORENUMVAL; else { if (strcmp(keyword, "type")==0) diff --git a/RX_FSK/src/Sonde.cpp b/RX_FSK/src/Sonde.cpp index 2357fed..832d072 100644 --- a/RX_FSK/src/Sonde.cpp +++ b/RX_FSK/src/Sonde.cpp @@ -23,8 +23,8 @@ const char *RXstr[]={"RX_OK", "RX_TIMEOUT", "RX_ERROR", "RX_UNKNOWN"}; // Dependency to enum SondeType const char *sondeTypeStr[NSondeTypes] = { "DFM ", "RS41", "RS92", "Mxx ", "M10 ", "M20 ", "MP3H" }; const char *sondeTypeLongStr[NSondeTypes] = { "DFM (all)", "RS41", "RS92", "M10/M20", "M10 ", "M20 ", "MP3-H1" }; -const char sondeTypeChar[NSondeTypes] = { 'D', '4', 'R', 'M', '2', '3' }; -const char *manufacturer_string[]={"Graw", "Vaisala", "Vaisala", "Meteomodem", "Meteomodem", "Meteo-Radiy"}; +const char sondeTypeChar[NSondeTypes] = { 'D', '4', 'R', 'M', 'M', '2', '3' }; +const char *manufacturer_string[]={"Graw", "Vaisala", "Vaisala", "Meteomodem", "Meteomodem", "Meteomodem", "Meteo-Radiy"}; int fingerprintValue[]={ 17, 31, 64, 4, 55, 48, 23, 128+23, 119, 128+119, -1 }; const char *fingerprintText[]={ @@ -43,7 +43,7 @@ const char *fingerprintText[]={ /* global variables from RX_FSK.ino */ int getKeyPressEvent(); int handlePMUirq(); -extern bool pmu_irq; +extern uint8_t pmu_irq; extern SX1278FSK sx1278; /* Task model: @@ -247,14 +247,12 @@ void Sonde::defaultConfig() { strcpy(config.udpfeed.symbol, "/O"); config.udpfeed.port = 9002; config.udpfeed.highrate = 1; - config.udpfeed.idformat = ID_DFMGRAW; config.tcpfeed.active = 0; config.tcpfeed.type = 1; strcpy(config.tcpfeed.host, "radiosondy.info"); strcpy(config.tcpfeed.symbol, "/O"); config.tcpfeed.port = 12345; config.tcpfeed.highrate = 10; - config.tcpfeed.idformat = ID_DFMDXL; config.kisstnc.active = 0; strcpy(config.ephftp,"igs.bkg.bund.de/IGS/BRDC/"); @@ -542,10 +540,10 @@ uint16_t Sonde::waitRXcomplete() { uint16_t res=0; uint32_t t0 = millis(); rxloop: - while( !pmu_irq && rxtask.receiveResult==0xFFFF && millis()-t0 < 3000) { delay(50); } + while( (pmu_irq!=1) && rxtask.receiveResult==0xFFFF && millis()-t0 < 3000) { delay(50); } if( pmu_irq ) { handlePMUirq(); - goto rxloop; + if(pmu_irq!=2) goto rxloop; } if( rxtask.receiveResult == RX_UPDATERSSI ) { rxtask.receiveResult = 0xFFFF; diff --git a/RX_FSK/src/Sonde.h b/RX_FSK/src/Sonde.h index 36a5470..5e31a3a 100644 --- a/RX_FSK/src/Sonde.h +++ b/RX_FSK/src/Sonde.h @@ -182,8 +182,6 @@ struct st_mp3hconfig { }; -enum IDTYPE { ID_DFMDXL, ID_DFMGRAW, ID_DFMAUTO }; - struct st_feedinfo { bool active; int type; // 0:UDP(axudp), 1:TCP(aprs.fi) @@ -193,14 +191,12 @@ struct st_feedinfo { int lowrate; int highrate; int lowlimit; - int idformat; // 0: dxl 1: real 2: auto }; // maybe extend for external Bluetooth interface? // internal bluetooth consumes too much memory struct st_kisstnc { bool active; - int idformat; }; struct st_mqtt { @@ -229,7 +225,7 @@ struct st_sondehub { int fiactive; int fiinterval; int fimaxdist; - int fimaxage; + double fimaxage; }; // to be extended @@ -287,6 +283,10 @@ typedef struct st_rdzconfig { // for now, one feed for each type is enough, but might get extended to more? char call[10]; // APRS callsign int passcode; // APRS passcode + int chase; + char objcall[10]; // APRS object call (for wettersonde.net) + char beaconsym[5]; // APRS beacon symbol + char comment[32]; struct st_feedinfo udpfeed; // target for AXUDP messages struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections struct st_kisstnc kisstnc; // target for KISS TNC (via TCP, mainly for APRSdroid) diff --git a/RX_FSK/src/aprs.cpp b/RX_FSK/src/aprs.cpp index dc7ff6c..ea6cfdb 100644 --- a/RX_FSK/src/aprs.cpp +++ b/RX_FSK/src/aprs.cpp @@ -18,6 +18,7 @@ #include "aprs.h" extern const char *version_name; +extern const char *version_id; #if 0 int openudp(const char *ip, int port, struct sockaddr_in *si) { int fd; @@ -258,15 +259,51 @@ static uint32_t dao91(double x) char b[251]; //char raw[201]; +const char *destcall="APRRDZ"; -char *aprs_senddata(SondeInfo *si, const char *usercall, const char *sym) { - SondeData *s = &(si->d); - *b=0; +char *aprs_send_beacon(const char *usercall, float lat, float lon, const char *sym, const char *comment) { + *b = 0; aprsstr_append(b, usercall); aprsstr_append(b, ">"); - const char *destcall="APRRDZ"; + aprsstr_append(b, destcall); +#if 0 + aprsstr_append(b, ":/"); // / is report with timestamp + int i = strlen(b); + int sec = 0; // TODO: NOW!!! + snprintf(b+i, APRS_MAXLEN, "%02d%02d%02dh", sec/(60*60), (sec%(60*60))/60, sec%60); +#else + // report without timestamp + aprsstr_append(b, ":!"); // ! is report w/p timestamp +#endif + // lat + int i = strlen(b); + int lati = abs((int)lat); + int latm = (fabs(lat)-lati)*6000; + snprintf(b+i, APRS_MAXLEN-i, "%02d%02d.%02d%c%c", lati, latm/100, latm%100, lat<0?'S':'N', sym[0]); + // lon + i = strlen(b); + int loni = abs((int)lon); + int lonm = (fabs(lon)-loni)*6000; + snprintf(b+i, APRS_MAXLEN-i, "%03d%02d.%02d%c%c", loni, lonm/100, lonm%100, lon<0?'W':'E', sym[1]); + // maybe add alt + // maybe add DAO? + i = strlen(b); + snprintf(b+i, APRS_MAXLEN-i, "%s", comment); + + i = strlen(b); + snprintf(b+i, APRS_MAXLEN-i, " %s-%s", version_name, version_id); + //sprintf(b + strlen(b), "%s", version_name); + return b; +} + +char *aprs_senddata(SondeInfo *si, const char *usercall, const char *objcall, const char *sym) { + SondeData *s = &(si->d); + *b=0; + aprsstr_append(b, *objcall ? objcall : usercall); + aprsstr_append(b, ">"); // const char *destcall="APRARX,SONDEGATE,TCPIP,qAR,oh3bsg"; aprsstr_append(b, destcall); +// if(*objcall) { aprsstr_append(b, ","); aprsstr_append(b, usercall); } // uncompressed aprsstr_append(b, ":;"); char tmp[10]; @@ -310,7 +347,14 @@ char *aprs_senddata(SondeInfo *si, const char *usercall, const char *sym) { if( !isnan(s->relativeHumidity) ) { sprintf(b+strlen(b), "h=%.1f%% ", s->relativeHumidity); } - sprintf(b+strlen(b), "%.3fMHz Type=%s ", si->freq, sondeTypeStr[sonde.realType(si)]); + char type[12]; + if ( si->type == STYPE_RS41 && RS41::getSubtype(type, 11, si) == 0 ) { + // type was copied to type + } else { + strncpy(type, sondeTypeStr[sonde.realType(si)], 11); type[11]=0; + } + + sprintf(b+strlen(b), "%.3fMHz Type=%s ", si->freq, type /* sondeTypeStr[sonde.realType(si)] */ ); if( s->countKT != 0xffff && s->vframe - s->crefKT < 51 ) { sprintf(b+strlen(b), "TxOff=%dh%dm ", s->countKT/3600, (s->countKT-s->countKT/3600*3600)/60); } diff --git a/RX_FSK/src/aprs.h b/RX_FSK/src/aprs.h index 6ac8b8e..d2e50c5 100644 --- a/RX_FSK/src/aprs.h +++ b/RX_FSK/src/aprs.h @@ -2,13 +2,15 @@ #ifndef _aprs_h #define _aprs_h #include "Sonde.h" +#include "RS41.h" #define APRS_MAXLEN 201 void aprs_gencrctab(void); int aprsstr_mon2raw(const char *mon, char raw[], int raw_len); int aprsstr_mon2kiss(const char *mon, char raw[], int raw_len); -char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym); +char *aprs_send_beacon(const char *call, float lat, float lon, const char *sym, const char *comment); +char *aprs_senddata(SondeInfo *s, const char *usercall, const char *objcall, const char *sym); #endif diff --git a/RX_FSK/src/nav_gps_vel.cpp b/RX_FSK/src/nav_gps_vel.cpp index 6d4f547..174ec5b 100644 --- a/RX_FSK/src/nav_gps_vel.cpp +++ b/RX_FSK/src/nav_gps_vel.cpp @@ -85,6 +85,15 @@ static EPHEM_t *te; #define fread(buffer, siz, els, file) (file.read((uint8_t *)buffer, (siz)*(els))/siz) #define fgetc(file) (char)file.read() +int readDbl(File *fp, double *dbl) { + uint8_t buf[20]; + int l = fp->read(buf, 19); + if(l!=19) return -1; + if (buf[15] == 'D') buf[15] = 'E'; + buf[19] = 0; + sscanf((char *)buf, "%lf", dbl); + return 0; +} EPHEM_t *read_RNXpephs(const char *file) { int l, i; @@ -137,56 +146,84 @@ EPHEM_t *read_RNXpephs(const char *file) { strncpy(ephem.epoch+2, str, 15); ephem.epoch[16] = '\0'; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af0 = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af1 = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af2 = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.af0 = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.af1 = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.af2 = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af0 = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af1 = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af2 = dbl; while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; } l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iode = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crs = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.delta_n = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.M0 = dbl; + if(readDbl(&fp, &dbl)<0) break; //ephem.iode = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.crs = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.delta_n = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.M0 = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iode = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crs = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.delta_n = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.M0 = dbl; while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; } l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cuc = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.e = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cus = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.sqrta = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.cuc = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.e = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.cus = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.sqrta = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cuc = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.e = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cus = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.sqrta = dbl; while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; } l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.toe = dbl; - ephem.toc = ephem.toe; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cic = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.Omega0 = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cis = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.toe = dbl; ephem.toc = ephem.toe; + if(readDbl(&fp, &dbl)<0) break; ephem.cic = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.Omega0 = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.cis = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.toe = dbl; + // ephem.toc = ephem.toe; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cic = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.Omega0 = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cis = dbl; while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; } l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.i0 = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crc = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.w = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.OmegaDot = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.i0 = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.crc = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.w = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.OmegaDot = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.i0 = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crc = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.w = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.OmegaDot = dbl; while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; } l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.idot = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.codeL2 = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.gpsweek = (int)dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.idot = dbl; + if(readDbl(&fp, &dbl)<0) break; //ephem.codeL2 = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.gpsweek = (int)dbl; + if(readDbl(&fp, &dbl)<0) break; //ephem.iodc = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.idot = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.codeL2 = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.gpsweek = (int)dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl; while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; } l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.sva = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.health = (uint8_t)(dbl+0.1); - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.tgd = dbl; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl; + if(readDbl(&fp, &dbl)<0) break; //ephem.sva = dbl; + if(readDbl(&fp, &dbl)<0) break; ephem.health = (uint8_t)(dbl+0.1); + if(readDbl(&fp, &dbl)<0) break; ephem.tgd = dbl; + if(readDbl(&fp, &dbl)<0) break; //ephem.iodc = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.sva = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.health = (uint8_t)(dbl+0.1); + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.tgd = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl; while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; } l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; - l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.ttom = dbl; + if(readDbl(&fp, &dbl)<0) break; //ephem.ttom = dbl; + //l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.ttom = dbl; String l = fp.readStringUntil('\n'); /* // die letzten beiden Felder (spare) sind manchmal leer (statt 0.00); manchmal fehlt sogar das drittletzte Feld l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.fit = dbl; diff --git a/RX_FSK/version.h b/RX_FSK/version.h index 20716b9..6d69ffe 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,4 +1,4 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "master_v0.9.0"; +const char *version_id = "master_v0.9.1"; const int SPIFFS_MAJOR=2; const int SPIFFS_MINOR=16; diff --git a/Setup.md b/Setup.md deleted file mode 100644 index 0240910..0000000 --- a/Setup.md +++ /dev/null @@ -1,83 +0,0 @@ -# Prerequisites - -## Arduini IDE - -Get the latest Arduino IDE software from arduino.cc/en/Main/Software - -## ESP32 support - -File -> Preferences (or Arduino -> Preferences on MacOS) - -go to "Additional Board Manager URLs" - -Add *https://dl.espressif.com/dl/package_esp32_index.json* and press oK - - -Tool -> Boad -> Boards Manager - -search for "esp32" - -Install "esp32 by Espressif Systems" - -## ESP32 Flash Filesystem Upload support - -Get the zip file of the latest release from -https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/ - -Unzip the content to the tools folder of your Arduino IDE (~/Documents/Arduino/tools on MacOS, -similar on other OS) and restart IDE - -## Additional libraries - -Select Tools -> Manage Libraries... - -Install "U8g2" - -Install "MicroNMEA" - -(Install "TFT_22_ILI9225" -- currently not needed, due to some issues with the official library, there is a modified version in the rdz_ttgo_sonde source tree) - -## Additional libraries, part 2 - -From https://github.com/me-no-dev/ESPAsyncWebServer select "Download ZIP", extract to the libraries -folder of your Arduino IDE (~/Documents/Arduino/libraries on MacOS), rename main folder to ESPAsyncWebServer -(remove the "-master") - -From https://github.com/me-no-dev/AsyncTCP select "Download ZIP", extract to the libraries folder -of your Arduino IDE, and rename main folder to AsyncTCP - -From https://github.com/lewisxhe/AXP202X_Library select "Download ZIP", extract to the libraries -folder of your Arduino IDE, and rename main folder to AXP202X_Library-1.0 - -From https://github.com/dx168b/async-mqtt-client select "Download ZIP", extract to the libraries -folder of your Arduino IDE, and rename main folder to async-mqtt-client - -## Additional libraries, part 3 - -Copy the SX1278FSK, SondeLib and fonts folders from libraries of this project to your Arduino IDE's libraries -folders, or, alternatively, create symbolic links (MacOS/Linux): - -``` -cd ~/Documents/Arduino/libraries -ln -s /rdz_ttgo_sonde/libraries/SondeLib/ . -ln -s /rdz_ttgo_sonde/libraries/SX1278FSK/ . -ln -s /rdz_ttgo_sonde/libraries/fonts/ . -``` - -Restart the Arduino IDE - -(symbolic links are the preferred way, otherwise you have to copy the the libraries again after -each update) - -## Final steps - -In the IDE Tools -> Board: -> -Select "TTGO LoRa32-OLED v1" (or something that fits your board. -The binary images are currently built with the "T-Beam" board selection) - -Compile and Upload code - -Upload data to SPIFFS with Tools -> ESP32 Sketch Data Upload - - - diff --git a/platformio.ini b/platformio.ini index 19aa9d9..1326766 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,7 +25,7 @@ lib_deps_external = https://github.com/dx168b/async-mqtt-client [env:ttgo-lora32] -platform = https://github.com/platformio/platform-espressif32.git +platform = https://github.com/platformio/platform-espressif32.git#v3.3.2 board = ttgo-lora32-v1 framework = arduino monitor_speed = 115200