merging pull request #2 by DL2MF to devel branch
This commit is contained in:
parent
619631f80e
commit
d056ec8b76
20
README.md
20
README.md
|
|
@ -4,14 +4,20 @@ RDZ_TTGO_SONDE
|
||||||
This a simple, experimental, not (well) tested, and incomplete decoder for
|
This a simple, experimental, not (well) tested, and incomplete decoder for
|
||||||
radiosonde RS41 and DFM06/09 on a TTGO LoRa ESP32 with OLED display board.
|
radiosonde RS41 and DFM06/09 on a TTGO LoRa ESP32 with OLED display board.
|
||||||
|
|
||||||
|
There have been made some additions for TTGO LoRa ESP32 with only RST button.
|
||||||
|
Please check also your OLED port settings, both versions use different ports.
|
||||||
|
You can setup the depending ports in config.txt, OLED Setup is depending on hardware of LoRa board
|
||||||
|
- TTGO v1: SDA=4 SCL=15, RST=16
|
||||||
|
- TTGO v2: SDA=21 SCL=22, RST=16
|
||||||
|
|
||||||
## Button commands
|
## Button commands
|
||||||
You can use the button on the board (not the reset button, the second one) to
|
You can use the button on the board (not the reset button, the second one) to
|
||||||
issue some commands. The software distinguishes between several inputs:
|
issue some commands. The software distinguishes between several inputs:
|
||||||
|
|
||||||
SHORT Short button press (<1.5 seconds)
|
- SHORT Short button press (<1.5 seconds)
|
||||||
DOUBLE Short button press, followed by another button press within 0.5 seconds
|
- DOUBLE Short button press, followed by another button press within 0.5 seconds
|
||||||
MID Medium-length button press (2-4 seconds)
|
- MID Medium-length button press (2-4 seconds)
|
||||||
LONG Long button press (>5 seconds)
|
- LONG Long button press (>5 seconds)
|
||||||
|
|
||||||
## Wireless configuration
|
## Wireless configuration
|
||||||
|
|
||||||
|
|
@ -39,10 +45,14 @@ for the last 18 frames, if reception was successfull (|) or failed (.)
|
||||||
A DOUBLE press will switch to scanning mode.
|
A DOUBLE press will switch to scanning mode.
|
||||||
A SHORT press will switch to the next channel in channels.txt
|
A SHORT press will switch to the next channel in channels.txt
|
||||||
|
|
||||||
# Spectrum mode
|
## Spectrum mode
|
||||||
|
|
||||||
A medium press will active scan the whole band (400..406 MHz) and display a
|
A medium press will active scan the whole band (400..406 MHz) and display a
|
||||||
spectrum diagram (each line == 50 kHz)
|
spectrum diagram (each line == 50 kHz)
|
||||||
|
For TTGO boards without configurable button there are some new parameter in config.txt:
|
||||||
|
- spectrum=10 // 0=off / 1-99 number of seconds to show spectrum after restart
|
||||||
|
- timer=1 // 0=off / 1= show spectrum countdown timer in spectrum display
|
||||||
|
- marker=1 // 0=off / 1= show channel edge freq in spectrum display
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
#include <U8x8lib.h>
|
#include <U8x8lib.h>
|
||||||
|
#include <U8g2lib.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
#include <SX1278FSK.h>
|
#include <SX1278FSK.h>
|
||||||
|
|
@ -12,11 +13,6 @@
|
||||||
|
|
||||||
#define LORA_LED 9
|
#define LORA_LED 9
|
||||||
|
|
||||||
// I2C OLED Display works with SSD1306 driver
|
|
||||||
//#define OLED_SDA 4
|
|
||||||
//#define OLED_SCL 15
|
|
||||||
//#define OLED_RST 16
|
|
||||||
|
|
||||||
// UNCOMMENT one of the constructor lines below
|
// UNCOMMENT one of the constructor lines below
|
||||||
U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8=NULL; // initialize later after reading config file
|
U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8=NULL; // initialize later after reading config file
|
||||||
//U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Unbuffered, basic graphics, software I2C
|
//U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Unbuffered, basic graphics, software I2C
|
||||||
|
|
@ -29,20 +25,14 @@ AsyncWebServer server(80);
|
||||||
|
|
||||||
#define LOCALUDPPORT 9002
|
#define LOCALUDPPORT 9002
|
||||||
|
|
||||||
// moved to sonde.config
|
|
||||||
//const char * udpAddress = "192.168.42.20";
|
|
||||||
//const int udpPort = 9002;
|
|
||||||
|
|
||||||
boolean connected = false;
|
boolean connected = false;
|
||||||
WiFiUDP udp;
|
WiFiUDP udp;
|
||||||
|
|
||||||
|
|
||||||
// Set LED GPIO
|
// Set LED GPIO
|
||||||
const int ledPin = 2;
|
int ledPin = 1;
|
||||||
// Stores LED state
|
// Stores LED state
|
||||||
String ledState;
|
String ledState;
|
||||||
|
|
||||||
|
|
||||||
// Replaces placeholder with LED state value
|
// Replaces placeholder with LED state value
|
||||||
String processor(const String& var){
|
String processor(const String& var){
|
||||||
Serial.println(var);
|
Serial.println(var);
|
||||||
|
|
@ -91,6 +81,7 @@ void setupChannelList() {
|
||||||
}
|
}
|
||||||
int i=0;
|
int i=0;
|
||||||
sonde.clearSonde();
|
sonde.clearSonde();
|
||||||
|
Serial.println("Reading channel config:");
|
||||||
while(file.available()) {
|
while(file.available()) {
|
||||||
String line = file.readStringUntil('\n');
|
String line = file.readStringUntil('\n');
|
||||||
if(!file.available()) break;
|
if(!file.available()) break;
|
||||||
|
|
@ -105,8 +96,9 @@ void setupChannelList() {
|
||||||
else if (space[1]=='6') { type=STYPE_DFM06; }
|
else if (space[1]=='6') { type=STYPE_DFM06; }
|
||||||
else continue;
|
else continue;
|
||||||
int active = space[3]=='+'?1:0;
|
int active = space[3]=='+'?1:0;
|
||||||
Serial.printf("Adding %f with type %d (active: %d)\n",freq,type,active);
|
char *launchsite = strchr(line.c_str(), ' ');
|
||||||
sonde.addSonde(freq, type, active);
|
Serial.printf("Add %f - type %d (on/off: %d)- Site: \n",freq,type,active,launchsite);
|
||||||
|
sonde.addSonde(freq, type, active, launchsite);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +106,7 @@ void setupChannelList() {
|
||||||
const char *createQRGForm() {
|
const char *createQRGForm() {
|
||||||
char *ptr = message;
|
char *ptr = message;
|
||||||
strcpy(ptr,"<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"qrg.html\" method=\"post\"><table><tr><th>ID</th><th>Active</th><th>Freq</th><th>Mode</th></tr>");
|
strcpy(ptr,"<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"qrg.html\" method=\"post\"><table><tr><th>ID</th><th>Active</th><th>Freq</th><th>Mode</th></tr>");
|
||||||
for(int i=0; i<10; i++) {
|
for(int i=0; i<sonde.config.maxsonde; i++) {
|
||||||
String s = sondeTypeSelect(i>=sonde.nSonde?2:sonde.sondeList[i].type);
|
String s = sondeTypeSelect(i>=sonde.nSonde?2:sonde.sondeList[i].type);
|
||||||
sprintf(ptr+strlen(ptr), "<tr><td>%d</td><td><input name=\"A%d\" type=\"checkbox\" %s/></td>"
|
sprintf(ptr+strlen(ptr), "<tr><td>%d</td><td><input name=\"A%d\" type=\"checkbox\" %s/></td>"
|
||||||
"<td><input name=\"F%d\" type=\"text\" value=\"%3.3f\"></td>"
|
"<td><input name=\"F%d\" type=\"text\" value=\"%3.3f\"></td>"
|
||||||
|
|
@ -161,6 +153,9 @@ const char *handleQRGPost(AsyncWebServerRequest *request) {
|
||||||
f.printf("%3.3f %c %c\n", atof(fstr), typech, active?'+':'-');
|
f.printf("%3.3f %c %c\n", atof(fstr), typech, active?'+':'-');
|
||||||
}
|
}
|
||||||
f.close();
|
f.close();
|
||||||
|
Serial.println("Channel setup finished");
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
setupChannelList();
|
setupChannelList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,9 +247,9 @@ void addSondeStatus(char *ptr, int i)
|
||||||
sprintf(ptr+strlen(ptr),"<tr><td id=\"sfreq\">%3.3f MHz, Type: %s</td><tr><td>ID: %s</td></tr><tr><td>QTH: %.6f,%.6f h=%.0fm</td></tr>\n",
|
sprintf(ptr+strlen(ptr),"<tr><td id=\"sfreq\">%3.3f MHz, Type: %s</td><tr><td>ID: %s</td></tr><tr><td>QTH: %.6f,%.6f h=%.0fm</td></tr>\n",
|
||||||
s->freq, sondeTypeStr[s->type],
|
s->freq, sondeTypeStr[s->type],
|
||||||
s->validID?s->id:"<??>",
|
s->validID?s->id:"<??>",
|
||||||
s->lat, s->lon, s->hei);
|
s->lat, s->lon, s->alt);
|
||||||
sprintf(ptr+strlen(ptr), "<tr><td><a target=\"_empty\" href=\"geo:%.6f,%.6f\">Geo-Ref</a> -", s->lat, s->lon);
|
sprintf(ptr+strlen(ptr), "<tr><td><a target=\"_empty\" href=\"geo:%.6f,%.6f\">GEO-App</a> - ", s->lat, s->lon);
|
||||||
sprintf(ptr+strlen(ptr), "<a target=\"_empty\" href=\"https://www.google.com/maps/search/?api=1&query=%.6f,%.6f\">Google map</a> - ", s->lat, s->lon);
|
sprintf(ptr+strlen(ptr), "<a target=\"_empty\" href=\"https://wx.dl2mf.de/?%s\">WX.DL2MF.de</a> - ", s->id);
|
||||||
sprintf(ptr+strlen(ptr), "<a target=\"_empty\" href=\"https://www.openstreetmap.org/?mlat=%.6f&mlon=%.6f&zoom=14\">OSM</a></td></tr>", s->lat, s->lon);
|
sprintf(ptr+strlen(ptr), "<a target=\"_empty\" href=\"https://www.openstreetmap.org/?mlat=%.6f&mlon=%.6f&zoom=14\">OSM</a></td></tr>", s->lat, s->lon);
|
||||||
strcat(ptr, "</table><p/>\n");
|
strcat(ptr, "</table><p/>\n");
|
||||||
}
|
}
|
||||||
|
|
@ -291,8 +286,12 @@ struct st_configitems {
|
||||||
int type; // 0: numeric; i>0 string of length i; -1: separator; -2: type selector
|
int type; // 0: numeric; i>0 string of length i; -1: separator; -2: type selector
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
#define N_CONFIG 16
|
#define N_CONFIG 20
|
||||||
struct st_configitems config_list[N_CONFIG] = {
|
struct st_configitems config_list[N_CONFIG] = {
|
||||||
|
{"ShowSpectrum (s)", 0, &sonde.config.spectrum},
|
||||||
|
{"Startfreq (MHz)", 0, &sonde.config.startfreq},
|
||||||
|
{"Bandwidth (kHz)", 0, &sonde.config.channelbw},
|
||||||
|
{"---", -1, NULL},
|
||||||
{"Call", 8, sonde.config.call},
|
{"Call", 8, sonde.config.call},
|
||||||
{"Passcode", 8, sonde.config.passcode},
|
{"Passcode", 8, sonde.config.passcode},
|
||||||
{"---", -1, NULL},
|
{"---", -1, NULL},
|
||||||
|
|
@ -415,11 +414,11 @@ void SetupAsyncServer() {
|
||||||
|
|
||||||
const char *fetchWifiPw(const char *id) {
|
const char *fetchWifiPw(const char *id) {
|
||||||
for(int i=0; i<nNetworks; i++) {
|
for(int i=0; i<nNetworks; i++) {
|
||||||
Serial.print("Comparing '");
|
//Serial.print("Comparing '");
|
||||||
Serial.print(id);
|
//Serial.print(id);
|
||||||
Serial.print("' and '");
|
//Serial.print("' and '");
|
||||||
Serial.print(networks[i].id.c_str());
|
//Serial.print(networks[i].id.c_str());
|
||||||
Serial.println("'");
|
//Serial.println("'");
|
||||||
if(strcmp(id,networks[i].id.c_str())==0) return networks[i].pw.c_str();
|
if(strcmp(id,networks[i].id.c_str())==0) return networks[i].pw.c_str();
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -471,28 +470,81 @@ int hasKeyPress() {
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
|
char buf[12];
|
||||||
// Open serial communications and wait for port to open:
|
// Open serial communications and wait for port to open:
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
pinMode(LORA_LED, OUTPUT);
|
||||||
|
|
||||||
aprs_gencrctab();
|
aprs_gencrctab();
|
||||||
|
|
||||||
pinMode(LORA_LED, OUTPUT);
|
// Initialize SPIFFS
|
||||||
|
|
||||||
// Initialize SPIFFS
|
|
||||||
if(!SPIFFS.begin(true)){
|
if(!SPIFFS.begin(true)){
|
||||||
Serial.println("An Error has occurred while mounting SPIFFS");
|
Serial.println("An Error has occurred while mounting SPIFFS");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupWifiList();
|
setupConfigData(); // configuration must be read first due to OLED ports!!!
|
||||||
setupConfigData();
|
|
||||||
button1.pin = sonde.config.button_pin;
|
|
||||||
|
|
||||||
u8x8 = new U8X8_SSD1306_128X64_NONAME_SW_I2C(/* clock=*/ sonde.config.oled_scl, /* data=*/ sonde.config.oled_sda, /* reset=*/ sonde.config.oled_rst); // Unbuffered, basic graphics, software I2C
|
u8x8 = new U8X8_SSD1306_128X64_NONAME_SW_I2C(/* clock=*/ sonde.config.oled_scl, /* data=*/ sonde.config.oled_sda, /* reset=*/ sonde.config.oled_rst); // Unbuffered, basic graphics, software I2C
|
||||||
u8x8->begin();
|
u8x8->begin();
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
u8x8->clear();
|
||||||
|
|
||||||
|
u8x8->setFont(u8x8_font_7x14_1x2_r);
|
||||||
|
u8x8->drawString(1, 1, "RDZ_TTGO_SONDE");
|
||||||
|
u8x8->drawString(2, 3, " V0.1e");
|
||||||
|
u8x8->drawString(1, 5, "Mods by DL2MF");
|
||||||
|
delay(3000);
|
||||||
|
|
||||||
|
sonde.clearDisplay();
|
||||||
|
|
||||||
|
setupWifiList();
|
||||||
|
button1.pin = sonde.config.button_pin;
|
||||||
|
|
||||||
|
// == show initial values from config.txt ========================= //
|
||||||
|
if (sonde.config.debug == 1) {
|
||||||
|
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||||
|
u8x8->drawString(0, 0, "Config:");
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
itoa(sonde.config.oled_sda, buf, 10);
|
||||||
|
u8x8->drawString(0, 1, " SDA:");
|
||||||
|
u8x8->drawString(6, 1, buf);
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
itoa(sonde.config.oled_scl, buf, 10);
|
||||||
|
u8x8->drawString(0, 2, " SCL:");
|
||||||
|
u8x8->drawString(6, 2, buf);
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
itoa(sonde.config.oled_rst, buf, 10);
|
||||||
|
u8x8->drawString(0, 3, " RST:");
|
||||||
|
u8x8->drawString(6, 3, buf);
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
itoa(sonde.config.led_pin, buf, 10);
|
||||||
|
u8x8->drawString(0, 4, " LED:");
|
||||||
|
u8x8->drawString(6, 4, buf);
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
itoa(sonde.config.spectrum, buf, 10);
|
||||||
|
u8x8->drawString(0, 5, " SPEC:");
|
||||||
|
u8x8->drawString(6, 5, buf);
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
itoa(sonde.config.maxsonde, buf, 10);
|
||||||
|
u8x8->drawString(0, 6, " MAX:");
|
||||||
|
u8x8->drawString(6, 6, buf);
|
||||||
|
|
||||||
|
delay(5000);
|
||||||
|
sonde.clearDisplay();
|
||||||
|
}
|
||||||
|
// == show initial values from config.txt ========================= //
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
// == check the radio chip by setting default frequency =========== //
|
||||||
if(rs41.setFrequency(402700000)==0) {
|
if(rs41.setFrequency(402700000)==0) {
|
||||||
Serial.println(F("Setting freq: SUCCESS "));
|
Serial.println(F("Setting freq: SUCCESS "));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -501,6 +553,7 @@ void setup()
|
||||||
float f = sx1278.getFrequency();
|
float f = sx1278.getFrequency();
|
||||||
Serial.print("Frequency set to ");
|
Serial.print("Frequency set to ");
|
||||||
Serial.println(f);
|
Serial.println(f);
|
||||||
|
// == check the radio chip by setting default frequency =========== //
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//sx1278.setLNAGain(-48);
|
//sx1278.setLNAGain(-48);
|
||||||
|
|
@ -511,11 +564,10 @@ void setup()
|
||||||
Serial.println(gain);
|
Serial.println(gain);
|
||||||
|
|
||||||
// Print a success message
|
// Print a success message
|
||||||
Serial.println(F("sx1278 configured finished"));
|
Serial.println(F("SX1278 configuration finished"));
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
|
|
||||||
Serial.println("Setup finished");
|
Serial.println("Setup finished");
|
||||||
|
Serial.println();
|
||||||
// int returnValue = pthread_create(&wifithread, NULL, wifiloop, (void *)0);
|
// int returnValue = pthread_create(&wifithread, NULL, wifiloop, (void *)0);
|
||||||
|
|
||||||
// if (returnValue) {
|
// if (returnValue) {
|
||||||
|
|
@ -526,20 +578,26 @@ void setup()
|
||||||
// Handle button press
|
// Handle button press
|
||||||
attachInterrupt(button1.pin, buttonISR, CHANGE);
|
attachInterrupt(button1.pin, buttonISR, CHANGE);
|
||||||
|
|
||||||
|
// == setup default channel list if qrg.txt read fails =========== //
|
||||||
setupChannelList();
|
setupChannelList();
|
||||||
#if 0
|
#if 0
|
||||||
sonde.clearSonde();
|
sonde.clearSonde();
|
||||||
sonde.addSonde(402.300, STYPE_RS41);
|
|
||||||
sonde.addSonde(402.700, STYPE_RS41);
|
sonde.addSonde(402.700, STYPE_RS41);
|
||||||
|
sonde.addSonde(405.700, STYPE_RS41);
|
||||||
|
sonde.addSonde(405.900, STYPE_RS41);
|
||||||
sonde.addSonde(403.450, STYPE_DFM09);
|
sonde.addSonde(403.450, STYPE_DFM09);
|
||||||
|
Serial.println("No channel config file, using defaults!");
|
||||||
|
Serial.println();
|
||||||
#endif
|
#endif
|
||||||
/// not here, done by sonde.setup(): rs41.setup();
|
/// not here, done by sonde.setup(): rs41.setup();
|
||||||
|
// == setup default channel list if qrg.txt read fails =========== //
|
||||||
|
|
||||||
sonde.setup();
|
sonde.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MainState { ST_DECODER, ST_SCANNER, ST_SPECTRUM, ST_WIFISCAN };
|
enum MainState { ST_DECODER, ST_SCANNER, ST_SPECTRUM, ST_WIFISCAN };
|
||||||
|
|
||||||
static MainState mainState = ST_DECODER;
|
static MainState mainState = ST_WIFISCAN;
|
||||||
|
|
||||||
void enterMode(int mode) {
|
void enterMode(int mode) {
|
||||||
mainState = (MainState)mode;
|
mainState = (MainState)mode;
|
||||||
|
|
@ -571,7 +629,7 @@ void loopDecoder() {
|
||||||
Serial.println("Sending position via UDP");
|
Serial.println("Sending position via UDP");
|
||||||
SondeInfo *s = sonde.si();
|
SondeInfo *s = sonde.si();
|
||||||
char raw[201];
|
char raw[201];
|
||||||
const char *str = aprs_senddata(s->lat, s->lon, s->hei, s->hs, s->dir, s->vs, sondeTypeStr[s->type], s->id, "TE0ST",
|
const char *str = aprs_senddata(s->lat, s->lon, s->alt, s->hs, s->dir, s->vs, sondeTypeStr[s->type], s->id, "TE0ST",
|
||||||
sonde.config.udpfeed.symbol);
|
sonde.config.udpfeed.symbol);
|
||||||
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
|
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
|
||||||
Serial.print("Sending: "); Serial.println(raw);
|
Serial.print("Sending: "); Serial.println(raw);
|
||||||
|
|
@ -601,7 +659,7 @@ void loopScanner() {
|
||||||
}
|
}
|
||||||
// receiveFrame returns 0 on success, 1 on timeout
|
// receiveFrame returns 0 on success, 1 on timeout
|
||||||
int res = sonde.receiveFrame(); // Maybe instead of receiveFrame, just detect if right type is present? TODO
|
int res = sonde.receiveFrame(); // Maybe instead of receiveFrame, just detect if right type is present? TODO
|
||||||
Serial.print("Scanner: receiveFrame returned");
|
Serial.print("Scanner: receiveFrame returned: ");
|
||||||
Serial.println(res);
|
Serial.println(res);
|
||||||
if(res==0) {
|
if(res==0) {
|
||||||
enterMode(ST_DECODER);
|
enterMode(ST_DECODER);
|
||||||
|
|
@ -666,44 +724,55 @@ void WiFiEvent(WiFiEvent_t event){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char* _scan[2]={"/","\\"};
|
static char* _scan[2]={"/","\\"};
|
||||||
void loopWifiScan() {
|
void loopWifiScan() {
|
||||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||||
u8x8->drawString(0,0,"WiFi Scan...");
|
if (sonde.config.wifi != 0) {
|
||||||
|
u8x8->drawString(0,0,"WiFi Scan...");
|
||||||
|
}
|
||||||
|
else if (sonde.config.wifiap != 0) {
|
||||||
|
u8x8->drawString(0,0,"WiFi AP-Mode:");
|
||||||
|
}
|
||||||
|
|
||||||
int line=0;
|
int line=0;
|
||||||
int cnt=0;
|
int cnt=0;
|
||||||
|
int marker=0;
|
||||||
|
char buf[5];
|
||||||
|
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
const char *id, *pw;
|
const char *id, *pw;
|
||||||
char idstr[64]="test";
|
char idstr[64]="test";
|
||||||
int n = WiFi.scanNetworks();
|
|
||||||
for (int i = 0; i < n; i++) {
|
if (sonde.config.wifi != 0) {
|
||||||
Serial.print("Network name: ");
|
int n = WiFi.scanNetworks();
|
||||||
Serial.println(WiFi.SSID(i));
|
for (int i = 0; i < n; i++) {
|
||||||
u8x8->drawString(0,1+line,WiFi.SSID(i).c_str());
|
Serial.print("Network name: ");
|
||||||
line = (line+1)%5;
|
Serial.println(WiFi.SSID(i));
|
||||||
Serial.print("Signal strength: ");
|
u8x8->drawString(0,1+line,WiFi.SSID(i).c_str());
|
||||||
Serial.println(WiFi.RSSI(i));
|
line = (line+1)%5;
|
||||||
Serial.print("MAC address: ");
|
Serial.print("Signal strength: ");
|
||||||
Serial.println(WiFi.BSSIDstr(i));
|
Serial.println(WiFi.RSSI(i));
|
||||||
Serial.print("Encryption type: ");
|
Serial.print("MAC address: ");
|
||||||
String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i));
|
Serial.println(WiFi.BSSIDstr(i));
|
||||||
Serial.println(encryptionTypeDescription);
|
Serial.print("Encryption type: ");
|
||||||
Serial.println("-----------------------");
|
String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i));
|
||||||
id=WiFi.SSID(i).c_str();
|
Serial.println(encryptionTypeDescription);
|
||||||
pw=fetchWifiPw(id);
|
Serial.println("-----------------------");
|
||||||
if(pw) { strncpy(idstr, id, 63); }
|
id=WiFi.SSID(i).c_str();
|
||||||
}
|
pw=fetchWifiPw(id);
|
||||||
if(!pw) { pw="test"; }
|
if(pw) { strncpy(idstr, id, 63); }
|
||||||
Serial.print("Connecting to: "); Serial.println(idstr);
|
}
|
||||||
u8x8->drawString(0,6, "Conn:");
|
if(!pw) { pw="test"; }
|
||||||
u8x8->drawString(6,6, idstr);
|
Serial.print("Connecting to: "); Serial.println(idstr);
|
||||||
//register event handler
|
u8x8->drawString(0,6, "Conn:");
|
||||||
WiFi.onEvent(WiFiEvent);
|
u8x8->drawString(6,6, idstr);
|
||||||
|
//register event handler
|
||||||
|
WiFi.onEvent(WiFiEvent);
|
||||||
|
|
||||||
|
WiFi.begin(idstr, pw);
|
||||||
|
}
|
||||||
|
|
||||||
WiFi.begin(idstr, pw);
|
|
||||||
while(WiFi.status() != WL_CONNECTED) {
|
while(WiFi.status() != WL_CONNECTED) {
|
||||||
delay(500);
|
delay(500);
|
||||||
Serial.print(".");
|
Serial.print(".");
|
||||||
|
|
@ -718,20 +787,58 @@ void loopWifiScan() {
|
||||||
#endif
|
#endif
|
||||||
if(cnt==15) {
|
if(cnt==15) {
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
delay(1000);
|
|
||||||
WiFi.softAP(networks[0].id.c_str(),networks[0].pw.c_str());
|
if (sonde.config.wifiap != 0) { // enable WiFi AP mode in config.txt: wifi=1
|
||||||
IPAddress myIP = WiFi.softAPIP();
|
delay(1000);
|
||||||
Serial.print("AP IP address: ");
|
WiFi.softAP(networks[0].id.c_str(),networks[0].pw.c_str());
|
||||||
Serial.println(myIP);
|
IPAddress myIP = WiFi.softAPIP();
|
||||||
u8x8->drawString(0,6, "AP: ");
|
Serial.print("AP IP address: ");
|
||||||
u8x8->drawString(6,6, networks[0].id.c_str());
|
Serial.println(myIP);
|
||||||
sonde.setIP(myIP.toString().c_str(), true);
|
u8x8->drawString(0,6, "AP: ");
|
||||||
sonde.updateDisplayIP();
|
u8x8->drawString(6,6, networks[0].id.c_str());
|
||||||
SetupAsyncServer();
|
sonde.setIP(myIP.toString().c_str(), true);
|
||||||
delay(3000);
|
sonde.updateDisplayIP();
|
||||||
enterMode(ST_DECODER);
|
SetupAsyncServer();
|
||||||
|
delay(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sonde.config.spectrum != 0) { // enable Spectrum in config.txt: spectrum=number_of_seconds
|
||||||
|
sonde.clearDisplay();
|
||||||
|
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||||
|
u8x8->drawString(0, 0, "Spectrum Scan...");
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
enterMode(ST_SPECTRUM);
|
||||||
|
|
||||||
|
for (int i = 0; i < sonde.config.spectrum; i++) {
|
||||||
|
scanner.scan();
|
||||||
|
scanner.plotResult();
|
||||||
|
|
||||||
|
if (sonde.config.marker != 0) {
|
||||||
|
itoa((sonde.config.startfreq), buf, 10);
|
||||||
|
u8x8->drawString(0, 1, buf);
|
||||||
|
u8x8->drawString(7, 1, "MHz");
|
||||||
|
itoa((sonde.config.startfreq + 6), buf, 10);
|
||||||
|
u8x8->drawString(13, 1, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sonde.config.timer != 0) {
|
||||||
|
itoa((sonde.config.spectrum - i), buf, 10);
|
||||||
|
if (sonde.config.marker != 0) {
|
||||||
|
marker = 1;
|
||||||
|
}
|
||||||
|
u8x8->drawString(0, 1+marker, buf);
|
||||||
|
u8x8->drawString(2, 1+marker, "Sec.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
enterMode(ST_SCANNER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("");
|
Serial.println("");
|
||||||
|
|
@ -742,9 +849,10 @@ void loopWifiScan() {
|
||||||
sonde.updateDisplayIP();
|
sonde.updateDisplayIP();
|
||||||
SetupAsyncServer();
|
SetupAsyncServer();
|
||||||
delay(2000);
|
delay(2000);
|
||||||
enterMode(ST_DECODER);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// enterMode(ST_DECODER); ### 2019-04-20 - changed DL2MF
|
||||||
|
enterMode(ST_SCANNER);
|
||||||
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
Serial.println("Running main loop");
|
Serial.println("Running main loop");
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,39 @@
|
||||||
# Input button
|
#-------------------------------#
|
||||||
|
# Hardware depending settings
|
||||||
|
#-------------------------------#
|
||||||
button_pin=0
|
button_pin=0
|
||||||
# oled: SDA, SCL, RST (4,15,16 für TTGO v1)
|
# LED port
|
||||||
oled_sda=4
|
led_pin=25
|
||||||
oled_scl=15
|
# OLED Setup is depending on hardware of LoRa board
|
||||||
|
# TTGO v1: SDA=4 SCL=15, RST=16
|
||||||
|
# TTGO v2: SDA=21 SCL=22, RST=16
|
||||||
|
oled_sda=21
|
||||||
|
oled_scl=22
|
||||||
oled_rst=16
|
oled_rst=16
|
||||||
|
#-------------------------------#
|
||||||
noisefloor=-130
|
# General config settings
|
||||||
call=NOCALL
|
#-------------------------------#
|
||||||
|
maxsonde=20
|
||||||
|
debug=0
|
||||||
|
wifi=0
|
||||||
|
wifiap=1
|
||||||
|
#-------------------------------#
|
||||||
|
# Spectrum display settings
|
||||||
|
#-------------------------------#
|
||||||
|
startfreq=400
|
||||||
|
channelbw=10
|
||||||
|
spectrum=10
|
||||||
|
timer=1
|
||||||
|
noisefloor=-110
|
||||||
|
marker=1
|
||||||
|
#-------------------------------#
|
||||||
|
# APRS settings
|
||||||
|
#-------------------------------#
|
||||||
|
call=N0CALL
|
||||||
passcode=12345
|
passcode=12345
|
||||||
|
#-------------------------------#
|
||||||
# axudp for sending to aprsmap
|
# axudp for sending to aprsmap
|
||||||
|
#-------------------------------#
|
||||||
# local use only, do not feed to public services
|
# local use only, do not feed to public services
|
||||||
# data not sanities / quality checked, outliers not filtered out
|
# data not sanities / quality checked, outliers not filtered out
|
||||||
axudp.active=1
|
axudp.active=1
|
||||||
|
|
@ -17,7 +42,9 @@ axudp.port=9002
|
||||||
axudp.symbol=/O
|
axudp.symbol=/O
|
||||||
axudp.highrate=1
|
axudp.highrate=1
|
||||||
axudp.idformat=0
|
axudp.idformat=0
|
||||||
|
#-------------------------------#
|
||||||
# maybe some time in the future
|
# maybe some time in the future
|
||||||
|
#-------------------------------#
|
||||||
# currently simply not implemented, no need to put anything here anyway
|
# currently simply not implemented, no need to put anything here anyway
|
||||||
tcp.active=0
|
tcp.active=0
|
||||||
tcp.host=radiosondy.info
|
tcp.host=radiosondy.info
|
||||||
|
|
@ -25,4 +52,6 @@ tcp.port=14590
|
||||||
tcp.symbol=/O
|
tcp.symbol=/O
|
||||||
tcp.highrate=20
|
tcp.highrate=20
|
||||||
tcp.idformat=0
|
tcp.idformat=0
|
||||||
|
#-------------------------------#
|
||||||
|
# EOF
|
||||||
|
#-------------------------------#
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>ESP32 Web Server</title>
|
<title>RDZSonde Server</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="icon" href="data:,">
|
<link rel="icon" href="data:,">
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>ESP32 Web Server</h1>
|
<h2>RDZSonde Server</h2>
|
||||||
<!--
|
<!--
|
||||||
<p>GPIO state: <strong> %STATE%</strong></p>
|
<p>GPIO state: <strong> %STATE%</strong></p>
|
||||||
<p><a href="/on"><button class="button">ON</button></a></p>
|
<p><a href="/on"><button class="button">ON</button></a></p>
|
||||||
|
|
@ -16,19 +16,20 @@
|
||||||
|
|
||||||
<div class="tab">
|
<div class="tab">
|
||||||
<button class="tablinks" onclick="selTab(event,'QRG')" id="defaultTab">QRG</button>
|
<button class="tablinks" onclick="selTab(event,'QRG')" id="defaultTab">QRG</button>
|
||||||
<button class="tablinks" onclick="selTab(event,'WIFI')">WLAN</button>
|
<button class="tablinks" onclick="selTab(event,'WLAN')">WLAN</button>
|
||||||
<button class="tablinks" onclick="selTab(event,'Data')">Data</button>
|
<button class="tablinks" onclick="selTab(event,'Data')">Data</button>
|
||||||
|
<button class="tablinks" onclick="selTab(event,'WebWX')">Webwx</button>
|
||||||
<button class="tablinks" onclick="selTab(event,'Config')">Config</button>
|
<button class="tablinks" onclick="selTab(event,'Config')">Config</button>
|
||||||
<button class="tablinks" onclick="selTab(event,'About')">About</button>
|
<button class="tablinks" onclick="selTab(event,'About')">About</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="QRG" class="tabcontent">
|
<div id="QRG" class="tabcontent">
|
||||||
<h3> QRG</h3>
|
<h3> QRG - Setup</h3>
|
||||||
<iframe src="qrg.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
<iframe src="qrg.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="WIFI" class="tabcontent">
|
<div id="WLAN" class="tabcontent">
|
||||||
<h3> WIFI</h3>
|
<h3> WLAN - Settings</h3>
|
||||||
<iframe src="wifi.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
<iframe src="wifi.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -37,14 +38,24 @@
|
||||||
<iframe src="status.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
<iframe src="status.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="Data" class="tabcontent">
|
||||||
|
<h3>wetterson.de</h3>
|
||||||
|
<iframe src="https://wetterson.de/karte/" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="Config" class="tabcontent">
|
<div id="Config" class="tabcontent">
|
||||||
<h3>Config</h3>
|
<h3>Configuration</h3>
|
||||||
<iframe src="config.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
<iframe src="config.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="About" class="tabcontent">
|
<div id="About" class="tabcontent">
|
||||||
<h3>About</h3>
|
<h3>About</h3>
|
||||||
RDZSonde
|
RDZSonde - OpenSource<br>
|
||||||
|
Copyright © 2019<br>
|
||||||
|
by Hans P. Reiser, DL9RDZ<br>
|
||||||
|
(devel-version 2019-04-23)<br>
|
||||||
|
-------------------------------<br>
|
||||||
|
with mods by Meinhard Guenther, DL2MF<br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
RDZsonde
|
AUTORX
|
||||||
RDZsonde
|
12345678
|
||||||
DinoGast
|
SONDERX
|
||||||
Schokolade
|
radiosonde
|
||||||
AndroidDD
|
|
||||||
dl9rdzhr
|
|
||||||
|
|
@ -1,8 +1,23 @@
|
||||||
# Frequency in Mhz (format nnn.nnn)
|
# Frequency in Mhz (format nnn.nnn)
|
||||||
# Type (4=RS41, 6=DFM normal, DFM-06, 9=DFM inverted, DFM-09)
|
# Type (4=RS41, 6=DFM normal, DFM-06, 9=DFM inverted, DFM-09)
|
||||||
#
|
#
|
||||||
402.700 4 +
|
402.300 4 - Greifswald
|
||||||
402.300 4 +
|
402.500 4 - Schleswig
|
||||||
403.450 9 +
|
402.700 4 + HH-Sasel
|
||||||
405.100 4 -
|
403.000 4 - DeBilt
|
||||||
|
404.100 4 + Norderney
|
||||||
|
404.300 4 - Schleswig_2
|
||||||
|
404.500 4 - Meppen
|
||||||
|
404.700 4 - Greifswald_2
|
||||||
|
405.100 4 - Lindenberg
|
||||||
|
405.700 4 + Bergen
|
||||||
|
405.900 4 + Bergen_2
|
||||||
|
405.100 4 + Meppen_2
|
||||||
|
405.300 4 - Essen
|
||||||
|
403.330 9 - TrUebPl
|
||||||
|
403.450 9 - TrUebPl
|
||||||
|
403.470 9 - TrUebPl
|
||||||
|
403.850 9 - TrUebPl
|
||||||
|
403.870 9 - TrUebPl
|
||||||
|
403.890 9 - TrUebPl
|
||||||
# end
|
# end
|
||||||
|
|
|
||||||
|
|
@ -228,12 +228,12 @@ int DFM::decodeDAT(uint8_t *dat)
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
float hei, vv;
|
float lat, vv;
|
||||||
hei = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + dat[3];
|
lat = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + dat[3];
|
||||||
vv = (int16_t)( (dat[4]<<8) | dat[5] );
|
vv = (int16_t)( (dat[4]<<8) | dat[5] );
|
||||||
Serial.print("GPS-height: "); Serial.print(hei*0.01);
|
Serial.print("GPS-height: "); Serial.print(lat*0.01);
|
||||||
Serial.print(", vv: "); Serial.print(vv*0.01);
|
Serial.print(", vv: "); Serial.print(vv*0.01);
|
||||||
sonde.si()->hei = hei*0.01;
|
sonde.si()->lat = lat*0.01;
|
||||||
sonde.si()->vs = vv*0.01;
|
sonde.si()->vs = vv*0.01;
|
||||||
sonde.si()->validPos |= 0x0C;
|
sonde.si()->validPos |= 0x0C;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
||||||
Serial.print("m/s ");
|
Serial.print("m/s ");
|
||||||
Serial.print(getcard16(b, b_len, p+18UL)&255UL);
|
Serial.print(getcard16(b, b_len, p+18UL)&255UL);
|
||||||
Serial.print("Sats");
|
Serial.print("Sats");
|
||||||
sonde.si()->hei = heig;
|
sonde.si()->alt = heig;
|
||||||
sonde.si()->validPos = true;
|
sonde.si()->validPos = true;
|
||||||
} /* end posrs41() */
|
} /* end posrs41() */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,26 @@
|
||||||
#include <SX1278FSK.h>
|
#include <SX1278FSK.h>
|
||||||
#include <U8x8lib.h>
|
#include <U8x8lib.h>
|
||||||
|
|
||||||
|
#include "Sonde.h"
|
||||||
|
|
||||||
extern U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8;
|
extern U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8;
|
||||||
|
|
||||||
#define CHANBW 10
|
#define CHANBW 10
|
||||||
#define PIXSAMPL (50/CHANBW)
|
#define PIXSAMPL (50/CHANBW)
|
||||||
#define SMOOTH 3
|
#define SMOOTH 3
|
||||||
#define STARTF 400000000
|
//#define STARTF 401000000
|
||||||
#define NCHAN ((int)(6000/CHANBW))
|
#define NCHAN ((int)(6000/CHANBW))
|
||||||
|
|
||||||
|
double STARTF = (sonde.config.startfreq * 1000000);
|
||||||
|
//int CHANBW = (sonde.config.channelbw);
|
||||||
|
//int NCHAN = ((int)(6000/CHANBW));
|
||||||
|
//int PIXSAMPL = (50/CHANBW);
|
||||||
|
|
||||||
int scanresult[NCHAN];
|
int scanresult[NCHAN];
|
||||||
int scandisp[NCHAN/PIXSAMPL];
|
int scandisp[NCHAN/PIXSAMPL];
|
||||||
|
|
||||||
#define PLOT_N 120
|
#define PLOT_N 128
|
||||||
#define TICK1 (120/6)
|
#define TICK1 (128/6)
|
||||||
#define TICK2 (TICK1/4)
|
#define TICK2 (TICK1/4)
|
||||||
#define PLOT_MIN -250
|
#define PLOT_MIN -250
|
||||||
#define PLOT_SCALE(x) (x<PLOT_MIN?0:(x-PLOT_MIN)/2)
|
#define PLOT_SCALE(x) (x<PLOT_MIN?0:(x-PLOT_MIN)/2)
|
||||||
|
|
@ -30,7 +37,7 @@ void Scanner::fillTiles(uint8_t *row, int value) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* There are 16*8 columns to plot, NPLOT must be lower than that
|
* There are 16*8 columns to plot, NPLOT must be lower than that
|
||||||
* currently, we use 120 * 50kHz channels
|
* currently, we use 128 * 50kHz channels
|
||||||
* There are 8*8 values to plot; MIN is bottom end,
|
* There are 8*8 values to plot; MIN is bottom end,
|
||||||
*/
|
*/
|
||||||
uint8_t tiles[16] = { 0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0, 1, 3, 7, 15, 31, 63, 127, 255};
|
uint8_t tiles[16] = { 0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0, 1, 3, 7, 15, 31, 63, 127, 255};
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,18 @@ Sonde::Sonde() {
|
||||||
config.oled_sda = 4;
|
config.oled_sda = 4;
|
||||||
config.oled_scl = 15;
|
config.oled_scl = 15;
|
||||||
config.oled_rst = 16;
|
config.oled_rst = 16;
|
||||||
|
|
||||||
config.noisefloor = -130;
|
config.noisefloor = -130;
|
||||||
strcpy(config.call,"NOCALL");
|
strcpy(config.call,"NOCALL");
|
||||||
strcpy(config.passcode, "---");
|
strcpy(config.passcode, "---");
|
||||||
|
config.maxsonde=15;
|
||||||
|
config.debug=0;
|
||||||
|
config.wifi=1;
|
||||||
|
config.wifiap=1;
|
||||||
|
config.startfreq=400;
|
||||||
|
config.channelbw=10;
|
||||||
|
config.spectrum=10;
|
||||||
|
config.timer=0;
|
||||||
|
config.marker=0;
|
||||||
config.udpfeed.active = 1;
|
config.udpfeed.active = 1;
|
||||||
config.udpfeed.type = 0;
|
config.udpfeed.type = 0;
|
||||||
strcpy(config.udpfeed.host, "192.168.42.20");
|
strcpy(config.udpfeed.host, "192.168.42.20");
|
||||||
|
|
@ -80,7 +88,7 @@ void Sonde::setConfig(const char *cfg) {
|
||||||
char *val = s+1;
|
char *val = s+1;
|
||||||
*s=0; s--;
|
*s=0; s--;
|
||||||
while(s>cfg && (*s==' '||*s=='\t')) { *s=0; s--; }
|
while(s>cfg && (*s==' '||*s=='\t')) { *s=0; s--; }
|
||||||
Serial.printf("handling option '%s'='%s'\n", cfg, val);
|
Serial.printf("configuration option '%s'=%s \n", cfg, val);
|
||||||
if(strcmp(cfg,"noisefloor")==0) {
|
if(strcmp(cfg,"noisefloor")==0) {
|
||||||
config.noisefloor = atoi(val);
|
config.noisefloor = atoi(val);
|
||||||
if(config.noisefloor==0) config.noisefloor=-130;
|
if(config.noisefloor==0) config.noisefloor=-130;
|
||||||
|
|
@ -90,12 +98,32 @@ void Sonde::setConfig(const char *cfg) {
|
||||||
strncpy(config.passcode, val, 9);
|
strncpy(config.passcode, val, 9);
|
||||||
} else if(strcmp(cfg,"button_pin")==0) {
|
} else if(strcmp(cfg,"button_pin")==0) {
|
||||||
config.button_pin = atoi(val);
|
config.button_pin = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"led_pin")==0) {
|
||||||
|
config.led_pin = atoi(val);
|
||||||
} else if(strcmp(cfg,"oled_sda")==0) {
|
} else if(strcmp(cfg,"oled_sda")==0) {
|
||||||
config.oled_sda = atoi(val);
|
config.oled_sda = atoi(val);
|
||||||
} else if(strcmp(cfg,"oled_scl")==0) {
|
} else if(strcmp(cfg,"oled_scl")==0) {
|
||||||
config.oled_scl = atoi(val);
|
config.oled_scl = atoi(val);
|
||||||
} else if(strcmp(cfg,"oled_rst")==0) {
|
} else if(strcmp(cfg,"oled_rst")==0) {
|
||||||
config.oled_rst = atoi(val);
|
config.oled_rst = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"maxsonde")==0) {
|
||||||
|
config.maxsonde = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"debug")==0) {
|
||||||
|
config.debug = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"wifi")==0) {
|
||||||
|
config.wifi = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"wifiap")==0) {
|
||||||
|
config.wifiap = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"startfreq")==0) {
|
||||||
|
config.startfreq = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"channelbw")==0) {
|
||||||
|
config.channelbw = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"spectrum")==0) {
|
||||||
|
config.spectrum = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"timer")==0) {
|
||||||
|
config.timer = atoi(val);
|
||||||
|
} else if(strcmp(cfg,"marker")==0) {
|
||||||
|
config.marker = atoi(val);
|
||||||
} else if(strcmp(cfg,"axudp.active")==0) {
|
} else if(strcmp(cfg,"axudp.active")==0) {
|
||||||
config.udpfeed.active = atoi(val)>0;
|
config.udpfeed.active = atoi(val)>0;
|
||||||
} else if(strcmp(cfg,"axudp.host")==0) {
|
} else if(strcmp(cfg,"axudp.host")==0) {
|
||||||
|
|
@ -121,7 +149,7 @@ void Sonde::setConfig(const char *cfg) {
|
||||||
} else if(strcmp(cfg,"tcp.idformat")==0) {
|
} else if(strcmp(cfg,"tcp.idformat")==0) {
|
||||||
config.tcpfeed.idformat = atoi(val);
|
config.tcpfeed.idformat = atoi(val);
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("Invalid config option '%s'='%s'\n", cfg, val);
|
Serial.printf("Invalid config option '%s'=%s \n", cfg, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,21 +174,22 @@ void Sonde::setIP(const char *ip, bool AP) {
|
||||||
void Sonde::clearSonde() {
|
void Sonde::clearSonde() {
|
||||||
nSonde = 0;
|
nSonde = 0;
|
||||||
}
|
}
|
||||||
void Sonde::addSonde(float frequency, SondeType type, int active) {
|
void Sonde::addSonde(float frequency, SondeType type, int active, char *launchsite) {
|
||||||
if(nSonde>=MAXSONDE) {
|
if(nSonde>=config.maxsonde) {
|
||||||
Serial.println("Cannot add another sonde, MAXSONDE reached");
|
Serial.println("Cannot add another sonde, MAXSONDE reached");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sondeList[nSonde].type = type;
|
sondeList[nSonde].type = type;
|
||||||
sondeList[nSonde].freq = frequency;
|
sondeList[nSonde].freq = frequency;
|
||||||
sondeList[nSonde].active = active;
|
sondeList[nSonde].active = active;
|
||||||
|
sondeList[nSonde].launchsite = launchsite;
|
||||||
memcpy(sondeList[nSonde].rxStat, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", 18); // unknown/undefined
|
memcpy(sondeList[nSonde].rxStat, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", 18); // unknown/undefined
|
||||||
nSonde++;
|
nSonde++;
|
||||||
}
|
}
|
||||||
void Sonde::nextConfig() {
|
void Sonde::nextConfig() {
|
||||||
currentSonde++;
|
currentSonde++;
|
||||||
// Skip non-active entries (but don't loop forever if there are no active ones
|
// Skip non-active entries (but don't loop forever if there are no active ones
|
||||||
for(int i=0; i<MAXSONDE; i++) {
|
for(int i=0; i<config.maxsonde; i++) {
|
||||||
if(!sondeList[currentSonde].active) {
|
if(!sondeList[currentSonde].active) {
|
||||||
currentSonde++;
|
currentSonde++;
|
||||||
if(currentSonde>=nSonde) currentSonde=0;
|
if(currentSonde>=nSonde) currentSonde=0;
|
||||||
|
|
@ -230,7 +259,7 @@ void Sonde::updateDisplayPos2() {
|
||||||
u8x8->drawString(10,4," ");
|
u8x8->drawString(10,4," ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
snprintf(buf, 16, si()->hei>999?" %5.0fm":" %3.1fm", si()->hei);
|
snprintf(buf, 16, si()->alt>999?" %5.0fm":" %3.1fm", si()->alt);
|
||||||
u8x8->drawString((10+6-strlen(buf)),2,buf);
|
u8x8->drawString((10+6-strlen(buf)),2,buf);
|
||||||
snprintf(buf, 16, si()->hs>99?" %3.0f":" %2.1f", si()->hs);
|
snprintf(buf, 16, si()->hs>99?" %3.0f":" %2.1f", si()->hs);
|
||||||
u8x8->drawString((10+4-strlen(buf)),3,buf);
|
u8x8->drawString((10+4-strlen(buf)),3,buf);
|
||||||
|
|
@ -276,7 +305,9 @@ void Sonde::updateDisplayRXConfig() {
|
||||||
u8x8->drawString(0,0, sondeTypeStr[si()->type]);
|
u8x8->drawString(0,0, sondeTypeStr[si()->type]);
|
||||||
snprintf(buf, 16, "%3.3f MHz", si()->freq);
|
snprintf(buf, 16, "%3.3f MHz", si()->freq);
|
||||||
u8x8->drawString(5,0, buf);
|
u8x8->drawString(5,0, buf);
|
||||||
|
//snprintf(buf, 8, "%s", si()->launchsite);
|
||||||
|
//u8x8->drawString(0,5, buf);
|
||||||
|
u8x8->drawTile(14,3,2,kmh_tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sonde::updateDisplayIP() {
|
void Sonde::updateDisplayIP() {
|
||||||
|
|
@ -287,11 +318,13 @@ void Sonde::updateDisplayIP() {
|
||||||
// 40x.xxx MHz
|
// 40x.xxx MHz
|
||||||
void Sonde::updateDisplayScanner() {
|
void Sonde::updateDisplayScanner() {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
u8x8->setFont(u8x8_font_7x14_1x2_r);
|
u8x8->setFont(u8x8_font_7x14_1x2_r);
|
||||||
u8x8->drawString(0, 0, "Probing");
|
u8x8->drawString(0, 0, "Scan:");
|
||||||
u8x8->drawString(8, 0, sondeTypeStr[si()->type]);
|
u8x8->drawString(8, 0, sondeTypeStr[si()->type]);
|
||||||
snprintf(buf, 16, "%3.3f MHz", si()->freq);
|
snprintf(buf, 16, "%3.3f MHz", si()->freq);
|
||||||
u8x8->drawString(0,3, buf);
|
u8x8->drawString(0,3, buf);
|
||||||
|
//snprintf(buf, 8, "%s", si()->launchsite);
|
||||||
|
//u8x8->drawString(0,5, buf);
|
||||||
updateDisplayIP();
|
updateDisplayIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,7 +337,7 @@ void Sonde::updateDisplay()
|
||||||
updateDisplayPos2();
|
updateDisplayPos2();
|
||||||
updateDisplayRSSI();
|
updateDisplayRSSI();
|
||||||
updateStat();
|
updateStat();
|
||||||
updateDisplayIP();
|
updateDisplayIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sonde::clearDisplay() {
|
void Sonde::clearDisplay() {
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,23 @@ enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41 };
|
||||||
extern const char *sondeTypeStr[5];
|
extern const char *sondeTypeStr[5];
|
||||||
|
|
||||||
typedef struct st_rdzconfig {
|
typedef struct st_rdzconfig {
|
||||||
int button_pin;
|
int button_pin; // pin number of second button (for some boards)
|
||||||
int oled_sda;
|
int led_pin; // pin number of LED
|
||||||
int oled_scl;
|
int oled_sda; // OLED data pin
|
||||||
int oled_rst;
|
int oled_scl; // OLED clock pin
|
||||||
|
int oled_rst; // OLED reset pin
|
||||||
|
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 startfreq; // spectrum display start freq (400, 401, ...)
|
||||||
|
int channelbw; // spectrum channel bandwidth (valid: 5, 10, 20, 25, 50, 100 kHz)
|
||||||
|
int spectrum; // show freq spectrum for n seconds 0=disable
|
||||||
|
int timer; // show remaining time in spectrum 0=disable
|
||||||
|
int marker; // show freq marker in spectrum 0=disable
|
||||||
|
int maxsonde; // number of max sonde in scan (range=1-99)
|
||||||
int noisefloor; // for spectrum display
|
int noisefloor; // for spectrum display
|
||||||
char call[9];
|
char call[9]; // APRS callsign
|
||||||
char passcode[9];
|
char passcode[9]; // APRS passcode
|
||||||
// for now, one feed for each type is enough, but might get extended to more?
|
// for now, one feed for each type is enough, but might get extended to more?
|
||||||
struct st_feedinfo udpfeed; // target for AXUDP messages
|
struct st_feedinfo udpfeed; // target for AXUDP messages
|
||||||
struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections
|
struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections
|
||||||
|
|
@ -27,28 +37,29 @@ typedef struct st_rdzconfig {
|
||||||
|
|
||||||
typedef struct st_sondeinfo {
|
typedef struct st_sondeinfo {
|
||||||
// receiver configuration
|
// receiver configuration
|
||||||
bool active;
|
bool active;
|
||||||
SondeType type;
|
SondeType type;
|
||||||
float freq;
|
float freq;
|
||||||
// decoded ID
|
// decoded ID
|
||||||
char id[10];
|
char id[10];
|
||||||
bool validID;
|
bool validID;
|
||||||
|
char *launchsite;
|
||||||
// decoded position
|
// decoded position
|
||||||
float lat;
|
float lat; // latitude
|
||||||
float lon;
|
float lon; // longitude
|
||||||
float hei;
|
float alt; // altitude
|
||||||
float vs;
|
float vs; // vertical speed
|
||||||
float hs;
|
float hs; // horizontal speed
|
||||||
float dir; // 0..360
|
float dir; // 0..360
|
||||||
uint8_t validPos; // bit pattern for validity of above 6 fields
|
uint8_t validPos; // bit pattern for validity of above 6 fields
|
||||||
// RSSI from receiver
|
// RSSI from receiver
|
||||||
int rssi;
|
int rssi; // signal strength
|
||||||
uint8_t rxStat[20];
|
uint8_t rxStat[20];
|
||||||
} SondeInfo;
|
} SondeInfo;
|
||||||
// rxState: 0=undef[empty] 1=timeout[.] 2=errro[E] 3=ok[1]
|
// rxState: 0=undef[empty] 1=timeout[.] 2=errro[E] 3=ok[1]
|
||||||
|
|
||||||
|
|
||||||
#define MAXSONDE 10
|
#define MAXSONDE 99
|
||||||
|
|
||||||
class Sonde
|
class Sonde
|
||||||
{
|
{
|
||||||
|
|
@ -63,7 +74,7 @@ public:
|
||||||
void setConfig(const char *str);
|
void setConfig(const char *str);
|
||||||
|
|
||||||
void clearSonde();
|
void clearSonde();
|
||||||
void addSonde(float frequency, SondeType type, int active);
|
void addSonde(float frequency, SondeType type, int active, char *launchsite);
|
||||||
void nextConfig();
|
void nextConfig();
|
||||||
void setup();
|
void setup();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ static uint32_t dao91(double x)
|
||||||
char b[201];
|
char b[201];
|
||||||
char raw[201];
|
char raw[201];
|
||||||
|
|
||||||
char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym)
|
char * aprs_senddata(float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym)
|
||||||
{
|
{
|
||||||
*b=0;
|
*b=0;
|
||||||
aprsstr_append(b, usercall);
|
aprsstr_append(b, usercall);
|
||||||
|
|
@ -281,9 +281,9 @@ char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, fl
|
||||||
snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(dir+1.5), realcard(speed*1.0/KNOTS+0.5));
|
snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(dir+1.5), realcard(speed*1.0/KNOTS+0.5));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(hei>0.5) {
|
if(alt>0.5) {
|
||||||
i=strlen(b);
|
i=strlen(b);
|
||||||
snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(hei*FEET+0.5));
|
snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(alt*FEET+0.5));
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
int dao=1;
|
int dao=1;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ typedef struct st_feedinfo {
|
||||||
#define APRS_MAXLEN 201
|
#define APRS_MAXLEN 201
|
||||||
void aprs_gencrctab(void);
|
void aprs_gencrctab(void);
|
||||||
int aprsstr_mon2raw(const char *mon, char raw[], int raw_len);
|
int aprsstr_mon2raw(const char *mon, char raw[], int raw_len);
|
||||||
char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym);
|
char * aprs_senddata(float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue