testing modified DFM decoder, ttgo 2.1_1.6 bugfix, modified screens

pull/42/head
Hansi, dl9rdz 2020-11-30 15:44:49 +01:00
rodzic 52a998ebd0
commit 67d0cbf858
17 zmienionych plików z 1374 dodań i 136 usunięć

Wyświetl plik

@ -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, "</table><input type=\"submit\" value=\"Update\"/></form></body></html>");
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, "</table><input type=\"submit\" value=\"Update\"></input></form></body></html>");
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, "<table>");
sprintf(ptr + strlen(ptr), "<tr><td id=\"sfreq\">%3.3f MHz, Type: %s</td><tr><td>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), "</td></tr><tr><td>QTH: %.6f,%.6f h=%.0fm</td></tr>\n", s->lat, s->lon, s->alt);
@ -392,7 +398,7 @@ const char *createStatusForm() {
}
}
strcat(ptr, "</body></html>");
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, "</table><input type=\"submit\" value=\"Update\"></input></form></body></html>");
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, "\"></input><br>");
}
strcat(ptr, "</form></body></html>");
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, "</textarea><input type=\"submit\" value=\"Save\"></input></form></body></html>");
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, "<input type=\"submit\" name=\"master\" value=\"Master-Update\"></input><br><input type=\"submit\" name=\"devel\" value=\"Devel-Update\">");
}
strcat(ptr, "</form></body></html>");
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", "<html><head>ERROR</head><body><p>Something went wrong. Uploaded file is empty.</p></body></hhtml>");
if (ret == NULL)
request->send(200, "text/html", "<html><head>ERROR</head><body><p>Something went wrong. Uploaded file is empty.</p></body></hhtml>");
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;

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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();

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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();

Wyświetl plik

@ -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; i<width*height; i++) { bitmap[i] = bg; } // fill with background
int x0 = 0;
int y0 = gfxoffsets[findex-3].yofs;
DebugPrintf(DEBUG_DISPLAY,"GFX: w=%d h=%d\n", width, height);
for (uint8_t k = 0; k < strlen(s); k++) {
x0 += tft->drawGFXcharBM(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<ILI9225Display *>(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<ILI9225Display *>(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) {

Wyświetl plik

@ -145,7 +145,7 @@ private:
return ret;
}
public:
void initFromFile();
void initFromFile(int index);
int layoutIdx;
DispInfo *layout;

Wyświetl plik

@ -10,7 +10,7 @@
#include "Display.h"
#include <Wire.h>
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;
}

Wyświetl plik

@ -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)

Wyświetl plik

@ -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<h; yy++) {
if(y+yo+yy>=bmwd) continue;
if(y+yo+yy>=bmheight) continue;
if(y+yo+yy<0) continue; // yo can be negative
for(xx=0; xx<w; xx++) {
if(x+xo+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+xx<bmwidth) ) {
bm[x+xo+xx + bmwidth*(y+yo+yy)] = color;
}
bits <<= 1;
}

Wyświetl plik

@ -389,7 +389,7 @@ class TFT22_ILI9225 {
/// @return width of character in display pixels
uint16_t drawGFXChar(int16_t x, int16_t y, unsigned char c, uint16_t color);
uint16_t drawGFXcharBM(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t *bm, int bmwd);
uint16_t drawGFXcharBM(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t *bm, int bmwidth, int bmheight);
void getGFXCharExtent(uint8_t c, int16_t *gw, int16_t *gh, int16_t *xa);

Wyświetl plik

@ -317,7 +317,7 @@ char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) {
char comm[100];
snprintf(comm, 100, "Clb=%.1fm/s %.3fMHz Type=%s", s->vs, 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);
}

Wyświetl plik

@ -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}