kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
merge
commit
cc7a00b60a
|
@ -7,9 +7,9 @@ before_install:
|
|||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
|
||||
- sleep 3
|
||||
- export DISPLAY=:1.0
|
||||
- wget https://downloads.arduino.cc/arduino-1.8.10-linux64.tar.xz
|
||||
- tar xf arduino-1.8.10-linux64.tar.xz
|
||||
- sudo mv arduino-1.8.10 /usr/local/share/arduino
|
||||
- wget https://downloads.arduino.cc/arduino-1.8.13-linux64.tar.xz
|
||||
- tar xf arduino-1.8.13-linux64.tar.xz
|
||||
- sudo mv arduino-1.8.13 /usr/local/share/arduino
|
||||
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||
- wget https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip
|
||||
- unzip master.zip
|
||||
|
|
|
@ -20,16 +20,8 @@
|
|||
#include "version.h"
|
||||
#include "geteph.h"
|
||||
#include "rs92gps.h"
|
||||
|
||||
#include "mqtt.h"
|
||||
|
||||
#ifdef TTGO_V2
|
||||
// platformio currently fails to build with board v2 so ve override v1 pins instead
|
||||
#define OLED_SDA 4
|
||||
#define OLED_SCL 15
|
||||
#define OLED_RST 16
|
||||
#endif
|
||||
|
||||
int e;
|
||||
|
||||
enum MainState { ST_DECODER, ST_SPECTRUM, ST_WIFISCAN, ST_UPDATE, ST_TOUCHCALIB };
|
||||
|
@ -100,8 +92,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;
|
||||
}
|
||||
|
||||
|
@ -134,13 +129,13 @@ const String sondeTypeSelect(int activeType) {
|
|||
String sts = "";
|
||||
for (int i = 0; i < NSondeTypes; i++) {
|
||||
sts += "<option value=\"";
|
||||
sts += sondeTypeStr[i];
|
||||
sts += sondeTypeLongStr[i];
|
||||
sts += "\"";
|
||||
if (activeType == i) {
|
||||
sts += " selected";
|
||||
}
|
||||
sts += ">";
|
||||
sts += sondeTypeStr[i];
|
||||
sts += sondeTypeLongStr[i];
|
||||
sts += "</option>";
|
||||
}
|
||||
return sts;
|
||||
|
@ -181,10 +176,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;
|
||||
|
@ -222,7 +220,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;
|
||||
}
|
||||
|
||||
|
@ -262,7 +260,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();
|
||||
|
@ -326,7 +324,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;
|
||||
}
|
||||
|
||||
|
@ -374,9 +372,9 @@ void addSondeStatus(char *ptr, int i)
|
|||
struct tm ts;
|
||||
SondeInfo *s = &sonde.sondeList[i];
|
||||
strcat(ptr, "<table>");
|
||||
sprintf(ptr + strlen(ptr), "<tr><td id=\"sfreq\">%3.3f MHz, Type: %s</td><tr><td>ID: %s", s->freq, sondeTypeStr[s->type],
|
||||
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);
|
||||
|
@ -405,7 +403,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;
|
||||
}
|
||||
|
||||
|
@ -438,6 +436,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},
|
||||
|
@ -453,8 +452,8 @@ struct st_configitems config_list[] = {
|
|||
{"rs41.rxbw", "RS41 RX bandwidth", 0, &sonde.config.rs41.rxbw},
|
||||
{"rs92.rxbw", "RS92 RX (and AGC) bandwidth", 0, &sonde.config.rs92.rxbw},
|
||||
{"rs92.alt2d", "RS92 2D fix default altitude", 0, &sonde.config.rs92.alt2d},
|
||||
{"dfm.agcbw", "DFM6/9 AGC bandwidth", 0, &sonde.config.dfm.agcbw},
|
||||
{"dfm.rxbw", "DFM6/9 RX bandwidth", 0, &sonde.config.dfm.rxbw},
|
||||
{"dfm.agcbw", "DFM AGC bandwidth", 0, &sonde.config.dfm.agcbw},
|
||||
{"dfm.rxbw", "DFM RX bandwidth", 0, &sonde.config.dfm.rxbw},
|
||||
{"", "Data feed configuration", -5, NULL},
|
||||
/* APRS settings */
|
||||
{"call", "Call", 8, sonde.config.call},
|
||||
|
@ -593,7 +592,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;
|
||||
}
|
||||
|
||||
|
@ -666,7 +665,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;
|
||||
}
|
||||
|
||||
|
@ -715,6 +714,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) {
|
||||
|
@ -733,41 +733,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;
|
||||
}
|
||||
|
@ -780,7 +784,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;
|
||||
}
|
||||
|
@ -796,7 +800,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;
|
||||
}
|
||||
|
||||
|
@ -921,14 +925,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
|
||||
|
@ -1311,6 +1315,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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1429,7 +1436,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);
|
||||
|
@ -1514,7 +1523,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);
|
||||
|
||||
|
||||
|
@ -1604,13 +1613,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();
|
||||
|
||||
|
@ -1666,7 +1675,7 @@ void loopDecoder() {
|
|||
// sonde knows the current type and frequency, and delegates to the right decoder
|
||||
uint16_t res = sonde.waitRXcomplete();
|
||||
int action;
|
||||
Serial.printf("waitRX result is %x\n", (int)res);
|
||||
//Serial.printf("waitRX result is %x\n", (int)res);
|
||||
action = (int)(res >> 8);
|
||||
// TODO: update displayed sonde?
|
||||
|
||||
|
@ -1690,7 +1699,7 @@ void loopDecoder() {
|
|||
}
|
||||
|
||||
if (!tncclient.connected()) {
|
||||
Serial.println("TNC client not connected");
|
||||
//Serial.println("TNC client not connected");
|
||||
tncclient = tncserver.available();
|
||||
if (tncclient.connected()) {
|
||||
Serial.println("new TCP KISS connection");
|
||||
|
@ -1714,8 +1723,8 @@ void loopDecoder() {
|
|||
if (connected) {
|
||||
char raw[201];
|
||||
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
|
||||
Serial.println("Sending position via UDP");
|
||||
Serial.print("Sending: "); 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();
|
||||
|
@ -1738,14 +1747,15 @@ void loopDecoder() {
|
|||
// also send to web socket
|
||||
//TODO
|
||||
}
|
||||
Serial.println("updateDisplay started");
|
||||
Serial.print("updateDisplay started... ");
|
||||
if (forceReloadScreenConfig) {
|
||||
disp.initFromFile();
|
||||
disp.initFromFile(sonde.config.screenfile);
|
||||
sonde.clearDisplay();
|
||||
forceReloadScreenConfig = false;
|
||||
}
|
||||
int t = millis();
|
||||
sonde.updateDisplay();
|
||||
Serial.println("updateDisplay done");
|
||||
Serial.printf("updateDisplay done (after %d ms)\n", (int)(millis() - t));
|
||||
}
|
||||
|
||||
void setCurrentDisplay(int value) {
|
||||
|
@ -2035,11 +2045,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);
|
||||
|
@ -2368,15 +2378,15 @@ void execOTA() {
|
|||
|
||||
|
||||
void loop() {
|
||||
Serial.printf("\nRunning main loop in state %d. free heap: %d;\n", mainState, ESP.getFreeHeap());
|
||||
Serial.printf("currentDisp:%d lastDisp:%d\n", currentDisplay, lastDisplay);
|
||||
Serial.printf("\nRunning main loop in state %d [currentDisp:%d, lastDiso:%d]. free heap: %d;\n",
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,7 +32,10 @@
|
|||
# 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 (dfm format by x: d=>dxlaprs, a=>autorx, s=>real serial number)
|
||||
# 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
|
||||
|
@ -223,7 +226,7 @@ key1action=+,0,F,W
|
|||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
color=FFD700
|
||||
0,0=Id
|
||||
0,0=Is
|
||||
color=0000FF
|
||||
0,11,-5.5=f
|
||||
1,1,6=c
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
const char *version_name = "rdzTTGOsonde";
|
||||
const char *version_id = "devel20201120";
|
||||
const char *version_id = "devel20201130";
|
||||
const int SPIFFS_MAJOR=2;
|
||||
const int SPIFFS_MINOR=4;
|
||||
const int SPIFFS_MINOR=5;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -12,11 +12,26 @@
|
|||
#define DFM_DBG(x)
|
||||
#endif
|
||||
|
||||
int DFM::setup(float frequency, int inv)
|
||||
#define DFM_FRAMELEN 33
|
||||
|
||||
// single data structure, search restarts after decoder change
|
||||
static struct st_dfmstat {
|
||||
int idcnt0;
|
||||
int idcnt1;
|
||||
int lastfrid;
|
||||
int lastfrcnt;
|
||||
uint8_t start[50];
|
||||
uint16_t dat[50*2];
|
||||
uint8_t cnt[50*2];
|
||||
uint8_t nameregok;
|
||||
uint8_t nameregtop;
|
||||
} dfmstate;
|
||||
|
||||
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"));
|
||||
|
@ -44,35 +59,70 @@ 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) {
|
||||
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;
|
||||
}
|
||||
|
@ -163,8 +213,147 @@ 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 */
|
||||
void DFM::finddfname(uint8_t *b)
|
||||
{
|
||||
uint8_t st;
|
||||
uint32_t thres;
|
||||
uint32_t i;
|
||||
uint8_t ix;
|
||||
uint16_t d;
|
||||
|
||||
st = b[0]; /* frame start byte */
|
||||
ix = b[3]; /* hi/lo part of ser; (LSB due to our bitsToBytes...) */
|
||||
d = (b[1]<<8) + b[2]; /* data byte */
|
||||
/* find highest channel number single frame serial,
|
||||
(2 frame serial will make a single serial too) */
|
||||
if(dfmstate.idcnt0 < DFMIDTHRESHOLD && dfmstate.idcnt1 < DFMIDTHRESHOLD) {
|
||||
uint32_t v = (st<<20) | (d<<4) | ix;
|
||||
if ( st > (dfmstate.lastfrid>>20) ) {
|
||||
dfmstate.lastfrid = v;
|
||||
Serial.print(" MAXCH:"); Serial.print(st);
|
||||
dfmstate.lastfrcnt = 0;
|
||||
} else if ( st == (dfmstate.lastfrid>>20) ) {
|
||||
/* same id found */
|
||||
if (v == dfmstate.lastfrid) {
|
||||
++dfmstate.lastfrcnt;
|
||||
thres = DFMIDTHRESHOLD * 2;
|
||||
/* may be a 2 frame serial so increase safety level */
|
||||
if (ix <= 1) thres *= 2;
|
||||
/* may be not a dfm6 so increase safety level */
|
||||
if ( (st>>4) != 6) thres *= 2;
|
||||
if (dfmstate.lastfrcnt >= thres) {
|
||||
/* id found */
|
||||
if (dfmstate.lastfrcnt == thres) {
|
||||
uint32_t id = ((st&0x0F)<<20) | (d<<4) | ix;
|
||||
uint32_t chkid = id;
|
||||
int i;
|
||||
/* check validity */
|
||||
for(i=0; i<6; i++) {
|
||||
if((chkid&0x0f)>9) { break; /* not ok */ }
|
||||
chkid >>= 4;
|
||||
}
|
||||
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;
|
||||
Serial.print(" NOT NUMERIC SERIAL");
|
||||
}
|
||||
//anonym->idtime = osic_time();
|
||||
} else {
|
||||
Serial.print(" MAXCHCNT/SECLVL:");
|
||||
Serial.print(dfmstate.lastfrcnt);
|
||||
Serial.print("/");
|
||||
Serial.print(thres);
|
||||
}
|
||||
} else {
|
||||
dfmstate.lastfrid = v; /* not stable ser */
|
||||
dfmstate.lastfrcnt = 0UL;
|
||||
}
|
||||
}
|
||||
} /*find highest channel number single frame serial */
|
||||
|
||||
i = 0;
|
||||
while (i<dfmstate.nameregtop && dfmstate.start[i]!=st) i++;
|
||||
Serial.printf(" %02x:i=%d,top=%d", st, i, dfmstate.nameregtop);
|
||||
if (i<dfmstate.nameregtop) {
|
||||
if (ix<=1UL && (dfmstate.cnt[2*i+ix]==0 || dfmstate.dat[2*i+ix]==d)) {
|
||||
dfmstate.dat[2*i+ix] = d;
|
||||
if(dfmstate.cnt[2*i+ix] < 255) dfmstate.cnt[2*i+ix]++;
|
||||
Serial.print(" ID:");
|
||||
Serial.print(st, HEX);
|
||||
Serial.print("[");
|
||||
Serial.print(ix);
|
||||
Serial.print("] CNT:");
|
||||
Serial.print(dfmstate.cnt[2*i]);
|
||||
Serial.print(",");
|
||||
Serial.print(dfmstate.cnt[2*i+1]);
|
||||
Serial.print(",st=");
|
||||
Serial.print(st);
|
||||
Serial.print(",lastfrid=");
|
||||
Serial.print(dfmstate.lastfrid>>20);
|
||||
if( (dfmstate.cnt[2*i]>DFMIDTHRESHOLD && dfmstate.cnt[2*i+1]>DFMIDTHRESHOLD) ||
|
||||
(dfmstate.cnt[2*i]>0 && dfmstate.cnt[2*i+1]>0 && st == (dfmstate.lastfrid>>20) && (st>>4)>6) ) {
|
||||
if(dfmstate.idcnt0 <= 1) {
|
||||
dfmstate.idcnt0 = dfmstate.cnt[2*i];
|
||||
dfmstate.idcnt1 = dfmstate.cnt[2*i+1];
|
||||
dfmstate.nameregok = i;
|
||||
// generate id.....
|
||||
snprintf(sonde.si()->id, 10, "D%d", ((dfmstate.dat[2*i]<<16)|dfmstate.dat[2*i+1])%100000000);
|
||||
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");
|
||||
// idtime = .... /* TODO */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* data changed so not ser */
|
||||
dfmstate.cnt[2*i] = 0;
|
||||
dfmstate.cnt[2*i+1] = 0;
|
||||
if(dfmstate.nameregok == i) { /* found id wrong */
|
||||
dfmstate.idcnt0 = 0;
|
||||
dfmstate.idcnt1 = 0;
|
||||
}
|
||||
}
|
||||
} else if (ix<=1) { /* add new entry for possible ID */
|
||||
dfmstate.start[dfmstate.nameregtop] = st;
|
||||
dfmstate.cnt[2*dfmstate.nameregtop] = 0;
|
||||
dfmstate.cnt[2*dfmstate.nameregtop+1] = 0;
|
||||
dfmstate.cnt[2*dfmstate.nameregtop+ix] = 1;
|
||||
dfmstate.dat[2*dfmstate.nameregtop+ix] = d;
|
||||
if(dfmstate.nameregtop<49) dfmstate.nameregtop++;
|
||||
}
|
||||
}
|
||||
|
||||
void DFM::decodeCFG(uint8_t *cfg)
|
||||
{
|
||||
#if 1
|
||||
// new ID
|
||||
finddfname(cfg);
|
||||
// new aprs ID (dxlaprs, autorx) is now "D" + serial (8 digits) by consensus
|
||||
memcpy(sonde.si()->ser, sonde.si()->id+1, 9);
|
||||
#else
|
||||
// old ID
|
||||
static int lowid, highid, idgood=0, type=0;
|
||||
if((cfg[0]>>4)==0x06 && type==0) { // DFM-6 ID
|
||||
lowid = ((cfg[0]&0x0F)<<20) | (cfg[1]<<12) | (cfg[2]<<4) | (cfg[3]&0x0f);
|
||||
|
@ -190,6 +379,7 @@ void DFM::decodeCFG(uint8_t *cfg)
|
|||
sonde.si()->validID = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bitCount(int x) {
|
||||
|
@ -288,20 +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;
|
||||
}
|
||||
|
||||
Serial.printf("inverse is %d\b", inverse);
|
||||
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);
|
||||
|
@ -318,7 +628,7 @@ int DFM::receive() {
|
|||
decodeCFG(byte_conf);
|
||||
decodeDAT(byte_dat1);
|
||||
decodeDAT(byte_dat2);
|
||||
}
|
||||
Serial.println("");
|
||||
return RX_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,16 +23,23 @@
|
|||
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);
|
||||
int check(uint8_t code[8]);
|
||||
int hamming(uint8_t *ham, int L, uint8_t *sym);
|
||||
void printRaw(const char *prefix, int len, int ret, const uint8_t* data);
|
||||
void finddfname(uint8_t *cfg);
|
||||
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
|
||||
|
@ -55,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();
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ extern SemaphoreHandle_t axpSemaphore;
|
|||
|
||||
SPIClass spiDisp(HSPI);
|
||||
|
||||
const char *sondeTypeStr[NSondeTypes] = { "DFM6", "DFM9", "RS41", "RS92", "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};
|
||||
|
@ -388,7 +389,7 @@ void ILI9225Display::drawString(uint8_t x, uint8_t y, const char *s, int16_t wid
|
|||
int16_t w,h;
|
||||
boolean alignright=false;
|
||||
if(findex<3) { // standard font
|
||||
Serial.printf("Simple Text %s at %d,%d [%d]\n", s, x, y, width);
|
||||
DebugPrintf(DEBUG_DISPLAY, "Simple Text %s at %d,%d [%d]\n", s, x, y, width);
|
||||
tft->drawText(x, y, s, fg);
|
||||
return;
|
||||
}
|
||||
|
@ -403,20 +404,37 @@ void ILI9225Display::drawString(uint8_t x, uint8_t y, const char *s, int16_t wid
|
|||
width=w;
|
||||
if(alignright) {
|
||||
x -= w;
|
||||
Serial.print("reducing x by widht, its now ");
|
||||
DebugPrint(DEBUG_DISPLAY, "reducing x by widht, its now ");
|
||||
Serial.println(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(findex-3>=ngfx) findex=3;
|
||||
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);
|
||||
Serial.printf("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(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) {
|
||||
|
@ -455,10 +473,10 @@ void ILI9225Display::welcome() {
|
|||
setFont(5);
|
||||
int l=3*22;
|
||||
if(sonde.config.tft_orient&1) {
|
||||
drawString(0, 1*22, "RS41/92,DFM6/9,M10");
|
||||
drawString(0, 1*22, "RS41/92,DFM,M10");
|
||||
} else {
|
||||
drawString(0, 1*22, "RS41,RS92,");
|
||||
drawString(0, 2*22, "DFM6/9,M10");
|
||||
drawString(0, 2*22, "DFM,M10");
|
||||
l+=22;
|
||||
}
|
||||
drawString(0, l, version_id);
|
||||
|
@ -795,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));
|
||||
|
@ -806,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;
|
||||
|
@ -821,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 (@)
|
||||
|
@ -832,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);
|
||||
|
@ -847,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);
|
||||
|
@ -901,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
|
||||
|
@ -1018,7 +1049,7 @@ void Display::drawVS(DispEntry *de) {
|
|||
return;
|
||||
}
|
||||
snprintf(buf, 16, " %+2.1f", sonde.si()->vs);
|
||||
Serial.printf("drawVS: extra is %s width=%d\n", de->extra?de->extra:"<null>", de->width);
|
||||
DebugPrintf(DEBUG_DISPLAY, "drawVS: extra is %s width=%d\n", de->extra?de->extra:"<null>", de->width);
|
||||
if(de->extra) { strcat(buf, de->extra); }
|
||||
drawString(de, buf+strlen(buf)-5- (de->extra?strlen(de->extra):0) );
|
||||
if(!de->extra) rdis->drawTile(de->x+5,de->y,2,ms_tiles);
|
||||
|
@ -1029,24 +1060,24 @@ void Display::drawID(DispEntry *de) {
|
|||
drawString(de, "nnnnnnnn ");
|
||||
return;
|
||||
}
|
||||
// TODO: handle DFM6 IDs
|
||||
|
||||
if(!de->extra || de->extra[0]=='s') {
|
||||
// real serial number, as printed on sonde
|
||||
if(de->extra && de->extra[0]=='n') {
|
||||
// real serial number, as printed on sonde, can be up to 11 digits long
|
||||
drawString(de, sonde.si()->ser);
|
||||
} else if (de->extra[0]=='a') {
|
||||
// autorx sonde number ("DF9" and last 6 digits of real serial number)
|
||||
if(sonde.si()->type == STYPE_DFM09) {
|
||||
int n = strlen(sonde.si()->ser) - 6;
|
||||
if(n<0) n=0;
|
||||
memcpy(buf, "DF9", 3);
|
||||
memcpy(buf+3, sonde.si()->ser+n, 6);
|
||||
drawString(de, buf);
|
||||
} else if (de->extra && de->extra[0]=='s') {
|
||||
// short ID, max 8 digits (no initial "D" for DFM, "M" instead of "ME" for M10)
|
||||
if( TYPE_IS_DFM(sonde.si()->type) ) {
|
||||
drawString(de, sonde.si()->id+1);
|
||||
} else if (TYPE_IS_METEO(sonde.si()->type)) {
|
||||
char sid[9];
|
||||
sid[0]='M';
|
||||
memcpy(sid+1, sonde.si()->id+2, 8);
|
||||
sid[8] = 0;
|
||||
drawString(de, sid);
|
||||
} else {
|
||||
drawString(de, sonde.si()->ser);
|
||||
drawString(de, sonde.si()->id);
|
||||
}
|
||||
} else {
|
||||
// dxlAPRS sonde number (DF6 (why??) and 5 last digits of serial number as hex number
|
||||
// dxlAPRS sonde number, max 9 digits, as used on aprs.fi and radiosondy.info
|
||||
drawString(de, sonde.si()->id);
|
||||
}
|
||||
}
|
||||
|
@ -1073,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);
|
||||
|
@ -1224,7 +1257,7 @@ static int tmpc=0;
|
|||
gpsBear = -1;
|
||||
}
|
||||
|
||||
Serial.printf("GPS data: valid%d GPS at %f,%f (alt=%d,cog=%d); sonde at dist=%d, dir=%d rel.bear=%d\n",gpsValid?1:0,
|
||||
DebugPrintf(DEBUG_DISPLAY, "GPS data: valid%d GPS at %f,%f (alt=%d,cog=%d); sonde at dist=%d, dir=%d rel.bear=%d\n",gpsValid?1:0,
|
||||
gpsLat, gpsLon, gpsAlt, gpsCourse, gpsDist, gpsDir, gpsBear);
|
||||
}
|
||||
|
||||
|
@ -1342,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) {
|
||||
|
|
|
@ -145,7 +145,7 @@ private:
|
|||
return ret;
|
||||
}
|
||||
public:
|
||||
void initFromFile();
|
||||
void initFromFile(int index);
|
||||
|
||||
int layoutIdx;
|
||||
DispInfo *layout;
|
||||
|
|
|
@ -138,7 +138,7 @@ void Scanner::scan()
|
|||
int wait = scanconfig.ADDWAIT + 20 + 1000*(1<<(scanconfig.SMOOTH+1))/4/(0.001*CHANBW);
|
||||
Serial.print("wait time (us) is: "); Serial.println(wait);
|
||||
for(int iter=0; iter<3; iter++) { // three interations, to catch all RS41 transmissions
|
||||
delayMicroseconds(20000);
|
||||
delayMicroseconds(20000); yield();
|
||||
for(int i=0; i<scanconfig.PLOT_W*scanconfig.SMPL_PIX; i++) {
|
||||
freq = STARTF + 1000.0*i*scanconfig.CHANSTEP;
|
||||
//freq = 404000000 + 100*i*scanconfig.CHANSTEP;
|
||||
|
@ -159,6 +159,7 @@ void Scanner::scan()
|
|||
}
|
||||
}
|
||||
}
|
||||
yield();
|
||||
unsigned long duration = millis()-start;
|
||||
Serial.print("wait: ");
|
||||
Serial.println(wait);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Display.h"
|
||||
#include <Wire.h>
|
||||
|
||||
uint8_t debug = 255-8-16;
|
||||
|
||||
RXTask rxtask = { -1, -1, -1, 0xFFFF, 0 };
|
||||
|
||||
|
@ -44,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
|
||||
|
@ -256,6 +257,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;
|
||||
|
@ -357,6 +360,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);
|
||||
|
@ -425,9 +429,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);
|
||||
|
@ -457,8 +462,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;
|
||||
}
|
||||
|
@ -488,7 +494,7 @@ void Sonde::receive() {
|
|||
int event = getKeyPressEvent();
|
||||
if (!event) event = timeoutEvent(si);
|
||||
int action = (event==EVT_NONE) ? ACT_NONE : disp.layout->actions[event];
|
||||
Serial.printf("event %x: action is %x\n", event, action);
|
||||
if(action!=ACT_NONE) { Serial.printf("event %x: action is %x\n", event, action); }
|
||||
// If action is to move to a different sonde index, we do update things here, set activate
|
||||
// to force the sx1278 task to call sonde.setup(), and pass information about sonde to
|
||||
// main loop (display update...)
|
||||
|
@ -505,7 +511,7 @@ void Sonde::receive() {
|
|||
}
|
||||
}
|
||||
res = (action<<8) | (res&0xff);
|
||||
Serial.printf("receive Result is %04x\n", res);
|
||||
Serial.printf("receive(): Result is %04x (action %d, res %d)\n", res, action, res&0xff);
|
||||
// let waitRXcomplete resume...
|
||||
rxtask.receiveResult = res;
|
||||
}
|
||||
|
@ -522,7 +528,7 @@ rxloop:
|
|||
}
|
||||
if( rxtask.receiveResult == RX_UPDATERSSI ) {
|
||||
rxtask.receiveResult = 0xFFFF;
|
||||
Serial.print("RSSI update: ");
|
||||
Serial.printf("RSSI update: %d/2\n", sonde.si()->rssi);
|
||||
disp.updateDisplayRSSI();
|
||||
goto rxloop;
|
||||
}
|
||||
|
@ -547,8 +553,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;
|
||||
}
|
||||
|
@ -560,12 +567,11 @@ rxloop:
|
|||
uint8_t Sonde::timeoutEvent(SondeInfo *si) {
|
||||
uint32_t now = millis();
|
||||
#if 1
|
||||
Serial.printf("Timeout check: %d - %d vs %d; %d - %d vs %d; %d - %d vs %d\n",
|
||||
Serial.printf("Timeout check: %d - %d vs %d; %d - %d vs %d; %d - %d vs %d; lastState: %d\n",
|
||||
now, si->viewStart, disp.layout->timeouts[0],
|
||||
now, si->rxStart, disp.layout->timeouts[1],
|
||||
now, si->norxStart, disp.layout->timeouts[2]);
|
||||
now, si->norxStart, disp.layout->timeouts[2], si->lastState);
|
||||
#endif
|
||||
Serial.printf("lastState is %d\n", si->lastState);
|
||||
if(disp.layout->timeouts[0]>=0 && now - si->viewStart >= disp.layout->timeouts[0]) {
|
||||
Serial.println("View timer expired");
|
||||
return EVT_VIEWTO;
|
||||
|
@ -673,9 +679,7 @@ void Sonde::updateDisplayIP() {
|
|||
|
||||
void Sonde::updateDisplay()
|
||||
{
|
||||
int t = millis();
|
||||
disp.updateDisplay();
|
||||
Serial.printf("updateDisplay took %d ms\n", (int)(millis()-t));
|
||||
}
|
||||
|
||||
void Sonde::clearDisplay() {
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
#ifndef Sonde_h
|
||||
#define Sonde_h
|
||||
|
||||
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); }
|
||||
#define DebugPrintln(l,x) if(debug&l) { Serial.println(x); }
|
||||
#define DebugPrintf(l,...) if(debug&l) { Serial.printf(__VA_ARGS__); }
|
||||
|
||||
// RX_TIMEOUT: no header detected
|
||||
// RX_ERROR: header detected, but data not decoded (crc error, etc.)
|
||||
// RX_OK: header and data ok
|
||||
|
@ -46,9 +53,13 @@ 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
|
||||
|
@ -56,6 +67,7 @@ typedef struct st_sondeinfo {
|
|||
SondeType type;
|
||||
float freq;
|
||||
// decoded ID
|
||||
char typestr[5]; // decoded type (use type if *typestr==0)
|
||||
char id[10];
|
||||
char ser[12];
|
||||
bool validID;
|
||||
|
@ -175,6 +187,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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ extern int aprsstr_mon2raw(const char *mon, char raw[], int raw_len)
|
|||
--n;
|
||||
}
|
||||
aprsstr_appcrc(raw, raw_len, p);
|
||||
fprintf(stderr,"results in %s\n",raw);
|
||||
//fprintf(stderr,"results in %s\n",raw);
|
||||
return p+2;
|
||||
} /* end mon2raw() */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue