diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 1835245..c650d17 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -87,8 +87,11 @@ String readLine(Stream &stream) { int readLine(Stream &stream, char *buffer, int maxlen) { int n = stream.readBytesUntil('\n', buffer, maxlen); buffer[n] = 0; - if(n <= 0) return 0; - if(buffer[n-1]=='\r') { buffer[n-1]=0; n--; } + if (n <= 0) return 0; + if (buffer[n - 1] == '\r') { + buffer[n - 1] = 0; + n--; + } return n; } @@ -168,10 +171,13 @@ void setupChannelList() { type = STYPE_RS92; } else if (space[1] == '9') { - type = STYPE_DFM09; + type = STYPE_DFM09_OLD; } else if (space[1] == '6') { - type = STYPE_DFM06; + type = STYPE_DFM06_OLD; + } + else if (space[1] == 'D') { + type = STYPE_DFM; } else if (space[1] == 'M') { type = STYPE_M10; @@ -209,7 +215,7 @@ const char *createQRGForm() { i + 1, s.c_str()); } strcat(ptr, ""); - Serial.printf("QRG form: size=%d bytes\n",strlen(message)); + Serial.printf("QRG form: size=%d bytes\n", strlen(message)); return message; } @@ -249,7 +255,7 @@ const char *handleQRGPost(AsyncWebServerRequest *request) { const char *tstr = tstring.c_str(); const char *sstr = sstring.c_str(); Serial.printf("Processing a=%s, f=%s, t=%s, site=%s\n", active ? "YES" : "NO", fstr, tstr, sstr); - char typech = (tstr[2] == '4' ? '4' : tstr[2] == '9' ? 'R' : tstr[0] == 'M' ? 'M' : tstr[3]); // a bit ugly + char typech = (tstr[2] == '4' ? '4' : tstr[2] == '9' ? 'R' : tstr[0] == 'M' ? 'M' : tstr[3] == ' ' ? 'D' : tstr[3]); // a bit ugly file.printf("%3.3f %c %c %s\n", atof(fstr), typech, active ? '+' : '-', sstr); } file.close(); @@ -313,7 +319,7 @@ const char *createWIFIForm() { i + 1, i < nNetworks ? networks[i].pw.c_str() : ""); } strcat(ptr, ""); - Serial.printf("WIFI form: size=%d bytes\n",strlen(message)); + Serial.printf("WIFI form: size=%d bytes\n", strlen(message)); return message; } @@ -363,7 +369,7 @@ void addSondeStatus(char *ptr, int i) strcat(ptr, ""); sprintf(ptr + strlen(ptr), "\n", s->lat, s->lon, s->alt); @@ -392,7 +398,7 @@ const char *createStatusForm() { } } strcat(ptr, ""); - Serial.printf("Status form: size=%d bytes\n",strlen(message)); + Serial.printf("Status form: size=%d bytes\n", strlen(message)); return message; } @@ -425,6 +431,7 @@ struct st_configitems config_list[] = { {"wifi", "Wifi mode (0/1/2/3)", 0, &sonde.config.wifi}, {"debug", "Debug mode (0/1)", 0, &sonde.config.debug}, {"maxsonde", "Maxsonde", 0, &sonde.config.maxsonde}, + {"screenfile", "Screen config (0=old, 1=OLED, 2=TFT, 3=TFT[port])", 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}, @@ -569,7 +576,7 @@ const char *createConfigForm() { } } strcat(ptr, "
%3.3f MHz, Type: %s
ID: %s", s->freq, sondeTypeLongStr[s->type], s->validID ? s->id : ""); - if (s->validID && (s->type == STYPE_DFM06 || s->type == STYPE_DFM09 || s->type == STYPE_M10)) { + if (s->validID && (TYPE_IS_DFM(s->type) || TYPE_IS_METEO(s->type)) ) { sprintf(ptr + strlen(ptr), " (ser: %s)", s->ser); } sprintf(ptr + strlen(ptr), "
QTH: %.6f,%.6f h=%.0fm
"); - Serial.printf("Config form: size=%d bytes\n",strlen(message)); + Serial.printf("Config form: size=%d bytes\n", strlen(message)); return message; } @@ -642,7 +649,7 @@ const char *createControlForm() { strcat(ptr, "\">
"); } strcat(ptr, ""); - Serial.printf("Control form: size=%d bytes\n",strlen(message)); + Serial.printf("Control form: size=%d bytes\n", strlen(message)); return message; } @@ -691,6 +698,7 @@ const char *handleControlPost(AsyncWebServerRequest *request) { // bad idea. prone to buffer overflow. use at your own risk... const char *createEditForm(String filename) { + Serial.println("Creating edit form"); char *ptr = message; File file = SPIFFS.open("/" + filename, "r"); if (!file) { @@ -709,41 +717,45 @@ const char *createEditForm(String filename) { strcat(ptr, line.c_str()); strcat(ptr, "\n"); } strcat(ptr, ""); - Serial.printf("Edit form: size=%d bytes\n",strlen(message)); + Serial.printf("Edit form: size=%d bytes\n", strlen(message)); return message; } const char *handleEditPost(AsyncWebServerRequest *request) { Serial.println("Handling post request"); - int params = request->params(); - Serial.printf("Post:, %d params\n", params); - for(int i = 0; i < params; i++) { - AsyncWebParameter* p = request->getParam(i); - String name = p->name(); - String value = p->value(); - if(name.c_str()==NULL) { name=String("NULL"); } - if(value.c_str()==NULL) { value=String("NULL"); } - if(p->isFile()){ - Serial.printf("_FILE[%s]: %s, size: %u\n", name.c_str(), value.c_str(), p->size()); - } else if(p->isPost()){ - Serial.printf("_POST[%s]: %s\n", name.c_str(), value.c_str()); - } else { - Serial.printf("_GET[%s]: %s\n", name.c_str(), value.c_str()); - } + int params = request->params(); + Serial.printf("Post:, %d params\n", params); + for (int i = 0; i < params; i++) { + AsyncWebParameter* p = request->getParam(i); + String name = p->name(); + String value = p->value(); + if (name.c_str() == NULL) { + name = String("NULL"); } + if (value.c_str() == NULL) { + value = String("NULL"); + } + if (p->isFile()) { + Serial.printf("_FILE[%s]: %s, size: %u\n", name.c_str(), value.c_str(), p->size()); + } else if (p->isPost()) { + Serial.printf("_POST[%s]: %s\n", name.c_str(), value.c_str()); + } else { + Serial.printf("_GET[%s]: %s\n", name.c_str(), value.c_str()); + } + } AsyncWebParameter *filep = request->getParam("file"); if (!filep) return NULL; String filename = filep->value(); - Serial.printf("Writing file <%s>\n",filename.c_str()); + Serial.printf("Writing file <%s>\n", filename.c_str()); AsyncWebParameter *textp = request->getParam("text", true); if (!textp) return NULL; Serial.printf("Parameter size is %d\n", textp->size()); Serial.printf("Multipart: %d contentlen=%d \n", - request->multipart(), request->contentLength()); + request->multipart(), request->contentLength()); String content = textp->value(); - if(content.length()==0) { + if (content.length() == 0) { Serial.println("File is empty. Not written."); return NULL; } @@ -756,7 +768,7 @@ const char *handleEditPost(AsyncWebServerRequest *request) { int len = file.print(content); file.close(); Serial.printf("Written: %d bytes\n", len); - if (strcmp(filename.c_str(), "screens.txt") == 0) { + if (strncmp(filename.c_str(), "screens", 7) == 0) { // screens update => reload forceReloadScreenConfig = true; } @@ -772,7 +784,7 @@ const char *createUpdateForm(boolean run) { strcat(ptr, "
"); } strcat(ptr, ""); - Serial.printf("Update form: size=%d bytes\n",strlen(message)); + Serial.printf("Update form: size=%d bytes\n", strlen(message)); return message; } @@ -897,14 +909,14 @@ void SetupAsyncServer() { }); server.on("/edit.html", HTTP_POST, [](AsyncWebServerRequest * request) { const char *ret = handleEditPost(request); - if(ret==NULL) - request->send(200, "text/html", "ERROR

Something went wrong. Uploaded file is empty.

"); + if (ret == NULL) + request->send(200, "text/html", "ERROR

Something went wrong. Uploaded file is empty.

"); else - request->send(200, "text/html", createEditForm(request->getParam(0)->value())); + request->send(200, "text/html", createEditForm(request->getParam(0)->value())); }, NULL, [](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) { - Serial.printf("post data: index=%d len=%d total=%d\n", index, len, total); + Serial.printf("post data: index=%d len=%d total=%d\n", index, len, total); }); // Route to load style.css file @@ -1287,6 +1299,9 @@ void handlePMUirq() { 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 } } @@ -1405,7 +1420,9 @@ void setup() Serial.println("Reading initial configuration"); setupConfigData(); // configuration must be read first due to OLED ports!!! - if ((sonde.fingerprint & 16) == 16) { // NOT TTGO v1 (fingerprint 64) or Heltec v1/v2 board (fingerprint 4) + // NOT TTGO v1 (fingerprint 64) or Heltec v1/v2 board (fingerprint 4) + // and NOT TTGO Lora32 v2.1_1.6 (fingerprint 31) + if ( (sonde.fingerprint != 31) && ((sonde.fingerprint & 16) == 16) ) { // FOr T-Beam 1.0 for (int i = 0; i < 10; i++) { // try multiple times Wire.begin(21, 22); @@ -1490,7 +1507,7 @@ void setup() setupWifiList(); Serial.printf("before disp.initFromFile... layouts is %p", disp.layouts); - disp.initFromFile(); + disp.initFromFile(sonde.config.screenfile); Serial.printf("disp.initFromFile... layouts is %p", disp.layouts); @@ -1580,13 +1597,13 @@ void setup() #endif /// not here, done by sonde.setup(): rs41.setup(); // == setup default channel list if qrg.txt read fails =========== // -#ifndef DISABLE_SX1278 +#ifndef DISABLE_SX1278 xTaskCreate( sx1278Task, "sx1278Task", 10000, /* stack size */ NULL, /* paramter */ 1, /* priority */ NULL); /* task handle*/ -#endif +#endif sonde.setup(); initGPS(); @@ -1689,8 +1706,8 @@ void loopDecoder() { if (connected) { char raw[201]; int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN); - Serial.print("Sending UDP:"); - Serial.println(raw); + Serial.println("Sending AXUDP"); + //Serial.println(raw); udp.beginPacket(sonde.config.udpfeed.host, sonde.config.udpfeed.port); udp.write((const uint8_t *)raw, rawlen); udp.endPacket(); @@ -1708,13 +1725,13 @@ void loopDecoder() { } Serial.print("updateDisplay started... "); if (forceReloadScreenConfig) { - disp.initFromFile(); + disp.initFromFile(sonde.config.screenfile); sonde.clearDisplay(); forceReloadScreenConfig = false; } int t = millis(); sonde.updateDisplay(); - Serial.printf("updateDisplay done (after %d ms)\n", (int)(millis()-t)); + Serial.printf("updateDisplay done (after %d ms)\n", (int)(millis() - t)); } void setCurrentDisplay(int value) { @@ -1997,11 +2014,11 @@ void startAP() { Serial.println("Activating access point mode"); wifi_state = WIFI_APMODE; WiFi.softAP(networks[0].id.c_str(), networks[0].pw.c_str()); - + Serial.println("Wait 100 ms for AP_START..."); delay(100); - Serial.println(WiFi.softAPConfig(IPAddress (192,168,4,1), IPAddress (0,0,0,0), IPAddress (255,255,255,0)) ? "Ready" : "Failed!"); - + Serial.println(WiFi.softAPConfig(IPAddress (192, 168, 4, 1), IPAddress (0, 0, 0, 0), IPAddress (255, 255, 255, 0)) ? "Ready" : "Failed!"); + IPAddress myIP = WiFi.softAPIP(); String myIPstr = myIP.toString(); sonde.setIP(myIPstr.c_str(), true); @@ -2331,14 +2348,14 @@ void execOTA() { void loop() { Serial.printf("\nRunning main loop in state %d [currentDisp:%d, lastDiso:%d]. free heap: %d;\n", - mainState, currentDisplay, lastDisplay, ESP.getFreeHeap()); + mainState, currentDisplay, lastDisplay, ESP.getFreeHeap()); switch (mainState) { - case ST_DECODER: -#ifndef DISABLE_MAINRX + case ST_DECODER: +#ifndef DISABLE_MAINRX loopDecoder(); #else delay(1000); -#endif +#endif break; case ST_SPECTRUM: loopSpectrum(); break; case ST_WIFISCAN: loopWifiScan(); break; diff --git a/RX_FSK/data/config.txt b/RX_FSK/data/config.txt index fcd6df0..a1e3e4f 100644 --- a/RX_FSK/data/config.txt +++ b/RX_FSK/data/config.txt @@ -41,6 +41,8 @@ wifi=3 # TCP/IP KISS TNC in port 14590 for APRSdroid (0=disabled, 1=enabled) kisstnc.active = 1 +# which screens file to use (0: screens.txt, i>0: screens${i}.txt +screenfile=0 # display configuration. List of "displays" # first entry: "Scanner" display # second entry: default "Receiver" display diff --git a/RX_FSK/data/screens1.txt b/RX_FSK/data/screens1.txt new file mode 100644 index 0000000..0c425d8 --- /dev/null +++ b/RX_FSK/data/screens1.txt @@ -0,0 +1,226 @@ +### screens1.txt: OLED display +# Definition of display content and action behaviour +# +# Timer: (view timer, rx timer, norx timer) +# - value -1: timer is disabled; value>=0: timer fires after (value) seconds +# - view timer: time since current view (display mode and sonde) was started +# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX) +# - norx timer: time since when no sonde data has been received continuously +# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving +# anything for a 1s period) +# +# Actions: +# - W: activate WiFi scan +# - F: activate frequency spectrum display +# - 0: activate "Scan:" display (this is basically just display mode 0) +# - x: (1..N): activate display mode x [deprecated] +# - >: activate next display mode +# - D: activate default receiver display (display mode specified in config) +# - +: advance to next active sonde from QRG config +# - #: no action +# +# Display content (lower/upper case: small/large font) +# line,column=content +# for ILI9225 its also possible to indicate +# line,column,width=content for text within a box of width 'width' +# line,column,-width=content for right-justified text +# +# XText : Text +# F(suffix): frequency (with suffix, e.g., " MHz") +# L latitade +# O lOngitute +# A altitude +# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only) +# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only) +# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only) +# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number) +# RS41,RS92: all identical R1234567 +# DFMx: ID M12345678; short ID and serial 12345678 +# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592 +# Q signal quality statistics bar +# T type string (RS41/DFM9/DFM6/RS92) +# C afC value +# N ip address (only tiny font) +# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t +# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown +# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde +# Mx telemetry value x (t temp p preassure h hyg) [not yet implemented, maybe some day in future] +# Gx GPS-related data +# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground +# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing +# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff +# "N" (what is on top: N=north C=course) +# "C" (where does the arrow point to: C=course, S=sonde) +# "S" (what is shown by the bullet: C=course, S=sonde) +# 50: circle radius, followed by fg and bg color +# 5: bullet radius, followed by fg color +# 4: arrow width, followed by fg color +# R RSSI +# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current +# U=USB volt I=USB current T=IC temp +# +# fonts=x,y can be used to select font (x=small, y=large) for all items below +# for SSD1306, x and y can be used to select one of those fonts: +# (y should be a 1x2 font (1,5,6,7), x a small font) +# u8x8_font_chroma48medium8_r, // 0 ** default small +# u8x8_font_7x14_1x2_f, // 1 ** default large +# u8x8_font_amstrad_cpc_extended_f, // 2 +# u8x8_font_5x7_f, // 3 +# u8x8_font_5x8_f, // 4 +# u8x8_font_8x13_1x2_f, // 5 +# u8x8_font_8x13B_1x2_f, // 6 +# u8x8_font_7x14B_1x2_f, // 7 +# u8x8_font_artossans8_r, // 8 +# u8x8_font_artosserif8_r, // 9 +# u8x8_font_torussansbold8_r, // 10 +# u8x8_font_victoriabold8_r, // 11 +# u8x8_font_victoriamedium8_r, // 12 +# u8x8_font_pressstart2p_f, // 13 +# u8x8_font_pcsenior_f, // 14 +# u8x8_font_pxplusibmcgathin_f, // 15 +# u8x8_font_pxplusibmcga_f, // 16 +# u8x8_font_pxplustandynewtv_f, // 17 +# +# for ILI9225, these fonts are available: +# Terminal6x8 // 0 +# Terminal11x16 // 1 +# Terminal12x16 // 2 +# FreeMono9pt7b, // 3 +# FreeMono12pt7b, // 4 +# FreeSans9pt7b, // 5 +# FreeSans12pt7b, // 6 +# Picopixel, // 7 +# +# color=rrggbb,rrggbb can be used to select color (foreground, background) +# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign) +# +# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels +# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns) +########### +# +# Default configuration for "Scanner" display: +# - view timer disabled; rx timer=0; norx timer = 0 +# => after 1 second immediately an action is triggered +# (norx: go to next sonde; rx: go to default receiver display) +# - key1 actions: D,0,F,W +# => Button press activates default receiver view, double press does nothing +# Mid press activates Spectrum display, long press activates Wifi scan +# - key2 has no function +@Scanner +timer=-1,0,0 +key1action=D,#,F,W +key2action=#,#,#,# +timeaction=#,D,+ +0,0=XScan +0,5=S#: +0,9=T +3,0=F MHz +5,0=S +7,5=n + +############ +# Default configuration for "Legacy" display: +# - view timer=-1, rx timer=-1 (disabled); norx timer=20 (or -1 for "old" behaviour) +# => norx timer fires after not receiving a singla for 20 seconds +# - key1 actions: +,0,F,W +# => Button1 press: next sonde; double press => @Scanner display +# => Mid press activates Spectrum display, long press activates Wifi scan +# - key2 actions: 2,#,#,# +# => BUtton2 activates display 2 (@Field) +# - timer actions: #,#,0 +# (norx timer: if no signal for >20 seconds: go back to scanner mode) +# +@Legacy +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,0 +0,5=f MHz +1,8=c +0,0=t +1,0=is +2,0=L +4,0=O +2,10=a +3,10=h +4,9=v +6,0=R +6,7=Q + +############ +# Configuratoon for "Field" display (display 2) +# similar to @Legacy, but no norx timer, and Key2 goes to display 4 +@Field +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +2,0=L +4,0=O +3,10=h +4,9=v +0,0=Is +6,0=A +6,7=Q + +############ +# Configuration for "Field2" display (display 3) +# similar to @Field +@Field2 +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +2,0=L +4,0=O +1,12=t +0,9=f +3,10=h +4,9=v +0,0=Is +6,0=A +6,7=Q + +############# +# Configuration for "GPS" display +# not yet the final version, just for testing +@GPSDIST +timer=-1,-1,-1 +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +0,0=Is +0,9=f +1,12=t +2,0=L +4,0=O +2,10=a +3,10=h +4,9=v +5,9=gC +5,13=gB +6,7=Q +7,0=gV +7,2=xd= +7,4=gD +7,12=gI° + +############ +@BatteryOLED +timer=-1,-1,-1 +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +fonts=0,1 +0,0=xBat.Status: +0,12=bS +1,0=xBatt: +1,6=bVV +2,0=bCmA (charge) +3,0=bDmA (disch.) +4,0=xUSB: +4,5=bUV +5,5=bImA +6,0=xTemp: +6,5=bT C + diff --git a/RX_FSK/data/screens2.txt b/RX_FSK/data/screens2.txt new file mode 100644 index 0000000..8c373e7 --- /dev/null +++ b/RX_FSK/data/screens2.txt @@ -0,0 +1,573 @@ +## screens2.txt: TFT display (landscape) +# Definition of display content and action behaviour +# +# Timer: (view timer, rx timer, norx timer) +# - value -1: timer is disabled; value>=0: timer fires after (value) seconds +# - view timer: time since current view (display mode and sonde) was started +# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX) +# - norx timer: time since when no sonde data has been received continuously +# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving +# anything for a 1s period) +# +# Actions: +# - W: activate WiFi scan +# - F: activate frequency spectrum display +# - 0: activate "Scan:" display (this is basically just display mode 0) +# - x: (1..N): activate display mode x [deprecated] +# - >: activate next display mode +# - D: activate default receiver display (display mode specified in config) +# - +: advance to next active sonde from QRG config +# - #: no action +# +# Display content (lower/upper case: small/large font) +# line,column=content +# for ILI9225 its also possible to indicate +# line,column,width=content for text within a box of width 'width' +# line,column,-width=content for right-justified text +# +# XText : Text +# F(suffix): frequency (with suffix, e.g., " MHz") +# L latitade +# O lOngitute +# A altitude +# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only) +# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only) +# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only) +# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number) +# RS41,RS92: all identical R1234567 +# DFMx: ID M12345678; short ID and serial 12345678 +# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592 +# Q signal quality statistics bar +# T type string (RS41/DFM9/DFM6/RS92) +# C afC value +# N ip address (only tiny font) +# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t +# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown +# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde +# Mx telemetry value x (t temp p preassure h hyg) [not yet implemented, maybe some day in future] +# Gx GPS-related data +# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground +# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing +# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff +# "N" (what is on top: N=north C=course) +# "C" (where does the arrow point to: C=course, S=sonde) +# "S" (what is shown by the bullet: C=course, S=sonde) +# 50: circle radius, followed by fg and bg color +# 5: bullet radius, followed by fg color +# 4: arrow width, followed by fg color +# R RSSI +# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current +# U=USB volt I=USB current T=IC temp +# +# fonts=x,y can be used to select font (x=small, y=large) for all items below +# for SSD1306, x and y can be used to select one of those fonts: +# (y should be a 1x2 font (1,5,6,7), x a small font) +# u8x8_font_chroma48medium8_r, // 0 ** default small +# u8x8_font_7x14_1x2_f, // 1 ** default large +# u8x8_font_amstrad_cpc_extended_f, // 2 +# u8x8_font_5x7_f, // 3 +# u8x8_font_5x8_f, // 4 +# u8x8_font_8x13_1x2_f, // 5 +# u8x8_font_8x13B_1x2_f, // 6 +# u8x8_font_7x14B_1x2_f, // 7 +# u8x8_font_artossans8_r, // 8 +# u8x8_font_artosserif8_r, // 9 +# u8x8_font_torussansbold8_r, // 10 +# u8x8_font_victoriabold8_r, // 11 +# u8x8_font_victoriamedium8_r, // 12 +# u8x8_font_pressstart2p_f, // 13 +# u8x8_font_pcsenior_f, // 14 +# u8x8_font_pxplusibmcgathin_f, // 15 +# u8x8_font_pxplusibmcga_f, // 16 +# u8x8_font_pxplustandynewtv_f, // 17 +# +# for ILI9225, these fonts are available: +# Terminal6x8 // 0 +# Terminal11x16 // 1 +# Terminal12x16 // 2 +# FreeMono9pt7b, // 3 +# FreeMono12pt7b, // 4 +# FreeSans9pt7b, // 5 +# FreeSans12pt7b, // 6 +# Picopixel, // 7 +# +# color=rrggbb,rrggbb can be used to select color (foreground, background) +# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign) +# +# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels +# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns) +########### + +############ +# Scan display for large 2" TFT dispaly +@ScannerTFT +timer=-1,0,0 +key1action=D,#,F,W +key2action=#,#,#,# +timeaction=#,D,+ +fonts=5,6 +0,0=XScan +0,5,-3=S#: +0,9,5.5=T +3,0=F MHz +5,0,16=S +7,5=n + +############ +@MainTFT +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,0 +color=FFD700 +0,0=Is +color=0000FF +0,11,-5.5=f +1,1,6=c +1,12.5,-4=t +color=00ff00 +2,0,7=L +4,0,7=O +color=FFA500 +2,9.5,-7=A +3,9.5,-7=vm/s +color=AA5522 +4,9.5,-7=hkkm/h +color=FFFFFF +6,2=r +6.3,10=Q4 +7,0=xd= +7,2,6=gD +7,12=gI + +############ +@PeilungTFT +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +color=ffff00,000033 +color=bbbbbb,000000 +0,2=xN Top: +0,8=xCourse Top: +color=ffff00,000033 +1,0=g0NCS,48,ffff00,000044,6,33ff33,5,eeaa00 +1,8=g0CCS,48,ffff00,000044,6,55ff55,5,eeaa00 +color=ffffff,000000 +6,0=xDirection: +6,8,4=gI +7,0=xCOG: +7,4,4=gC +7,8=xturn: +7,12,4=gB + +############ +@GPSdataTFT +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +0,0=xOn-board GPS: +1,0,8=gA +2,0,8=gO +3,0,8=gH +4,0,8=gC +5,0=xGPS vs Sonde: +6,0,8=gD +7,0,8=gI +7,8,8=gB + +############ +@BatteryTFT +timer=-1,-1,-1 +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +0,0=xBattery status: +0,14=bS +1,0=xBatt: +1,5,5=bVV +2,0,16=bCmA(charging) +3,0,16=bDmA(discharging) +4.4,0=xUSB: +4.4,5,5=bUV +5.4,0,10=bImA +6.4,0=xTemp: +6.4,5,5=bT C + +### Alternative display layouts based on https://gist.github.com/bazjo +# Scan display for large 2" TFT dispaly +@Scan.TFT.Bazjo +timer=-1,0,0 +key1action=D,#,F,W +key2action=#,#,#,# +timeaction=#,D,+ +scale=11,10 +fonts=0,2 +color=e0e0e0 +#Row 1 +0.5,0=XScanning... +#Row 2 +3,0=xIndex +4,0=S/ +3,9=xSite +4,9=S +#Row 3 +6,0=xType +7,0=T +6,9=xFrequency +7,9=F +#Row 4 +9,0=xWeb UI IP +10,0=N +#Row 5 +#Footer +color=6C757D +15,0=xScan Mode +15,18=bVV + +############ +@Decode/General.TFT.Bazjo +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,0 +scale=11,10 +fonts=0,2 +#Row 1 +color=996A06 +0,0=xSerial +0,5=t +color=FFB10B +1,0=Is +color=996A06 +0,11=xFreq. +0,16=c +color=FFB10B +1,11=F +#Row 2 +color=3C5C99 +3,0=xLatitude +color=639AFF +4,0=L +color=3C5C99 +3,11=xLongitude +color=639AFF +4,11=O +#Row 3 +color=3C5C99 +6,0=xHoriz. Speed +color=639AFF +7,0=Hkkm/h +color=3C5C99 +6,11=xVert. Speed +color=639AFF +7,11=Vm/s +#Row 4 +color=99004A +9,0=xAltitude +color=FF007B +10,0=A +color=99004A +9,11=xBearing +color=FF007B +10,11=GB +#Row 5 +color=06998E +12,0=xRSSI +color=0AFFEF +13,0=R +color=06998E +12,11=xHistory +color=0AFFEF +13.5,11=Q4 +#Footer +color=6C757D +15,0=xDecode Mode / General View +15,18=bVV + +############ +@Decode/Battery.TFT.Bazjo +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +scale=11,10 +fonts=0,2 +#Row 1 +color=99001F +0,0=xBattery Status +0,11=xBattery Voltage +color=FF0035 +1,0=BS +1,11=BVV +#Row 2 +color=99001F +3,0=xCharge Current +3,11=xDischarge Current +color=FF0035 +4,0=BCmA +4,11=BDmA +#Row 3 +color=99001F +6,0=xUSB Voltage +6,11=xUSB Current +color=FF0035 +7,0=BUV +7,11=BImA +#Row 4 +color=99001F +9,0=xIC Temperature +#9,11=xKey +color=FF0035 +10,0=BTC +#10,11=XValue +#Row 5 +#12,0=xKey +#12,11=xKey +#13,0=XValue +#13,11=XValue +#Footer +color=99001F +15,0=xDecode Mode/Battery View +15,18=bVV + +# based on https://github.com/puspis/rdz_ttgo_sonde +########## +@Scanner.Puspis +timer=-1,0,4 +key1action=D,#,F,W +key2action=#,#,#,# +timeaction=#,D,+ +scale=13,10 +fonts=0,1 +#Row 1 +color=90EE90 +0.5,3=XFREQUENCY SCAN +#Row 2 +color=00FF00 +3,0=xMEMORY +3,9=xLAUNCH SITE +color=639AFF +4,0=S/ +4,9=S +#Row 3 +color=00FF00 +6,0=xTYPE +6,9=xFREQUENCY +color=639AFF +7,0=T +7,9=F MHz +#Row 4 +fonts=0,5 +color=285454 +11.5,0=xIP ADDRESS: +10.9,8.8=N +#Footer +color=FF0000 +12.7,18=bVV + +############ +@Main.Puspis +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,0 +scale=11,10 +fonts=0,2 +#Row 1 +color=00FF00 +0,0=xSONDE ID +0,11=xFREQUENCY +color=90EE90 +0,7.4=t +1,0=Is +1,11=F +#Row 2 +fonts=0,1 +color=00FF00 +3,0=xLATITUDE +3,11=xLONGITUDE +color=FF007B +4,0=L +4,11=O +#Row 3 +color=00FF00 +6,0=xWIND SPEED +6,11=xCLIMB RATE +color=639AFF +7,0=Hkkm/h +7,11=Vm/s +#Row 4 +color=00FF00 +9,0=xRX ALTITUDE +9,11=xSONDE ALTITUDE +color=639AFF +10,0=GH +10,11=A +#Row 5 +color=00FF00 +12,0=xDISTANCE +12,11=xFRAMES +color=FFFFFF +13,0=GD +13.5,11=Q4 +#Footer +color=FF0000 +15,0.2=xIP: +15,2.5=n +15,18=bVV + +############ +@JotaEme.Puspis +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,0 +scale=11,10 +fonts=0,1 +#Row 1 +color=90EE90 +0,0=Is +0.7,10.5=t +0,14=F +#Row 2 +color=00FF00 +2,1.2=xWIND SPEED +2,14=xCLIMB RATE +color=639AFF +3,1=Hkkm/h +3,13=Vm/s +#Row 3 +color=00FF00 +5,1=xRX ALTITUDE +5,12.5=xSONDE ALTITUDE +color=639AFF +6,2=GH +6,14=A +#Row 4 +color=00FF00 +8,0=xSONDE POSITION +color=FF007B +9,2=l +10,2=o +#Row 5 +color=00FF00 +11.4,2=xDISTANCE +color=FFFFFF +12.4,1.5=GD +#Circle +color=EEAA00,000033 +8,13.8=g0CCS,28,FFFF00,000033,5,9ACD32,5,EEAA00 +#Footer +color=FF0000 +15,0=n +color=FFFFFF,000000 +15,8.7=Q4 +color=FF0000 +15,18.4=bVV + +############ +@CompassTFT.Puspis +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +scale=13,10 +fonts=0,1 +#Row 1 +color=90EE90 +0.5,1.5=XCOMPASS +#Row 2 +color=00FF00 +4,2=xRX HEADING +color=639AFF +5,3.8=GC +#Row 3 +color=00FF00 +9.5,3=xDISTANCE +9.5,13.5=xBEARING +color=639AFF +10.5,3.4=GD +10.5,14.3=GI +#Circle +color=EEAA00,000033 +0.2,10=g0CCS,52,FFFF00,000033,10,9ACD32,6,EEAA00 +#Footer +color=FF0000,000000 +12.7,1=Q4 +12.7,18=bVV + +############ +@GPSdataTFT.Puspis +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +scale=13,10 +fonts=0,1 +#Row 1 +color=90EE90 +0.5,0.5=XGPS RECEIVER STATION +#Row 2 +color=00FF00 +3,0=xRX LATITUDE +3,12=xRX LONGITUDE +color=639AFF +4,0=GA +4,12=GO +#Row 3 +color=00FF00 +6,0=xRX ALTITUDE +6,12=xRX HEADING +color=639AFF +7,0=GH +7,12=GC +#Row 4 +color=00FF00 +9,0=xDISTANCE +9,12=xBEARING +color=639AFF +10,0=GD +10,12=GB +#Footer +color=FF0000,000000 +12.7,0.4=Q4 +12.7,18=bVV + +############ +@BatteryTFT.Puspis +timer=-1,-1,-1 +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +scale=13,10 +fonts=0,1 +#Row 1 +color=90EE90 +0.5,4=XBATTERY STATUS +#Row 2 +color=00FF00 +3,0=x(C)HARGE/(B)ATT +3,11.5=xBATTERY VOLTAGE +color=639AFF +4,4=BS +4,11.5=BVV +#Row 3 +color=00FF00 +6,0=xCHARGE CURRENT +6,11.5=xDISCHG. CURRENT +color=639AFF +7,0=BCmA +7,11.5=BDmA +#Row 3 +color=00FF00 +9,0=xIC TEMPERATURE +9,11.5=xFREQ. OFFSET +color=639AFF +10,0=BTC +10,10=C +#Footer +color=FF0000,000000 +12.7,0.4=Q4 +12.7,18=bVV diff --git a/RX_FSK/data/screens3.txt b/RX_FSK/data/screens3.txt new file mode 100644 index 0000000..dfb5317 --- /dev/null +++ b/RX_FSK/data/screens3.txt @@ -0,0 +1,217 @@ +## screens3.txt: TFT display (portrait) +## based on http://www.p1337.synology.me/dokuwiki/doku.php?id=public:wettersonden +# Definition of display content and action behaviour +# +# Timer: (view timer, rx timer, norx timer) +# - value -1: timer is disabled; value>=0: timer fires after (value) seconds +# - view timer: time since current view (display mode and sonde) was started +# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX) +# - norx timer: time since when no sonde data has been received continuously +# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving +# anything for a 1s period) +# +# Actions: +# - W: activate WiFi scan +# - F: activate frequency spectrum display +# - 0: activate "Scan:" display (this is basically just display mode 0) +# - x: (1..N): activate display mode x [deprecated] +# - >: activate next display mode +# - D: activate default receiver display (display mode specified in config) +# - +: advance to next active sonde from QRG config +# - #: no action +# +# Display content (lower/upper case: small/large font) +# line,column=content +# for ILI9225 its also possible to indicate +# line,column,width=content for text within a box of width 'width' +# line,column,-width=content for right-justified text +# +# XText : Text +# F(suffix): frequency (with suffix, e.g., " MHz") +# L latitade +# O lOngitute +# A altitude +# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only) +# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only) +# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only) +# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number) +# RS41,RS92: all identical R1234567 +# DFMx: ID M12345678; short ID and serial 12345678 +# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592 +# Q signal quality statistics bar +# T type string (RS41/DFM9/DFM6/RS92) +# C afC value +# N ip address (only tiny font) +# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t +# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown +# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde +# Mx telemetry value x (t temp p preassure h hyg) [not yet implemented, maybe some day in future] +# Gx GPS-related data +# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground +# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing +# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff +# "N" (what is on top: N=north C=course) +# "C" (where does the arrow point to: C=course, S=sonde) +# "S" (what is shown by the bullet: C=course, S=sonde) +# 50: circle radius, followed by fg and bg color +# 5: bullet radius, followed by fg color +# 4: arrow width, followed by fg color +# R RSSI +# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current +# U=USB volt I=USB current T=IC temp +# +# fonts=x,y can be used to select font (x=small, y=large) for all items below +# for SSD1306, x and y can be used to select one of those fonts: +# (y should be a 1x2 font (1,5,6,7), x a small font) +# u8x8_font_chroma48medium8_r, // 0 ** default small +# u8x8_font_7x14_1x2_f, // 1 ** default large +# u8x8_font_amstrad_cpc_extended_f, // 2 +# u8x8_font_5x7_f, // 3 +# u8x8_font_5x8_f, // 4 +# u8x8_font_8x13_1x2_f, // 5 +# u8x8_font_8x13B_1x2_f, // 6 +# u8x8_font_7x14B_1x2_f, // 7 +# u8x8_font_artossans8_r, // 8 +# u8x8_font_artosserif8_r, // 9 +# u8x8_font_torussansbold8_r, // 10 +# u8x8_font_victoriabold8_r, // 11 +# u8x8_font_victoriamedium8_r, // 12 +# u8x8_font_pressstart2p_f, // 13 +# u8x8_font_pcsenior_f, // 14 +# u8x8_font_pxplusibmcgathin_f, // 15 +# u8x8_font_pxplusibmcga_f, // 16 +# u8x8_font_pxplustandynewtv_f, // 17 +# +# for ILI9225, these fonts are available: +# Terminal6x8 // 0 +# Terminal11x16 // 1 +# Terminal12x16 // 2 +# FreeMono9pt7b, // 3 +# FreeMono12pt7b, // 4 +# FreeSans9pt7b, // 5 +# FreeSans12pt7b, // 6 +# Picopixel, // 7 +# +# color=rrggbb,rrggbb can be used to select color (foreground, background) +# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign) +# +# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels +# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns) + +########### +# +# Default configuration for "Scanner" display: +# - view timer disabled; rx timer=0; norx timer = 0 +# => after 1 second immediately an action is triggered +# (norx: go to next sonde; rx: go to default receiver display) +# - key1 actions: D,0,F,W +# => Button press activates default receiver view, double press does nothing +# Mid press activates Spectrum display, long press activates Wifi scan +# - key2 has no function +@ScannerPortrait +timer=-1,0,0 +key1action=D,#,F,W +key2action=>,#,#,# +timeaction=#,D,+ +0,0=XScan +0,5=S#: +0,9=T +6,0=XHoehe +6,5=GH +color=ffff00 +2,0=F MHz +4,0=S +color=00ff00,444444 +7,5=n +7,0=bV + +############ +# Default configuration for "Legacy" display: +# - view timer=-1, rx timer=-1 (disabled); norx timer=20 (or -1 for "old" behaviour) +# => norx timer fires after not receiving a singla for 20 seconds +# - key1 actions: +,0,F,W +# => Button1 press: next sonde; double press => @Scanner display +# => Mid press activates Spectrum display, long press activates Wifi scan +# - key2 actions: 2,#,#,# +# => BUtton2 activates display 2 (@Field) +# - timer actions: #,#,0 +# (norx timer: if no signal for >20 seconds: go back to scanner mode) +# +@LegacyPortrait +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,0 +9,10=f +9,0=r +9,4=Q +5,0=g0NCS,35,ffff00,000044,6,33ff33,5,eeaa00 +5,7=g0CCS,35,ffff00,000044,6,55ff55,5,eeaa00 +0,0=s +0,9=is +2,0=L +3,0=O +color=FFFF00 +1,6=Hk km/h +color=FF0000 +1,0=GD +color=FFFFFF +4,9=GH +3,9=V +4,0=A + +############ +@PeilungTFTPortrait +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +color=ffff00,000033 +color=bbbbbb,000000 +0,2=xN Top: +0,8=xCourse Top: +color=ffff00,000033 +1,0=g0NCS,35,ffff00,000044,6,33ff33,5,eeaa00 +1,7=g0CCS,35,ffff00,000044,6,55ff55,5,eeaa00 +color=ffffff,000000 +6,0=xDirection: +6,8,4=gI +7,0=xCOG: +7,4,4=gC +7,8=xturn: +7,12,4=gB + +############ +@GPSdataTFTPortrait +timer=-1,-1,N +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +0,0=xOn-board GPS: +1,0,8=gA +2,0,8=gO +3,0,8=gH +4,0,8=gC +5,0=xGPS vs Sonde: +6,0,8=gD +7,0,8=gI +7,8,8=gB + +############ +@BatteryTFTPortrait +timer=-1,-1,-1 +key1action=+,0,F,W +key2action=>,#,#,# +timeaction=#,#,# +0,0=xBattery status: +0,14=bS +1,0=xBatt: +1,5,5=bVV +2,0,16=bCmA(charging) +3,0,16=bDmA(discharging) +4.4,0=xUSB: +4.4,5,5=bUV +5.4,0,10=bImA +6.4,0=xTemp: +6.4,5,5=bT C + diff --git a/RX_FSK/version.h b/RX_FSK/version.h index 02d4286..b8e3361 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,4 +1,4 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "devel20201129"; +const char *version_id = "devel20201130"; const int SPIFFS_MAJOR=2; -const int SPIFFS_MINOR=4; +const int SPIFFS_MINOR=5; diff --git a/libraries/SX1278FSK/SX1278FSK.cpp b/libraries/SX1278FSK/SX1278FSK.cpp index fa25d87..e4b3869 100644 --- a/libraries/SX1278FSK/SX1278FSK.cpp +++ b/libraries/SX1278FSK/SX1278FSK.cpp @@ -165,19 +165,22 @@ void SX1278FSK::writeRegister(byte address, byte data) void SX1278FSK::clearIRQFlags() { byte st0; - +#if 0 // Save the previous status st0 = readRegister(REG_OP_MODE); // Stdby mode to write in registers writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); +#endif // FSK mode flags1 register writeRegister(REG_IRQ_FLAGS1, 0xFF); // FSK mode flags2 register writeRegister(REG_IRQ_FLAGS2, 0xFF); +#if 0 // Getting back to previous status if(st0 != FSK_STANDBY_MODE) { writeRegister(REG_OP_MODE, st0); } +#endif #if (SX1278FSK_debug_mode > 1) Serial.println(F("## FSK flags cleared ##")); #endif @@ -719,7 +722,6 @@ uint8_t SX1278FSK::receivePacketTimeout(uint32_t wait, byte *data) // It's a bit of a hack.... get RSSI and AFC (a) at beginning of packet and // for RS41 after about 0.5 sec. It might be more logical to put this decoder-specific // code into RS41.cpp instead of this file... (maybe TODO?) - if(di==1 || di==290 ) { int rssi=getRSSI(); int afc=getAFC(); diff --git a/libraries/SondeLib/DFM.cpp b/libraries/SondeLib/DFM.cpp index e7459cb..93c47be 100644 --- a/libraries/SondeLib/DFM.cpp +++ b/libraries/SondeLib/DFM.cpp @@ -12,6 +12,8 @@ #define DFM_DBG(x) #endif +#define DFM_FRAMELEN 33 + // single data structure, search restarts after decoder change static struct st_dfmstat { int idcnt0; @@ -25,11 +27,11 @@ static struct st_dfmstat { uint8_t nameregtop; } dfmstate; -int DFM::setup(float frequency, int inv) +int DFM::setup(float frequency, int type) { - inverse = inv; + stype = type; #if DFM_DEBUG - Serial.printf("Setup sx1278 for DFM sonde (inv=%d)\n",inv); + Serial.printf("Setup sx1278 for DFM sonde (type=%d)\n", stype); #endif if(sx1278.ON()!=0) { DFM_DBG(Serial.println("Setting SX1278 power on FAILED")); @@ -57,36 +59,69 @@ int DFM::setup(float frequency, int inv) DFM_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.dfm.rxbw)); return 1; } - // Enable auto-AFC, auto-AGC, RX Trigger by preamble - if(sx1278.setRxConf(0x1E)!=0) { - DFM_DBG(Serial.println("Setting RX Config FAILED")); - return 1; - } - // Set autostart_RX to 01, preamble 0, SYNC detect==on, syncsize=3 (==4 byte - //char header[] = "0110.0101 0110.0110 1010.0101 1010.1010"; - const char *SYNC=inverse?"\x9A\x99\x5A\x55":"\x65\x66\xA5\xAA"; - if(sx1278.setSyncConf(0x53, 4, (const uint8_t *)SYNC)!=0) { - DFM_DBG(Serial.println("Setting SYNC Config FAILED")); - return 1; - } - //if(sx1278.setPreambleDetect(0xA8)!=0) { - if(sx1278.setPreambleDetect(0xAA)!=0) { - DFM_DBG(Serial.println("Setting PreambleDetect FAILED")); - return 1; - } + if(type == STYPE_DFM09_OLD || type == STYPE_DFM06_OLD) { + // packet mode, old version, misses some frames because chip enables rx too late after + // one frame was recevied. TODO: check if this can be fixed by changing parameters + // Enable auto-AFC, auto-AGC, RX Trigger by preamble + if(sx1278.setRxConf(0x1E)!=0) { + DFM_DBG(Serial.println("Setting RX Config FAILED")); + return 1; + } + // Set autostart_RX to 01, preamble 0, SYNC detect==on, syncsize=3 (==4 byte + //char header[] = "0110.0101 0110.0110 1010.0101 1010.1010"; + + const char *SYNC=(stype==STYPE_DFM09_OLD)?"\x9A\x99\x5A\x55":"\x65\x66\xA5\xAA"; + if(sx1278.setSyncConf(0x53, 4, (const uint8_t *)SYNC)!=0) { + DFM_DBG(Serial.println("Setting SYNC Config FAILED")); + return 1; + } + //if(sx1278.setPreambleDetect(0xA8)!=0) { + if(sx1278.setPreambleDetect(0xAA)!=0) { + DFM_DBG(Serial.println("Setting PreambleDetect FAILED")); + return 1; + } - // Packet config 1: fixed len, mancecer, no crc, no address filter - // Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0) - if(sx1278.setPacketConfig(0x28, 0x40)!=0) { - DFM_DBG(Serial.println("Setting Packet config FAILED")); - return 1; + // Packet config 1: fixed len, mancecer, no crc, no address filter + // Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0) + if(sx1278.setPacketConfig(0x28, 0x40)!=0) { + DFM_DBG(Serial.println("Setting Packet config FAILED")); + return 1; + } + sx1278.setPayloadLength(33); // Expect 33 bytes (7+13+13 bytes) + } else { + // continuous mode + // Enable auto-AFC, auto-AGC, RX Trigger by preamble ???? + if(sx1278.setRxConf(0x1E)!=0) { + DFM_DBG(Serial.println("Setting RX Config FAILED")); + return 1; + } + // working with continuous RX + const char *SYNC="\xAA\xAA"; + if(sx1278.setSyncConf(0x70, 2, (const uint8_t *)SYNC)!=0) { + DFM_DBG(Serial.println("Setting SYNC Config FAILED")); + return 1; + } + if(sx1278.setPreambleDetect(0xA8)!=0) { + //if(sx1278.setPreambleDetect(0x9F)!=0) { + DFM_DBG(Serial.println("Setting PreambleDetect FAILED")); + return 1; + } + if(sx1278.setPacketConfig(0x08, 0x40)!=0) { + DFM_DBG(Serial.println("Setting Packet config FAILED")); + return 1; + } + sx1278.setPayloadLength(0); // infinite for now... } Serial.print("DFM: setting RX frequency to "); Serial.println(frequency); int retval = sx1278.setFrequency(frequency); sx1278.clearIRQFlags(); + + // Do this only once in setup in continous mode + sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); + memset((void *)&dfmstate, 0, sizeof(dfmstate)); DFM_DBG(Serial.println("Setting SX1278 config for DFM finished\n"); Serial.println()); return retval; @@ -178,7 +213,17 @@ void DFM::printRaw(const char *label, int len, int ret, const uint8_t *data) Serial.print(" "); } - +const char* typestr[16]={ + "", "", "", "", "", "", // 00..05 + "DFM6", // 06 => DFM6 + "PS15", // 07 => PS15 (untested) + "", "", + "DFM9", // 0A => DFM9 + "DF17", // 0B => DFM17? + "DF9P", // 0C => DFM9P or DFM17 test + "DF17", // 0D => DFM17 + "", "" +}; #define DFMIDTHRESHOLD 2 /* inspired by oe5dxl's finddnmae in sondeudp.c of dxlaprs */ @@ -224,6 +269,7 @@ void DFM::finddfname(uint8_t *b) if(i==6) { snprintf(sonde.si()->id, 10, "D%x ", id); sonde.si()->validID = true; + strncpy(sonde.si()->typestr, typestr[ (st>>4)&0x0F ], 5); return; } dfmstate.lastfrcnt = 0; @@ -273,6 +319,7 @@ void DFM::finddfname(uint8_t *b) Serial.print("\nNEW AUTOID:"); Serial.println(sonde.si()->id); sonde.si()->validID = true; + strncpy(sonde.si()->typestr, typestr[ (st>>4)&0x0F ], 5); } if(dfmstate.nameregok==i) { Serial.print(" ID OK"); @@ -431,19 +478,140 @@ void DFM::bitsToBytes(uint8_t *bits, uint8_t *bytes, int len) bytes[(i-1)/8] &= 0x0F; } +static int haveNewFrame = 0; + +int DFM::processDFMdata(uint8_t dt) { + static uint8_t data[1024]; + static uint32_t rxdata = 0; + static uint8_t rxbitc = 0; + static uint8_t rxbyte = 0; + static uint8_t rxsearching = 1; + static uint8_t rxp; + static int rssi=0, fei=0, afc=0; + static uint8_t invers = 0; + + for(int i=0; i<8; i++) { + uint8_t d = (dt&0x80)?1:0; + dt <<= 1; + rxdata = (rxdata<<1) | d; + if( (rxbitc&1)==0 ) { + // "bit1" + rxbyte = (rxbyte<<1) | d; + } else { + // "bit2" ==> 01 or 10 => 1, otherweise => 0 + // not here: (10=>1, 01=>0)!!! rxbyte = rxbyte ^ d; + } + // + if(rxsearching) { + if( rxdata == 0x6566A5AA || rxdata == 0x9A995A55 ) { + rxsearching = false; + rxbitc = 0; + rxp = 0; + rxbyte = 0; + rssi=sx1278.getRSSI(); + fei=sx1278.getFEI(); + afc=sx1278.getAFC(); + sonde.si()->rssi = rssi; + sonde.si()->afc = afc; + invers = (rxdata == 0x6566A5AA)?1:0; + } + } else { + rxbitc = (rxbitc+1)%16; // 16; + if(rxbitc == 0) { // got 8 data bit + if(invers) rxbyte=~rxbyte; + data[rxp++] = rxbyte&0xff; // (rxbyte>>1)&0xff; + if(rxp>=DFM_FRAMELEN) { + rxsearching = true; + //Serial.println("Got a DFM frame!"); + Serial.print("[RSSI="); Serial.print(rssi); + Serial.print(" FEI="); Serial.print(fei); + Serial.print(" AFC="); Serial.print(afc); Serial.print("] "); + decodeFrameDFM(data); + haveNewFrame = 1; + } + } + } + } + return 0; +} + int DFM::receive() { + if( stype == STYPE_DFM ) { + return receiveNew(); + } else { + return receiveOld(); + } +} + + +int DFM::receiveNew() { + int rxframes = 4; + // tentative continuous RX version... + unsigned long t0 = millis(); + while( ( millis() - t0 ) < 1000 ) { + uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2); + if ( bitRead(value, 7) ) { + Serial.println("FIFO full"); + } + if ( bitRead(value, 4) ) { + Serial.println("FIFO overflow"); + // new: (maybe clear only overflow??) TODO + sx1278.clearIRQFlags(); + } + if ( bitRead(value, 2) == 1 ) { + Serial.println("FIFO: payload ready()"); + // does not make much sence? (from m10): TODO + // ??????? sx1278.clearIRQFlags(); + } + if(bitRead(value, 6) == 0) { // while FIFO not empty + byte data = sx1278.readRegister(REG_FIFO); + processDFMdata(data); + value = sx1278.readRegister(REG_IRQ_FLAGS2); + } else { +#if 0 + if(headerDetected) { + t0 = millis(); // restart timer... don't time out if header detected... + headerDetected = 0; + } +#endif + if(haveNewFrame) { + //Serial.printf("DFM::receive(): new frame complete after %ldms\n", millis()-t0); + haveNewFrame = 0; + rxframes--; + if(rxframes==0) return RX_OK; + } + delay(2); + } + } + return RX_TIMEOUT; +} + +int DFM::receiveOld() { byte data[1000]; // pending data from previous mode may write more than 33 bytes. TODO. for(int i=0; i<2; i++) { - sx1278.setPayloadLength(33); // Expect 33 bytes (7+13+13 bytes) + sx1278.setPayloadLength(33); // Expect 33 bytes (7+13+13 bytes) + sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); + int t = millis(); + int e = sx1278.receivePacketTimeout(1000, data); + //Serial.printf("rxPTO done after %d ms", (int)(millis()-t)); + if(e) { return RX_TIMEOUT; } //if timeout... return 1 - sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); - int e = sx1278.receivePacketTimeout(1000, data); - if(e) { return RX_TIMEOUT; } //if timeout... return 1 + if(!(stype==STYPE_DFM09_OLD)) { for(int i=0; i<33; i++) { data[i]^=0xFF; } } + decodeFrameDFM(data); + } + return RX_OK; +} - if(!inverse) { for(int i=0; i<33; i++) { data[i]^=0xFF; } } +int DFM::decodeFrameDFM(uint8_t *data) { deinterleave(data, 7, hamming_conf); deinterleave(data+7, 13, hamming_dat1); deinterleave(data+20, 13, hamming_dat2); +#if 0 + Serial.print("RAWCFG:"); + for(int i=0; i<7*8; i++) { + Serial.print(hamming_conf[i]?"1":"0"); + } +#endif int ret0 = hamming(hamming_conf, 7, block_conf); int ret1 = hamming(hamming_dat1, 13, block_dat1); @@ -461,7 +629,6 @@ int DFM::receive() { decodeDAT(byte_dat1); decodeDAT(byte_dat2); Serial.println(""); - } return RX_OK; } diff --git a/libraries/SondeLib/DFM.h b/libraries/SondeLib/DFM.h index b5a3691..baf5ea1 100644 --- a/libraries/SondeLib/DFM.h +++ b/libraries/SondeLib/DFM.h @@ -23,7 +23,8 @@ class DFM { private: - int inverse=0; + int stype; + char *stypename=NULL; void deinterleave(uint8_t *str, int L, uint8_t *block); uint32_t bits2val(const uint8_t *bits, int len); @@ -34,6 +35,11 @@ private: void decodeCFG(uint8_t *cfg); void decodeDAT(uint8_t *dat); void bitsToBytes(uint8_t *bits, uint8_t *bytes, int len); + int processDFMdata(uint8_t dt); + int decodeFrameDFM(uint8_t *data); + int receiveOld(); + int receiveNew(); + #define B 8 #define S 4 @@ -56,7 +62,7 @@ private: public: DFM(); // main decoder API - int setup(float frequency, int inverse); + int setup(float frequency, int type); int receive(); int waitRXcomplete(); diff --git a/libraries/SondeLib/Display.cpp b/libraries/SondeLib/Display.cpp index 09557fd..d6b455f 100644 --- a/libraries/SondeLib/Display.cpp +++ b/libraries/SondeLib/Display.cpp @@ -28,11 +28,8 @@ extern SemaphoreHandle_t axpSemaphore; SPIClass spiDisp(HSPI); -const char *sondeTypeStr[NSondeTypes] = { "DFM6", "DFM9", "RS41", "RS92", "M10 " }; -const char *sondeTypeLongStr[NSondeTypes] = { "DFM6/17", "DFM9", "RS41", "RS92", "M10 " }; - -#define TYPE_IS_DFM(t) ( (t)==STYPE_DFM06 || (t)==STYPE_DFM09 ) -#define TYPE_IS_METEO(t) ( (t)==STYPE_M10 ) +const char *sondeTypeStr[NSondeTypes] = { "DFM ", "DFM9", "RS41", "RS92", "M10 ", "DFM6" }; +const char *sondeTypeLongStr[NSondeTypes] = { "DFM (all)", "DFM9 (old)", "RS41", "RS92", "M10 ", "DFM6 (old)" }; byte myIP_tiles[8*11]; static uint8_t ap_tile[8]={0x00,0x04,0x22,0x92, 0x92, 0x22, 0x04, 0x00}; @@ -414,13 +411,30 @@ void ILI9225Display::drawString(uint8_t x, uint8_t y, const char *s, int16_t wid } if(findex-3>=ngfx) findex=3; - tft->fillRectangle(x, y, x + width, y + gfxoffsets[findex-3].yclear, bg); DebugPrintf(DEBUG_DISPLAY,"GFX Text %s at %d,%d+%d in color %x, width=%d (w=%d)\n", s, x, y, gfxoffsets[findex-3].yofs, fg, width, w); +#if 0 + // Text by clear rectangle and refill, causes some flicker + tft->fillRectangle(x, y, x + width, y + gfxoffsets[findex-3].yclear, bg); if(alignright) { tft->drawGFXText(x + width - w, y + gfxoffsets[findex-3].yofs, s, fg); } else { tft->drawGFXText(x, y + gfxoffsets[findex-3].yofs, s, fg); } +#else + // Text by drawing bitmap.... => less "flicker" + uint16_t height = gfxoffsets[findex-3].yclear; + uint16_t *bitmap = (uint16_t *)malloc(sizeof(uint16_t) * width * height); + for(int i=0; idrawGFXcharBM(x0, y0, s[k], fg, bitmap, width, height) + 1; + DebugPrintf(DEBUG_DISPLAY,"[%c->%d]",s[k],x0); + } + drawBitmap(x, y, bitmap, width, height); + free(bitmap); +#endif } void ILI9225Display::drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) { @@ -799,8 +813,16 @@ int Display::countEntries(File f) { return n; } -void Display::initFromFile() { - File d = SPIFFS.open("/screens.txt", "r"); +void Display::initFromFile(int index) { + File d; + if(index>0) { + char file[20]; + snprintf(file, 20, "/screens%d.txt", index); + Serial.printf("Trying %i (%s)\n", index, file); + d = SPIFFS.open(file, "r"); + if(!d || d.available()==0 ) { Serial.printf("%s not found, using /screens.txt\n", file); } + } + if(!d || d.available()==0 ) d = SPIFFS.open("/screens.txt", "r"); if(!d) return; DispInfo *newlayouts = (DispInfo *)malloc(MAXSCREENS * sizeof(DispInfo)); @@ -810,13 +832,18 @@ void Display::initFromFile() { } memset(newlayouts, 0, MAXSCREENS * sizeof(DispInfo)); + // default values + xscale=13; + yscale=22; + fontsma=0; + fontlar=1; // default color colfg = 0xffff; // white; only used for ILI9225 colbg = 0; // black; only used for ILI9225 int idx = -1; int what = -1; int entrysize; - Serial.printf("Reading from /screens.txt. available=%d\n",d.available()); + Serial.printf("Reading from screen config: available=%d\n",d.available()); while(d.available()) { //Serial.printf("Unused stack: %d\n", uxTaskGetStackHighWaterMark(0)); const char *ptr; @@ -825,7 +852,7 @@ void Display::initFromFile() { // String line = readLine(d); // line.trim(); // const char *s = line.c_str(); - Serial.printf("Line: '%s'\n", s); + DebugPrintf(DEBUG_SPARSER, "Line: '%s'\n", s); if(*s == '#') continue; // ignore comments switch(what) { case -1: // wait for start of screen (@) @@ -836,7 +863,7 @@ void Display::initFromFile() { } char *label = strdup(s+1); entrysize = countEntries(d); - Serial.printf("Reading entry with %d elements\n", entrysize); + DebugPrintf(DEBUG_SPARSER,"Reading entry with %d elements\n", entrysize); idx++; int res = allocDispInfo(entrysize, &newlayouts[idx], label); Serial.printf("allocDispInfo: idx %d: label is %p - %s\n",idx,newlayouts[idx].label, newlayouts[idx].label); @@ -851,7 +878,7 @@ void Display::initFromFile() { if(strncmp(s,"timer=",6)==0) { // timer values char t1[10],t2[10],t3[10]; sscanf(s+6, "%5[0-9a-zA-Z-] , %5[0-9a-zA-Z-] , %5[0-9a-zA-Z-]", t1, t2, t3); - Serial.printf("timers are %s, %s, %s\n", t1, t2, t3); + DebugPrintf(DEBUG_SPARSER,"timers are %s, %s, %s\n", t1, t2, t3); newlayouts[idx].timeouts[0] = (*t1=='n'||*t1=='N')?sonde.config.norx_timeout:atoi(t1); newlayouts[idx].timeouts[1] = (*t2=='n'||*t2=='N')?sonde.config.norx_timeout:atoi(t2); newlayouts[idx].timeouts[2] = (*t3=='n'||*t3=='N')?sonde.config.norx_timeout:atoi(t3); @@ -905,7 +932,7 @@ void Display::initFromFile() { newlayouts[idx].de[what].y = y; newlayouts[idx].de[what].width = n>2 ? w : WIDTH_AUTO; parseDispElement(text, newlayouts[idx].de+what); - Serial.printf("entry at %d,%d width=%d font %d, color=%x,%x\n", (int)x, (int)y, newlayouts[idx].de[what].width, newlayouts[idx].de[what].fmt, + DebugPrintf(DEBUG_SPARSER,"entry at %d,%d width=%d font %d, color=%x,%x\n", (int)x, (int)y, newlayouts[idx].de[what].width, newlayouts[idx].de[what].fmt, newlayouts[idx].de[what].fg, newlayouts[idx].de[what].bg); if(newlayouts[idx].de[what].func == disp.drawGPS) { newlayouts[idx].usegps = GPSUSE_BASE|GPSUSE_DIST|GPSUSE_BEARING; // just all for now @@ -1077,7 +1104,9 @@ void Display::drawQS(DispEntry *de) { void Display::drawType(DispEntry *de) { rdis->setFont(de->fmt); - drawString(de, sondeTypeStr[sonde.si()->type]); + const char *typestr = sonde.si()->typestr; + if(*typestr==0) typestr = sondeTypeStr[sonde.si()->type]; + drawString(de, typestr); } void Display::drawFreq(DispEntry *de) { rdis->setFont(de->fmt); @@ -1346,7 +1375,7 @@ void Display::drawGPS(DispEntry *de) { } Serial.printf("GPS0: %c%c%c N=%d, A=%d, B=%d\n", circinfo->top, circinfo->arr, circinfo->bul, angN, angA, angB); // "N" in direction angN - static_cast(rdis)->tft->drawGFXcharBM(x0 + circinfo->radius*sin(angN*PI/180)-6, y0 - circinfo->radius*cos(angN*PI/180)+7, 'N', 0xffff, bitmap, size); + static_cast(rdis)->tft->drawGFXcharBM(x0 + circinfo->radius*sin(angN*PI/180)-6, y0 - circinfo->radius*cos(angN*PI/180)+7, 'N', 0xffff, bitmap, size, size); // small circle in direction angB if(validB) { diff --git a/libraries/SondeLib/Display.h b/libraries/SondeLib/Display.h index f2c6e92..b76ef32 100644 --- a/libraries/SondeLib/Display.h +++ b/libraries/SondeLib/Display.h @@ -145,7 +145,7 @@ private: return ret; } public: - void initFromFile(); + void initFromFile(int index); int layoutIdx; DispInfo *layout; diff --git a/libraries/SondeLib/Sonde.cpp b/libraries/SondeLib/Sonde.cpp index 5c0de5a..d5953d9 100644 --- a/libraries/SondeLib/Sonde.cpp +++ b/libraries/SondeLib/Sonde.cpp @@ -10,7 +10,7 @@ #include "Display.h" #include -uint8_t debug = 255-8; +uint8_t debug = 255-8-16; RXTask rxtask = { -1, -1, -1, 0xFFFF, 0 }; @@ -45,7 +45,7 @@ extern SX1278FSK sx1278; * - Periodically it calls Sonde::receive(), which calls the current decoder's receive() * function. It should return control to the SX1278 main loop at least once per second. * It will also set the internal variable receiveResult. The decoder's receive function - * must make sure that there are no FIFI overflows in the SX1278. + * must make sure that there are no FIFO overflows in the SX1278. * - the Arduino main loop will call the waitRXcomplete function, which should return as * soon as there is some new data to display, or no later than after 1s, returning the * value of receiveResult (or timeout, if receiveResult was not set within 1s). It @@ -250,6 +250,8 @@ void Sonde::setConfig(const char *cfg) { config.wifiap = atoi(val); } else if(strcmp(cfg,"mdnsname")==0) { strncpy(config.mdnsname, val, 14); + } else if(strcmp(cfg,"screenfile")==0) { + config.screenfile = atoi(val); } else if(strcmp(cfg,"display")==0) { int i = 0; char *ptr; @@ -335,6 +337,7 @@ void Sonde::addSonde(float frequency, SondeType type, int active, char *launchsi } Serial.printf("Adding %f - %d - %d - %s\n", frequency, type, active, launchsite); sondeList[nSonde].type = type; + sondeList[nSonde].typestr[0] = 0; sondeList[nSonde].freq = frequency; sondeList[nSonde].active = active; strncpy(sondeList[nSonde].launchsite, launchsite, 17); @@ -403,9 +406,10 @@ void Sonde::setup() { case STYPE_RS41: rs41.setup(sondeList[rxtask.currentSonde].freq * 1000000); break; - case STYPE_DFM06: - case STYPE_DFM09: - dfm.setup( sondeList[rxtask.currentSonde].freq * 1000000, sondeList[rxtask.currentSonde].type==STYPE_DFM06?0:1 ); + case STYPE_DFM06_OLD: + case STYPE_DFM09_OLD: + case STYPE_DFM: + dfm.setup( sondeList[rxtask.currentSonde].freq * 1000000, sondeList[rxtask.currentSonde].type ); break; case STYPE_RS92: rs92.setup( sondeList[rxtask.currentSonde].freq * 1000000); @@ -435,8 +439,9 @@ void Sonde::receive() { case STYPE_M10: res = m10.receive(); break; - case STYPE_DFM06: - case STYPE_DFM09: + case STYPE_DFM06_OLD: + case STYPE_DFM09_OLD: + case STYPE_DFM: res = dfm.receive(); break; } @@ -525,8 +530,9 @@ rxloop: case STYPE_M10: m10.waitRXcomplete(); break; - case STYPE_DFM06: - case STYPE_DFM09: + case STYPE_DFM06_OLD: + case STYPE_DFM09_OLD: + case STYPE_DFM: dfm.waitRXcomplete(); break; } diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index 450455a..daa2654 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -2,7 +2,7 @@ #ifndef Sonde_h #define Sonde_h -enum DbgLevel { DEBUG_OFF=0, DEBUG_INFO=1, DEBUG_DISPLAY=8 }; // to be extended for configuring serial debug output +enum DbgLevel { DEBUG_OFF=0, DEBUG_INFO=1, DEBUG_SPARSER=16, DEBUG_DISPLAY=8 }; // to be extended for configuring serial debug output extern uint8_t debug; #define DebugPrint(l,x) if(debug&l) { Serial.print(x); } @@ -53,17 +53,21 @@ extern const char *RXstr[]; // 01000000 => goto sonde -1 // 01000001 => goto sonde +1 -#define NSondeTypes 5 -enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41, STYPE_RS92, STYPE_M10 }; +#define NSondeTypes 6 +enum SondeType { STYPE_DFM, STYPE_DFM09_OLD, STYPE_RS41, STYPE_RS92, STYPE_M10, STYPE_DFM06_OLD }; extern const char *sondeTypeStr[NSondeTypes]; extern const char *sondeTypeLongStr[NSondeTypes]; +#define TYPE_IS_DFM(t) ( (t)==STYPE_DFM || (t)==STYPE_DFM09_OLD || (t)==STYPE_DFM06_OLD ) +#define TYPE_IS_METEO(t) ( (t)==STYPE_M10 ) + typedef struct st_sondeinfo { // receiver configuration bool active; SondeType type; float freq; // decoded ID + char typestr[5]; // decoded type (use type if *typestr==0) char id[10]; char ser[12]; bool validID; @@ -174,6 +178,7 @@ typedef struct st_rdzconfig { int debug; // show port and config options after reboot int wifi; // connect to known WLAN 0=skip int wifiap; // enable/disable WiFi AccessPoint mode 0=disable + int screenfile; int8_t display[30]; // list of display mode (0:scanner, 1:default, 2,... additional modes) int startfreq; // spectrum display start freq (400, 401, ...) int channelbw; // spectrum channel bandwidth (valid: 5, 10, 20, 25, 50, 100 kHz) diff --git a/libraries/SondeLib/TFT22_ILI9225.cpp b/libraries/SondeLib/TFT22_ILI9225.cpp index bad6016..1bd3762 100644 --- a/libraries/SondeLib/TFT22_ILI9225.cpp +++ b/libraries/SondeLib/TFT22_ILI9225.cpp @@ -1344,7 +1344,7 @@ uint16_t TFT22_ILI9225::drawGFXChar(int16_t x, int16_t y, unsigned char c, uint1 } // Write a character to a bitmap -uint16_t TFT22_ILI9225::drawGFXcharBM(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t *bm, int bmwd) { +uint16_t TFT22_ILI9225::drawGFXcharBM(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t *bm, int bmwidth, int bmheight) { c -= (uint8_t)pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); @@ -1356,17 +1356,15 @@ uint16_t TFT22_ILI9225::drawGFXcharBM(int16_t x, int16_t y, unsigned char c, uin int8_t xo = pgm_read_byte(&glyph->xOffset), yo = pgm_read_byte(&glyph->yOffset); uint8_t xx, yy, bits = 0, bit = 0; - for(yy=0; yy=bmwd) continue; + if(y+yo+yy>=bmheight) continue; if(y+yo+yy<0) continue; // yo can be negative for(xx=0; xx=bmwd) continue; if(!(bit++ & 7)) { bits = pgm_read_byte(&bitmap[bo++]); } - if(bits & 0x80) { - bm[x+xo+xx + bmwd*(y+yo+yy)] = color; + if( (bits & 0x80) && (x+xo+xxvs, s->freq, sondeTypeStr[s->type]); strcat(b, comm); - if(s->type==STYPE_M10||s->type==STYPE_DFM06||s->type==STYPE_DFM09) { + if( TYPE_IS_DFM(s->type) || TYPE_IS_METEO(s->type) ) { snprintf(comm, 100, " ser=%s", s->ser); strcat(b, comm); } diff --git a/platformio.ini b/platformio.ini index 0094f3d..d85b8a3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,7 +25,7 @@ lib_deps_external = nkawu/TFT 22 ILI9225 @ ^1.4.4 me-no-dev/ESP Async WebServer @ ^1.2.3 -[env:ttgo-lora32-v1] +[env:ttgo-lora32] platform = espressif32 board = ttgo-lora32-v1 framework = arduino @@ -34,13 +34,3 @@ lib_deps = ${extra.lib_deps_builtin} ${extra.lib_deps_external} -[env:ttgo-lora32-v2] -platform = espressif32 -# platformio currently fails to build with board v2 so ve override v1 pins instead -build_flags = -D TTGO_V2 -board = ttgo-lora32-v1 -framework = arduino -monitor_speed = 115200 -lib_deps = - ${extra.lib_deps_builtin} - ${extra.lib_deps_external}