kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
v0.1
Some working things... Squashed commit of the following: commitpull/4/headda9d4367be
Author: Hans P. Reiser <hr@sec.uni-passau.de> Date: Fri Apr 5 23:32:26 2019 +0200 some minor updates commite7360f2c1e
Author: Hans P. Reiser <hr@sec.uni-passau.de> Date: Fri Apr 5 20:05:22 2019 +0200 incremental enhancements on train trip commitb3ac2c5506
Author: Hans P. Reiser <hr@sec.uni-passau.de> Date: Fri Apr 5 20:05:18 2019 +0200 incremental enhancements on train trip commitab4367992e
Author: Hans P. Reiser <hr@sec.uni-passau.de> Date: Thu Apr 4 23:46:48 2019 +0200 some more testing commitd02d687670
Author: Hans P. Reiser <hr@sec.uni-passau.de> Date: Thu Apr 4 23:46:37 2019 +0200 some more testing commit34f9971143
Author: Hansi Reiser <dl9rdz@darc.de> Date: Thu Apr 4 08:11:14 2019 +0200 scanner-test commita22bb43c89
Author: Hansi Reiser <dl9rdz@darc.de> Date: Thu Apr 4 08:10:56 2019 +0200 scanner-test
rodzic
c4f3e8d63b
commit
f9a16f827c
46
README.md
46
README.md
|
@ -1 +1,45 @@
|
||||||
# rdz_ttgo_sonde
|
RDZ_TTGO_SONDE
|
||||||
|
==============
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Button commands
|
||||||
|
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:
|
||||||
|
|
||||||
|
SHORT Short button press (<1.5 seconds)
|
||||||
|
DOUBLE Short button press, followed by another button press within 0.5 seconds
|
||||||
|
MID Medium-length button press (2-4 seconds)
|
||||||
|
LONG Long button press (>5 seconds)
|
||||||
|
|
||||||
|
## Wireless configuration
|
||||||
|
|
||||||
|
On startup, as well as after a LONG button press, the WiFI configuration will
|
||||||
|
be started. The board will scan available WiFi networks, if the scan results
|
||||||
|
contains a WiFi network configured with ID and Password in networks.txt, it
|
||||||
|
will connect to that network in station mode. If no known network is found, or
|
||||||
|
the connection does not suceed after 5 seconds, it instead starts in access point
|
||||||
|
mode. In both cases, the ESP32's IP address will be shown in tiny letters in the
|
||||||
|
bottom line. Then the board will switch to scanning mode.
|
||||||
|
|
||||||
|
## Scanning mode
|
||||||
|
|
||||||
|
In the scanning mode, the board will iterate over all channels configured in
|
||||||
|
channels.txt, trying to decode a radio sonde on each channel for about 1 second
|
||||||
|
for RS41, a bit less for DMF06/09. If a valid signal is found, the board switches
|
||||||
|
to receiving mode on that channel. a SHORT buttong press will also switch to
|
||||||
|
receiving mode.
|
||||||
|
|
||||||
|
## Receiving mode
|
||||||
|
|
||||||
|
In receiving mode, a single frequency will be decoded, and sonde info (ID, GPS
|
||||||
|
coordinates, RSSI) will be displayed. The bar above the IP address indicates,
|
||||||
|
for the last 18 frames, if reception was successfull (|) or failed (.)
|
||||||
|
A DOUBLE press will switch to scanning mode.
|
||||||
|
A SHORT press will switch to the next channel in channels.txt
|
||||||
|
|
||||||
|
# Spectrum mode
|
||||||
|
|
||||||
|
A medium press will active scan the whole band (400..406 MHz) and display a
|
||||||
|
spectrum diagram (each line == 50 kHz)
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
#include <U8x8lib.h>
|
|
||||||
#include <Sonde.h>
|
|
||||||
|
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <RS41.h>
|
#include <SPIFFS.h>
|
||||||
#include <SX1278FSK.h>
|
#include <U8x8lib.h>
|
||||||
#include <rsc.h>
|
|
||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
|
#include <SX1278FSK.h>
|
||||||
|
#include <Sonde.h>
|
||||||
|
#include <Scanner.h>
|
||||||
|
//#include <RS41.h>
|
||||||
|
//#include <DFM.h>
|
||||||
|
|
||||||
#define LORA_LED 9
|
#define LORA_LED 9
|
||||||
|
|
||||||
// I2C OLED Display works with SSD1306 driver
|
// I2C OLED Display works with SSD1306 driver
|
||||||
|
@ -22,90 +23,169 @@ U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ OLED_SCL, /* data=*/ OLED_SDA
|
||||||
//U8G2_SSD1306_128X64_NONAME_F_SW_I2C Display(U8G2_R0, /* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Full framebuffer, SW I2C
|
//U8G2_SSD1306_128X64_NONAME_F_SW_I2C Display(U8G2_R0, /* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Full framebuffer, SW I2C
|
||||||
|
|
||||||
int e;
|
int e;
|
||||||
char my_packet[100];
|
|
||||||
|
|
||||||
const char* ssid = "DinoGast";
|
AsyncWebServer server(80);
|
||||||
const char* password = "Schokolade";
|
|
||||||
|
|
||||||
WiFiServer server(80);
|
// Set LED GPIO
|
||||||
|
const int ledPin = 2;
|
||||||
pthread_t wifithread;
|
// Stores LED state
|
||||||
|
String ledState;
|
||||||
|
|
||||||
|
|
||||||
int conn = 0;
|
// Replaces placeholder with LED state value
|
||||||
String currentLine;
|
String processor(const String& var){
|
||||||
WiFiClient client;
|
Serial.println(var);
|
||||||
unsigned long lastdu;
|
if(var == "STATE"){
|
||||||
|
if(digitalRead(ledPin)){
|
||||||
void wifiloop(void *arg){
|
ledState = "ON";
|
||||||
lastdu=millis();
|
|
||||||
while(true) {
|
|
||||||
if(millis()-lastdu>500) {
|
|
||||||
// This is too slow to do in main loop
|
|
||||||
//u8x8.setFont(u8x8_font_chroma48medium8_r);
|
|
||||||
//u8x8.clearDisplay();
|
|
||||||
sonde.updateDisplay();
|
|
||||||
lastdu=millis();
|
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
ledState = "OFF";
|
||||||
delay(1);
|
|
||||||
if(!conn) {
|
|
||||||
client = server.available(); // listen for incoming clients
|
|
||||||
if (client) { // if you get a client,
|
|
||||||
Serial.println("New Client."); // print a message out the serial port
|
|
||||||
currentLine = ""; // make a String to hold incoming data from the client
|
|
||||||
conn = 1;
|
|
||||||
}
|
}
|
||||||
|
Serial.print(ledState);
|
||||||
|
return ledState;
|
||||||
|
}
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupAsyncServer() {
|
||||||
|
// Route for root / web page
|
||||||
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
request->send(200, "text/plain", "Hello, world");
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/index.html", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
request->send(SPIFFS, "/index.html", String(), false, processor);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Route to load style.css file
|
||||||
|
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
request->send(SPIFFS, "/style.css", "text/css");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Route to set GPIO to HIGH
|
||||||
|
server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
digitalWrite(ledPin, HIGH);
|
||||||
|
request->send(SPIFFS, "/index.html", String(), false, processor);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Route to set GPIO to LOW
|
||||||
|
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
digitalWrite(ledPin, LOW);
|
||||||
|
request->send(SPIFFS, "/index.html", String(), false, processor);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start server
|
||||||
|
server.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
int nNetworks;
|
||||||
|
struct { String id; String pw; } networks[20];
|
||||||
|
|
||||||
|
void setupWifiList() {
|
||||||
|
File file = SPIFFS.open("/networks.txt", "r");
|
||||||
|
if(!file){
|
||||||
|
Serial.println("There was an error opening the file '/networks.txt' for reading");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int i=0;
|
||||||
|
while(file.available()) {
|
||||||
|
String line = file.readStringUntil('\n');
|
||||||
|
if(!file.available()) break;
|
||||||
|
networks[i].id = line;
|
||||||
|
networks[i].pw = file.readStringUntil('\n');
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
nNetworks = i;
|
||||||
|
Serial.print(i); Serial.println(" networks in networks.txt\n");
|
||||||
|
for(int j=0; j<i; j++) { Serial.print(networks[j].id); Serial.print(": "); Serial.println(networks[j].pw); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupChannelList() {
|
||||||
|
File file = SPIFFS.open("/qrg.txt", "r");
|
||||||
|
if(!file) {
|
||||||
|
Serial.println("There was an error opening the file '/qrg.txt' for reading");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int i=0;
|
||||||
|
sonde.clearSonde();
|
||||||
|
while(file.available()) {
|
||||||
|
String line = file.readStringUntil('\n');
|
||||||
|
if(!file.available()) break;
|
||||||
|
if(line[0] == '#') continue;
|
||||||
|
char *space = strchr(line.c_str(), ' ');
|
||||||
|
if(!space) continue;
|
||||||
|
*space = 0;
|
||||||
|
float freq = atof(line.c_str());
|
||||||
|
SondeType type;
|
||||||
|
if(space[1]=='4') { type=STYPE_RS41; }
|
||||||
|
else if (space[1]=='9') { type=STYPE_DFM09; }
|
||||||
|
else if (space[1]=='6') { type=STYPE_DFM06; }
|
||||||
|
else continue;
|
||||||
|
Serial.printf("Adding %f with type %d\b",freq,type);
|
||||||
|
sonde.addSonde(freq, type);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
nNetworks = i;
|
||||||
|
Serial.print(i); Serial.println(" networks in networks.txt\n");
|
||||||
|
for(int j=0; j<i; j++) { Serial.print(networks[j].id); Serial.print(": "); Serial.println(networks[j].pw); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *fetchWifiPw(const char *id) {
|
||||||
|
for(int i=0; i<nNetworks; i++) {
|
||||||
|
Serial.print("Comparing '");
|
||||||
|
Serial.print(id);
|
||||||
|
Serial.print("' and '");
|
||||||
|
Serial.print(networks[i].id.c_str());
|
||||||
|
Serial.println("'");
|
||||||
|
if(strcmp(id,networks[i].id.c_str())==0) return networks[i].pw.c_str();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum KeyPress { KP_NONE=0, KP_SHORT, KP_DOUBLE, KP_MID, KP_LONG };
|
||||||
|
|
||||||
|
struct Button {
|
||||||
|
const uint8_t PIN;
|
||||||
|
uint32_t numberKeyPresses;
|
||||||
|
KeyPress pressed;
|
||||||
|
unsigned long press_ts;
|
||||||
|
boolean doublepress;
|
||||||
|
};
|
||||||
|
Button button1 = {0, 0, KP_NONE, 0, false};
|
||||||
|
|
||||||
|
void IRAM_ATTR buttonISR() {
|
||||||
|
if(digitalRead(0)==0) { // Button down
|
||||||
|
if(millis()-button1.press_ts<500) {
|
||||||
|
// Double press
|
||||||
|
button1.doublepress = true;
|
||||||
} else {
|
} else {
|
||||||
if(!client.connected()) { // loop while the client's connected
|
button1.doublepress = false;
|
||||||
conn = 0;
|
|
||||||
Serial.println("Client no longer connected");
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
while (client.available()) { // if there's bytes to read from the client,
|
button1.press_ts = millis();
|
||||||
char c = client.read(); // read a byte, then
|
} else { //Button up
|
||||||
Serial.write(c); // print it out the serial monitor
|
unsigned int elapsed = millis()-button1.press_ts;
|
||||||
if (c == '\n') { // if the byte is a newline character
|
if(elapsed>1500) {
|
||||||
|
if(elapsed<4000) { button1.pressed=KP_MID; }
|
||||||
|
else { button1.pressed=KP_LONG; }
|
||||||
|
} else {
|
||||||
|
if(button1.doublepress) button1.pressed=KP_DOUBLE;
|
||||||
|
else button1.pressed=KP_SHORT;
|
||||||
|
}
|
||||||
|
button1.numberKeyPresses += 1;
|
||||||
|
button1.press_ts = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if the current line is blank, you got two newline characters in a row.
|
int getKeyPress() {
|
||||||
// that's the end of the client HTTP request, so send a response:
|
KeyPress p = button1.pressed;
|
||||||
if (currentLine.length() == 0) {
|
button1.pressed = KP_NONE;
|
||||||
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
|
return p;
|
||||||
// and a content-type so the client knows what's coming, then a blank line:
|
}
|
||||||
client.println("HTTP/1.1 200 OK");
|
int hasKeyPress() {
|
||||||
client.println("Content-type:text/html");
|
return button1.pressed;
|
||||||
client.println();
|
|
||||||
|
|
||||||
// the content of the HTTP response follows the header:
|
|
||||||
client.print("Click <a href=\"/H\">here</a> to turn the LED on pin 5 on.<br>");
|
|
||||||
client.print("Click <a href=\"/L\">here</a> to turn the LED on pin 5 off.<br>");
|
|
||||||
|
|
||||||
// The HTTP response ends with another blank line:
|
|
||||||
client.println();
|
|
||||||
// break out of the while loop:
|
|
||||||
// close the connection:
|
|
||||||
client.stop();
|
|
||||||
Serial.println("Client Disconnected.");
|
|
||||||
continue;
|
|
||||||
} else { // if you got a newline, then clear currentLine:
|
|
||||||
currentLine = "";
|
|
||||||
}
|
|
||||||
} else if (c != '\r') { // if you got anything else but a carriage return character,
|
|
||||||
currentLine += c; // add it to the end of the currentLine
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if the client request was "GET /H" or "GET /L":
|
|
||||||
if (currentLine.endsWith("GET /H")) {
|
|
||||||
digitalWrite(5, HIGH); // GET /H turns the LED on
|
|
||||||
}
|
|
||||||
if (currentLine.endsWith("GET /L")) {
|
|
||||||
digitalWrite(5, LOW); // GET /L turns the LED off
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
|
@ -115,26 +195,17 @@ void setup()
|
||||||
|
|
||||||
u8x8.begin();
|
u8x8.begin();
|
||||||
|
|
||||||
|
|
||||||
pinMode(LORA_LED, OUTPUT);
|
pinMode(LORA_LED, OUTPUT);
|
||||||
WiFi.begin(ssid, password);
|
|
||||||
while(WiFi.status() != WL_CONNECTED) {
|
// Initialize SPIFFS
|
||||||
delay(500);
|
if(!SPIFFS.begin(true)){
|
||||||
Serial.print(".");
|
Serial.println("An Error has occurred while mounting SPIFFS");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("");
|
setupWifiList();
|
||||||
Serial.println("WiFi connected");
|
|
||||||
Serial.println("IP address: ");
|
|
||||||
Serial.println(WiFi.localIP());
|
|
||||||
|
|
||||||
server.begin();
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore(wifiloop, "WifiServer", 10240, NULL, 10, NULL, 0);
|
|
||||||
|
|
||||||
|
|
||||||
rs41.setup();
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
if(rs41.setFrequency(402700000)==0) {
|
if(rs41.setFrequency(402700000)==0) {
|
||||||
Serial.println(F("Setting freq: SUCCESS "));
|
Serial.println(F("Setting freq: SUCCESS "));
|
||||||
} else {
|
} else {
|
||||||
|
@ -143,8 +214,9 @@ 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);
|
||||||
|
#endif
|
||||||
|
|
||||||
sx1278.setLNAGain(-48);
|
sx1278.setLNAGain(0); //-48);
|
||||||
int gain = sx1278.getLNAGain();
|
int gain = sx1278.getLNAGain();
|
||||||
Serial.print("RX LNA Gain is ");
|
Serial.print("RX LNA Gain is ");
|
||||||
Serial.println(gain);
|
Serial.println(gain);
|
||||||
|
@ -162,16 +234,195 @@ void setup()
|
||||||
// }
|
// }
|
||||||
// xTaskCreate(mainloop, "MainServer", 10240, NULL, 10, NULL);
|
// xTaskCreate(mainloop, "MainServer", 10240, NULL, 10, NULL);
|
||||||
|
|
||||||
|
// Handle button press
|
||||||
|
attachInterrupt(0, buttonISR, CHANGE);
|
||||||
|
|
||||||
|
setupChannelList();
|
||||||
|
#if 0
|
||||||
|
sonde.clearSonde();
|
||||||
|
sonde.addSonde(402.300, STYPE_RS41);
|
||||||
|
sonde.addSonde(402.700, STYPE_RS41);
|
||||||
|
sonde.addSonde(403.450, STYPE_DFM09);
|
||||||
|
#endif
|
||||||
|
/// not here, done by sonde.setup(): rs41.setup();
|
||||||
|
sonde.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MainState { ST_DECODER, ST_SCANNER, ST_SPECTRUM, ST_WIFISCAN };
|
||||||
|
|
||||||
|
static MainState mainState = ST_DECODER;
|
||||||
|
|
||||||
|
void enterMode(int mode) {
|
||||||
|
mainState = (MainState)mode;
|
||||||
|
sonde.clearDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loopDecoder() {
|
||||||
|
switch(getKeyPress()) {
|
||||||
|
case KP_SHORT:
|
||||||
|
sonde.nextConfig();
|
||||||
|
break;
|
||||||
|
case KP_DOUBLE:
|
||||||
|
enterMode(ST_SCANNER);
|
||||||
|
return;
|
||||||
|
case KP_MID:
|
||||||
|
enterMode(ST_SPECTRUM);
|
||||||
|
return;
|
||||||
|
case KP_LONG:
|
||||||
|
enterMode(ST_WIFISCAN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// sonde knows the current type and frequency, and delegates to the right decoder
|
||||||
|
sonde.receiveFrame();
|
||||||
|
sonde.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCAN_MAXTRIES 1
|
||||||
|
void loopScanner() {
|
||||||
|
sonde.updateDisplayScanner();
|
||||||
|
static int tries=0;
|
||||||
|
switch(getKeyPress()) {
|
||||||
|
case KP_SHORT:
|
||||||
|
enterMode(ST_DECODER);
|
||||||
|
return;
|
||||||
|
case KP_DOUBLE: break; /* ignored */
|
||||||
|
case KP_MID:
|
||||||
|
enterMode(ST_SPECTRUM);
|
||||||
|
return;
|
||||||
|
case KP_LONG:
|
||||||
|
enterMode(ST_WIFISCAN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// receiveFrame returns 0 on success, 1 on timeout
|
||||||
|
int res = sonde.receiveFrame(); // Maybe instead of receiveFrame, just detect if right type is present? TODO
|
||||||
|
Serial.print("Scanner: receiveFrame returned");
|
||||||
|
Serial.println(res);
|
||||||
|
if(res==0) {
|
||||||
|
enterMode(ST_DECODER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(++tries>=SCAN_MAXTRIES && !hasKeyPress()) {
|
||||||
|
sonde.nextConfig();
|
||||||
|
tries = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loopSpectrum() {
|
||||||
|
switch(getKeyPress()) {
|
||||||
|
case KP_SHORT: /* move selection of peak, TODO */
|
||||||
|
sonde.nextConfig(); // TODO: Should be set specific frequency
|
||||||
|
enterMode(ST_DECODER);
|
||||||
|
return;
|
||||||
|
case KP_MID: /* restart, TODO */ break;
|
||||||
|
case KP_LONG:
|
||||||
|
enterMode(ST_WIFISCAN);
|
||||||
|
return;
|
||||||
|
case KP_DOUBLE: /* ignore */ break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
scanner.scan();
|
||||||
|
scanner.plotResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
String translateEncryptionType(wifi_auth_mode_t encryptionType) {
|
||||||
|
switch (encryptionType) {
|
||||||
|
case (WIFI_AUTH_OPEN):
|
||||||
|
return "Open";
|
||||||
|
case (WIFI_AUTH_WEP):
|
||||||
|
return "WEP";
|
||||||
|
case (WIFI_AUTH_WPA_PSK):
|
||||||
|
return "WPA_PSK";
|
||||||
|
case (WIFI_AUTH_WPA2_PSK):
|
||||||
|
return "WPA2_PSK";
|
||||||
|
case (WIFI_AUTH_WPA_WPA2_PSK):
|
||||||
|
return "WPA_WPA2_PSK";
|
||||||
|
case (WIFI_AUTH_WPA2_ENTERPRISE):
|
||||||
|
return "WPA2_ENTERPRISE";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* _scan[2]={"/","\\"};
|
||||||
|
void loopWifiScan() {
|
||||||
|
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||||
|
u8x8.drawString(0,0,"WiFi Scan...");
|
||||||
|
int line=0;
|
||||||
|
int cnt=0;
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
const char *id, *pw;
|
||||||
|
int n = WiFi.scanNetworks();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
Serial.print("Network name: ");
|
||||||
|
Serial.println(WiFi.SSID(i));
|
||||||
|
u8x8.drawString(0,1+line,WiFi.SSID(i).c_str());
|
||||||
|
line = (line+1)%5;
|
||||||
|
Serial.print("Signal strength: ");
|
||||||
|
Serial.println(WiFi.RSSI(i));
|
||||||
|
Serial.print("MAC address: ");
|
||||||
|
Serial.println(WiFi.BSSIDstr(i));
|
||||||
|
Serial.print("Encryption type: ");
|
||||||
|
String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i));
|
||||||
|
Serial.println(encryptionTypeDescription);
|
||||||
|
Serial.println("-----------------------");
|
||||||
|
id=WiFi.SSID(i).c_str();
|
||||||
|
pw=fetchWifiPw(id);
|
||||||
|
if(pw) break;
|
||||||
|
}
|
||||||
|
if(1||!pw) { id="test"; pw="test"; }
|
||||||
|
Serial.print("Connecting to: "); Serial.println(id);
|
||||||
|
u8x8.drawString(0,6, "Conn:");
|
||||||
|
u8x8.drawString(6,6, id);
|
||||||
|
WiFi.begin(id, pw);
|
||||||
|
while(WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
u8x8.drawString(15,7,_scan[cnt&1]);
|
||||||
|
cnt++;
|
||||||
|
if(cnt==4) {
|
||||||
|
WiFi.disconnect(); // retry, for my buggy FritzBox
|
||||||
|
WiFi.begin(id, pw);
|
||||||
|
}
|
||||||
|
if(cnt==10) {
|
||||||
|
WiFi.disconnect();
|
||||||
|
delay(1000);
|
||||||
|
WiFi.softAP("sonde","sondesonde");
|
||||||
|
IPAddress myIP = WiFi.softAPIP();
|
||||||
|
Serial.print("AP IP address: ");
|
||||||
|
Serial.println(myIP);
|
||||||
|
sonde.setIP(myIP.toString().c_str());
|
||||||
|
sonde.updateDisplayIP();
|
||||||
|
SetupAsyncServer();
|
||||||
|
delay(5000);
|
||||||
|
enterMode(ST_DECODER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println("WiFi connected");
|
||||||
|
Serial.println("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
sonde.setIP(WiFi.localIP().toString().c_str());
|
||||||
|
sonde.updateDisplayIP();
|
||||||
|
SetupAsyncServer();
|
||||||
|
delay(5000);
|
||||||
|
enterMode(ST_DECODER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
Serial.println("Running main loop");
|
Serial.println("Running main loop");
|
||||||
|
switch(mainState) {
|
||||||
|
case ST_DECODER: loopDecoder(); break;
|
||||||
|
case ST_SCANNER: loopScanner(); break;
|
||||||
|
case ST_SPECTRUM: loopSpectrum(); break;
|
||||||
|
case ST_WIFISCAN: loopWifiScan(); break;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
//wifiloop(NULL);
|
//wifiloop(NULL);
|
||||||
//e = dfm.receiveFrame();
|
//e = dfm.receiveFrame();
|
||||||
e = rs41.receiveFrame();
|
//e = rs41.receiveFrame();
|
||||||
#if 0
|
delay(1000);
|
||||||
int rssi = sx1278.getRSSI();
|
int rssi = sx1278.getRSSI();
|
||||||
Serial.print(" RSSI: ");
|
Serial.print(" RSSI: ");
|
||||||
Serial.print(rssi);
|
Serial.print(rssi);
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>ESP32 Web Server</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" href="data:,">
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>ESP32 Web Server</h1>
|
||||||
|
<!--
|
||||||
|
<p>GPIO state: <strong> %STATE%</strong></p>
|
||||||
|
<p><a href="/on"><button class="button">ON</button></a></p>
|
||||||
|
<p><a href="/off"><button class="button button2">OFF</button></a></p>
|
||||||
|
-->
|
||||||
|
<table class="KKK">
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th style="width:100px">ID</th>
|
||||||
|
<th style="width:100px">PW</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>1</td>
|
||||||
|
<td contenteditable>DinoGast</td>
|
||||||
|
<td contenteditable>Schokolade</td>
|
||||||
|
<tr>
|
||||||
|
<td>2</td>
|
||||||
|
<td contenteditable></td>
|
||||||
|
<td contenteditable></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
DinoGast
|
||||||
|
Schokolade
|
||||||
|
AndroidDD
|
||||||
|
dl9rdzhr
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Frequency in Mhz (format nnn.nnn)
|
||||||
|
# Type (4=RS41, 6=DFM normal, DFM-06, 9=DFM inverted, DFM-09)
|
||||||
|
#
|
||||||
|
402.700 4
|
||||||
|
402.300 4
|
||||||
|
403.450 9
|
||||||
|
405.100 4
|
||||||
|
# end
|
|
@ -0,0 +1,28 @@
|
||||||
|
html {
|
||||||
|
font-family: Helvetica;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0px auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
h1{
|
||||||
|
color: #0F3376;
|
||||||
|
padding: 2vh;
|
||||||
|
}
|
||||||
|
p{
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #008CBA;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: white;
|
||||||
|
padding: 16px 40px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 30px;
|
||||||
|
margin: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.button2 {
|
||||||
|
background-color: #f44336;
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "SX1278FSK.h"
|
#include "SX1278FSK.h"
|
||||||
#include "SPI.h"
|
#include "SPI.h"
|
||||||
|
#include <Sonde.h>
|
||||||
|
|
||||||
SX1278FSK::SX1278FSK()
|
SX1278FSK::SX1278FSK()
|
||||||
{
|
{
|
||||||
|
@ -98,7 +99,7 @@ byte SX1278FSK::readRegister(byte address)
|
||||||
|
|
||||||
digitalWrite(SX1278_SS,LOW);
|
digitalWrite(SX1278_SS,LOW);
|
||||||
|
|
||||||
delay(1);
|
//delay(1);
|
||||||
bitClear(address, 7); // Bit 7 cleared to write in registers
|
bitClear(address, 7); // Bit 7 cleared to write in registers
|
||||||
SPI.transfer(address);
|
SPI.transfer(address);
|
||||||
value = SPI.transfer(0x00);
|
value = SPI.transfer(0x00);
|
||||||
|
@ -129,7 +130,7 @@ void SX1278FSK::writeRegister(byte address, byte data)
|
||||||
{
|
{
|
||||||
digitalWrite(SX1278_SS,LOW);
|
digitalWrite(SX1278_SS,LOW);
|
||||||
|
|
||||||
delay(1);
|
//delay(1);
|
||||||
bitSet(address, 7); // Bit 7 set to read from registers
|
bitSet(address, 7); // Bit 7 set to read from registers
|
||||||
SPI.transfer(address);
|
SPI.transfer(address);
|
||||||
SPI.transfer(data);
|
SPI.transfer(data);
|
||||||
|
@ -648,6 +649,9 @@ uint8_t SX1278FSK::receive()
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ugly. shouldn't be here in a nice software design
|
||||||
|
extern int hasKeyPress();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: Configures the module to receive a packet
|
Function: Configures the module to receive a packet
|
||||||
Returns: Integer that determines if there has been any error
|
Returns: Integer that determines if there has been any error
|
||||||
|
@ -682,7 +686,7 @@ uint8_t SX1278FSK::receivePacketTimeout(uint32_t wait, byte *data)
|
||||||
value = readRegister(REG_IRQ_FLAGS2);
|
value = readRegister(REG_IRQ_FLAGS2);
|
||||||
byte ready=0;
|
byte ready=0;
|
||||||
// while not yet done or FIFO not yet empty
|
// while not yet done or FIFO not yet empty
|
||||||
while( (!ready || bitRead(value,6)==0) && (millis() - previous < wait) )
|
while( (!ready || bitRead(value,6)==0) && (millis() - previous < wait) &&(!hasKeyPress()) )
|
||||||
{
|
{
|
||||||
if( bitRead(value,2)==1 ) ready=1;
|
if( bitRead(value,2)==1 ) ready=1;
|
||||||
if( bitRead(value, 6) == 0 ) { // FIFO not empty
|
if( bitRead(value, 6) == 0 ) { // FIFO not empty
|
||||||
|
@ -690,6 +694,7 @@ uint8_t SX1278FSK::receivePacketTimeout(uint32_t wait, byte *data)
|
||||||
if(di==1) {
|
if(di==1) {
|
||||||
int rssi=getRSSI();
|
int rssi=getRSSI();
|
||||||
Serial.print("Test: RSSI="); Serial.println(rssi);
|
Serial.print("Test: RSSI="); Serial.println(rssi);
|
||||||
|
sonde.si()->rssi = rssi;
|
||||||
}
|
}
|
||||||
if(di>520) {
|
if(di>520) {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -705,6 +710,7 @@ uint8_t SX1278FSK::receivePacketTimeout(uint32_t wait, byte *data)
|
||||||
Serial.println(F("** The timeout has expired **"));
|
Serial.println(F("** The timeout has expired **"));
|
||||||
Serial.println();
|
Serial.println();
|
||||||
#endif
|
#endif
|
||||||
|
sonde.si()->rssi = getRSSI();
|
||||||
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); // Setting standby FSK mode
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); // Setting standby FSK mode
|
||||||
return 1; // TIMEOUT
|
return 1; // TIMEOUT
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/* DFM decoder functions */
|
/* DFM decoder functions */
|
||||||
#include "DFM.h"
|
#include "DFM.h"
|
||||||
#include "SX1278FSK.h"
|
#include "SX1278FSK.h"
|
||||||
|
#include "Sonde.h"
|
||||||
|
|
||||||
#define DFM_DEBUG 1
|
#define DFM_DEBUG 1
|
||||||
|
|
||||||
|
@ -71,6 +72,8 @@ int DFM::setup(int inverse)
|
||||||
}
|
}
|
||||||
|
|
||||||
int DFM::setFrequency(float frequency) {
|
int DFM::setFrequency(float frequency) {
|
||||||
|
Serial.print("DFM: setting RX frequency to ");
|
||||||
|
Serial.println(frequency);
|
||||||
return sx1278.setFrequency(frequency);
|
return sx1278.setFrequency(frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +168,8 @@ int DFM::decodeCFG(uint8_t *cfg)
|
||||||
if((cfg[0]>>4)==0x06 && type==0) { // DFM-6 ID
|
if((cfg[0]>>4)==0x06 && type==0) { // DFM-6 ID
|
||||||
lowid = ((cfg[0]&0x0F)<<20) | (cfg[1]<<12) | (cfg[2]<<4) | (cfg[3]&0x0f);
|
lowid = ((cfg[0]&0x0F)<<20) | (cfg[1]<<12) | (cfg[2]<<4) | (cfg[3]&0x0f);
|
||||||
Serial.print("DFM-06 ID: "); Serial.print(lowid, HEX);
|
Serial.print("DFM-06 ID: "); Serial.print(lowid, HEX);
|
||||||
|
snprintf(sonde.si()->id, 10, "%x", lowid);
|
||||||
|
sonde.si()->validID = true;
|
||||||
}
|
}
|
||||||
if((cfg[0]>>4)==0x0A) { // DMF-9 ID
|
if((cfg[0]>>4)==0x0A) { // DMF-9 ID
|
||||||
type=9;
|
type=9;
|
||||||
|
@ -178,6 +183,8 @@ int DFM::decodeCFG(uint8_t *cfg)
|
||||||
if(idgood==3) {
|
if(idgood==3) {
|
||||||
uint32_t dfmid = (highid<<16) | lowid;
|
uint32_t dfmid = (highid<<16) | lowid;
|
||||||
Serial.print("DFM-09 ID: "); Serial.print(dfmid);
|
Serial.print("DFM-09 ID: "); Serial.print(dfmid);
|
||||||
|
snprintf(sonde.si()->id, 10, "%d", dfmid);
|
||||||
|
sonde.si()->validID = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,6 +209,9 @@ int DFM::decodeDAT(uint8_t *dat)
|
||||||
vh = (dat[4]<<8) + dat[5];
|
vh = (dat[4]<<8) + dat[5];
|
||||||
Serial.print("GPS-lat: "); Serial.print(lat*0.0000001);
|
Serial.print("GPS-lat: "); Serial.print(lat*0.0000001);
|
||||||
Serial.print(", hor-V: "); Serial.print(vh*0.01);
|
Serial.print(", hor-V: "); Serial.print(vh*0.01);
|
||||||
|
sonde.si()->lat = lat*0.0000001;
|
||||||
|
sonde.si()->hs = vh*0.01;
|
||||||
|
sonde.si()->validPos |= 0x11;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -211,6 +221,9 @@ int DFM::decodeDAT(uint8_t *dat)
|
||||||
dir = ((uint16_t)dat[4]<<8) + dat[5];
|
dir = ((uint16_t)dat[4]<<8) + dat[5];
|
||||||
Serial.print("GPS-lon: "); Serial.print(lon*0.0000001);
|
Serial.print("GPS-lon: "); Serial.print(lon*0.0000001);
|
||||||
Serial.print(", dir: "); Serial.print(dir*0.01);
|
Serial.print(", dir: "); Serial.print(dir*0.01);
|
||||||
|
sonde.si()->lon = lon*0.0000001;
|
||||||
|
sonde.si()->dir = dir*0.01;
|
||||||
|
sonde.si()->validPos |= 0x42;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -220,6 +233,9 @@ int DFM::decodeDAT(uint8_t *dat)
|
||||||
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(hei*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()->vs = vv*0.01;
|
||||||
|
sonde.si()->validPos |= 0x0C;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -256,7 +272,7 @@ int DFM::receiveFrame() {
|
||||||
|
|
||||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||||
int e = sx1278.receivePacketTimeout(1000, data);
|
int e = sx1278.receivePacketTimeout(1000, data);
|
||||||
if(e) { return 1; } //if timeout... return 1
|
if(e) { return RX_TIMEOUT; } //if timeout... return 1
|
||||||
|
|
||||||
deinterleave(data, 7, hamming_conf);
|
deinterleave(data, 7, hamming_conf);
|
||||||
deinterleave(data+7, 13, hamming_dat1);
|
deinterleave(data+7, 13, hamming_dat1);
|
||||||
|
@ -277,6 +293,7 @@ int DFM::receiveFrame() {
|
||||||
decodeCFG(byte_conf);
|
decodeCFG(byte_conf);
|
||||||
decodeDAT(byte_dat1);
|
decodeDAT(byte_dat1);
|
||||||
decodeDAT(byte_dat2);
|
decodeDAT(byte_dat2);
|
||||||
|
return RX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DFM dfm = DFM();
|
DFM dfm = DFM();
|
||||||
|
|
|
@ -133,6 +133,8 @@ int RS41::setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
int RS41::setFrequency(float frequency) {
|
int RS41::setFrequency(float frequency) {
|
||||||
|
Serial.print("RS41: setting RX frequency to ");
|
||||||
|
Serial.println(frequency);
|
||||||
return sx1278.setFrequency(frequency);
|
return sx1278.setFrequency(frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,11 +313,11 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
||||||
z = (double)getint32(b, b_len, p+8UL)*0.01;
|
z = (double)getint32(b, b_len, p+8UL)*0.01;
|
||||||
wgs84r(x, y, z, &lat, &long0, &heig);
|
wgs84r(x, y, z, &lat, &long0, &heig);
|
||||||
Serial.print(" ");
|
Serial.print(" ");
|
||||||
si.lat = (float)(X2C_DIVL(lat,1.7453292519943E-2));
|
sonde.si()->lat = (float)(X2C_DIVL(lat,1.7453292519943E-2));
|
||||||
Serial.print(si.lat);
|
Serial.print(sonde.si()->lat);
|
||||||
Serial.print(" ");
|
Serial.print(" ");
|
||||||
si.lon = (float)(X2C_DIVL(long0,1.7453292519943E-2));
|
sonde.si()->lon = (float)(X2C_DIVL(long0,1.7453292519943E-2));
|
||||||
Serial.print(si.lon);
|
Serial.print(sonde.si()->lon);
|
||||||
if (heig<1.E+5 && heig>(-1.E+5)) {
|
if (heig<1.E+5 && heig>(-1.E+5)) {
|
||||||
Serial.print(" ");
|
Serial.print(" ");
|
||||||
Serial.print((uint32_t)heig);
|
Serial.print((uint32_t)heig);
|
||||||
|
@ -338,18 +340,18 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
||||||
dir = X2C_DIVL(atang2(vn, ve),1.7453292519943E-2);
|
dir = X2C_DIVL(atang2(vn, ve),1.7453292519943E-2);
|
||||||
if (dir<0.0) dir = 360.0+dir;
|
if (dir<0.0) dir = 360.0+dir;
|
||||||
Serial.print(" ");
|
Serial.print(" ");
|
||||||
si.hs = sqrt((float)(vn*vn+ve*ve))*3.6f;
|
sonde.si()->hs = sqrt((float)(vn*vn+ve*ve))*3.6f;
|
||||||
Serial.print(si.hs);
|
Serial.print(sonde.si()->hs);
|
||||||
Serial.print("km/h ");
|
Serial.print("km/h ");
|
||||||
Serial.print(dir);
|
Serial.print(dir);
|
||||||
Serial.print("deg ");
|
Serial.print("deg ");
|
||||||
Serial.print((float)vu);
|
Serial.print((float)vu);
|
||||||
si.vs = vu;
|
sonde.si()->vs = vu;
|
||||||
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");
|
||||||
si.hei = heig;
|
sonde.si()->hei = heig;
|
||||||
si.validPos = true;
|
sonde.si()->validPos = true;
|
||||||
} /* end posrs41() */
|
} /* end posrs41() */
|
||||||
|
|
||||||
|
|
||||||
|
@ -400,10 +402,10 @@ void RS41::decode41(byte *data, int MAXLEN)
|
||||||
Serial.print("; RS41 ID ");
|
Serial.print("; RS41 ID ");
|
||||||
snprintf(buf, 10, "%.8s ", data+p+2);
|
snprintf(buf, 10, "%.8s ", data+p+2);
|
||||||
Serial.print(buf);
|
Serial.print(buf);
|
||||||
strcpy(si.type, "RS41");
|
sonde.si()->type=STYPE_RS41;
|
||||||
strncpy(si.id, (const char *)(data+p+2), 8);
|
strncpy(sonde.si()->id, (const char *)(data+p+2), 8);
|
||||||
si.id[8]=0;
|
sonde.si()->id[8]=0;
|
||||||
si.validID=true;
|
sonde.si()->validID=true;
|
||||||
}
|
}
|
||||||
// TODO: some more data
|
// TODO: some more data
|
||||||
break;
|
break;
|
||||||
|
@ -463,14 +465,15 @@ int RS41::receiveFrame() {
|
||||||
sx1278.setPayloadLength(MAXLEN-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
|
sx1278.setPayloadLength(MAXLEN-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
|
||||||
|
|
||||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||||
int e = sx1278.receivePacketTimeout(3000, data+8);
|
int e = sx1278.receivePacketTimeout(1000, data+8);
|
||||||
if(e) { Serial.println("TIMEOUT"); return 1; } //if timeout... return 1
|
if(e) { Serial.println("TIMEOUT"); return RX_TIMEOUT; } //if timeout... return 1
|
||||||
|
|
||||||
for(int i=0; i<MAXLEN; i++) { data[i] = reverse(data[i]); }
|
for(int i=0; i<MAXLEN; i++) { data[i] = reverse(data[i]); }
|
||||||
//printRaw(data, MAXLEN);
|
//printRaw(data, MAXLEN);
|
||||||
for(int i=0; i<MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
|
for(int i=0; i<MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
|
||||||
//printRaw(data, MAXLEN);
|
//printRaw(data, MAXLEN);
|
||||||
decode41(data, MAXLEN);
|
decode41(data, MAXLEN);
|
||||||
|
return RX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RS41 rs41 = RS41();
|
RS41 rs41 = RS41();
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include "Scanner.h"
|
||||||
|
#include <SX1278FSK.h>
|
||||||
|
#include <U8x8lib.h>
|
||||||
|
|
||||||
|
extern U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8;
|
||||||
|
|
||||||
|
#define CHANBW 25
|
||||||
|
#define SMOOTH 2
|
||||||
|
#define STARTF 400000000
|
||||||
|
#define NCHAN ((int)(6000/CHANBW))
|
||||||
|
|
||||||
|
int scanresult[NCHAN];
|
||||||
|
int scandisp[NCHAN/2];
|
||||||
|
|
||||||
|
#define PLOT_N 120
|
||||||
|
#define PLOT_MIN -220
|
||||||
|
#define PLOT_SCALE(x) (x<PLOT_MIN?0:(x-PLOT_MIN)/2)
|
||||||
|
|
||||||
|
const byte tilepatterns[9]={0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF};
|
||||||
|
void Scanner::fillTiles(uint8_t *row, int value) {
|
||||||
|
for(int y=0; y<8; y++) {
|
||||||
|
int nbits = value - 8*(7-y);
|
||||||
|
if(nbits<0) { row[8*y]=0; continue; }
|
||||||
|
if(nbits>=8) { row[8*y]=255; continue; }
|
||||||
|
row[8*y] = tilepatterns[nbits];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* There are 16*8 columns to plot, NPLOT must be lower than that
|
||||||
|
* currently, we use 120 * 50kHz channels
|
||||||
|
* 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};
|
||||||
|
void Scanner::plotResult()
|
||||||
|
{
|
||||||
|
uint8_t row[8*8];
|
||||||
|
for(int i=0; i<PLOT_N; i+=8) {
|
||||||
|
for(int j=0; j<8; j++) {
|
||||||
|
fillTiles(row+j, PLOT_SCALE(scandisp[i+j]));
|
||||||
|
}
|
||||||
|
for(int y=0; y<8; y++) {
|
||||||
|
u8x8.drawTile(i/8, y, 1, row+8*y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scanner::scan()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// Test only
|
||||||
|
for(int i=0; i<PLOT_N; i++) {
|
||||||
|
scandisp[i] = 30*sin(2*3.1415*i/50)-180;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
// Configure
|
||||||
|
sx1278.writeRegister(REG_PLL_HOP, 0x80); // FastHopOn
|
||||||
|
sx1278.setRxBandwidth(CHANBW*1000);
|
||||||
|
sx1278.writeRegister(REG_RSSI_CONFIG, SMOOTH&0x07);
|
||||||
|
sx1278.setFrequency(STARTF);
|
||||||
|
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||||
|
delay(5);
|
||||||
|
|
||||||
|
unsigned long start = millis();
|
||||||
|
uint32_t lastfrf=-1;
|
||||||
|
for(int i=0; i<NCHAN; i++) {
|
||||||
|
float freq = STARTF + 1000.0*i*CHANBW;
|
||||||
|
uint32_t frf = freq * 1.0 * (1<<19) / SX127X_CRYSTAL_FREQ;
|
||||||
|
if( (lastfrf>>16)!=(frf>>16) ) {
|
||||||
|
sx1278.writeRegister(REG_FRF_MSB, (frf&0xff0000)>>16);
|
||||||
|
}
|
||||||
|
if( ((lastfrf&0x00ff00)>>8) != ((frf&0x00ff00)>>8) ) {
|
||||||
|
sx1278.writeRegister(REG_FRF_MID, (frf&0x00ff00)>>8);
|
||||||
|
}
|
||||||
|
sx1278.writeRegister(REG_FRF_LSB, (frf&0x0000ff));
|
||||||
|
lastfrf = frf;
|
||||||
|
// Wait TS_HOP (20us) + TS_RSSI ( 2^(SMOOTH+1) / 4 / CHANBW us)
|
||||||
|
int wait = 20 + 1000*(1<<(SMOOTH+1))/4/CHANBW;
|
||||||
|
delayMicroseconds(wait);
|
||||||
|
int rssi = -(int)sx1278.readRegister(REG_RSSI_VALUE_FSK);
|
||||||
|
scanresult[i] = rssi;
|
||||||
|
}
|
||||||
|
unsigned long duration = millis()-start;
|
||||||
|
Serial.print("Scan time: ");
|
||||||
|
Serial.println(duration);
|
||||||
|
for(int i=0; i<NCHAN; i+=2) {
|
||||||
|
scandisp[i/2] = scanresult[i];
|
||||||
|
for(int j=1; j<2; j++) { if(scanresult[i+j]>scandisp[i/2]) scandisp[i/2] = scanresult[i+j]; }
|
||||||
|
Serial.print(scanresult[i]); Serial.print(", ");
|
||||||
|
if(((i+1)%32) == 0) Serial.println();
|
||||||
|
}
|
||||||
|
Serial.println("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Scanner scanner = Scanner();
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _SCANNER_H
|
||||||
|
#define _SCANNER_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#ifndef inttypes_h
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Scanner
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void fillTiles(uint8_t *row, int value);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void plotResult();
|
||||||
|
void scan(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Scanner scanner;
|
||||||
|
#endif
|
|
@ -2,10 +2,13 @@
|
||||||
#include <U8g2lib.h>
|
#include <U8g2lib.h>
|
||||||
|
|
||||||
#include "Sonde.h"
|
#include "Sonde.h"
|
||||||
|
#include "RS41.h"
|
||||||
|
#include "DFM.h"
|
||||||
|
|
||||||
extern U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8;
|
extern U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8;
|
||||||
|
|
||||||
SondeInfo si = { "RS41", 403.450, "P1234567", true, 48.1234, 14.9876, 543, 3.97, -0.5, true, 120 };
|
//SondeInfo si = { STYPE_RS41, 403.450, "P1234567", true, 48.1234, 14.9876, 543, 3.97, -0.5, true, 120 };
|
||||||
|
const char *sondeTypeStr[5] = { "DFM6", "DFM9", "RS41" };
|
||||||
|
|
||||||
static unsigned char kmh_tiles[] U8X8_PROGMEM = {
|
static unsigned char kmh_tiles[] U8X8_PROGMEM = {
|
||||||
0x1F, 0x04, 0x0A, 0x11, 0x00, 0x1F, 0x02, 0x04, 0x42, 0x3F, 0x10, 0x08, 0xFC, 0x22, 0x20, 0xF8
|
0x1F, 0x04, 0x0A, 0x11, 0x00, 0x1F, 0x02, 0x04, 0x42, 0x3F, 0x10, 0x08, 0xFC, 0x22, 0x20, 0xF8
|
||||||
|
@ -13,14 +16,108 @@ static unsigned char kmh_tiles[] U8X8_PROGMEM = {
|
||||||
static unsigned char ms_tiles[] U8X8_PROGMEM = {
|
static unsigned char ms_tiles[] U8X8_PROGMEM = {
|
||||||
0x1F, 0x02, 0x04, 0x02, 0x1F, 0x40, 0x20, 0x10, 0x08, 0x04, 0x12, 0xA4, 0xA4, 0xA4, 0x40, 0x00
|
0x1F, 0x02, 0x04, 0x02, 0x1F, 0x40, 0x20, 0x10, 0x08, 0x04, 0x12, 0xA4, 0xA4, 0xA4, 0x40, 0x00
|
||||||
};
|
};
|
||||||
|
static unsigned char stattiles[4][4] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00 ,
|
||||||
|
0x00, 0x10, 0x10, 0x00 ,
|
||||||
|
0x1F, 0x15, 0x15, 0x00 ,
|
||||||
|
0x00, 0x1F, 0x00, 0x00 };
|
||||||
|
|
||||||
|
byte myIP_tiles[8*10];
|
||||||
|
|
||||||
|
static const uint8_t font[10][5]={
|
||||||
|
0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
|
||||||
|
0x00, 0x42, 0x7F, 0x40, 0x00, // 1
|
||||||
|
0x42, 0x61, 0x51, 0x49, 0x46, // 2
|
||||||
|
0x21, 0x41, 0x45, 0x4B, 0x31, // 3
|
||||||
|
0x18, 0x14, 0x12, 0x7F, 0x10, // 4
|
||||||
|
0x27, 0x45, 0x45, 0x45, 0x39, // 5
|
||||||
|
0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
|
||||||
|
0x01, 0x01, 0x79, 0x05, 0x03, // 7
|
||||||
|
0x36, 0x49, 0x49, 0x49, 0x36, // 8
|
||||||
|
0x06, 0x49, 0x39, 0x29, 0x1E }; // 9; .=0x40
|
||||||
|
|
||||||
|
static uint8_t halfdb_tile[8]={0x80, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x00};
|
||||||
|
static uint8_t empty_tile[8]={0x80, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00};
|
||||||
|
|
||||||
|
|
||||||
|
void Sonde::setIP(const char *ip) {
|
||||||
|
int tp = 0;
|
||||||
|
int len = strlen(ip);
|
||||||
|
for(int i=0; i<len; i++) {
|
||||||
|
if(ip[i]=='.') { myIP_tiles[tp++]=0x40; myIP_tiles[tp++]=0x00; }
|
||||||
|
else {
|
||||||
|
int idx = ip[i]-'0';
|
||||||
|
memcpy(myIP_tiles+tp, &font[idx], 5);
|
||||||
|
myIP_tiles[tp+5] = 0;
|
||||||
|
tp+=6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(tp<8*10) { myIP_tiles[tp++]=0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonde::clearSonde() {
|
||||||
|
nSonde = 0;
|
||||||
|
}
|
||||||
|
void Sonde::addSonde(float frequency, SondeType type) {
|
||||||
|
if(nSonde>=MAXSONDE) {
|
||||||
|
Serial.println("Cannot add another sonde, MAXSONDE reached");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sondeList[nSonde].type = type;
|
||||||
|
sondeList[nSonde].freq = frequency;
|
||||||
|
memcpy(sondeList[nSonde].rxStat, "\x00\x01\x2\x3\x2\x1\x1\x2\x0\x3\x0\x0\x1\x2\x3\x1\x0", 18);
|
||||||
|
nSonde++;
|
||||||
|
}
|
||||||
|
void Sonde::nextConfig() {
|
||||||
|
currentSonde++;
|
||||||
|
if(currentSonde>=nSonde) {
|
||||||
|
currentSonde=0;
|
||||||
|
}
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
SondeInfo *Sonde::si() {
|
||||||
|
return &sondeList[currentSonde];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonde::setup() {
|
||||||
|
// Test only: setIP("123.456.789.012");
|
||||||
|
// update receiver config: TODO
|
||||||
|
Serial.print("Setting up receiver on channel ");
|
||||||
|
Serial.println(currentSonde);
|
||||||
|
switch(sondeList[currentSonde].type) {
|
||||||
|
case STYPE_RS41:
|
||||||
|
rs41.setup();
|
||||||
|
rs41.setFrequency(sondeList[currentSonde].freq * 1000000);
|
||||||
|
break;
|
||||||
|
case STYPE_DFM06:
|
||||||
|
case STYPE_DFM09:
|
||||||
|
dfm.setup( sondeList[currentSonde].type==STYPE_DFM06?0:1 );
|
||||||
|
dfm.setFrequency(sondeList[currentSonde].freq * 1000000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Update display
|
||||||
|
//updateDisplayRXConfig();
|
||||||
|
//updateDisplay();
|
||||||
|
}
|
||||||
|
int Sonde::receiveFrame() {
|
||||||
|
int ret;
|
||||||
|
if(sondeList[currentSonde].type == STYPE_RS41) {
|
||||||
|
ret = rs41.receiveFrame();
|
||||||
|
} else {
|
||||||
|
ret = dfm.receiveFrame();
|
||||||
|
}
|
||||||
|
memmove(sonde.si()->rxStat+1, sonde.si()->rxStat, 17);
|
||||||
|
sonde.si()->rxStat[0] = ret==0 ? 3 : 1; // OK or Timeout; TODO: add error (2)
|
||||||
|
return ret; // 0: OK, 1: Timeuot, 2: Other error (TODO)
|
||||||
|
}
|
||||||
|
|
||||||
void Sonde::updateDisplayPos() {
|
void Sonde::updateDisplayPos() {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
u8x8.setFont(u8x8_font_7x14_1x2_r);
|
u8x8.setFont(u8x8_font_7x14_1x2_r);
|
||||||
if(si.validPos) {
|
if(si()->validPos) {
|
||||||
snprintf(buf, 16, "%2.5f", si.lat);
|
snprintf(buf, 16, "%2.5f", si()->lat);
|
||||||
u8x8.drawString(0,2,buf);
|
u8x8.drawString(0,2,buf);
|
||||||
snprintf(buf, 16, "%2.5f", si.lon);
|
snprintf(buf, 16, "%2.5f", si()->lon);
|
||||||
u8x8.drawString(0,4,buf);
|
u8x8.drawString(0,4,buf);
|
||||||
} else {
|
} else {
|
||||||
u8x8.drawString(0,2,"<??> ");
|
u8x8.drawString(0,2,"<??> ");
|
||||||
|
@ -31,17 +128,17 @@ void Sonde::updateDisplayPos() {
|
||||||
void Sonde::updateDisplayPos2() {
|
void Sonde::updateDisplayPos2() {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||||
if(!si.validPos) {
|
if(!si()->validPos) {
|
||||||
u8x8.drawString(10,2," ");
|
u8x8.drawString(10,2," ");
|
||||||
u8x8.drawString(10,3," ");
|
u8x8.drawString(10,3," ");
|
||||||
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()->hei>999?"%5.0fm":"%3.1fm", si()->hei);
|
||||||
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);
|
||||||
snprintf(buf, 16, "%+2.1f", si.vs);
|
snprintf(buf, 16, "%+2.1f", si()->vs);
|
||||||
u8x8.drawString((10+4-strlen(buf)),4,buf);
|
u8x8.drawString((10+4-strlen(buf)),4,buf);
|
||||||
u8x8.drawTile(14,3,2,kmh_tiles);
|
u8x8.drawTile(14,3,2,kmh_tiles);
|
||||||
u8x8.drawTile(14,4,2,ms_tiles);
|
u8x8.drawTile(14,4,2,ms_tiles);
|
||||||
|
@ -49,8 +146,8 @@ void Sonde::updateDisplayPos2() {
|
||||||
|
|
||||||
void Sonde::updateDisplayID() {
|
void Sonde::updateDisplayID() {
|
||||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||||
if(si.validID) {
|
if(si()->validID) {
|
||||||
u8x8.drawString(0,1, si.id);
|
u8x8.drawString(0,1, si()->id);
|
||||||
} else {
|
} else {
|
||||||
u8x8.drawString(0,1, "nnnnnnnn ");
|
u8x8.drawString(0,1, "nnnnnnnn ");
|
||||||
}
|
}
|
||||||
|
@ -59,19 +156,48 @@ void Sonde::updateDisplayID() {
|
||||||
void Sonde::updateDisplayRSSI() {
|
void Sonde::updateDisplayRSSI() {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
u8x8.setFont(u8x8_font_7x14_1x2_r);
|
u8x8.setFont(u8x8_font_7x14_1x2_r);
|
||||||
snprintf(buf, 16, "%ddB ", si.rssi);
|
snprintf(buf, 16, "-%d ", sonde.si()->rssi/2);
|
||||||
|
int len=strlen(buf)-3;
|
||||||
|
buf[5]=0;
|
||||||
u8x8.drawString(0,6,buf);
|
u8x8.drawString(0,6,buf);
|
||||||
|
u8x8.drawTile(len,6,1,(sonde.si()->rssi&1)?halfdb_tile:empty_tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonde::updateStat() {
|
||||||
|
uint8_t *stat = si()->rxStat;
|
||||||
|
for(int i=0; i<18; i+=2) {
|
||||||
|
uint8_t tile[8];
|
||||||
|
*(uint32_t *)(&tile[0]) = *(uint32_t *)(&(stattiles[stat[i]]));
|
||||||
|
*(uint32_t *)(&tile[4]) = *(uint32_t *)(&(stattiles[stat[i+1]]));
|
||||||
|
u8x8.drawTile(7+i/2, 6, 1, tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sonde::updateDisplayRXConfig() {
|
void Sonde::updateDisplayRXConfig() {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||||
u8x8.drawString(0,0, 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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sonde::updateDisplayIP() {
|
||||||
|
u8x8.drawTile(6, 7, 10, myIP_tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probing RS41
|
||||||
|
// 40x.xxx MHz
|
||||||
|
void Sonde::updateDisplayScanner() {
|
||||||
|
char buf[16];
|
||||||
|
u8x8.setFont(u8x8_font_7x14_1x2_r);
|
||||||
|
u8x8.drawString(0, 0, "Probing");
|
||||||
|
u8x8.drawString(8, 0, sondeTypeStr[si()->type]);
|
||||||
|
snprintf(buf, 16, "%3.3f MHz", si()->freq);
|
||||||
|
u8x8.drawString(0,3, buf);
|
||||||
|
updateDisplayIP();
|
||||||
|
}
|
||||||
|
|
||||||
void Sonde::updateDisplay()
|
void Sonde::updateDisplay()
|
||||||
{
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
@ -80,6 +206,12 @@ void Sonde::updateDisplay()
|
||||||
updateDisplayPos();
|
updateDisplayPos();
|
||||||
updateDisplayPos2();
|
updateDisplayPos2();
|
||||||
updateDisplayRSSI();
|
updateDisplayRSSI();
|
||||||
|
updateStat();
|
||||||
|
updateDisplayIP();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonde::clearDisplay() {
|
||||||
|
u8x8.clearDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
Sonde sonde = Sonde();
|
Sonde sonde = Sonde();
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef Sonde_h
|
#ifndef Sonde_h
|
||||||
#define Sonde_H
|
#define Sonde_H
|
||||||
|
|
||||||
|
// RX_TIMEOUT: no header detected
|
||||||
|
// RX_ERROR: header detected, but data not decoded (crc error, etc.)
|
||||||
|
// RX_OK: header and data ok
|
||||||
|
enum RxResult { RX_OK, RX_TIMEOUT, RX_ERROR };
|
||||||
|
|
||||||
|
enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41 };
|
||||||
|
extern const char *sondeTypeStr[5];
|
||||||
|
|
||||||
typedef struct st_sondeinfo {
|
typedef struct st_sondeinfo {
|
||||||
// receiver configuration
|
// receiver configuration
|
||||||
char type[5];
|
SondeType type;
|
||||||
float freq;
|
float freq;
|
||||||
// decoded ID
|
// decoded ID
|
||||||
char id[10];
|
char id[10];
|
||||||
|
@ -16,23 +23,43 @@ typedef struct st_sondeinfo {
|
||||||
float hei;
|
float hei;
|
||||||
float vs;
|
float vs;
|
||||||
float hs;
|
float hs;
|
||||||
bool validPos;
|
float dir; // 0..360
|
||||||
|
uint8_t validPos; // bit pattern for validity of above 6 fields
|
||||||
// RSSI from receiver
|
// RSSI from receiver
|
||||||
int rssi;
|
int rssi;
|
||||||
|
uint8_t rxStat[20];
|
||||||
} SondeInfo;
|
} SondeInfo;
|
||||||
|
// rxState: 0=undef[empty] 1=timeout[.] 2=errro[E] 3=ok[1]
|
||||||
|
|
||||||
extern SondeInfo si;
|
|
||||||
|
#define MAXSONDE 10
|
||||||
|
|
||||||
class Sonde
|
class Sonde
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
int nSonde;
|
||||||
|
int currentSonde = 0;
|
||||||
|
SondeInfo sondeList[MAXSONDE+1];
|
||||||
public:
|
public:
|
||||||
|
void clearSonde();
|
||||||
|
void addSonde(float frequency, SondeType type);
|
||||||
|
void nextConfig();
|
||||||
|
void setup();
|
||||||
|
|
||||||
|
int receiveFrame();
|
||||||
|
SondeInfo *si();
|
||||||
|
|
||||||
void updateDisplayPos();
|
void updateDisplayPos();
|
||||||
void updateDisplayPos2();
|
void updateDisplayPos2();
|
||||||
void updateDisplayID();
|
void updateDisplayID();
|
||||||
void updateDisplayRSSI();
|
void updateDisplayRSSI();
|
||||||
void updateDisplayRXConfig();
|
void updateDisplayRXConfig();
|
||||||
|
void updateStat();
|
||||||
|
void updateDisplayIP();
|
||||||
void updateDisplay();
|
void updateDisplay();
|
||||||
|
void updateDisplayScanner();
|
||||||
|
void clearDisplay();
|
||||||
|
void setIP(const char *ip);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Sonde sonde;
|
extern Sonde sonde;
|
||||||
|
|
Ładowanie…
Reference in New Issue