Compare commits
No commits in common. "0.8.8" and "1.0.0" have entirely different histories.
BIN
Display.pdf
Executable file → Normal file
BIN
Display.pdf
Executable file → Normal file
Binary file not shown.
147
README.md
147
README.md
|
@ -1,9 +1,10 @@
|
|||
RadioSonde Version 0.8.8
|
||||
RadioSonde Version 1.0.0
|
||||
============================
|
||||
<img src="http://xavier.debert.free.fr/RS/TTGO.jpg" width="50%"><img src="http://xavier.debert.free.fr/RS/TTGO2.jpg" width="50%">
|
||||
<img src="http://xavier.debert.free.fr/RS/TTGO3.jpg" width="50%"><img src="http://xavier.debert.free.fr/RS/TTGO4.jpg" width="50%"><img src="http://xavier.debert.free.fr/RS/TTGO5.jpg" width="50%">
|
||||
<img src="http://xavier.debert.free.fr/RS/TTGO2.jpg" width="50%">
|
||||
<img src="http://xavier.debert.free.fr/RS/TTGO4.jpg" width="50%"><img src="http://xavier.debert.free.fr/RS/TTGO6.jpg" width="50%">
|
||||
<img src="http://xavier.debert.free.fr/RS/TTGO7.jpg" width="50%"><img src="http://xavier.debert.free.fr/RS/TTGO8.jpg" width="50%">
|
||||
<img src="http://xavier.debert.free.fr/RS/Web4.png" width="20%"><img src="http://xavier.debert.free.fr/RS/Web.png" width="20%">
|
||||
<img src="http://xavier.debert.free.fr/RS/Web3.png" width="20%"><img src="http://xavier.debert.free.fr/RS/Web2.png" width="20%">
|
||||
<img src="http://xavier.debert.free.fr/RS/Web3.png" width="20%">
|
||||
<img src="http://xavier.debert.free.fr/RS/Web5.png" width="20%"><img src="http://xavier.debert.free.fr/RS/Web6.png" width="20%">
|
||||
<img src="http://xavier.debert.free.fr/RS/Web7.png" width="20%">
|
||||
|
||||
|
@ -11,66 +12,121 @@
|
|||
Projet basé sur le travail de DL9RDZ
|
||||
====================================
|
||||
|
||||
Pour TTGO LORA 32 esp32 pico D4
|
||||
Décodage de RadioSonde RS41 and DFM06/09 et M10
|
||||
Pour TTGO LORA 32 esp32 pico D4 <br>
|
||||
Décodage de RadioSonde RS41/92 and DFM06/09/17 et M10+/20 et MP3H
|
||||
|
||||
Attention à la version de votre TTGO!
|
||||
vous devez modifier dans config.txt, le port de l'écran OLED
|
||||
- TTGO v1: SDA=4 SCL=15, RST=16
|
||||
- TTGO v2: SDA=21 SCL=22, RST=16
|
||||
Attention à la version de votre TTGO! <br>
|
||||
vous devez modifier dans config.txt, le port de l'écran OLED <br>
|
||||
- TTGO v1: SDA=4 SCL=15, RST=16 <br>
|
||||
- TTGO v2: SDA=21 SCL=22, RST=16 <br>
|
||||
- puis pour le GPS:<br>
|
||||
Lilygo esp32 GPS pin 34 Rx, 12 Tx<br>
|
||||
- puis Buzzer<br>
|
||||
par defaut 4 si gps mettre 2 <br>
|
||||
- puis led<br>
|
||||
par defaut 25 <br>
|
||||
|
||||
## Version en production 0.8.5 devel 0.8.7
|
||||
## 1ère Mise en route
|
||||
## Wifi configuration
|
||||
|
||||
## 0.8.0
|
||||
travail de refonte et réécriture du code
|
||||
Au démarrage, si aucune connexion possible du wifi paramètré, il monte un Wifi AP<br>
|
||||
le SSID et mot de passe par défaut est: Radiosonde<br>
|
||||
en mode AP, il doit être en 192.168.4.1<br>
|
||||
Une fois connécté au Wifi du TTGO<br>
|
||||
ouvrir une page web sur http://192.168.4.1<br>
|
||||
ou aussi la possibilité de mettre http://radiosonde.local<br>
|
||||
|
||||
## Version en production 1.0.0 devel 1.0.1
|
||||
|
||||
## 1.0.0
|
||||
refonte du system OS, et des pages Web<br>
|
||||
toujours avec la gestion:<br>
|
||||
- du buzzer<br>
|
||||
- du db ou smetre<br>
|
||||
- de la vbat nouvelle gestion(plus necessaire calibrage)<br>
|
||||
- suppression du mode telemetry export csv<br>
|
||||
- suppression de la bousole<br>
|
||||
- importation des RadioSonde Thank's DL9RDZ<br>
|
||||
- gestion update OTA<br>
|
||||
|
||||
## 0.9.2
|
||||
Correctif Dash SiteWeb config
|
||||
ADD API SondeHub Thank's DL9RDZ
|
||||
|
||||
## 0.9.1
|
||||
Corection RS41 <br>
|
||||
Correction DFM 06/09 <br>
|
||||
Add DFM17 <br>
|
||||
Correction for all trame recived for M10 and M20 1000ms to 1512ms,<br>
|
||||
Correction formulaire QRG, and end RS no save
|
||||
|
||||
## 0.9.0
|
||||
Add M20
|
||||
|
||||
## 0.8.8
|
||||
|
||||
Add M10+ <br>
|
||||
Add Temps restant avant impacte au sol si 99: 0. 0 soit le balon de la sonde n a pas encore éclaté, <br>
|
||||
ou les informations ne sont pas disponible actuellement <br>
|
||||
Add Test Buzzer au démarrage "Arche Perdu" Lol pour des chasseurs de sonde!<br>
|
||||
Compatible Lilygo esp32 GPS inboard pin 34 Rx, 12 Tx
|
||||
|
||||
## 0.8.7
|
||||
|
||||
correction bug Buzzer Off->On->Off <br>
|
||||
Add GainLNA RX SX1278FSK on Web config paramètre <br>
|
||||
Add update OTA Os + DataWeb <br>
|
||||
correction bugs sondmap.html <br>
|
||||
correction text upgrade Os et DataWeb <br>
|
||||
correction texte boussole S et N <br>
|
||||
correction bugs distance 4928Km si lat et lon =0 erroné <br>
|
||||
correction bugs fonction Vbat <br>
|
||||
Add Telemetry width export data.csv <br>
|
||||
Suppression µSD incompatible avec pin SX1278FSK et SPI <br>
|
||||
Add transfert Telemetry To µSD on put SD automatic
|
||||
|
||||
## 0.8.5
|
||||
|
||||
Evolution majeur du système <br>
|
||||
affichage du pourcentage de la batterie en mode scanning <br>
|
||||
création d'une fenetre Batterie, Boussole <br>
|
||||
suppresion lib et code TFT <br>
|
||||
création Azimute, elevation correction de Bugs majeur , mineur <br>
|
||||
Ajout fonction Smetre, Buzzer, QTH, Gps on off ... <br>
|
||||
mise à jour OTA <br>
|
||||
trop de modification pour toutes les expliciter!
|
||||
|
||||
## 0.8.1
|
||||
|
||||
modification de la partie Web
|
||||
|
||||
## 0.8.5
|
||||
## 0.8.0
|
||||
|
||||
Evolution majeur du système
|
||||
affichage du pourcentage de la batterie en mode scanning
|
||||
création d'une fenetre Batterie, Boussole
|
||||
suppresion lib et code TFT
|
||||
création Azimute, elevation correction de Bugs majeur , mineur
|
||||
Ajout fonction Smetre, Buzzer, QTH, Gps on off ...
|
||||
mise à jour OTA
|
||||
trop de modification pour toutes les expliciter!
|
||||
travail de refonte et réécriture du code
|
||||
|
||||
## 0.8.7
|
||||
correction bug Buzzer Off->On->Off
|
||||
Add GainLNA RX SX1278FSK on Web config paramètre
|
||||
Add update OTA Os + DataWeb
|
||||
correction bugs sondmap.html
|
||||
correction text upgrade Os et DataWeb
|
||||
correction texte boussole S et N
|
||||
correction bugs distance 4928Km si lat et lon =0 erroné
|
||||
correction bugs fonction Vbat
|
||||
Add Telemetry width export data.csv
|
||||
Suppression µSD incompatible avec pin SX1278FSK et SPI
|
||||
Add transfert Telemetry To µSD on put SD automatic
|
||||
|
||||
## 0.8.8
|
||||
Add M10+
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## Les Boutons optionnel à ajouter(souder)
|
||||
sur les GPIO 1002 et 1004
|
||||
sur les GPIO 1002 et 1004 <br>
|
||||
attention:
|
||||
|
||||
+5V--[ SW ]---GPIO----[ R1 ]---/ R1=10 ou 12KOhms
|
||||
+3.3V--[ SW ]---GPIO----[ R1 ]---/ R1=10 ou 12KOhms
|
||||
|
||||
- appuie court <1.5 seconds
|
||||
- appuie double court 0.5 seconds
|
||||
- appuie moyen 2-4 seconds
|
||||
- appuie court <1.5 seconds <br>
|
||||
- appuie double court 0.5 seconds <br>
|
||||
- appuie moyen 2-4 seconds <br>
|
||||
- appuie long >5 seconds
|
||||
|
||||
## Buzzer optionnel à ajouter(souder)
|
||||
sur les GPIO 25 ou 12 suivant le modèl
|
||||
|
||||
GPIO --[ BUZZER ]---/
|
||||
|
||||
## Wifi configuration
|
||||
|
||||
Au démarrage, si aucune connexion possible au wifi paramètré, il monte un Wifi AP
|
||||
le SSID et mot de passe par défaut est: Radiosonde
|
||||
en mode AP, il doit être en 192.168.4.1,
|
||||
Au démarrage, si aucune connexion possible au wifi paramètré, il monte un Wifi AP<br>
|
||||
le SSID et mot de passe par défaut est: <b>Radiosonde</b> <br>
|
||||
en mode AP, il doit être en 192.168.4.1, <br>
|
||||
mais vous avez aussi la possibilité de mettre http://radiosonde.local dans n'importe quel Wifi
|
||||
connecté.
|
||||
|
||||
|
@ -108,4 +164,3 @@ voir Setup.md pour l'installation!
|
|||
73
|
||||
Xavier
|
||||
|
||||
|
||||
|
|
3874
RX_FSK/RX_FSK.ino
Normal file
3874
RX_FSK/RX_FSK.ino
Normal file
File diff suppressed because it is too large
Load Diff
BIN
RX_FSK/data.tar
Normal file
BIN
RX_FSK/data.tar
Normal file
Binary file not shown.
1
RX_FSK/data/GPSRESET
Normal file
1
RX_FSK/data/GPSRESET
Normal file
|
@ -0,0 +1 @@
|
|||
+
|
177
RX_FSK/data/cfg.js
Normal file
177
RX_FSK/data/cfg.js
Normal file
|
@ -0,0 +1,177 @@
|
|||
var cfgs = [
|
||||
[ "", "General configuration", "" ],
|
||||
[ "wifi", "Wifi mode (0=off, 1=client, 2=AP, 3=client or AP autoselect on startup)" ],
|
||||
[ "mdnsname", "Network mDNS name"],
|
||||
[ "ephftp", "FTP server for ephemeris data (RS92 decoder)"],
|
||||
[ "debug", "Debug mode (0/1)" ],
|
||||
[ "maxsonde", "Maximum number of QRG entries (must be ≤ 50)" ],
|
||||
[ "rxlat", "Receiver fixed latitude"],
|
||||
[ "rxlon", "Receiver fixed longitude"],
|
||||
[ "rxalt", "Receiver fixed altitude"],
|
||||
[ "", "OLED display configuration", "" ],
|
||||
[ "screenfile", "Screen config (0=automatic; 1-2=OLED predefined; other=custom)" ],
|
||||
[ "display", "Display screens (scan, default, ...)" ],
|
||||
[ "dispsaver", "Display saver (0=never/1=always/2=ifnorx [+10*n: after n sec.])" ],
|
||||
[ "dispcontrast", "OLED contrast (-1=use default; 0..255=set contrast)" ],
|
||||
[ "norx_timeout", "No-RX-timeout in seconds (-1=disabled)"],
|
||||
[ "", "Spectrum display configuration", "" ],
|
||||
[ "spectrum", "Show spectrum on start (-1=no, 0=forever, >0=time [sec])" ],
|
||||
[ "startfreq", "Start frequency (MHz, default 400)" ],
|
||||
[ "channelbw", "Bandwidth (kHz)" ],
|
||||
[ "marker", "Spectrum MHz marker" ], // maybe remove, assume always ==1?
|
||||
[ "noisefloor", "Spectrum noisefloor" ],
|
||||
[ "", "Receiver configuration", "" ],
|
||||
[ "freqofs", "RX frequency offset (Hz)"],
|
||||
[ "rs41.agcbw", "RS41 AGC bandwidth"],
|
||||
[ "rs41.rxbw", "RS41 RX bandwidth"],
|
||||
[ "rs92.rxbw", "RS92 RX (and AGC) bandwidth"],
|
||||
[ "rs92.alt2d", "RS92 2D fix default altitude"],
|
||||
[ "dfm.agcbw", "DFM AGC bandwidth"],
|
||||
[ "dfm.rxbw", "DFM RX bandwidth"],
|
||||
[ "m10m20.agcbw", "M10/M20 AGC bandwidth"],
|
||||
[ "m10m20.rxbw", "M10/M20 RX bandwidth"],
|
||||
[ "mp3h.agcbw", "MP3H AGC bandwidth"],
|
||||
[ "mp3h.rxbw", "MP3H RX bandwidth"],
|
||||
[ "", "KISS TNC/AXUDP/AXTCP data feed configuration", ""],
|
||||
[ "call", "Call"],
|
||||
[ "passcode", "Passcode"],
|
||||
[ "kisstnc.active", "KISS TNC (port 14590) (needs reboot)"],
|
||||
[ "axudp.active", "AXUDP active"],
|
||||
[ "axudp.host", "AXUDP host"],
|
||||
[ "axudp.port", "AXUDP port"],
|
||||
[ "axudp.highrate", "Rate limit"],
|
||||
[ "tcp.active", "APRS TCP active"],
|
||||
[ "tcp.host", "APRS TCP host"],
|
||||
[ "tcp.port", "APRS TCP port"],
|
||||
[ "tcp.highrate", "Rate limit"],
|
||||
[ "tcp.objcall", "APRS object call"],
|
||||
[ "tcp.beaconsym", "APRS tracker symbol"],
|
||||
[ "tcp.chase", "APRS location reporting (0=off, 1=fixed, 2=chase/GPS, 3=auto)"],
|
||||
[ "tcp.comment", "APRS location comment"],
|
||||
[ "", "MQTT data feed configuration", ""],
|
||||
[ "mqtt.active", "MQTT active (needs reboot)"],
|
||||
[ "mqtt.id", "MQTT client ID"],
|
||||
[ "mqtt.host", "MQTT server hostname"],
|
||||
[ "mqtt.port", "MQTT port"],
|
||||
[ "mqtt.username", "MQTT username"],
|
||||
[ "mqtt.password", "MQTT password"],
|
||||
[ "mqtt.prefix", "MQTT prefix"],
|
||||
[ "", "Chasemapper settings", ""],
|
||||
[ "cm.active", "Chasemapper active (0=disabled, 1=active)"],
|
||||
[ "cm.host", "Chasemapper UDP host"],
|
||||
[ "cm.port", "Chasemapper UDP port"],
|
||||
[ "", "SondeHub settings", ""],
|
||||
[ "sondehub.active", "SondeHub reporting (0=disabled, 1=active)"],
|
||||
[ "sondehub.chase", "SondeHub location reporting (0=off, 1=fixed, 2=chase/GPS, 3=auto)"],
|
||||
[ "sondehub.host", "SondeHub host (DO NOT CHANGE)"],
|
||||
[ "sondehub.callsign", "Callsign"],
|
||||
[ "sondehub.antenna", "Antenna (optional, visisble on SondeHub tracker)"],
|
||||
[ "sondehub.email", "SondeHub email (optional, only used to contact in case of upload errors)"],
|
||||
[ "", "SondeHub frequency import", "" ],
|
||||
[ "sondehub.fiactive", "SondeHub frequency import active (0=disabled, 1=active)" ],
|
||||
[ "sondehub.fiinterval", "Import frequency (minutes, ≥ 5)" ],
|
||||
[ "sondehub.fimaxdist", "Import maximum distance (km, ≤ 700)" ],
|
||||
[ "sondehub.fimaxage", "Import maximum age (hours, ≤ 48)" ],
|
||||
[ "", "Hardware configuration (requires reboot)", ""],
|
||||
[ "disptype", "Display type (0=OLED/SSD1306, 2=OLED/SH1106, 5=ST7789)"],
|
||||
[ "oled_sda", "OLED SDA/TFT SDA"],
|
||||
[ "oled_scl", "OLED SCL/TFT CLK"],
|
||||
[ "oled_rst", "OLED RST/TFT RST (needs reboot)"],
|
||||
[ "button_pin", "Button input port"],
|
||||
[ "button2_pin", "Button 2 input port"],
|
||||
[ "button2_axp", "Use AXP192 PWR as Button 2"],
|
||||
[ "touch_thresh", "Touch button threshold<br>(0 for calib mode)"],
|
||||
[ "power_pout", "Power control port"],
|
||||
[ "led_pout", "LED output port (25)"],
|
||||
|
||||
["buzzerOn", "Buzzer (0=Disabled, 1 Enable)"],
|
||||
["buzzerPort", "Buzzer Port (4)"],
|
||||
["buzzerFreq", "Buzzer Frequency (700)"],
|
||||
["dbsmetre", "dB = 0 / Smetre =1)"],
|
||||
["degdec", "Lat,Lon Decimal =0 ou Degres =1)"],
|
||||
|
||||
[ "gps_rxd", "GPS RXD pin (-1 to disable)"],
|
||||
[ "gps_txd", "GPS TXD pin (not really needed)"],
|
||||
[ "batt_adc", "Battery measurement pin"],
|
||||
[ "sx1278_ss", "SX1278 SS"],
|
||||
[ "sx1278_miso", "SX1278 MISO"],
|
||||
[ "sx1278_mosi", "SX1278 MOSI"],
|
||||
[ "sx1278_sck", "SX1278 SCK"],
|
||||
];
|
||||
|
||||
function mkcfg(id, key, label, value) {
|
||||
var s = "<tr style=\"visibility: collapse;\" class=\"cfgpanel\"><td>" + label + "</td><td><input name=\"" + key + "\" type=\"text\" value=\"" + value + "\"/></td></tr>\n";
|
||||
return s;
|
||||
}
|
||||
function mkcfgbtn(id, key, label, value) {
|
||||
var touch = "";
|
||||
var v = value;
|
||||
if(v != -1 && (v&128)) {
|
||||
touch = " checked";
|
||||
v = v & 127;
|
||||
}
|
||||
var s = "<tr style=\"visibility:collapse\" class=\"cfgpanel\"><td>" + label + "</td><td><input name=\"" + key + "\" type=\"text\" size=\"3\" value=\"" + v + "\"/>";
|
||||
s += "<input type=\"checkbox\" name=\"" + key + "#\" "+touch+"> Touch</td></tr>\n";
|
||||
return s;
|
||||
}
|
||||
|
||||
function mksep(id,label,url) {
|
||||
return "<tr class=\"cfgheader\"><th class=\"cfg\" align=\"left\" colspan=\"2\">"+label+" <a href=\""+url+"\" target=\”_blank\">[wiki]</a></th></tr>\n";
|
||||
}
|
||||
function rowdisp(id,disp) {
|
||||
var matches = document.querySelectorAll("tr."+id);
|
||||
matches.forEach(function(e) { if(disp) e.hidden=true; else e.removeAttribute('hidden');});
|
||||
hid=id; nid="N"+id;
|
||||
if(!disp) { hid=nid; nid=id; }
|
||||
document.querySelector("span."+hid).hidden=true;
|
||||
document.querySelector("span."+nid).removeAttribute('hidden');
|
||||
}
|
||||
function configTable() {
|
||||
// iterate over cfgs
|
||||
var tab = "<table width=\"100%\"><tr><th>Option</th><th>Value</th></tr>\n";
|
||||
var id=0;
|
||||
for(i=0; i<cfgs.length; i++) {
|
||||
var key = cfgs[i][0];
|
||||
var lbl = cfgs[i][1];
|
||||
if(key) {
|
||||
if(key=="button_pin" || key=="button2_pin") {
|
||||
tab += mkcfgbtn("s"+id, key, lbl, cf.get(key));
|
||||
} else if (key=="display") {
|
||||
tab += mkcfg("s"+id, key, lbl, cf.get(key));
|
||||
tab += "<tr style=\"visibility:collapse\" class=\"cfgpanel\"><td>"+scr+"</td><td></td></tr>"
|
||||
} else {
|
||||
tab += mkcfg("s"+id, key, lbl, cf.get(key));
|
||||
}
|
||||
} else {
|
||||
id++;
|
||||
tab += mksep("s"+id, lbl, cfgs[i][2]);
|
||||
}
|
||||
}
|
||||
tab += "</table>";
|
||||
var cfgdiv = document.getElementById("cfgtab");
|
||||
cfgdiv.innerHTML = tab;
|
||||
// enable collapse / expand of items below a header
|
||||
var acc = document.getElementsByClassName("cfgheader");
|
||||
for(i=0; i<acc.length; i++) {
|
||||
acc[i].firstChild.innerHTML = "[+] " + acc[i].firstChild.innerHTML;
|
||||
acc[i].addEventListener("click", function(e) {
|
||||
if(e.target.nodeName=="A") return;
|
||||
achar = "[+]";
|
||||
if(this.classList.toggle("active")) achar = "[\u2212]";
|
||||
this.firstChild.innerHTML = achar + this.firstChild.innerHTML.substring(3);
|
||||
var panel = this;
|
||||
console.log(panel);
|
||||
while( panel = panel.nextElementSibling) {
|
||||
console.log(panel);
|
||||
if ( panel.className!="cfgpanel") { break; }
|
||||
if(panel.style.visibility==="collapse") {
|
||||
panel.style.visibility="visible";
|
||||
} else {
|
||||
console.log("none");
|
||||
panel.style.visibility="collapse";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
acc[0].click();
|
||||
}
|
94
RadioSonde_FSK/data/config.txt → RX_FSK/data/config.txt
Executable file → Normal file
94
RadioSonde_FSK/data/config.txt → RX_FSK/data/config.txt
Executable file → Normal file
|
@ -2,8 +2,8 @@
|
|||
# Hardware depending settings
|
||||
#-------------------------------#
|
||||
# pin: 255=disabled; x=button x+128=touch button
|
||||
#button_pin=2
|
||||
#button2_pin=4
|
||||
#button_pin=130
|
||||
#button2_pin=142
|
||||
# No specification in config file: try autodetection (gpio4 pin level at startup)
|
||||
#button_pin=0
|
||||
#button2_pin=255
|
||||
|
@ -22,15 +22,12 @@
|
|||
#oled_sda=21
|
||||
#oled_scl=22
|
||||
#oled_rst=16
|
||||
rxlat=
|
||||
rxlon=
|
||||
rxalt=
|
||||
oled_orient=1
|
||||
gpsOn=0
|
||||
gps_rxd=-1
|
||||
gps_txd=-1
|
||||
gps_lat=43.59169
|
||||
gps_lon=7.10071
|
||||
gps_alt=123
|
||||
# Show AFC value (for RS41 only, maybe also DFM, but useful for RS92 or M10)
|
||||
# showafc=1
|
||||
#gps_rxd=-1
|
||||
#gps_txd=-1
|
||||
# Frequency correction, in Hz
|
||||
# freqofs=0
|
||||
#-------------------------------#
|
||||
|
@ -42,35 +39,39 @@ debug=0
|
|||
wifi=3
|
||||
# TCP/IP KISS TNC in port 14590 for APRSdroid (0=disabled, 1=enabled)
|
||||
kisstnc.active = 1
|
||||
mdnsname=radiosonde
|
||||
|
||||
# which screens file to use (0: automated selection based on display type and orientation, i>0: screens${i}.txt
|
||||
# predefined: 1: for OLED, 2: for ILI9225; 3: for ILI9225 (portrait mode); 4: for ILI9431; 5: for ILI9431 (portrait mode)
|
||||
# screenfile=2
|
||||
# display configuration. List of "displays"
|
||||
# first entry: "Scanner" display
|
||||
# second entry: default "Receiver" display
|
||||
# additional entries: alternative receiver display, activated by button
|
||||
display=0,1,2,3,4,5,6
|
||||
display=0,1,2,3,4,5,6,7
|
||||
# turn off display: 0=never, 1=always, 2=if no RX; (+n*10: after n seconds)
|
||||
dispsaver=0
|
||||
# set OLED contrast (0..255) or leave at factory default (-1)
|
||||
dispcontrast=-1
|
||||
# set to -1 to disable (used for "N" values in timers in screens.txt). Value in seconds
|
||||
norx_timeout=20
|
||||
vbatmax=1.86
|
||||
vbatmin=1.64
|
||||
telemetryOn=0
|
||||
buzzerOn=0
|
||||
buzzerPort=12
|
||||
#Add F4IYT
|
||||
buzzerOn=1
|
||||
buzzerPort=25
|
||||
buzzerFreq=700
|
||||
dbsmetre=1
|
||||
gainLNA=0
|
||||
#-------------------------------#
|
||||
# Spectrum display settings
|
||||
#-------------------------------#
|
||||
startfreq=400
|
||||
channelbw=10
|
||||
spectrum=30 #10
|
||||
spectrum=-1 #10
|
||||
noisefloor=-125
|
||||
marker=1
|
||||
#-------------------------------#
|
||||
# APRS settings
|
||||
#-------------------------------#
|
||||
call=FR2013
|
||||
passcode=14003
|
||||
call=N0CALL
|
||||
passcode=12345
|
||||
#-------------------------------#
|
||||
# Sonde specific settings: bandwidth
|
||||
# valid values: 3100, 3900, 5200, 6300, 7800, 10400, 12500,
|
||||
|
@ -85,26 +86,65 @@ rs92.alt2d=480
|
|||
dfm.agcbw=20800
|
||||
dfm.rxbw=10400
|
||||
#-------------------------------#
|
||||
# ftp server for RINEX data (for RS92)
|
||||
# YYYY/DDD/brdcDDD0.YYn.gz is appended
|
||||
# s1: igs.bkg.bund.de/IGS/BRDC/
|
||||
# s2: www.ngs.noaa.gov/cors/rinex/
|
||||
#-------------------------------#
|
||||
#ephftp=www.ngs.noaa.gov/cors/rinex/
|
||||
#ephftp=igs.bkg.bund.de/IGS/BRDC/
|
||||
ephftp=gssc.esa.int/gnss/data/daily/
|
||||
#-------------------------------#
|
||||
# axudp for sending to aprsmap
|
||||
#-------------------------------#
|
||||
# local use only, do not feed to public services
|
||||
# data not sanitized / quality checked, outliers not filtered out
|
||||
axudp.active=1
|
||||
axudp.host=fra1od.fr.to
|
||||
axudp.port=14580
|
||||
axudp.host=192.168.42.20
|
||||
axudp.port=9002
|
||||
axudp.symbol=/O
|
||||
axudp.highrate=1
|
||||
axudp.idformat=0
|
||||
#-------------------------------#
|
||||
# maybe some time in the future
|
||||
# connect to some aprs server
|
||||
#-------------------------------#
|
||||
# currently simply not implemented, no need to put anything here anyway
|
||||
tcp.active=0
|
||||
tcp.host=radiosondy.info
|
||||
tcp.port=14590
|
||||
tcp.symbol=/O
|
||||
tcp.highrate=20
|
||||
tcp.idformat=0
|
||||
# send beacon (possibly with different call or SSID)
|
||||
tcp.chase=0
|
||||
tcp.objcall=
|
||||
tcp.beaconsym=/`/(
|
||||
tcp.comment=
|
||||
#-------------------------------#
|
||||
# mqtt settings
|
||||
#-------------------------------#
|
||||
# data not sanitized / quality checked, outliers not filtered out
|
||||
mqtt.active=0
|
||||
mqtt.id=rdz_sonde_server
|
||||
mqtt.ip=192.168.1.5
|
||||
mqtt.port=1883
|
||||
mqtt.username=
|
||||
mqtt.password=
|
||||
mqtt.prefix=rdz_sonde_server/
|
||||
#-------------------------------#
|
||||
# Sondehub v2 settings
|
||||
#-------------------------------#
|
||||
# Sondehub v2 DB settings
|
||||
sondehub.active=0
|
||||
sondehub.chase=3
|
||||
sondehub.host=api.v2.sondehub.org
|
||||
sondehub.callsign=CHANGEME_RDZTTGO
|
||||
sondehub.antenna=
|
||||
sondehub.email=
|
||||
#-------------------------------#
|
||||
# Sondehub freq import settings
|
||||
#-------------------------------#
|
||||
shfimp.active=0
|
||||
shfimp.interval=60
|
||||
shfimp.maxdist=150
|
||||
shfimp.maxage=6
|
||||
#-------------------------------#
|
||||
# EOF
|
||||
#-------------------------------#
|
|
@ -23,11 +23,11 @@
|
|||
<button class="tablinks fa fa-dashboard" onclick="selTab(event,'QRG'); w3_close()" id="defaultTab"> QRG</button><br>
|
||||
<button class="tablinks fa fa-wifi" onclick="selTab(event,'WiFi'); w3_close()"> WiFi</button><br>
|
||||
<button class="tablinks fa fa-database" onclick="selTab(event,'Data'); w3_close()"> Data</button><br>
|
||||
<button class="tablinks fa fa-map-marker" onclick="selTab(event,'SondeMap'); w3_close()"> URL SondeMap</button><br>
|
||||
<button class="tablinks fa fa-map-marker" onclick="selTab(event,'Map'); w3_close()"> Map</button><br>
|
||||
<button class="tablinks fa fa-map-marker" onclick="document.location.href='livemap.html'"> Livemap</button><br>
|
||||
<button class="tablinks fa fa-gears" onclick="selTab(event,'Config'); w3_close()"> Config</button><br>
|
||||
<button class="tablinks fa fa-sliders" onclick="selTab(event,'Control'); w3_close()"> Control</button><br>
|
||||
<button class="tablinks fa fa-download" onclick="selTab(event,'Update'); w3_close()"> Update</button><br>
|
||||
<button class="tablinks fa fa-file" onclick="selTab(event,'Telemetry'); w3_close()"> Telemetry</button><br>
|
||||
<button class="tablinks fa fa-support" onclick="selTab(event,'About'); w3_close()"> About</button><br><br><br><br>
|
||||
</nav>
|
||||
|
||||
|
@ -46,8 +46,12 @@
|
|||
<iframe src="status.html" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="SondeMap" class="tabcontent" data-src="sondemap.html">
|
||||
<iframe src="sondemap.html" style="border:none;" width="98%%" height="98%%"></iframe>
|
||||
<div id="Map" class="tabcontent" data-src="map.html">
|
||||
<iframe src="map.html" style="border:none;" width="98%%" height="98%%"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="LiveMap" class="tabcontent" data-src="livemap.html">
|
||||
<iframe src="livemap.html" style="border:none;" width="98%%" height="98%%"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="Config" class="tabcontent">
|
||||
|
@ -69,21 +73,29 @@
|
|||
<button onclick="javascript:window.open('/download','_self');">Telemetry</button>
|
||||
</div>
|
||||
<div id="About" class="tabcontent">
|
||||
<h3>About</h3>
|
||||
%VERSION_NAME%<br>
|
||||
Copyright © 2019 by Hansi Reiser, DL9RDZ<br>
|
||||
(version %VERSION_ID%)<br>
|
||||
with mods by <a href="https://www.dl2mf.de/" target="_blank">Meinhard Guenther, DL2MF</a><br>
|
||||
CopyLeft 2020-2022 Modifier par <a href="http://openpmr.fr.nf/">Xav, FRS2013</a> & Vigor<br>
|
||||
<a href="#Update">Check for update (requires TTGO internet connection via WiFi)</a><br><br>
|
||||
<br>
|
||||
(version %VERSION_ID%)
|
||||
<br>
|
||||
Original project by Hansi<br>
|
||||
Copyright © 2019-2022 by Hansi Reiser, DL9RDZ<br>
|
||||
<br><br>
|
||||
Autodetect info: %AUTODETECT_INFO%<br>
|
||||
<br>
|
||||
CopyLeft 2020 Modifier par <a href="http://openpmr.cla.fr">FRS2013</a><br>
|
||||
Licence GNU GPL <a href="https://www.gnu.org/licenses/gpl-2.0.txt">https://www.gnu.org/licenses/gpl-2.0.txt</a>
|
||||
for details
|
||||
RS92 RINEX eph state: %EPHSTATE%<br>
|
||||
<br>
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.<br>
|
||||
See <a href="https://www.gnu.org/licenses/gpl-2.0.txt">https://www.gnu.org/licenses/gpl-2.0.txt</a>
|
||||
for details.
|
||||
</div>
|
||||
|
||||
<div style="background-color: #008CBA;"><br>
|
||||
<h2>by FRS2013</h2>
|
||||
<div class="footer"><span></span><span class="ttgoinfo">RadioSonde %VERSION_ID%</span></div>
|
||||
</div>
|
||||
<script>
|
||||
function selTab(evt, id) {
|
18
RX_FSK/data/livemap.html
Normal file
18
RX_FSK/data/livemap.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>RadioSonde LiveMap</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
<link rel="stylesheet" type="text/css" href="style_map.css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css" />
|
||||
<script>var mapcenter=[%MAPCENTER%];</script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js"></script>
|
||||
<script src="https://unpkg.com/leaflet.marker.slideto@0.2.0/Leaflet.Marker.SlideTo.js"></script>
|
||||
<script src="livemap.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
</body>
|
||||
</html>
|
530
RX_FSK/data/livemap.js
Normal file
530
RX_FSK/data/livemap.js
Normal file
|
@ -0,0 +1,530 @@
|
|||
try {
|
||||
var check = $(document);
|
||||
} catch (e) {
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
document.getElementById('map').innerHTML = '<br /><br />In order to use this functionality, there must be an internet connection.<br /><br/><a href="livemap.html">retry</a><br /><br/><a href="index.html">go back</a>';
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
var map = L.map('map', { attributionControl: false, zoomControl: false });
|
||||
map.on('mousedown touchstart',function () { follow=false; });
|
||||
|
||||
L.control.scale().addTo(map);
|
||||
L.control.attribution({prefix:false}).addTo(map);
|
||||
|
||||
var osmlight = L.tileLayer('https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
});
|
||||
|
||||
var osmdark = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||
maxZoom: 19
|
||||
});
|
||||
|
||||
var opentopo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 17,
|
||||
attribution: 'Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a><br />Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
|
||||
});
|
||||
|
||||
var esri = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
||||
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye,<br />Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community',
|
||||
maxZoom: 21
|
||||
});
|
||||
|
||||
var basemap;
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
map.addLayer(osmdark);
|
||||
basemap='osmdark';
|
||||
} else {
|
||||
map.addLayer(osmlight);
|
||||
basemap='osmlight';
|
||||
}
|
||||
|
||||
basemap_change = function () {
|
||||
if (basemap == 'osmlight') {
|
||||
map.removeLayer(osmlight);
|
||||
map.addLayer(opentopo);
|
||||
basemap = 'opentopo';
|
||||
} else if (basemap == 'opentopo') {
|
||||
map.removeLayer(opentopo);
|
||||
map.addLayer(esri);
|
||||
basemap = 'esri';
|
||||
} else if (basemap == 'esri') {
|
||||
map.removeLayer(esri);
|
||||
map.addLayer(osmdark);
|
||||
basemap = 'osmdark';
|
||||
} else {
|
||||
map.removeLayer(osmdark);
|
||||
map.addLayer(osmlight);
|
||||
basemap = 'osmlight';
|
||||
}
|
||||
};
|
||||
|
||||
if(mapcenter) map.setView(mapcenter, 5);
|
||||
else map.setView([51.163361,10.447683], 5); // Mitte DE
|
||||
|
||||
var reddot = '<span class="ldot rbg"></span>';
|
||||
var yellowdot = '<span class="ldot ybg"></span>';
|
||||
var greendot = '<span class="ldot gbg"></span>';
|
||||
var lastframe = 0;
|
||||
|
||||
$('#map .leaflet-control-container').append(L.DomUtil.create('div', 'leaflet-top leaflet-center leaflet-header'));
|
||||
var header = '';
|
||||
header += '<div id="sonde_main"><b>rdzTTGOSonde LiveMap</b><br />🎈 <b><span id="sonde_id"></span> - <span id="sonde_freq"></span> MHz - <span id="sonde_type"></span></b></div>';
|
||||
header += '<div id="sonde_detail"><span id="sonde_alt"></span>m | <span id="sonde_climb"></span>m/s | <span id="sonde_speed"></span>km/h | <span id="sonde_dir"></span>°<br /><span id="sonde_time"></span> | -<span id="sonde_rssi"></span>dBm</div>';
|
||||
header += '<div id="sonde_status"><span id="sonde_statbar"></span></div>';
|
||||
header += '<div id="settings"><br /><b>Prediction-Settings</b><br />';
|
||||
|
||||
header += '<label for="burst">Burst at:</label><input type="text" id="burst" maxlength="5" value="..." /> m<br />';
|
||||
header += '<label for="overwrite_descend">Descending:</label><input type="text" id="overwrite_descend" maxlength="2" value="..." /> m/s<br />';
|
||||
header += '<label for="overwrite_descend_till">Use this descending until:</label><input type="text" id="overwrite_descend_till" maxlength="5" value="..." /> m<br />';
|
||||
header += '<small>after the transmitted descend will be used</small>';
|
||||
header += '<div id="submit"><input type="button" value="save" onclick="settings_save();"/> <input type="button" id="submit" value="reset" onclick="settings_reset();"/></div>';
|
||||
header += '</div>';
|
||||
$('.leaflet-header').append(header);
|
||||
|
||||
|
||||
$('#map .leaflet-control-container').append(L.DomUtil.create('div', 'leaflet-bottom leaflet-center leaflet-footer'));
|
||||
var footer = '';
|
||||
footer += '<div id="gps_main"><b>Direction: </b><span class="gps_dir">...</span>°<br /><b>Distance: </b><span class="gps_dist">...</span>m</div>';
|
||||
$('.leaflet-footer').append(footer);
|
||||
|
||||
var statbar = '';
|
||||
headtxt = function(data,stat) {
|
||||
var staticon = (stat == '1')?greendot:yellowdot;
|
||||
statbar = staticon + statbar;
|
||||
if ((statbar.length) > 10*greendot.length) { statbar = statbar.substring(0,10*greendot.length); }
|
||||
if (data.id && data.vframe != lastframe ) {
|
||||
lastframe = data.vframe;
|
||||
$('#sonde_id').html(data.id);
|
||||
$('#sonde_alt').html(data.alt);
|
||||
$('#sonde_climb').html(data.climb);
|
||||
$('#sonde_speed').html( mr(data.speed * 3.6 * 10) / 10 );
|
||||
$('#sonde_dir').html(data.dir);
|
||||
$('#sonde_time').html(new Date(data.time * 1000).toISOString());
|
||||
$('#sonde_rssi').html(data.rssi / 2 );
|
||||
$('#sonde_detail').show();
|
||||
} else {
|
||||
if (!data.id) {
|
||||
$('#sonde_id').html(data.launchsite.trim());
|
||||
// $('#sonde_detail').hide();
|
||||
}
|
||||
}
|
||||
$('#sonde_freq').html(data.freq);
|
||||
$('#sonde_type').html(data.type);
|
||||
$('#sonde_statbar').html(' '+statbar);
|
||||
};
|
||||
|
||||
map.addControl(new L.Control.Button([ { position: 'topleft', text: '🔙', href: 'index.html' } ]));
|
||||
|
||||
L.control.zoom({ position:'topleft' }).addTo(map);
|
||||
|
||||
map.addControl(new L.Control.Button([ { position: 'topleft', text: '🗺️', href: 'javascript:basemap_change();' } ]));
|
||||
|
||||
map.addControl(new L.Control.Button([ { position: 'topright', id: "status", text: '', href: 'javascript:get_data();' } ]));
|
||||
|
||||
map.addControl(new L.Control.Button([
|
||||
{ position:'topright', text: '🎈', href: 'javascript:show(marker[last_id],\'marker\');' },
|
||||
{ text: '〰️', href: 'javascript:show_line();' },
|
||||
{ text: '💥', href: 'javascript:show(marker_burst[last_id],\'burst\');' },
|
||||
{ text: '🎯', href: 'javascript:show(marker_landing[last_id],\'landing\');' }
|
||||
]));
|
||||
|
||||
map.addControl(new L.Control.Button([ { position:'topright', text: '⚙️', href: 'javascript:show_settings();' } ]));
|
||||
|
||||
|
||||
|
||||
show = function(e,p) {
|
||||
if (p == 'landing') { get_predict(last_data); }
|
||||
if (e) {
|
||||
map.closePopup();
|
||||
map.setView(map._layers[e._leaflet_id].getLatLng());
|
||||
map._layers[e._leaflet_id].openPopup();
|
||||
follow = p;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
getTwoBounds = function (a,b) {
|
||||
var sW = new L.LatLng((a._southWest.lat > b._southWest.lat)?b._southWest.lat:a._southWest.lat, (a._southWest.lng > b._southWest.lng)?b._southWest.lng:a._southWest.lng);
|
||||
var nE = new L.LatLng((a._northEast.lat < b._northEast.lat)?b._northEast.lat:a._northEast.lat, (a._northEast.lng < b._northEast.lng)?b._northEast.lng:a._northEast.lng);
|
||||
|
||||
return new L.LatLngBounds(sW, nE);
|
||||
};
|
||||
|
||||
show_line = function() {
|
||||
$('.i_position, .i_landing').remove();
|
||||
map.closePopup();
|
||||
if (line[last_id]._latlngs.length != 0 && line_predict[last_id]._latlngs.length != 0) {
|
||||
map.fitBounds(getTwoBounds(line[last_id].getBounds(),line_predict[last_id].getBounds()));
|
||||
} else if (line[last_id]._latlngs.length != 0) {
|
||||
map.fitBounds(line[last_id].getBounds());
|
||||
} else if (line_predict[last_id]._latlngs.length != 0) {
|
||||
map.fitBounds(line_predict[last_id].getBounds());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
last_data = false;
|
||||
last_id = false;
|
||||
follow = 'marker';
|
||||
|
||||
marker_landing = [];
|
||||
icon_landing = L.divIcon({className: 'leaflet-landing'});
|
||||
dots_predict = [];
|
||||
line_predict = [];
|
||||
marker_burst = [];
|
||||
icon_burst = L.divIcon({className: 'leaflet-burst'});
|
||||
|
||||
marker = [];
|
||||
dots = [];
|
||||
line = [];
|
||||
|
||||
draw = function(data) {
|
||||
var stat;
|
||||
if (data.id) {
|
||||
last_id = data.id;
|
||||
// data.res: 0: ok 1: no rx (timeout), 2: crc err, >2 some other error
|
||||
if ((data.lat && data.lon && data.alt) && (lastframe != 0)) {
|
||||
var location = [data.lat,data.lon,data.alt];
|
||||
if (!marker[data.id]) {
|
||||
map.setView(location, 14);
|
||||
marker[data.id] = L.marker(location).addTo(map)
|
||||
.bindPopup(poptxt('position',data),{closeOnClick:false, autoPan:false}).openPopup();
|
||||
get_predict(data);
|
||||
} else {
|
||||
marker[data.id].slideTo(location, {
|
||||
duration: 500,
|
||||
keepAtCenter: (follow=='marker')?true:false
|
||||
})
|
||||
.setPopupContent(poptxt('position',data));
|
||||
}
|
||||
if (!dots[data.id]) { dots[data.id] = []; }
|
||||
dots[data.id].push(location);
|
||||
if (!line[data.id]) {
|
||||
line[data.id] = L.polyline(dots[data.id]).addTo(map);
|
||||
} else {
|
||||
line[data.id].setLatLngs(dots[data.id]);
|
||||
}
|
||||
|
||||
}
|
||||
if (data.res == 0) {
|
||||
storage_write(data);
|
||||
$('#status').html(greendot);
|
||||
stat = 1;
|
||||
} else {
|
||||
$('#status').html(yellowdot);
|
||||
stat = 0;
|
||||
}
|
||||
headtxt(data,stat);
|
||||
last_data = data;
|
||||
} else {
|
||||
$('#status').html(yellowdot);
|
||||
headtxt(data,0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
marker_gps = false;
|
||||
icon_gps = L.divIcon({className: 'leaflet-gps'});
|
||||
circ_gps = false;
|
||||
|
||||
gps = function(e) {
|
||||
gps_location = [e.lat,e.lon];
|
||||
gps_accuracy = e.hdop*2;
|
||||
|
||||
if (last_data && last_data.lat != '0.000000') {
|
||||
if ($('.leaflet-footer').css('display') == 'none') { $('.leaflet-footer').show(); }
|
||||
|
||||
var distance = Math.round(map.distance(gps_location,[last_data.lat, last_data.lon]));
|
||||
distance = (distance > 1000)?(distance / 1000) + 'k':distance;
|
||||
$('.leaflet-footer .gps_dist').html(distance);
|
||||
|
||||
$('.leaflet-footer .gps_dir').html( bearing(gps_location,[last_data.lat, last_data.lon]) );
|
||||
}
|
||||
|
||||
if (!marker_gps) {
|
||||
map.addControl(new L.Control.Button([{ position: 'topleft', text: '🛰️', href: 'javascript:show(marker_gps,\'gps\');' }]));
|
||||
|
||||
marker_gps = L.marker(gps_location,{icon:icon_gps}).addTo(map)
|
||||
.bindPopup(poptxt('gps',e),{closeOnClick:false, autoPan:false});
|
||||
circ_gps = L.circle(gps_location, gps_accuracy).addTo(map);
|
||||
} else {
|
||||
marker_gps.slideTo(gps_location, {
|
||||
duration: 500,
|
||||
keepAtCenter: (follow=='gps')?true:false
|
||||
})
|
||||
.setPopupContent(poptxt('gps',e));
|
||||
circ_gps.slideTo(gps_location, { duration: 500 });
|
||||
circ_gps.setRadius(gps_accuracy);
|
||||
}
|
||||
};
|
||||
|
||||
get_data = function() {
|
||||
$('#status').html(reddot);
|
||||
$.ajax({url: 'live.json', success: (function( data ) {
|
||||
if (typeof data != "object") { data = $.parseJSON(data); }
|
||||
if (data.sonde) {
|
||||
draw(data.sonde);
|
||||
} else {
|
||||
setTimeout(function() {$('#status').html(yellowdot);},100);
|
||||
}
|
||||
if (data.gps) {
|
||||
gps(data.gps);
|
||||
}
|
||||
}),
|
||||
timeout: 1000}
|
||||
);
|
||||
};
|
||||
|
||||
storage = (typeof(Storage) !== "undefined")?true:false;
|
||||
|
||||
settings_std = {
|
||||
burst: 32500,
|
||||
overwrite_descend: 6,
|
||||
overwrite_descend_till: 12000
|
||||
};
|
||||
|
||||
settings_read = function() {
|
||||
if (storage) {
|
||||
if (sessionStorage.settings) {
|
||||
return JSON.parse(sessionStorage.settings);
|
||||
} else {
|
||||
settings_write(settings_std);
|
||||
return settings_std;
|
||||
}
|
||||
} else {
|
||||
return settings_std;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
settings_write = function (data) {
|
||||
if (storage) {
|
||||
sessionStorage.settings = JSON.stringify(data);
|
||||
settings = data;
|
||||
}
|
||||
};
|
||||
|
||||
settings = settings_read();
|
||||
|
||||
settings_save = function() {
|
||||
settings.burst = parseInt($('#settings #burst').val());
|
||||
settings.overwrite_descend = parseInt($('#settings #overwrite_descend').val());
|
||||
settings.overwrite_descend_till = parseInt($('#settings #overwrite_descend_till').val());
|
||||
if (Number.isInteger(settings.burst) && Number.isInteger(settings.overwrite_descend) && Number.isInteger(settings.overwrite_descend_till)) {
|
||||
settings_write(settings);
|
||||
$("#settings").slideUp();
|
||||
get_predict(last_data);
|
||||
} else {
|
||||
alert('Error: only numeric values allowed!');
|
||||
}
|
||||
};
|
||||
|
||||
settings_reset = function() {
|
||||
if (confirm('Reset to default?')) {
|
||||
settings_write(settings_std);
|
||||
show_settings();
|
||||
}
|
||||
};
|
||||
|
||||
show_settings = function() {
|
||||
$('#settings #burst').val(settings.burst);
|
||||
$('#settings #overwrite_descend').val(settings.overwrite_descend);
|
||||
$('#settings #overwrite_descend_till').val(settings.overwrite_descend_till);
|
||||
$("#settings").slideToggle();
|
||||
};
|
||||
|
||||
predictor = false;
|
||||
get_predict = function(data) {
|
||||
if (!data) { return; }
|
||||
var ascent = (data.climb > 0)? data.climb : 15;
|
||||
var descent = (data.climb > 0)? settings.overwrite_descend : data.climb * -1;
|
||||
|
||||
var burst;
|
||||
if (data.climb > 0) {
|
||||
burst = (data.alt > settings.burst )?data.alt + 100 : settings.burst;
|
||||
} else {
|
||||
burst = parseInt(data.alt) + 7;
|
||||
if (data.alt > settings.overwrite_descend_till ) { descent = settings.overwrite_descend; }
|
||||
}
|
||||
|
||||
var m = new Date();
|
||||
var datetime = m.getUTCFullYear() + "-" + az(m.getUTCMonth()+1) + "-" + az(m.getUTCDate()) + "T" +
|
||||
az(m.getUTCHours()) + ":" + az(m.getUTCMinutes()) + ":" + az(m.getUTCSeconds()) + "Z";
|
||||
var url = 'https://api.v2.sondehub.org/tawhiri';
|
||||
url += '?launch_latitude='+data.lat + '&launch_longitude='+tawhiri_lon(data.lon);
|
||||
url += '&launch_altitude='+data.alt + '&launch_datetime='+datetime;
|
||||
url += '&ascent_rate='+ascent + '&burst_altitude=' + burst + '&descent_rate='+descent;
|
||||
|
||||
$.getJSON(url, function( prediction ) {
|
||||
draw_predict(prediction,data);
|
||||
});
|
||||
};
|
||||
|
||||
draw_predict = function(prediction,data) {
|
||||
var ascending = prediction.prediction[0].trajectory;
|
||||
var highest = ascending[ascending.length-1];
|
||||
var highest_location = [highest.latitude,sanitize_lon(highest.longitude)];
|
||||
|
||||
var descending = prediction.prediction[1].trajectory;
|
||||
var landing = descending[descending.length-1];
|
||||
var landing_location = [landing.latitude,sanitize_lon(landing.longitude)];
|
||||
|
||||
if (!marker_landing[data.id]) {
|
||||
marker_landing[data.id] = L.marker(landing_location,{icon: icon_landing}).addTo(map)
|
||||
.bindPopup(poptxt('landing',landing),{closeOnClick:false, autoPan:false});
|
||||
} else {
|
||||
marker_landing[data.id].slideTo(landing_location, {
|
||||
duration: 500,
|
||||
keepAtCenter: (follow=='landing')?true:false
|
||||
})
|
||||
.setPopupContent(poptxt('landing',landing));
|
||||
}
|
||||
|
||||
dots_predict[data.id]=[];
|
||||
|
||||
if (data.climb > 0) {
|
||||
ascending.forEach(p => dots_predict[data.id].push([p.latitude,sanitize_lon(p.longitude)]));
|
||||
|
||||
if (!marker_burst[data.id]) {
|
||||
marker_burst[data.id] = L.marker(highest_location,{icon:icon_burst}).addTo(map).bindPopup(poptxt('burst',highest),{closeOnClick:false, autoPan:false});
|
||||
} else {
|
||||
marker_burst[data.id].slideTo(highest_location, {
|
||||
duration: 500,
|
||||
keepAtCenter: (follow=='burst')?true:false
|
||||
}).setPopupContent(poptxt('burst',highest));
|
||||
}
|
||||
}
|
||||
|
||||
descending.forEach(p => dots_predict[data.id].push([p.latitude,sanitize_lon(p.longitude)]));
|
||||
|
||||
if (!line_predict[data.id]) {
|
||||
line_predict[data.id] = L.polyline(dots_predict[data.id],{color: 'yellow'}).addTo(map);
|
||||
} else {
|
||||
line_predict[data.id].setLatLngs(dots_predict[data.id]);
|
||||
}
|
||||
|
||||
if (data.climb > 0) {
|
||||
predictor_time = 5 * 60; // ascending, every 5 min
|
||||
} else if (data.climb < 0 && data.alt > 5000) {
|
||||
predictor_time = 2 * 60; // descending, above 5km, every 2 min
|
||||
} else {
|
||||
predictor_time = 30; // descending, below 5km, every 30 sec
|
||||
}
|
||||
clearTimeout(predictor);
|
||||
predictor = setTimeout(function() {get_predict(last_data);}, predictor_time*1000);
|
||||
};
|
||||
|
||||
sanitize_lon = function(lon) {
|
||||
if (lon > 180) { return lon - 360; }
|
||||
return lon;
|
||||
}
|
||||
tawhiri_lon = function(lon) {
|
||||
if (lon < 0) { return lon + 360; }
|
||||
return lon;
|
||||
}
|
||||
|
||||
poptxt = function(t,i) {
|
||||
var lat_input = (i.id)?i.lat:i.latitude;
|
||||
var lon_input = sanitize_lon((i.id)?i.lon:i.longitude);
|
||||
|
||||
var lat = Math.round(lat_input * 1000000) / 1000000;
|
||||
var lon = Math.round(lon_input * 1000000) / 1000000;
|
||||
|
||||
var add =
|
||||
'<br /><b>Position:</b> '+lat+', '+lon+'<br />'+
|
||||
'<b>Open:</b> <a href="https://www.google.de/maps/?q='+lat+', '+lon+'" target="_blank">GMaps</a> | <a href="https://www.openstreetmap.org/?mlat='+lat+'&mlon='+lon+'&zoom=15" target="_blank">OSM</a> | <a href="geo://'+lat+','+lon+'">GeoApp</a>';
|
||||
|
||||
if (t == 'position') { return '<div class="i_position"><b>🎈 '+i.id+'</b>'+add+'</div>'; }
|
||||
if (t == 'burst') { return '<div class="i_burst"><b>💥 Predicted Burst:</b><br />'+fd(i.datetime)+' in '+mr(i.altitude)+'m'+add+'</div>'; }
|
||||
if (t == 'highest') { return '<div class="i_burst"><b>💥 Burst:</b> '+mr(i.altitude)+'m'+add+'</div>';}
|
||||
if (t == 'landing') { return '<div class="i_landing"><b>🎯 Predicted Landing:</b><br />'+fd(i.datetime)+' at '+mr(i.altitude)+'m'+add+'</div>'; }
|
||||
if (t == 'gps') { return '<div class="i_gps">Position: '+(i.lat)+','+(i.lon)+'<br />Altitude: '+i.alt+'m<br />Speed: '+mr(i.speed * 3.6 * 10)/10+'km/h '+i.dir+'°<br />Sat: '+i.sat+' Hdop:'+(i.hdop/10)+'</div>'; }
|
||||
};
|
||||
|
||||
fd = function(date) {
|
||||
var d = new Date(Date.parse(date));
|
||||
return az(d.getUTCHours()) +':'+ az(d.getUTCMinutes())+' UTC';
|
||||
};
|
||||
az = function(n) { return (n<10)?'0'+n:n; };
|
||||
mr = function(n) { return Math.round(n); };
|
||||
|
||||
storage = (typeof(Storage) !== "undefined")?true:false;
|
||||
storage_write = function (data) {
|
||||
if (storage) {
|
||||
if (sessionStorage.sonde) {
|
||||
storage_data = JSON.parse(sessionStorage.sonde);
|
||||
} else {
|
||||
storage_data = [];
|
||||
}
|
||||
if (JSON.stringify(data) != JSON.stringify(storage_data[storage_data.length - 1])) {
|
||||
storage_data.push(data);
|
||||
sessionStorage.sonde = JSON.stringify(storage_data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
storage_read = function() {
|
||||
if (storage) {
|
||||
if (sessionStorage.sonde) {
|
||||
storage_data = JSON.parse(sessionStorage.sonde);
|
||||
return storage_data;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
storage_remove = function() {
|
||||
sessionStorage.removeItem('sonde');
|
||||
};
|
||||
|
||||
session_storage = storage_read();
|
||||
if (session_storage) {
|
||||
session_storage.forEach(function(d) {
|
||||
dots.push([d.lat,d.lon,d.alt]);
|
||||
session_storage_last = d;
|
||||
});
|
||||
draw(session_storage_last);
|
||||
}
|
||||
|
||||
setInterval(get_data,1000);
|
||||
|
||||
});
|
||||
|
||||
L.Control.Button = L.Control.extend({
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control');
|
||||
options = this.options;
|
||||
Object.keys(options).forEach(function(key) {
|
||||
this.link = L.DomUtil.create('a', '', container);
|
||||
this.link.text = options[key].text;
|
||||
this.link.href = options[key].href;
|
||||
this.link.id = options[key].id;
|
||||
});
|
||||
|
||||
this.options.position = this.options[0].position;
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// https://github.com/makinacorpus/Leaflet.GeometryUtil/blob/master/src/leaflet.geometryutil.js#L682
|
||||
// modified to fit
|
||||
function bearing(latlng1, latlng2) {
|
||||
var rad = Math.PI / 180,
|
||||
lat1 = latlng1[0] * rad,
|
||||
lat2 = latlng2[0] * rad,
|
||||
lon1 = latlng1[1] * rad,
|
||||
lon2 = latlng2[1] * rad,
|
||||
y = Math.sin(lon2 - lon1) * Math.cos(lat2),
|
||||
x = Math.cos(lat1) * Math.sin(lat2) -
|
||||
Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
|
||||
var bearing = ((Math.atan2(y, x) * 180 / Math.PI) + 360) % 360;
|
||||
bearing = bearing < 0 ? bearing-360 : bearing;
|
||||
return Math.round(bearing);
|
||||
}
|
25
RX_FSK/data/map.html
Normal file
25
RX_FSK/data/map.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<html>
|
||||
<head>
|
||||
<script>
|
||||
maptype = "SH"; // TODO: Get from config
|
||||
|
||||
const maps = {
|
||||
"WS": ["https://www.wettersonde.net/map.php", (s)=>"?sonde="+s, (lat,lon)=>""],
|
||||
"SH": ["https://sondehub.org/#!mt=Mapnik", (lat,lon)=>'&mz=7&qm=12h&mc=' + lat + ',' + lon],
|
||||
"RS": ["https://radiosondy.info/", (s)=>"sonde.php?sondenumber="+s, (lat,lon)=>""],
|
||||
"OW": ["https://v2.openwx.de/start.php", (s)=>"?sonde="+s, (lat,lon)=>"?mode=mobile"],
|
||||
};
|
||||
|
||||
|
||||
const data = {"gps_lat":45.62172,"gps_lon":7.02026};
|
||||
|
||||
urlarg = + maps[maptype][1] + data['gps_lat']+","+data['gps_lon'];
|
||||
|
||||
iftxt='<iframe src="' + maps[maptype][0] + urlarg +'" style="border:1px solid #00A3D3;border-radius:20px;height:98vh;width:100%"></iframe>';
|
||||
document.write(iftxt);
|
||||
document.getElementsByTagName('body')[0].innerHTML = iftxt;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
6
RX_FSK/data/networks.txt
Executable file
6
RX_FSK/data/networks.txt
Executable file
|
@ -0,0 +1,6 @@
|
|||
Radiosonde
|
||||
Radiosonde
|
||||
SSIDMobile
|
||||
123456
|
||||
SSIDBox
|
||||
123456
|
26
RX_FSK/data/qrg.txt
Normal file
26
RX_FSK/data/qrg.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Frequency in Mhz (format nnn.nnn)
|
||||
# Type (4=RS41, R=RS92, D=DFM (automated normal/inverted), M=M10/M20, 3=MP3H)
|
||||
# (older versions: 6=DFM6, 9=DFM9, now both treated the same as D)
|
||||
# (older versions: M=M10, 2=M20, now both treaded the same: automated M10/M20 decoding)
|
||||
# +: active, -: not active
|
||||
#
|
||||
400.000 9 + Test(FR)
|
||||
402.000 2 + Nimes(FR)
|
||||
402.800 4 + Cuneo(IT)
|
||||
403.000 6 - Ajactio(FR)
|
||||
403.200 M - OHP(FR)
|
||||
403.010 6 - Canjuers(FR)
|
||||
404.200 4 - Rome(IT)
|
||||
404.789 9 - Frejus1(FR)
|
||||
404.800 4 - Milan(IT)
|
||||
405.000 R - Frejus2(FR)
|
||||
405.789 9 - Pegomas(FR)
|
||||
403.700 4 - Cuneo2(IT)
|
||||
400.000 D -
|
||||
400.000 D -
|
||||
400.000 D -
|
||||
400.000 D -
|
||||
400.000 D -
|
||||
400.000 D -
|
||||
400.000 D -
|
||||
# end
|
54
RX_FSK/data/rdz.js
Normal file
54
RX_FSK/data/rdz.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
let stypes=new Map();
|
||||
stypes.set('4', 'RS41');
|
||||
stypes.set('R', 'RS92');
|
||||
stypes.set('D', 'DFM');
|
||||
stypes.set('M', 'M10/M20');
|
||||
stypes.set('3', 'MP3H');
|
||||
|
||||
function footer() {
|
||||
document.addEventListener("DOMContentLoaded", function(){
|
||||
var form = document.querySelector(".wrapper");
|
||||
form.addEventListener("input", function() {
|
||||
document.querySelector(".save").disabled = false;
|
||||
});
|
||||
document.querySelector(".save").disabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
/* Used by qrg.html in RX_FSK.ino */
|
||||
function prep() {
|
||||
var stlist=document.querySelectorAll("input.stype");
|
||||
for(txt of stlist){
|
||||
var val=txt.getAttribute('value'); var nam=txt.getAttribute('name');
|
||||
if(val=='2') { val='M'; }
|
||||
var sel=document.createElement('select');
|
||||
sel.setAttribute('name',nam);
|
||||
for(stype of stypes) {
|
||||
var opt=document.createElement('option');
|
||||
opt.value=stype[0];
|
||||
opt.innerHTML=stype[1];
|
||||
if(stype[0]==val) { opt.setAttribute('selected','selected'); }
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
txt.replaceWith(sel);
|
||||
}
|
||||
}
|
||||
|
||||
function qrgTable() {
|
||||
var tab=document.getElementById("divTable");
|
||||
|
||||
var table = "<table><tr><th>Ch</th><th>Active</th><th>Frequency</th><th>Decoder</th><th>Launchsite</th></tr>";
|
||||
for(i=0; i<qrgs.length; i++) {
|
||||
var ck = "";
|
||||
if(qrgs[i][0]) ck="checked";
|
||||
table += "<tr><td class=\"ch\">" + (i+1) + "</td><td class=\"act\"><input name=\"A" + (i+1) + "\" type=\"checkbox\" " + ck + "/></td>";
|
||||
table += "<td><input name=\"F" + (i+1) + "\" type=\"text\" size=7 value=\"" + qrgs[i][1] + "\"></td>";
|
||||
table += "<td><input class=\"stype\" name=\"T" + (i+1) + "\" value=\"" + qrgs[i][3] + "\"></td>";
|
||||
table += "<td><input name=\"S" + (i+1) + "\" type=\"text\" value=\"" + qrgs[i][2] +"\"></td></tr>";
|
||||
}
|
||||
table += "</table>";
|
||||
tab.innerHTML = table;
|
||||
prep();
|
||||
footer();
|
||||
}
|
||||
|
460
RX_FSK/data/screens.txt
Normal file
460
RX_FSK/data/screens.txt
Normal file
|
@ -0,0 +1,460 @@
|
|||
# Definition of display content and action behaviour
|
||||
#
|
||||
# Timer: (view timer, rx timer, norx timer)
|
||||
# - value -1: timer is disabled; value>=0: timer fires after (value) seconds
|
||||
# - view timer: time since current view (display mode and sonde) was started
|
||||
# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX)
|
||||
# - norx timer: time since when no sonde data has been received continuously
|
||||
# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving
|
||||
# anything for a 1s period)
|
||||
#
|
||||
# Actions:
|
||||
# - W: activate WiFi scan
|
||||
# - F: activate frequency spectrum display
|
||||
# - 0: activate "Scan:" display (this is basically just display mode 0)
|
||||
# - x: (1..N): activate display mode x [deprecated]
|
||||
# - >: activate next display mode
|
||||
# - D: activate default receiver display (display mode specified in config)
|
||||
# - +: advance to next active sonde from QRG config
|
||||
# - #: no action
|
||||
#
|
||||
# Display content (lower/upper case: small/large font)
|
||||
# line,column=content
|
||||
# for ILI9225 its also possible to indicate
|
||||
# line,column,width=content for text within a box of width 'width'
|
||||
# line,column,-width=content for right-justified text
|
||||
#
|
||||
# XText : Text
|
||||
# F(suffix): frequency (with suffix, e.g., " MHz")
|
||||
# L latitade
|
||||
# O lOngitute
|
||||
# A altitude
|
||||
# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only)
|
||||
# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number)
|
||||
# RS41,RS92: all identical R1234567
|
||||
# DFMx: ID M12345678; short ID and serial 12345678
|
||||
# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592
|
||||
# Q signal quality statistics bar
|
||||
# T type string (RS41/DFM9/DFM6/RS92)
|
||||
# C afC value
|
||||
# N ip address (only tiny font)
|
||||
# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t
|
||||
# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown
|
||||
# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde
|
||||
# Mx telemetry value x (t temp p preassure h hyg) [not yet implemented, maybe some day in future]
|
||||
# Gx GPS-related data
|
||||
# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground
|
||||
# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing
|
||||
# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff
|
||||
# "N" (what is on top: N=north C=course)
|
||||
# "C" (where does the arrow point to: C=course, S=sonde)
|
||||
# "S" (what is shown by the bullet: C=course, S=sonde)
|
||||
# 50: circle radius, followed by fg and bg color
|
||||
# 5: bullet radius, followed by fg color
|
||||
# 4: arrow width, followed by fg color
|
||||
# R RSSI
|
||||
# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current
|
||||
# U=USB volt I=USB current T=IC temp
|
||||
#
|
||||
# fonts=x,y can be used to select font (x=small, y=large) for all items below
|
||||
# for SSD1306, x and y can be used to select one of those fonts:
|
||||
# (y should be a 1x2 font (1,5,6,7), x a small font)
|
||||
# u8x8_font_chroma48medium8_r, // 0 ** default small
|
||||
# u8x8_font_7x14_1x2_f, // 1 ** default large
|
||||
# u8x8_font_amstrad_cpc_extended_f, // 2
|
||||
# u8x8_font_5x7_f, // 3
|
||||
# u8x8_font_5x8_f, // 4
|
||||
# u8x8_font_8x13_1x2_f, // 5
|
||||
# u8x8_font_8x13B_1x2_f, // 6
|
||||
# u8x8_font_7x14B_1x2_f, // 7
|
||||
# u8x8_font_artossans8_r, // 8
|
||||
# u8x8_font_artosserif8_r, // 9
|
||||
# u8x8_font_torussansbold8_r, // 10
|
||||
# u8x8_font_victoriabold8_r, // 11
|
||||
# u8x8_font_victoriamedium8_r, // 12
|
||||
# u8x8_font_pressstart2p_f, // 13
|
||||
# u8x8_font_pcsenior_f, // 14
|
||||
# u8x8_font_pxplusibmcgathin_f, // 15
|
||||
# u8x8_font_pxplusibmcga_f, // 16
|
||||
# u8x8_font_pxplustandynewtv_f, // 17
|
||||
#
|
||||
# for ILI9225, these fonts are available:
|
||||
# Terminal6x8 // 0
|
||||
# Terminal11x16 // 1
|
||||
# Terminal12x16 // 2
|
||||
# FreeMono9pt7b, // 3
|
||||
# FreeMono12pt7b, // 4
|
||||
# FreeSans9pt7b, // 5
|
||||
# FreeSans12pt7b, // 6
|
||||
# Picopixel, // 7
|
||||
#
|
||||
# color=rrggbb,rrggbb can be used to select color (foreground, background)
|
||||
# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign)
|
||||
#
|
||||
# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels
|
||||
# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns)
|
||||
###########
|
||||
#
|
||||
# Default configuration for "Scanner" display:
|
||||
# - view timer disabled; rx timer=0; norx timer = 0
|
||||
# => after 1 second immediately an action is triggered
|
||||
# (norx: go to next sonde; rx: go to default receiver display)
|
||||
# - key1 actions: D,0,F,W
|
||||
# => Button press activates default receiver view, double press does nothing
|
||||
# Mid press activates Spectrum display, long press activates Wifi scan
|
||||
# - key2 has no function
|
||||
@Scanner
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=#,#,#,#
|
||||
timeaction=#,D,+
|
||||
0,0=XScan
|
||||
0,5=S#:
|
||||
0,9=T
|
||||
3,0=F MHz
|
||||
5,0=S
|
||||
7,5=n
|
||||
|
||||
############
|
||||
# Default configuration for "Legacy" display:
|
||||
# - view timer=-1, rx timer=-1 (disabled); norx timer=20 (or -1 for "old" behaviour)
|
||||
# => norx timer fires after not receiving a singla for 20 seconds
|
||||
# - key1 actions: +,0,F,W
|
||||
# => Button1 press: next sonde; double press => @Scanner display
|
||||
# => Mid press activates Spectrum display, long press activates Wifi scan
|
||||
# - key2 actions: 2,#,#,#
|
||||
# => BUtton2 activates display 2 (@Field)
|
||||
# - timer actions: #,#,0
|
||||
# (norx timer: if no signal for >20 seconds: go back to scanner mode)
|
||||
#
|
||||
@Legacy
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
0,5=f MHz
|
||||
1,8=c
|
||||
0,0=t
|
||||
1,0=is
|
||||
2,0=L
|
||||
4,0=O
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,9=v
|
||||
6,0=R
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
# Configuratoon for "Field" display (display 2)
|
||||
# similar to @Legacy, but no norx timer, and Key2 goes to display 4
|
||||
@Field
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
# Configuration for "Field2" display (display 3)
|
||||
# similar to @Field
|
||||
@Field2
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
1,12=t
|
||||
0,9=f
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
#############
|
||||
# Configuration for "GPS" display
|
||||
# not yet the final version, just for testing
|
||||
@GPSDIST
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=L
|
||||
4,0=O
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,7=Q
|
||||
7,0=gV
|
||||
7,2=xd=
|
||||
7,4=gD
|
||||
7,12=gI°
|
||||
|
||||
############
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@ScannerTFT
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=#,#,#,#
|
||||
timeaction=#,D,+
|
||||
fonts=5,6
|
||||
0,0=XScan
|
||||
0,8,-3=S#:
|
||||
0,9,5=T
|
||||
3,0=F MHz
|
||||
5,0,16=S
|
||||
7,5=n
|
||||
|
||||
############
|
||||
@MainTFT
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
color=FFD700
|
||||
0,0=Is
|
||||
color=0000FF
|
||||
0,11,-5.5=f
|
||||
1,1,6=c
|
||||
1,12.5,-4=t
|
||||
color=00ff00
|
||||
2,0=L
|
||||
4,0=O
|
||||
color=FFA500
|
||||
2,9.5,-7=A
|
||||
3,9.5,-7=vm/s
|
||||
color=AA5522
|
||||
4,9.5,-7=hkkm/h
|
||||
color=FFFFFF
|
||||
6,2=r
|
||||
7,0=xd=
|
||||
7,2,6=gD
|
||||
7,12=gI
|
||||
|
||||
############
|
||||
@PeilungTFT
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
color=ffff00,000033
|
||||
color=bbbbbb,000000
|
||||
0,2=xN Top:
|
||||
0,8=xCourse Top:
|
||||
color=ffff00,000033
|
||||
1,0=g0NCS,48,ffff00,000044,6,33ff33,5,eeaa00
|
||||
1,8=g0CCS,48,ffff00,000044,6,55ff55,5,eeaa00
|
||||
color=ffffff,000000
|
||||
6,0=xDirection:
|
||||
6,8,4=gI
|
||||
7,0=xCOG:
|
||||
7,4,4=gC
|
||||
7,8=xturn:
|
||||
7,12,4=gB
|
||||
|
||||
|
||||
############
|
||||
@GPSdataTFT
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=xOn-board GPS:
|
||||
1,0,8=gA
|
||||
2,0,8=gO
|
||||
3,0,8=gH
|
||||
4,0,8=gC
|
||||
5,0=xGPS vs Sonde:
|
||||
6,0,8=gD
|
||||
7,0,8=gI
|
||||
7,8,8=gB
|
||||
|
||||
############
|
||||
@BatteryTFT
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=xBattery status:
|
||||
0,14=bS
|
||||
1,0=xBatt:
|
||||
1,5,5=bVV
|
||||
2,0,16=bCmA(charging)
|
||||
3,0,16=bDmA(discharging)
|
||||
4.4,0=xUSB:
|
||||
4.4,5,5=bUV
|
||||
5.4,0,10=bImA
|
||||
6.4,0=xTemp:
|
||||
6.4,5,5=bT C
|
||||
|
||||
############
|
||||
@BatteryOLED
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xBat.Status:
|
||||
0,12=bS
|
||||
1,0=xBatt:
|
||||
1,6=bVV
|
||||
2,0=bCmA (charge)
|
||||
3,0=bDmA (disch.)
|
||||
4,0=xUSB:
|
||||
4,5=bUV
|
||||
5,5=bImA
|
||||
6,0=xTemp:
|
||||
6,5=bT C
|
||||
|
||||
### Alternative display layouts based on https://gist.github.com/bazjo
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@Scan.TFT.Bazjo
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=#,#,#,#
|
||||
timeaction=#,D,+
|
||||
scale=11,10
|
||||
fonts=0,2
|
||||
color=e0e0e0
|
||||
#Row 1
|
||||
0.5,0=XScanning...
|
||||
#Row 2
|
||||
3,0=xIndex
|
||||
4,0=S/
|
||||
3,9=xSite
|
||||
4,9=S
|
||||
#Row 3
|
||||
6,0=xType
|
||||
7,0=T
|
||||
6,9=xFrequency
|
||||
7,9=F
|
||||
#Row 4
|
||||
9,0=xWeb UI IP
|
||||
10,0=N
|
||||
#Row 5
|
||||
#Footer
|
||||
color=6C757D
|
||||
15,0=xScan Mode
|
||||
15,18=bVV
|
||||
|
||||
############
|
||||
@Decode/General.TFT.Bazjo
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
scale=11,10
|
||||
fonts=0,2
|
||||
#Row 1
|
||||
color=996A06
|
||||
0,0=xSerial
|
||||
0,5=t
|
||||
color=FFB10B
|
||||
1,0=Is
|
||||
color=996A06
|
||||
0,11=xFreq.
|
||||
0,16=c
|
||||
color=FFB10B
|
||||
1,11=F
|
||||
#Row 2
|
||||
color=3C5C99
|
||||
3,0=xLatitude
|
||||
color=639AFF
|
||||
4,0=L
|
||||
color=3C5C99
|
||||
3,11=xLongitude
|
||||
color=639AFF
|
||||
4,11=O
|
||||
#Row 3
|
||||
color=3C5C99
|
||||
6,0=xHoriz. Speed
|
||||
color=639AFF
|
||||
7,0=Hkkm/h
|
||||
color=3C5C99
|
||||
6,11=xVert. Speed
|
||||
color=639AFF
|
||||
7,11=Vm/s
|
||||
#Row 4
|
||||
color=99004A
|
||||
9,0=xAltitude
|
||||
color=FF007B
|
||||
10,0=A
|
||||
color=99004A
|
||||
9,11=xBearing
|
||||
color=FF007B
|
||||
10,11=GB
|
||||
#Row 5
|
||||
color=06998E
|
||||
12,0=xRSSI
|
||||
color=0AFFEF
|
||||
13,0=R
|
||||
color=06998E
|
||||
12,11=xHistory
|
||||
color=0AFFEF
|
||||
13.5,11=Q4
|
||||
#Footer
|
||||
color=6C757D
|
||||
15,0=xDecode Mode / General View
|
||||
15,18=bVV
|
||||
|
||||
|
||||
############
|
||||
@Decode/Battery.TFT.Bazjo
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
scale=11,10
|
||||
fonts=0,2
|
||||
#Row 1
|
||||
color=99001F
|
||||
0,0=xBattery Status
|
||||
0,11=xBattery Voltage
|
||||
color=FF0035
|
||||
1,0=BS
|
||||
1,11=BVV
|
||||
#Row 2
|
||||
color=99001F
|
||||
3,0=xCharge Current
|
||||
3,11=xDischarge Current
|
||||
color=FF0035
|
||||
4,0=BCmA
|
||||
4,11=BDmA
|
||||
#Row 3
|
||||
color=99001F
|
||||
6,0=xUSB Voltage
|
||||
6,11=xUSB Current
|
||||
color=FF0035
|
||||
7,0=BUV
|
||||
7,11=BImA
|
||||
#Row 4
|
||||
color=99001F
|
||||
9,0=xIC Temperature
|
||||
#9,11=xKey
|
||||
color=FF0035
|
||||
10,0=BTC
|
||||
#10,11=XValue
|
||||
#Row 5
|
||||
#12,0=xKey
|
||||
#12,11=xKey
|
||||
#13,0=XValue
|
||||
#13,11=XValue
|
||||
#Footer
|
||||
color=99001F
|
||||
15,0=xDecode Mode/Battery View
|
||||
15,18=bVV
|
||||
|
140
RadioSonde_FSK/data/screens.txt → RX_FSK/data/screens1.txt
Executable file → Normal file
140
RadioSonde_FSK/data/screens.txt → RX_FSK/data/screens1.txt
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
|||
### screens1.txt: OLED display
|
||||
# Definition of display content and action behaviour
|
||||
#
|
||||
# Timer: (view timer, rx timer, norx timer)
|
||||
|
@ -32,7 +33,10 @@
|
|||
# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only)
|
||||
# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Ix sonde ID (dfm format by x: d=>dxlaprs, a=>autorx, s=>real serial number)
|
||||
# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number)
|
||||
# RS41,RS92: all identical R1234567
|
||||
# DFMx: ID M12345678; short ID and serial 12345678
|
||||
# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592
|
||||
# Q signal quality statistics bar
|
||||
# T type string (RS41/DFM9/DFM6/RS92)
|
||||
# C afC value
|
||||
|
@ -40,7 +44,7 @@
|
|||
# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t
|
||||
# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown
|
||||
# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde
|
||||
# Mx telemetry value x (t temp p preassure h hyg) [not yet implemented, maybe some day in future]
|
||||
# Mx telemetry value x (t temp p preassure h hyg b battery)
|
||||
# Gx GPS-related data
|
||||
# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground
|
||||
# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing
|
||||
|
@ -54,8 +58,7 @@
|
|||
# R RSSI
|
||||
# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current
|
||||
# U=USB volt I=USB current T=IC temp
|
||||
# AA Azimut degres
|
||||
# Z duree vol H:m.s
|
||||
#
|
||||
# fonts=x,y can be used to select font (x=small, y=large) for all items below
|
||||
# for SSD1306, x and y can be used to select one of those fonts:
|
||||
# (y should be a 1x2 font (1,5,6,7), x a small font)
|
||||
|
@ -78,6 +81,15 @@
|
|||
# u8x8_font_pxplusibmcga_f, // 16
|
||||
# u8x8_font_pxplustandynewtv_f, // 17
|
||||
#
|
||||
# for ILI9225, these fonts are available:
|
||||
# Terminal6x8 // 0
|
||||
# Terminal11x16 // 1
|
||||
# Terminal12x16 // 2
|
||||
# FreeMono9pt7b, // 3
|
||||
# FreeMono12pt7b, // 4
|
||||
# FreeSans9pt7b, // 5
|
||||
# FreeSans12pt7b, // 6
|
||||
# Picopixel, // 7
|
||||
#
|
||||
# color=rrggbb,rrggbb can be used to select color (foreground, background)
|
||||
# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign)
|
||||
|
@ -97,14 +109,15 @@
|
|||
@Scanner
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=#,#,#,#
|
||||
key2action=D,#,#,#
|
||||
timeaction=#,D,+
|
||||
0,0=XScan
|
||||
0,5=S#:
|
||||
0,9=T
|
||||
3,0=F MHz
|
||||
5,0=S
|
||||
7,0=y%
|
||||
5,0,16=S
|
||||
7,0=bVV
|
||||
#7,0=gV
|
||||
7,5=n
|
||||
|
||||
############
|
||||
|
@ -124,23 +137,17 @@ timer=-1,-1,N
|
|||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
0,0=t
|
||||
0,5=f MHz
|
||||
1,8=c
|
||||
0,0=t
|
||||
1,0=is
|
||||
#1,8=c
|
||||
1,8=z
|
||||
2,0=L
|
||||
4,0=O
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,0=O
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,0=R
|
||||
6,7=Q
|
||||
7,6=gD
|
||||
7,12=gI°
|
||||
|
||||
|
||||
############
|
||||
# Configuratoon for "Field" display (display 2)
|
||||
|
@ -150,19 +157,13 @@ timer=-1,-1,N
|
|||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=Is
|
||||
2,0=L
|
||||
2,9=xEl:
|
||||
2,12=gE
|
||||
4,0=O
|
||||
3,10=h
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
7,6=gD
|
||||
7,12=gI°
|
||||
|
||||
############
|
||||
# Configuration for "Field2" display (display 3)
|
||||
|
@ -172,21 +173,15 @@ timer=-1,-1,N
|
|||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,9=xEl:
|
||||
2,12=gE
|
||||
2,0=L
|
||||
3,10=h
|
||||
4,0=O
|
||||
1,12=t
|
||||
0,9=f
|
||||
3,10=h
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
7,6=gD
|
||||
7,12=gI°
|
||||
|
||||
#############
|
||||
# Configuration for "GPS" display
|
||||
|
@ -206,32 +201,11 @@ timeaction=#,#,#
|
|||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,0=xEl:
|
||||
6,2=gE
|
||||
6,7=Q
|
||||
7,0=gW
|
||||
7,0=gV
|
||||
7,2=xd=
|
||||
7,4=gD
|
||||
7,11=gI°
|
||||
|
||||
############
|
||||
# Boussole Oled
|
||||
@BOUSSOLE
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=g0
|
||||
0,10=a
|
||||
1,10=h
|
||||
2,9=v
|
||||
3,10=gC
|
||||
3,13=gB
|
||||
4,9=gD
|
||||
5,11=gI°
|
||||
6,9=xEl:
|
||||
6,11=gE
|
||||
7,9=t
|
||||
7,12=gI°
|
||||
|
||||
############
|
||||
@BatteryOLED
|
||||
|
@ -241,11 +215,53 @@ key2action=>,#,#,#
|
|||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xBat.Status:
|
||||
2,0=xCpu:
|
||||
2,7=bVV
|
||||
4,0=xVbus:
|
||||
4,7=bCV
|
||||
6,0=xPower:
|
||||
6,7=bPmW
|
||||
0,12=bS
|
||||
1,0=xBatt:
|
||||
1,6=bVV
|
||||
2,0=bCmA (charge)
|
||||
3,0=bDmA (disch.)
|
||||
4,0=xUSB:
|
||||
4,5=bUV
|
||||
5,5=bImA
|
||||
6,0=xTemp:
|
||||
6,5=bT C
|
||||
|
||||
#############
|
||||
@Meteo
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=xSonde
|
||||
3,0=xData
|
||||
2,10=A
|
||||
4,0=Mt°C
|
||||
4,9=Mh%rH
|
||||
6,0=MphPa
|
||||
6,11=MbV
|
||||
|
||||
#############
|
||||
@GPS-Data
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xGPS-Data
|
||||
1,0=xLAT :
|
||||
1,6=gA
|
||||
2,0=xLONG:
|
||||
2,6=gO
|
||||
3,0=xALT :
|
||||
3,9=gH
|
||||
4,0=xSonde
|
||||
5,0=xAlt :
|
||||
5,6=a
|
||||
6,0=xDist:
|
||||
6,6=gD
|
||||
|
||||
|
276
RX_FSK/data/screens2.txt
Normal file
276
RX_FSK/data/screens2.txt
Normal file
|
@ -0,0 +1,276 @@
|
|||
## screens2.txt: TFT display (landscape)
|
||||
# Definition of display content and action behaviour
|
||||
#
|
||||
# Timer: (view timer, rx timer, norx timer)
|
||||
# - value -1: timer is disabled; value>=0: timer fires after (value) seconds
|
||||
# - view timer: time since current view (display mode and sonde) was started
|
||||
# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX)
|
||||
# - norx timer: time since when no sonde data has been received continuously
|
||||
# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving
|
||||
# anything for a 1s period)
|
||||
#
|
||||
# Actions:
|
||||
# - W: activate WiFi scan
|
||||
# - F: activate frequency spectrum display
|
||||
# - 0: activate "Scan:" display (this is basically just display mode 0)
|
||||
# - x: (1..N): activate display mode x [deprecated]
|
||||
# - >: activate next display mode
|
||||
# - D: activate default receiver display (display mode specified in config)
|
||||
# - +: advance to next active sonde from QRG config
|
||||
# - #: no action
|
||||
#
|
||||
# Display content (lower/upper case: small/large font)
|
||||
# line,column=content
|
||||
# for ILI9225 its also possible to indicate
|
||||
# line,column,width=content for text within a box of width 'width'
|
||||
# line,column,-width=content for right-justified text
|
||||
#
|
||||
# XText : Text
|
||||
# F(suffix): frequency (with suffix, e.g., " MHz")
|
||||
# L latitade
|
||||
# O lOngitute
|
||||
# A altitude
|
||||
# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only)
|
||||
# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number)
|
||||
# RS41,RS92: all identical R1234567
|
||||
# DFMx: ID M12345678; short ID and serial 12345678
|
||||
# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592
|
||||
# Q signal quality statistics bar
|
||||
# T type string (RS41/DFM9/DFM6/RS92)
|
||||
# C afC value
|
||||
# N ip address (only tiny font)
|
||||
# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t
|
||||
# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown
|
||||
# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde
|
||||
# Mx telemetry value x (t temp p preassure h hyg b batt)
|
||||
# Gx GPS-related data
|
||||
# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground
|
||||
# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing
|
||||
# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff
|
||||
# "N" (what is on top: N=north C=course)
|
||||
# "C" (where does the arrow point to: C=course, S=sonde)
|
||||
# "S" (what is shown by the bullet: C=course, S=sonde)
|
||||
# 50: circle radius, followed by fg and bg color
|
||||
# 5: bullet radius, followed by fg color
|
||||
# 4: arrow width, followed by fg color
|
||||
# R RSSI
|
||||
# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current
|
||||
# U=USB volt I=USB current T=IC temp
|
||||
#
|
||||
# fonts=x,y can be used to select font (x=small, y=large) for all items below
|
||||
# for SSD1306, x and y can be used to select one of those fonts:
|
||||
# (y should be a 1x2 font (1,5,6,7), x a small font)
|
||||
# u8x8_font_chroma48medium8_r, // 0 ** default small
|
||||
# u8x8_font_7x14_1x2_f, // 1 ** default large
|
||||
# u8x8_font_amstrad_cpc_extended_f, // 2
|
||||
# u8x8_font_5x7_f, // 3
|
||||
# u8x8_font_5x8_f, // 4
|
||||
# u8x8_font_8x13_1x2_f, // 5
|
||||
# u8x8_font_8x13B_1x2_f, // 6
|
||||
# u8x8_font_7x14B_1x2_f, // 7
|
||||
# u8x8_font_artossans8_r, // 8
|
||||
# u8x8_font_artosserif8_r, // 9
|
||||
# u8x8_font_torussansbold8_r, // 10
|
||||
# u8x8_font_victoriabold8_r, // 11
|
||||
# u8x8_font_victoriamedium8_r, // 12
|
||||
# u8x8_font_pressstart2p_f, // 13
|
||||
# u8x8_font_pcsenior_f, // 14
|
||||
# u8x8_font_pxplusibmcgathin_f, // 15
|
||||
# u8x8_font_pxplusibmcga_f, // 16
|
||||
# u8x8_font_pxplustandynewtv_f, // 17
|
||||
#
|
||||
# for ILI9225, these fonts are available:
|
||||
# Terminal6x8 // 0
|
||||
# Terminal11x16 // 1
|
||||
# Terminal12x16 // 2
|
||||
# FreeMono9pt7b, // 3
|
||||
# FreeMono12pt7b, // 4
|
||||
# FreeSans9pt7b, // 5
|
||||
# FreeSans12pt7b, // 6
|
||||
# Picopixel, // 7
|
||||
#
|
||||
# color=rrggbb,rrggbb can be used to select color (foreground, background)
|
||||
# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign)
|
||||
#
|
||||
# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels
|
||||
# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns)
|
||||
###########
|
||||
|
||||
############
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@ScannerTFT
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=D,#,#,#
|
||||
timeaction=#,D,+
|
||||
0,0=XScan
|
||||
0,5=S#:
|
||||
0,9=T
|
||||
3,0=F MHz
|
||||
5,0,16=S
|
||||
7,0=bVV
|
||||
7,5=n
|
||||
|
||||
############
|
||||
@Legacy
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
0,0=t
|
||||
0,5=f MHz
|
||||
1,0=is
|
||||
#1,8=c
|
||||
1,8=z
|
||||
2,0=L
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,0=O
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,0=R
|
||||
6,7=Q
|
||||
7,6=gD
|
||||
7,12=gI°
|
||||
|
||||
############
|
||||
@Field
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@Field2
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
1,12=t
|
||||
0,9=f
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@GPSDIST
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=L
|
||||
4,0=O
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,7=Q
|
||||
7,0=gV
|
||||
7,2=xd=
|
||||
7,4=gD
|
||||
7,12=gI°
|
||||
|
||||
### Alternative display layouts based on https://gist.github.com/bazjo
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@BatteryOLED
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xBat.Status:
|
||||
0,12=bS
|
||||
1,0=xBatt:
|
||||
1,6=bVV
|
||||
2,0=bCmA (charge)
|
||||
3,0=bDmA (disch.)
|
||||
4,0=xUSB:
|
||||
4,5=bUV
|
||||
5,5=bImA
|
||||
6,0=xTemp:
|
||||
6,5=bT C
|
||||
|
||||
############
|
||||
@Meteo
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=xSonde
|
||||
3,0=xData
|
||||
2,10=A
|
||||
4,0=Mt°C
|
||||
4,9=Mh%rH
|
||||
6,0=MphPa
|
||||
6,11=MbV
|
||||
|
||||
##################
|
||||
@GPS-Data
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xGPS-Data
|
||||
1,0=xLAT :
|
||||
1,6=gA
|
||||
2,0=xLONG:
|
||||
2,6=gO
|
||||
3,0=xALT :
|
||||
3,9=gH
|
||||
4,0=xSonde
|
||||
5,0=xAlt :
|
||||
5,6=a
|
||||
6,0=xDist:
|
||||
6,6=gD
|
||||
|
||||
#################
|
||||
@TelemetryData
|
||||
scale=22,13
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
fonts=5,6
|
||||
color=FFD700
|
||||
0,0,10.5=Is
|
||||
color=0000FF
|
||||
0,11,-5.5=f
|
||||
1,0,4=t
|
||||
1,10.5,-6=c
|
||||
color=00ff00
|
||||
2,0,7=L
|
||||
3,0,7=O
|
||||
color=FFA500
|
||||
2,9.5,-7=a
|
||||
2.8,9.5,-7=vm/s
|
||||
color=AA5522
|
||||
3.6,9.5,-7=hkkm/h
|
||||
color=FFFFFF
|
||||
4.4,0=xTelemetry Data:
|
||||
5.3,0=Mt C
|
||||
5.3,9=Mh%rH
|
||||
6.5,0=MphPa
|
||||
6.5,11=MbV
|
276
RX_FSK/data/screens3.txt
Normal file
276
RX_FSK/data/screens3.txt
Normal file
|
@ -0,0 +1,276 @@
|
|||
## screens2.txt: TFT display (landscape)
|
||||
# Definition of display content and action behaviour
|
||||
#
|
||||
# Timer: (view timer, rx timer, norx timer)
|
||||
# - value -1: timer is disabled; value>=0: timer fires after (value) seconds
|
||||
# - view timer: time since current view (display mode and sonde) was started
|
||||
# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX)
|
||||
# - norx timer: time since when no sonde data has been received continuously
|
||||
# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving
|
||||
# anything for a 1s period)
|
||||
#
|
||||
# Actions:
|
||||
# - W: activate WiFi scan
|
||||
# - F: activate frequency spectrum display
|
||||
# - 0: activate "Scan:" display (this is basically just display mode 0)
|
||||
# - x: (1..N): activate display mode x [deprecated]
|
||||
# - >: activate next display mode
|
||||
# - D: activate default receiver display (display mode specified in config)
|
||||
# - +: advance to next active sonde from QRG config
|
||||
# - #: no action
|
||||
#
|
||||
# Display content (lower/upper case: small/large font)
|
||||
# line,column=content
|
||||
# for ILI9225 its also possible to indicate
|
||||
# line,column,width=content for text within a box of width 'width'
|
||||
# line,column,-width=content for right-justified text
|
||||
#
|
||||
# XText : Text
|
||||
# F(suffix): frequency (with suffix, e.g., " MHz")
|
||||
# L latitade
|
||||
# O lOngitute
|
||||
# A altitude
|
||||
# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only)
|
||||
# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number)
|
||||
# RS41,RS92: all identical R1234567
|
||||
# DFMx: ID M12345678; short ID and serial 12345678
|
||||
# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592
|
||||
# Q signal quality statistics bar
|
||||
# T type string (RS41/DFM9/DFM6/RS92)
|
||||
# C afC value
|
||||
# N ip address (only tiny font)
|
||||
# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t
|
||||
# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown
|
||||
# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde
|
||||
# Mx telemetry value x (t temp p preassure h hyg b batt)
|
||||
# Gx GPS-related data
|
||||
# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground
|
||||
# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing
|
||||
# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff
|
||||
# "N" (what is on top: N=north C=course)
|
||||
# "C" (where does the arrow point to: C=course, S=sonde)
|
||||
# "S" (what is shown by the bullet: C=course, S=sonde)
|
||||
# 50: circle radius, followed by fg and bg color
|
||||
# 5: bullet radius, followed by fg color
|
||||
# 4: arrow width, followed by fg color
|
||||
# R RSSI
|
||||
# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current
|
||||
# U=USB volt I=USB current T=IC temp
|
||||
#
|
||||
# fonts=x,y can be used to select font (x=small, y=large) for all items below
|
||||
# for SSD1306, x and y can be used to select one of those fonts:
|
||||
# (y should be a 1x2 font (1,5,6,7), x a small font)
|
||||
# u8x8_font_chroma48medium8_r, // 0 ** default small
|
||||
# u8x8_font_7x14_1x2_f, // 1 ** default large
|
||||
# u8x8_font_amstrad_cpc_extended_f, // 2
|
||||
# u8x8_font_5x7_f, // 3
|
||||
# u8x8_font_5x8_f, // 4
|
||||
# u8x8_font_8x13_1x2_f, // 5
|
||||
# u8x8_font_8x13B_1x2_f, // 6
|
||||
# u8x8_font_7x14B_1x2_f, // 7
|
||||
# u8x8_font_artossans8_r, // 8
|
||||
# u8x8_font_artosserif8_r, // 9
|
||||
# u8x8_font_torussansbold8_r, // 10
|
||||
# u8x8_font_victoriabold8_r, // 11
|
||||
# u8x8_font_victoriamedium8_r, // 12
|
||||
# u8x8_font_pressstart2p_f, // 13
|
||||
# u8x8_font_pcsenior_f, // 14
|
||||
# u8x8_font_pxplusibmcgathin_f, // 15
|
||||
# u8x8_font_pxplusibmcga_f, // 16
|
||||
# u8x8_font_pxplustandynewtv_f, // 17
|
||||
#
|
||||
# for ILI9225, these fonts are available:
|
||||
# Terminal6x8 // 0
|
||||
# Terminal11x16 // 1
|
||||
# Terminal12x16 // 2
|
||||
# FreeMono9pt7b, // 3
|
||||
# FreeMono12pt7b, // 4
|
||||
# FreeSans9pt7b, // 5
|
||||
# FreeSans12pt7b, // 6
|
||||
# Picopixel, // 7
|
||||
#
|
||||
# color=rrggbb,rrggbb can be used to select color (foreground, background)
|
||||
# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign)
|
||||
#
|
||||
# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels
|
||||
# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns)
|
||||
###########
|
||||
|
||||
############
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@ScannerTFT
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=D,#,#,#
|
||||
timeaction=#,D,+
|
||||
0,0=XScan
|
||||
0,5=S#:
|
||||
0,9=T
|
||||
3,0=F MHz
|
||||
5,0,16=S
|
||||
7,0=bVV
|
||||
7,5=n
|
||||
|
||||
############
|
||||
@Legacy
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
0,0=t
|
||||
0,5=f MHz
|
||||
1,0=is
|
||||
#1,8=c
|
||||
1,8=z
|
||||
2,0=L
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,0=O
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,0=R
|
||||
6,7=Q
|
||||
7,6=gD
|
||||
7,12=gI°
|
||||
|
||||
############
|
||||
@Field
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@Field2
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
1,12=t
|
||||
0,9=f
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@GPSDIST
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=L
|
||||
4,0=O
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,7=Q
|
||||
7,0=gV
|
||||
7,2=xd=
|
||||
7,4=gD
|
||||
7,12=gI°
|
||||
|
||||
### Alternative display layouts based on https://gist.github.com/bazjo
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@BatteryOLED
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xBat.Status:
|
||||
0,12=bS
|
||||
1,0=xBatt:
|
||||
1,6=bVV
|
||||
2,0=bCmA (charge)
|
||||
3,0=bDmA (disch.)
|
||||
4,0=xUSB:
|
||||
4,5=bUV
|
||||
5,5=bImA
|
||||
6,0=xTemp:
|
||||
6,5=bT C
|
||||
|
||||
############
|
||||
@Meteo
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=xSonde
|
||||
3,0=xData
|
||||
2,10=A
|
||||
4,0=Mt°C
|
||||
4,9=Mh%rH
|
||||
6,0=MphPa
|
||||
6,11=MbV
|
||||
|
||||
##################
|
||||
@GPS-Data
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xGPS-Data
|
||||
1,0=xLAT :
|
||||
1,6=gA
|
||||
2,0=xLONG:
|
||||
2,6=gO
|
||||
3,0=xALT :
|
||||
3,9=gH
|
||||
4,0=xSonde
|
||||
5,0=xAlt :
|
||||
5,6=a
|
||||
6,0=xDist:
|
||||
6,6=gD
|
||||
|
||||
#################
|
||||
@TelemetryData
|
||||
scale=22,13
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
fonts=5,6
|
||||
color=FFD700
|
||||
0,0,10.5=Is
|
||||
color=0000FF
|
||||
0,11,-5.5=f
|
||||
1,0,4=t
|
||||
1,10.5,-6=c
|
||||
color=00ff00
|
||||
2,0,7=L
|
||||
3,0,7=O
|
||||
color=FFA500
|
||||
2,9.5,-7=a
|
||||
2.8,9.5,-7=vm/s
|
||||
color=AA5522
|
||||
3.6,9.5,-7=hkkm/h
|
||||
color=FFFFFF
|
||||
4.4,0=xTelemetry Data:
|
||||
5.3,0=Mt C
|
||||
5.3,9=Mh%rH
|
||||
6.5,0=MphPa
|
||||
6.5,11=MbV
|
276
RX_FSK/data/screens4.txt
Normal file
276
RX_FSK/data/screens4.txt
Normal file
|
@ -0,0 +1,276 @@
|
|||
## screens2.txt: TFT display (landscape)
|
||||
# Definition of display content and action behaviour
|
||||
#
|
||||
# Timer: (view timer, rx timer, norx timer)
|
||||
# - value -1: timer is disabled; value>=0: timer fires after (value) seconds
|
||||
# - view timer: time since current view (display mode and sonde) was started
|
||||
# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX)
|
||||
# - norx timer: time since when no sonde data has been received continuously
|
||||
# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving
|
||||
# anything for a 1s period)
|
||||
#
|
||||
# Actions:
|
||||
# - W: activate WiFi scan
|
||||
# - F: activate frequency spectrum display
|
||||
# - 0: activate "Scan:" display (this is basically just display mode 0)
|
||||
# - x: (1..N): activate display mode x [deprecated]
|
||||
# - >: activate next display mode
|
||||
# - D: activate default receiver display (display mode specified in config)
|
||||
# - +: advance to next active sonde from QRG config
|
||||
# - #: no action
|
||||
#
|
||||
# Display content (lower/upper case: small/large font)
|
||||
# line,column=content
|
||||
# for ILI9225 its also possible to indicate
|
||||
# line,column,width=content for text within a box of width 'width'
|
||||
# line,column,-width=content for right-justified text
|
||||
#
|
||||
# XText : Text
|
||||
# F(suffix): frequency (with suffix, e.g., " MHz")
|
||||
# L latitade
|
||||
# O lOngitute
|
||||
# A altitude
|
||||
# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only)
|
||||
# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number)
|
||||
# RS41,RS92: all identical R1234567
|
||||
# DFMx: ID M12345678; short ID and serial 12345678
|
||||
# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592
|
||||
# Q signal quality statistics bar
|
||||
# T type string (RS41/DFM9/DFM6/RS92)
|
||||
# C afC value
|
||||
# N ip address (only tiny font)
|
||||
# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t
|
||||
# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown
|
||||
# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde
|
||||
# Mx telemetry value x (t temp p preassure h hyg b batt)
|
||||
# Gx GPS-related data
|
||||
# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground
|
||||
# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing
|
||||
# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff
|
||||
# "N" (what is on top: N=north C=course)
|
||||
# "C" (where does the arrow point to: C=course, S=sonde)
|
||||
# "S" (what is shown by the bullet: C=course, S=sonde)
|
||||
# 50: circle radius, followed by fg and bg color
|
||||
# 5: bullet radius, followed by fg color
|
||||
# 4: arrow width, followed by fg color
|
||||
# R RSSI
|
||||
# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current
|
||||
# U=USB volt I=USB current T=IC temp
|
||||
#
|
||||
# fonts=x,y can be used to select font (x=small, y=large) for all items below
|
||||
# for SSD1306, x and y can be used to select one of those fonts:
|
||||
# (y should be a 1x2 font (1,5,6,7), x a small font)
|
||||
# u8x8_font_chroma48medium8_r, // 0 ** default small
|
||||
# u8x8_font_7x14_1x2_f, // 1 ** default large
|
||||
# u8x8_font_amstrad_cpc_extended_f, // 2
|
||||
# u8x8_font_5x7_f, // 3
|
||||
# u8x8_font_5x8_f, // 4
|
||||
# u8x8_font_8x13_1x2_f, // 5
|
||||
# u8x8_font_8x13B_1x2_f, // 6
|
||||
# u8x8_font_7x14B_1x2_f, // 7
|
||||
# u8x8_font_artossans8_r, // 8
|
||||
# u8x8_font_artosserif8_r, // 9
|
||||
# u8x8_font_torussansbold8_r, // 10
|
||||
# u8x8_font_victoriabold8_r, // 11
|
||||
# u8x8_font_victoriamedium8_r, // 12
|
||||
# u8x8_font_pressstart2p_f, // 13
|
||||
# u8x8_font_pcsenior_f, // 14
|
||||
# u8x8_font_pxplusibmcgathin_f, // 15
|
||||
# u8x8_font_pxplusibmcga_f, // 16
|
||||
# u8x8_font_pxplustandynewtv_f, // 17
|
||||
#
|
||||
# for ILI9225, these fonts are available:
|
||||
# Terminal6x8 // 0
|
||||
# Terminal11x16 // 1
|
||||
# Terminal12x16 // 2
|
||||
# FreeMono9pt7b, // 3
|
||||
# FreeMono12pt7b, // 4
|
||||
# FreeSans9pt7b, // 5
|
||||
# FreeSans12pt7b, // 6
|
||||
# Picopixel, // 7
|
||||
#
|
||||
# color=rrggbb,rrggbb can be used to select color (foreground, background)
|
||||
# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign)
|
||||
#
|
||||
# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels
|
||||
# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns)
|
||||
###########
|
||||
|
||||
############
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@ScannerTFT
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=D,#,#,#
|
||||
timeaction=#,D,+
|
||||
0,0=XScan
|
||||
0,5=S#:
|
||||
0,9=T
|
||||
3,0=F MHz
|
||||
5,0,16=S
|
||||
7,0=bVV
|
||||
7,5=n
|
||||
|
||||
############
|
||||
@Legacy
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
0,0=t
|
||||
0,5=f MHz
|
||||
1,0=is
|
||||
#1,8=c
|
||||
1,8=z
|
||||
2,0=L
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,0=O
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,0=R
|
||||
6,7=Q
|
||||
7,6=gD
|
||||
7,12=gI°
|
||||
|
||||
############
|
||||
@Field
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@Field2
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
1,12=t
|
||||
0,9=f
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@GPSDIST
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=L
|
||||
4,0=O
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,7=Q
|
||||
7,0=gV
|
||||
7,2=xd=
|
||||
7,4=gD
|
||||
7,12=gI°
|
||||
|
||||
### Alternative display layouts based on https://gist.github.com/bazjo
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@BatteryOLED
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xBat.Status:
|
||||
0,12=bS
|
||||
1,0=xBatt:
|
||||
1,6=bVV
|
||||
2,0=bCmA (charge)
|
||||
3,0=bDmA (disch.)
|
||||
4,0=xUSB:
|
||||
4,5=bUV
|
||||
5,5=bImA
|
||||
6,0=xTemp:
|
||||
6,5=bT C
|
||||
|
||||
############
|
||||
@Meteo
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=xSonde
|
||||
3,0=xData
|
||||
2,10=A
|
||||
4,0=Mt°C
|
||||
4,9=Mh%rH
|
||||
6,0=MphPa
|
||||
6,11=MbV
|
||||
|
||||
##################
|
||||
@GPS-Data
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xGPS-Data
|
||||
1,0=xLAT :
|
||||
1,6=gA
|
||||
2,0=xLONG:
|
||||
2,6=gO
|
||||
3,0=xALT :
|
||||
3,9=gH
|
||||
4,0=xSonde
|
||||
5,0=xAlt :
|
||||
5,6=a
|
||||
6,0=xDist:
|
||||
6,6=gD
|
||||
|
||||
#################
|
||||
@TelemetryData
|
||||
scale=22,13
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
fonts=5,6
|
||||
color=FFD700
|
||||
0,0,10.5=Is
|
||||
color=0000FF
|
||||
0,11,-5.5=f
|
||||
1,0,4=t
|
||||
1,10.5,-6=c
|
||||
color=00ff00
|
||||
2,0,7=L
|
||||
3,0,7=O
|
||||
color=FFA500
|
||||
2,9.5,-7=a
|
||||
2.8,9.5,-7=vm/s
|
||||
color=AA5522
|
||||
3.6,9.5,-7=hkkm/h
|
||||
color=FFFFFF
|
||||
4.4,0=xTelemetry Data:
|
||||
5.3,0=Mt C
|
||||
5.3,9=Mh%rH
|
||||
6.5,0=MphPa
|
||||
6.5,11=MbV
|
276
RX_FSK/data/screens5.txt
Normal file
276
RX_FSK/data/screens5.txt
Normal file
|
@ -0,0 +1,276 @@
|
|||
## screens2.txt: TFT display (landscape)
|
||||
# Definition of display content and action behaviour
|
||||
#
|
||||
# Timer: (view timer, rx timer, norx timer)
|
||||
# - value -1: timer is disabled; value>=0: timer fires after (value) seconds
|
||||
# - view timer: time since current view (display mode and sonde) was started
|
||||
# - rx timer: time since when sonde data has been received continuously (trigger immediatly after RX)
|
||||
# - norx timer: time since when no sonde data has been received continuously
|
||||
# (rx and norx timer is started after tuning a new frequency and receiving a signal or not receiving
|
||||
# anything for a 1s period)
|
||||
#
|
||||
# Actions:
|
||||
# - W: activate WiFi scan
|
||||
# - F: activate frequency spectrum display
|
||||
# - 0: activate "Scan:" display (this is basically just display mode 0)
|
||||
# - x: (1..N): activate display mode x [deprecated]
|
||||
# - >: activate next display mode
|
||||
# - D: activate default receiver display (display mode specified in config)
|
||||
# - +: advance to next active sonde from QRG config
|
||||
# - #: no action
|
||||
#
|
||||
# Display content (lower/upper case: small/large font)
|
||||
# line,column=content
|
||||
# for ILI9225 its also possible to indicate
|
||||
# line,column,width=content for text within a box of width 'width'
|
||||
# line,column,-width=content for right-justified text
|
||||
#
|
||||
# XText : Text
|
||||
# F(suffix): frequency (with suffix, e.g., " MHz")
|
||||
# L latitade
|
||||
# O lOngitute
|
||||
# A altitude
|
||||
# Hm(suffix) hor. speed m/s (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Hk(suffix) hor. speed km/h (suffix: e.g. "km/h"; no suffix=>km/h as 16x8 bitmap for SSD1306 display only)
|
||||
# V(suffix) vert. speef (suffix: e.g. "m/s"; no suffix=>m/s as 16x8 bitmap for SSD1306 display only)
|
||||
# Ix sonde ID (default/d: dxlaprs; s: short id, n: real serial number)
|
||||
# RS41,RS92: all identical R1234567
|
||||
# DFMx: ID M12345678; short ID and serial 12345678
|
||||
# M10: ID ME95231F0; short ID: M95231F0; serial 9062104592
|
||||
# Q signal quality statistics bar
|
||||
# T type string (RS41/DFM9/DFM6/RS92)
|
||||
# C afC value
|
||||
# N ip address (only tiny font)
|
||||
# S scan list entry info: l/empty: launch site name, #=entry nr, t=total entries, a=active entries, /: #/t
|
||||
# K RS41 kill timer values: Kl launch timer, Kb burst timer, Kc kill countdown
|
||||
# format: K_4: h:mm k_6: h:mm:ss k_s: sssss, nothing shown for other sonde
|
||||
# Mx telemetry value x (t temp p preassure h hyg b batt)
|
||||
# Gx GPS-related data
|
||||
# raw data from GPS: GA, GO, GH, GC: LAtitude, lOngitude, Altutide(Height), Course over ground
|
||||
# relative to sonde: GD, GI, GB: Distance, dIrection (absolute), relative Bearing
|
||||
# G0 GPS circle diagram e.g. 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff
|
||||
# "N" (what is on top: N=north C=course)
|
||||
# "C" (where does the arrow point to: C=course, S=sonde)
|
||||
# "S" (what is shown by the bullet: C=course, S=sonde)
|
||||
# 50: circle radius, followed by fg and bg color
|
||||
# 5: bullet radius, followed by fg color
|
||||
# 4: arrow width, followed by fg color
|
||||
# R RSSI
|
||||
# B battery(T-Beam 1.0) S=status V=Batt.Volt C=charge current D=discharge current
|
||||
# U=USB volt I=USB current T=IC temp
|
||||
#
|
||||
# fonts=x,y can be used to select font (x=small, y=large) for all items below
|
||||
# for SSD1306, x and y can be used to select one of those fonts:
|
||||
# (y should be a 1x2 font (1,5,6,7), x a small font)
|
||||
# u8x8_font_chroma48medium8_r, // 0 ** default small
|
||||
# u8x8_font_7x14_1x2_f, // 1 ** default large
|
||||
# u8x8_font_amstrad_cpc_extended_f, // 2
|
||||
# u8x8_font_5x7_f, // 3
|
||||
# u8x8_font_5x8_f, // 4
|
||||
# u8x8_font_8x13_1x2_f, // 5
|
||||
# u8x8_font_8x13B_1x2_f, // 6
|
||||
# u8x8_font_7x14B_1x2_f, // 7
|
||||
# u8x8_font_artossans8_r, // 8
|
||||
# u8x8_font_artosserif8_r, // 9
|
||||
# u8x8_font_torussansbold8_r, // 10
|
||||
# u8x8_font_victoriabold8_r, // 11
|
||||
# u8x8_font_victoriamedium8_r, // 12
|
||||
# u8x8_font_pressstart2p_f, // 13
|
||||
# u8x8_font_pcsenior_f, // 14
|
||||
# u8x8_font_pxplusibmcgathin_f, // 15
|
||||
# u8x8_font_pxplusibmcga_f, // 16
|
||||
# u8x8_font_pxplustandynewtv_f, // 17
|
||||
#
|
||||
# for ILI9225, these fonts are available:
|
||||
# Terminal6x8 // 0
|
||||
# Terminal11x16 // 1
|
||||
# Terminal12x16 // 2
|
||||
# FreeMono9pt7b, // 3
|
||||
# FreeMono12pt7b, // 4
|
||||
# FreeSans9pt7b, // 5
|
||||
# FreeSans12pt7b, // 6
|
||||
# Picopixel, // 7
|
||||
#
|
||||
# color=rrggbb,rrggbb can be used to select color (foreground, background)
|
||||
# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign)
|
||||
#
|
||||
# for TFT display, coordinates and width are multiplied by xscale,yscale and later used in pixels
|
||||
# with scale=1,1 you can directly use pixel coordinates. (default: xscale=13,yscale=22 => 8 lines, 16 columns)
|
||||
###########
|
||||
|
||||
############
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@ScannerTFT
|
||||
timer=-1,0,0
|
||||
key1action=D,#,F,W
|
||||
key2action=D,#,#,#
|
||||
timeaction=#,D,+
|
||||
0,0=XScan
|
||||
0,5=S#:
|
||||
0,9=T
|
||||
3,0=F MHz
|
||||
5,0,16=S
|
||||
7,0=bVV
|
||||
7,5=n
|
||||
|
||||
############
|
||||
@Legacy
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
0,0=t
|
||||
0,5=f MHz
|
||||
1,0=is
|
||||
#1,8=c
|
||||
1,8=z
|
||||
2,0=L
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,0=O
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,0=R
|
||||
6,7=Q
|
||||
7,6=gD
|
||||
7,12=gI°
|
||||
|
||||
############
|
||||
@Field
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@Field2
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
2,0=L
|
||||
4,0=O
|
||||
1,12=t
|
||||
0,9=f
|
||||
3,10=h
|
||||
4,9=v
|
||||
0,0=Is
|
||||
6,0=A
|
||||
6,7=Q
|
||||
|
||||
############
|
||||
@GPSDIST
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=L
|
||||
4,0=O
|
||||
2,10=a
|
||||
3,10=h
|
||||
4,9=v
|
||||
5,9=gC
|
||||
5,13=gB
|
||||
6,7=Q
|
||||
7,0=gV
|
||||
7,2=xd=
|
||||
7,4=gD
|
||||
7,12=gI°
|
||||
|
||||
### Alternative display layouts based on https://gist.github.com/bazjo
|
||||
# Scan display for large 2" TFT dispaly
|
||||
@BatteryOLED
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xBat.Status:
|
||||
0,12=bS
|
||||
1,0=xBatt:
|
||||
1,6=bVV
|
||||
2,0=bCmA (charge)
|
||||
3,0=bDmA (disch.)
|
||||
4,0=xUSB:
|
||||
4,5=bUV
|
||||
5,5=bImA
|
||||
6,0=xTemp:
|
||||
6,5=bT C
|
||||
|
||||
############
|
||||
@Meteo
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=Is
|
||||
0,9=f
|
||||
1,12=t
|
||||
2,0=xSonde
|
||||
3,0=xData
|
||||
2,10=A
|
||||
4,0=Mt°C
|
||||
4,9=Mh%rH
|
||||
6,0=MphPa
|
||||
6,11=MbV
|
||||
|
||||
##################
|
||||
@GPS-Data
|
||||
timer=-1,-1,-1
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,#
|
||||
fonts=0,1
|
||||
0,0=xGPS-Data
|
||||
1,0=xLAT :
|
||||
1,6=gA
|
||||
2,0=xLONG:
|
||||
2,6=gO
|
||||
3,0=xALT :
|
||||
3,9=gH
|
||||
4,0=xSonde
|
||||
5,0=xAlt :
|
||||
5,6=a
|
||||
6,0=xDist:
|
||||
6,6=gD
|
||||
|
||||
#################
|
||||
@TelemetryData
|
||||
scale=22,13
|
||||
timer=-1,-1,N
|
||||
key1action=+,0,F,W
|
||||
key2action=>,#,#,#
|
||||
timeaction=#,#,0
|
||||
fonts=5,6
|
||||
color=FFD700
|
||||
0,0,10.5=Is
|
||||
color=0000FF
|
||||
0,11,-5.5=f
|
||||
1,0,4=t
|
||||
1,10.5,-6=c
|
||||
color=00ff00
|
||||
2,0,7=L
|
||||
3,0,7=O
|
||||
color=FFA500
|
||||
2,9.5,-7=a
|
||||
2.8,9.5,-7=vm/s
|
||||
color=AA5522
|
||||
3.6,9.5,-7=hkkm/h
|
||||
color=FFFFFF
|
||||
4.4,0=xTelemetry Data:
|
||||
5.3,0=Mt C
|
||||
5.3,9=Mh%rH
|
||||
6.5,0=MphPa
|
||||
6.5,11=MbV
|
392
RX_FSK/data/style_map.css
Executable file
392
RX_FSK/data/style_map.css
Executable file
|
@ -0,0 +1,392 @@
|
|||
body, html {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: Arial;
|
||||
}
|
||||
|
||||
.active, .cfgheader:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
.cfgpanel {
|
||||
}
|
||||
|
||||
th.cfg {
|
||||
padding:5pt
|
||||
}
|
||||
table.stat {
|
||||
margin:0px 0px 5px 0px;
|
||||
}
|
||||
|
||||
.hamburger {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 1.25em;
|
||||
height: 0.8em;
|
||||
margin-right: 0.3em;
|
||||
border-top: 0.2em solid #fff;
|
||||
border-bottom: 0.2em solid #fff;
|
||||
}
|
||||
|
||||
.hamburger:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0.3em;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
border-top: 0.2em solid #fff;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
}
|
||||
.tci {
|
||||
flex-grow: 1; border: none; margin: 0; padding: 0;
|
||||
}
|
||||
.footer {
|
||||
background-color: #333;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
td.ch {
|
||||
text-align: right;
|
||||
padding: 0px 8px;
|
||||
}
|
||||
td.act {
|
||||
text-align: center;
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
background-color: #ddd
|
||||
}
|
||||
|
||||
td#caption {
|
||||
text-align: center;
|
||||
background-color: #aaa;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td#sfreq {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
.tabcontent {
|
||||
display: none;
|
||||
flex: 1;
|
||||
border-top: none;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: Helvetica;
|
||||
display: inline-block;
|
||||
margin: 0px auto;
|
||||
text-align: center;
|
||||
}
|
||||
h1{
|
||||
color: #0F3376;
|
||||
font-size: 24px
|
||||
}
|
||||
p{
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.button2 {
|
||||
background-color: #f44336;
|
||||
}
|
||||
:disabled.save {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.save {
|
||||
background-color: #CC1111; /* 0F33C6; */
|
||||
border: white;
|
||||
border-width: 1;
|
||||
color: white;
|
||||
padding: 8px 30px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.ttgoinfo {
|
||||
color: white;
|
||||
padding: 8px 10px;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
margin: 0
|
||||
}
|
||||
.ctlbtn {
|
||||
background-color: #ccc;
|
||||
border: black;
|
||||
border-width: 1;
|
||||
color: black;
|
||||
padding: 4px 30px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
margin: 2;
|
||||
font-size: 4vh;
|
||||
}
|
||||
.update {
|
||||
margin: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#map {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.leaflet-popup-content table, .leaflet-popup-content table td {
|
||||
border:0;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.leaflet-popup-content table td:nth-child(2),.leaflet-popup-content table td:nth-child(5) {
|
||||
text-align: right;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.leaflet-popup-content table td:nth-child(3),.leaflet-popup-content table td:nth-child(6) {
|
||||
text-align: left;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.leaflet-gps{animation:fading 1s infinite}@keyframes fading{0%{opacity:0.7}50%{opacity:1}100%{opacity:0.7}}
|
||||
|
||||
.leaflet-gps::after {
|
||||
content: '🔵';
|
||||
}
|
||||
.leaflet-gps {
|
||||
margin-left: -7px !important;
|
||||
margin-top: -9px !important;
|
||||
}
|
||||
|
||||
.leaflet-burst::after {
|
||||
content: '💥';
|
||||
}
|
||||
.leaflet-burst {
|
||||
margin-left: -20px !important;
|
||||
margin-top: -22px !important;
|
||||
font-weight: bold;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.leaflet-landing::after {
|
||||
content: '×';
|
||||
}
|
||||
|
||||
.leaflet-landing {
|
||||
margin-left: -13px !important;
|
||||
margin-top: -30px !important;
|
||||
font-weight: bold;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
|
||||
.leaflet-header {
|
||||
text-align: center;
|
||||
width: 250px;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
|
||||
.leaflet-header #settings {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.leaflet-header label {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.leaflet-header input {
|
||||
width: 80px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.leaflet-header #submit {
|
||||
margin: 3px auto;
|
||||
}
|
||||
|
||||
.leaflet-footer {
|
||||
display:none;
|
||||
text-align: center;
|
||||
width: 180px;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.leaflet-center {
|
||||
left:0;
|
||||
right:0;
|
||||
margin: 0 auto;
|
||||
padding: 5px;
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.leaflet-header #sonde_detail {
|
||||
display:none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.leaflet-control-attribution {
|
||||
-moz-transform: rotate(-90deg) translateX(100%);
|
||||
-ms-transform: rotate(-90deg) translateX(100%);
|
||||
-o-transform: rotate(-90deg) translateX(100%);;
|
||||
-webkit-transform: rotate(-90deg) translateX(100%);
|
||||
transform: rotate(-90deg) translateX(100%);
|
||||
-webkit-transform-origin: 100% 100%;
|
||||
-moz-transform-origin: 100% 100%;
|
||||
-ms-transform-origin: 100% 100%;
|
||||
-o-transform-origin: 100% 100%;
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.ldot {
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
margin-top: 8px;
|
||||
margin-left: -1px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ybg {
|
||||
background-color: orange;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(yellow), to(orange));
|
||||
background-image: linear-gradient(top, yellow, orange);
|
||||
}
|
||||
.gbg {
|
||||
background-color: green;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(lime), to(green));
|
||||
background-image: linear-gradient(top, lime, green);
|
||||
}
|
||||
.rbg {
|
||||
background-color: red;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(orange), to(red));
|
||||
background-image: linear-gradient(top, orange, red);
|
||||
}
|
||||
|
||||
#sonde_statbar .ldot {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
/* Add a black background color to the top navigation */
|
||||
.topnav {
|
||||
background-color: #333;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Style the links inside the navigation bar */
|
||||
.topnav a {
|
||||
float: left;
|
||||
display: block;
|
||||
color: #f2f2f2;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
/* Change the color of links on hover */
|
||||
.topnav a:hover {
|
||||
background-color: #ddd;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* Add an active class to highlight the current page */
|
||||
.topnav a.active {
|
||||
background-color: #04AA6D;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Hide the link that should open and close the topnav on small screens */
|
||||
.topnav .icon {
|
||||
display: none;
|
||||
padding-bottom: 12px;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */
|
||||
@media screen and (max-width: 600px) {
|
||||
.topnav a:not(.active) {display: none;}
|
||||
.topnav a.icon {
|
||||
float: right;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */
|
||||
@media screen and (max-width: 600px) {
|
||||
.topnav.responsive {position: relative;}
|
||||
.topnav.responsive a.icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
.topnav.responsive a {
|
||||
float: none;
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #333;
|
||||
}
|
||||
h2{
|
||||
color: white;
|
||||
}
|
||||
table, th, td, .save, a.active {
|
||||
color: white;
|
||||
border: 1px solid grey;
|
||||
border-collapse: collapse;
|
||||
background-color: #333;
|
||||
}
|
||||
input, select, .tci, .warning {
|
||||
color: white;
|
||||
background-color: #333;
|
||||
}
|
||||
a:link, a:visited {
|
||||
color: #D3D3D3;
|
||||
}
|
||||
.topnav, td#sfreq {
|
||||
background-color: grey;
|
||||
}
|
||||
.topnav a:visited {
|
||||
color: white;
|
||||
}
|
||||
.ctlbtn {
|
||||
color: white;
|
||||
background-color: grey;
|
||||
}
|
||||
.leaflet-center {
|
||||
color: white;
|
||||
background-color: grey;
|
||||
}
|
||||
.leaflet-bar a {
|
||||
background-color: grey !important;
|
||||
}
|
||||
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||
color: white !important;
|
||||
background: grey !important;
|
||||
}
|
||||
}
|
24
RX_FSK/features.h
Normal file
24
RX_FSK/features.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
// Configuration flags for including/excluding fuctionality from the compiled binary
|
||||
// set flag to 0 for exclude/1 for include
|
||||
|
||||
/* data feed to sondehubv2 */
|
||||
/* needs about 4k4 code, 200b data, 200b stack, 200b heap */
|
||||
#define FEATURE_SONDEHUB 1
|
||||
#define FEATURE_CHASEMAPPER 1
|
||||
#define FEATURE_MQTT 0
|
||||
|
||||
#define FEATURE_RS92 1
|
||||
|
||||
/* Most recent version support fonts in a dedicated flash parition "fonts".
|
||||
* This is incomabtible (in terms of code and flash layout) to previous versions.
|
||||
* If LEGACY_FONTS_IN_CODEBIN is sets, fonts are also included in the bin image.
|
||||
* This maintains compatibility for OTA with previous versions (in which case the
|
||||
* bin image fonts will be used as before).
|
||||
* The code automatically uses fonts in flash partition if that exists, otherwise
|
||||
* fonts in code.
|
||||
* The flash partition fonts support latin15 codeset (instead of 7bit ascii).
|
||||
* Also, it is easier to use different fonts :) just flash the font partition w/ something else...
|
||||
* This option will likely be removed post-master1.0
|
||||
*/
|
||||
#define LEGACY_FONTS_IN_CODEBIN 1
|
43
RX_FSK/src/Chasemapper.cpp
Normal file
43
RX_FSK/src/Chasemapper.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "Chasemapper.h"
|
||||
|
||||
extern const char *sondeTypeStrSH[];
|
||||
|
||||
int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) {
|
||||
char buf[1024];
|
||||
struct tm tim;
|
||||
time_t t = si->d.time;
|
||||
gmtime_r(&t, &tim);
|
||||
uint8_t realtype = si->type;
|
||||
if (TYPE_IS_METEO(realtype)) {
|
||||
realtype = si->d.subtype == 1 ? STYPE_M10 : STYPE_M20;
|
||||
}
|
||||
sprintf(buf, "{ \"type\": \"PAYLOAD_SUMMARY\","
|
||||
"\"callsign\": \"%s\","
|
||||
"\"latitude\": %.5f,"
|
||||
"\"longitude\": %.5f,"
|
||||
"\"altitude\": %d,"
|
||||
"\"speed\": %d,"
|
||||
"\"heading\": %d,"
|
||||
"\"time\": \"%02d:%02d:%02d\","
|
||||
"\"model\": \"%s\","
|
||||
"\"freq\": \"%.3f MHz\"",
|
||||
si->d.ser,
|
||||
si->d.lat,
|
||||
si->d.lon,
|
||||
(int)si->d.alt,
|
||||
(int)(si->d.hs * 1.9438445), // m/s into knots
|
||||
(int)si->d.dir,
|
||||
tim.tm_hour, tim.tm_min, tim.tm_sec,
|
||||
sondeTypeStrSH[realtype],
|
||||
si->freq);
|
||||
if( !isnan(si->d.temperature) ) {
|
||||
sprintf(buf + strlen(buf), ", \"temp\": %.1f", si->d.temperature);
|
||||
}
|
||||
strcat(buf, "}");
|
||||
Serial.printf("Sending chasemapper json: %s\n", buf);
|
||||
udp.beginPacket(sonde.config.cm.host, sonde.config.cm.port);
|
||||
udp.write((const uint8_t *)buf, strlen(buf));
|
||||
udp.endPacket();
|
||||
return 0;
|
||||
}
|
||||
|
13
RX_FSK/src/Chasemapper.h
Normal file
13
RX_FSK/src/Chasemapper.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef _CHASEMAPPER_H
|
||||
#define _CHASEMAPPER_H
|
||||
|
||||
#include "Sonde.h"
|
||||
//#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <time.h>
|
||||
class Chasemapper {
|
||||
public:
|
||||
static int send(WiFiUDP &udb, SondeInfo *si);
|
||||
};
|
||||
|
||||
#endif
|
693
RX_FSK/src/DFM.cpp
Normal file
693
RX_FSK/src/DFM.cpp
Normal file
|
@ -0,0 +1,693 @@
|
|||
|
||||
/* DFM decoder functions */
|
||||
#include "DFM.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
#define DFM_DEBUG 0
|
||||
|
||||
#if DFM_DEBUG
|
||||
#define DFM_DBG(x) x
|
||||
#else
|
||||
#define DFM_DBG(x)
|
||||
#endif
|
||||
|
||||
#define DFM_FRAMELEN 33
|
||||
|
||||
#define MAXIDAGE 1800
|
||||
|
||||
/*
|
||||
* observed DAT patterns for DFM-9:
|
||||
* A: 0+1; 2+3; 4+5; 6+7; 8+0 => keep frame in shadowFrame
|
||||
* B: 1+2; 3+4; 5+6; 7+8 => all good => keep date in shadowDate
|
||||
* C: 0+1; 2+3; 4+5; 6+7; 8+15 => all good => keep date in shadowDate
|
||||
* D: 0+1; 2+3; 4+5; 6+7; 0+1 => use shadowDate
|
||||
* not seen:5+6; 7+1
|
||||
* values:
|
||||
* 0:packet counter; 1:utc-msec; 2:lat,vh; 3:lon,dir, 4:alt,vv, 8=utc-date(day-hh-mm)
|
||||
*/
|
||||
|
||||
// single data structure, search restarts after decoder change
|
||||
static struct st_dfmstat {
|
||||
int idcnt0;
|
||||
int idcnt1;
|
||||
int lastfrid;
|
||||
int lastfrcnt;
|
||||
uint8_t start[50];
|
||||
uint16_t dat[50*2];
|
||||
uint8_t cnt[50*2];
|
||||
uint16_t good;
|
||||
uint32_t datesec;
|
||||
uint8_t frame;
|
||||
uint16_t msec;
|
||||
uint8_t nameregok;
|
||||
uint8_t nameregtop;
|
||||
uint8_t lastdat;
|
||||
uint8_t cycledone; // 0=no; 1=OK, 2=partially/with errors
|
||||
float meas[5+2];
|
||||
} dfmstate;
|
||||
|
||||
decoderSetupCfg DFMSetupCfg {
|
||||
.bitrate = 2500,
|
||||
// continuous mode
|
||||
// Enable auto-AFC, auto-AGC, RX Trigger by preamble ????
|
||||
.rx_cfg = 0x1E,
|
||||
.sync_cfg = 0x70,
|
||||
.sync_len = 2,
|
||||
.sync_data = (const uint8_t *)"\xAA\xAA",
|
||||
.preamble_cfg = 0xA8,
|
||||
};
|
||||
|
||||
int DFM::setup(float frequency, int type)
|
||||
{
|
||||
stype = type;
|
||||
#if DFM_DEBUG
|
||||
Serial.printf("Setup sx1278 for DFM sonde (type=%d)\n", stype);
|
||||
#endif
|
||||
if(sx1278.ON()!=0) {
|
||||
DFM_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(DecoderBase::setup(DFMSetupCfg, sonde.config.dfm.agcbw, sonde.config.dfm.rxbw) != 0) {
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
// This is now all done by the generic setup method in base class
|
||||
if(sx1278.setFSK()!=0) {
|
||||
DFM_DBG(Serial.println("Setting FSM mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setBitrate(2500)!=0) {
|
||||
DFM_DBG(Serial.println("Setting bitrate 2500bit/s FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setAFCBandwidth(sonde.config.dfm.agcbw)!=0) {
|
||||
DFM_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.dfm.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.dfm.rxbw)!=0) {
|
||||
DFM_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.dfm.rxbw));
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if(sx1278.setRxConf(0x1E)!=0) {
|
||||
DFM_DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// working with continuous RX
|
||||
const char *SYNC="\xAA\xAA";
|
||||
if(sx1278.setSyncConf(0x70, 2, (const uint8_t *)SYNC)!=0) {
|
||||
DFM_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setPreambleDetect(0xA8)!=0) {
|
||||
//if(sx1278.setPreambleDetect(0x9F)!=0) {
|
||||
DFM_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(sx1278.setPacketConfig(0x08, 0x40)!=0) {
|
||||
DFM_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
sx1278.setPayloadLength(0); // infinite for now...
|
||||
Serial.print("DFM: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
|
||||
int retval = sx1278.setFrequency(frequency);
|
||||
sx1278.clearIRQFlags();
|
||||
|
||||
// Do this only once in setup in continous mode
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
|
||||
memset((void *)&dfmstate, 0, sizeof(dfmstate));
|
||||
DFM_DBG(Serial.println("Setting SX1278 config for DFM finished\n"); Serial.println());
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
#define bitpick(value,bitpos) (((value)>>(7-(bitpos)))&0x01)
|
||||
// Input: str: packed data, MSB first
|
||||
void DFM::deinterleave(uint8_t *str, int L, uint8_t *block) {
|
||||
int i, j;
|
||||
for (j = 0; j < B; j++) { // L = 7 (CFG), 13 (DAT1, DAT2)
|
||||
for (i = 0; i < L; i++) {
|
||||
block[B*i+j] = bitpick( str[(L*j+i)/8], (L*j+i)&7 )?0:1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DFM::bits2val(const uint8_t *bits, int len) {
|
||||
uint32_t val = 0;
|
||||
for (int j = 0; j < len; j++) {
|
||||
val |= (bits[j] << (len-1-j));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// Error correction for hamming code
|
||||
// returns 0: ok >0: 1 error was corrected -1: uncorrectable error
|
||||
int DFM::check(uint8_t code[8]) {
|
||||
int i, j;
|
||||
uint32_t synval = 0;
|
||||
uint8_t syndrom[4];
|
||||
int ret=0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
syndrom[i] = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
syndrom[i] ^= H[i][j] & code[j];
|
||||
}
|
||||
}
|
||||
synval = bits2val(syndrom, 4);
|
||||
if (synval) {
|
||||
ret = -1;
|
||||
for (j = 0; j < 8; j++) { // 1-bit-error
|
||||
if (synval == He[j]) { // reicht auf databits zu pruefen, d.h.
|
||||
ret = j+1; // (systematischer Code) He[0..3]
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else ret = 0;
|
||||
if (ret > 0) code[ret-1] ^= 0x1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Extended (8,4) Hamming code
|
||||
// Return number of corrected bits, -1 if uncorrectable error
|
||||
int DFM::hamming(uint8_t *ham, int L, uint8_t *sym) {
|
||||
int i, j;
|
||||
int ret = 0; // DFM: length L = 7 or 13
|
||||
for (i = 0; i < L; i++) { // L bytes (4bit data, 4bit parity)
|
||||
if (use_ecc) {
|
||||
int res = check(ham+8*i);
|
||||
if( res<0 ) ret = -1;
|
||||
else if ( ret >= 0 && res > 0 ) ret++;
|
||||
}
|
||||
// systematic Hamming code: copy bits 0..3
|
||||
for (j = 0; j < 4; j++) {
|
||||
sym[4*i+j] = ham[8*i+j];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DFM::DFM() {
|
||||
}
|
||||
|
||||
void DFM::printRaw(const char *label, int len, int ret, const uint8_t *data)
|
||||
{
|
||||
Serial.print(label); Serial.print("(");
|
||||
Serial.print(ret);
|
||||
Serial.print("):");
|
||||
int i;
|
||||
for(i=0; i<len/2; i++) {
|
||||
char str[10];
|
||||
snprintf(str, 10, "%02X", data[i]);
|
||||
Serial.print(str);
|
||||
}
|
||||
Serial.print(data[i]&0x0F, HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
|
||||
const char* typestr[16]={
|
||||
"", "", "", "", "", "", // 00..05
|
||||
"DFM6", // 06 => DFM6
|
||||
"PS15", // 07 => PS15 (untested)
|
||||
"", "",
|
||||
"DFM9", // 0A => DFM9
|
||||
"DF17", // 0B => DFM17?
|
||||
"DF9P", // 0C => DFM9P or DFM17 test
|
||||
"DF17", // 0D => DFM17
|
||||
"", ""
|
||||
};
|
||||
|
||||
void DFM::killid() {
|
||||
SondeData *sd = &(sonde.si()->d);
|
||||
sd->validID = false;
|
||||
*(sd->id) = 0;
|
||||
*(sd->ser) = 0;
|
||||
memset((void *)&dfmstate, 0, sizeof(dfmstate));
|
||||
}
|
||||
|
||||
#define DFMIDTHRESHOLD 2
|
||||
/* inspired by oe5dxl's finddnmae in sondeudp.c of dxlaprs */
|
||||
void DFM::finddfname(uint8_t *b)
|
||||
{
|
||||
uint8_t st;
|
||||
uint32_t thres;
|
||||
uint32_t i;
|
||||
uint8_t ix;
|
||||
uint16_t d;
|
||||
SondeData *sd = &(sonde.si()->d);
|
||||
|
||||
st = b[0]; /* frame start byte */
|
||||
ix = b[3]; /* hi/lo part of ser; (LSB due to our bitsToBytes...) */
|
||||
d = (b[1]<<8) + b[2]; /* data byte */
|
||||
/* find highest channel number single frame serial,
|
||||
(2 frame serial will make a single serial too) */
|
||||
if(dfmstate.idcnt0 < DFMIDTHRESHOLD && dfmstate.idcnt1 < DFMIDTHRESHOLD) {
|
||||
uint32_t v = (st<<20) | (d<<4) | ix;
|
||||
if ( st > (dfmstate.lastfrid>>20) ) {
|
||||
dfmstate.lastfrid = v;
|
||||
Serial.print(" MAXCH:"); Serial.print(st);
|
||||
dfmstate.lastfrcnt = 0;
|
||||
} else if ( st == (dfmstate.lastfrid>>20) ) {
|
||||
/* same id found */
|
||||
if (v == dfmstate.lastfrid) {
|
||||
++dfmstate.lastfrcnt;
|
||||
thres = DFMIDTHRESHOLD * 2;
|
||||
/* may be a 2 frame serial so increase safety level */
|
||||
if (ix <= 1) thres *= 2;
|
||||
/* may be not a dfm6 so increase safety level */
|
||||
if ( (st>>4) != 6) thres *= 2;
|
||||
if (dfmstate.lastfrcnt >= thres) {
|
||||
/* id found */
|
||||
if (dfmstate.lastfrcnt == thres) {
|
||||
uint32_t id = ((st&0x0F)<<20) | (d<<4) | ix;
|
||||
uint32_t chkid = id;
|
||||
int i;
|
||||
/* check validity */
|
||||
for(i=0; i<6; i++) {
|
||||
if((chkid&0x0f)>9) { break; /* not ok */ }
|
||||
chkid >>= 4;
|
||||
}
|
||||
if(i==6) {
|
||||
snprintf(sd->id, 10, "D%x ", id);
|
||||
memcpy(sd->ser, sd->id+1, 9);
|
||||
sd->validID = true;
|
||||
sd->subtype = (st>>4)&0x0F;
|
||||
strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5);
|
||||
return;
|
||||
}
|
||||
dfmstate.lastfrcnt = 0;
|
||||
Serial.print(" NOT NUMERIC SERIAL");
|
||||
}
|
||||
//anonym->idtime = osic_time();
|
||||
} else {
|
||||
Serial.print(" MAXCHCNT/SECLVL:");
|
||||
Serial.print(dfmstate.lastfrcnt);
|
||||
Serial.print("/");
|
||||
Serial.print(thres);
|
||||
}
|
||||
} else {
|
||||
dfmstate.lastfrid = v; /* not stable ser */
|
||||
dfmstate.lastfrcnt = 0UL;
|
||||
}
|
||||
}
|
||||
} /*find highest channel number single frame serial */
|
||||
|
||||
i = 0;
|
||||
while (i<dfmstate.nameregtop && dfmstate.start[i]!=st) i++;
|
||||
Serial.printf(" %02x:i=%d,top=%d", st, i, dfmstate.nameregtop);
|
||||
if (i<dfmstate.nameregtop) {
|
||||
if (ix<=1UL && (dfmstate.cnt[2*i+ix]==0 || dfmstate.dat[2*i+ix]==d)) {
|
||||
dfmstate.dat[2*i+ix] = d;
|
||||
if(dfmstate.cnt[2*i+ix] < 255) dfmstate.cnt[2*i+ix]++;
|
||||
Serial.print(" ID:");
|
||||
Serial.print(st, HEX);
|
||||
Serial.print("[");
|
||||
Serial.print(ix);
|
||||
Serial.print("] CNT:");
|
||||
Serial.print(dfmstate.cnt[2*i]);
|
||||
Serial.print(",");
|
||||
Serial.print(dfmstate.cnt[2*i+1]);
|
||||
Serial.print(",st=");
|
||||
Serial.print(st);
|
||||
Serial.print(",lastfrid=");
|
||||
Serial.print(dfmstate.lastfrid>>20);
|
||||
if( (dfmstate.cnt[2*i]>DFMIDTHRESHOLD && dfmstate.cnt[2*i+1]>DFMIDTHRESHOLD) ||
|
||||
(dfmstate.cnt[2*i]>0 && dfmstate.cnt[2*i+1]>0 && st == (dfmstate.lastfrid>>20) && (st>>4)>6) ) {
|
||||
if(dfmstate.idcnt0 <= 1) {
|
||||
dfmstate.idcnt0 = dfmstate.cnt[2*i];
|
||||
dfmstate.idcnt1 = dfmstate.cnt[2*i+1];
|
||||
dfmstate.nameregok = i;
|
||||
// generate id.....
|
||||
snprintf(sd->id, 10, "D%d", ((dfmstate.dat[2*i]<<16)|dfmstate.dat[2*i+1])%100000000);
|
||||
Serial.print("\nNEW AUTOID:");
|
||||
Serial.println(sd->id);
|
||||
memcpy(sd->ser, sd->id+1, 9);
|
||||
sd->validID = true;
|
||||
sd->subtype = (st>>4)&0x0F;
|
||||
strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5);
|
||||
}
|
||||
if(dfmstate.nameregok==i) {
|
||||
Serial.print(" ID OK");
|
||||
// idtime = .... /* TODO */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* data changed so not ser */
|
||||
dfmstate.cnt[2*i] = 0;
|
||||
dfmstate.cnt[2*i+1] = 0;
|
||||
if(dfmstate.nameregok == i) { /* found id wrong */
|
||||
dfmstate.idcnt0 = 0;
|
||||
dfmstate.idcnt1 = 0;
|
||||
}
|
||||
}
|
||||
} else if (ix<=1) { /* add new entry for possible ID */
|
||||
dfmstate.start[dfmstate.nameregtop] = st;
|
||||
dfmstate.cnt[2*dfmstate.nameregtop] = 0;
|
||||
dfmstate.cnt[2*dfmstate.nameregtop+1] = 0;
|
||||
dfmstate.cnt[2*dfmstate.nameregtop+ix] = 1;
|
||||
dfmstate.dat[2*dfmstate.nameregtop+ix] = d;
|
||||
if(dfmstate.nameregtop<49) dfmstate.nameregtop++;
|
||||
}
|
||||
}
|
||||
|
||||
static float get_Temp() {
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
if(!si->validID) { // type not yet known, so don't try to decode
|
||||
return NAN;
|
||||
}
|
||||
float f = dfmstate.meas[0],
|
||||
f1 = dfmstate.meas[3],
|
||||
f2 = dfmstate.meas[4];
|
||||
if(si->subtype >= 0x0C) {
|
||||
f = dfmstate.meas[1];
|
||||
f1 = dfmstate.meas[5];
|
||||
f2 = dfmstate.meas[6];
|
||||
}
|
||||
Serial.printf("Meas: %f %f %f\n", f, f1, f2);
|
||||
// as in autorx / dfm
|
||||
float BB0 = 3260.0; // B/Kelvin, fit -55C..+40C
|
||||
float T0 = 25 + 273.15; // t0=25C
|
||||
float R0 = 5.0e3; // R0=R25=5k
|
||||
float Rf = 220e3; // Rf = 220k
|
||||
float g = f2/Rf;
|
||||
float R = (f-f1) / g; // meas[0,3,4] > 0 ?
|
||||
float T = 0; // T/Kelvin
|
||||
if (f*f1*f2 == 0) R = 0;
|
||||
if (R > 0) T = 1/(1/T0 + 1/BB0 * log(R/R0));
|
||||
T = T - 273.15; // Celsius
|
||||
if(T<-100 || T>50) {
|
||||
Serial.printf("Temperature invalid: %f\n", T);
|
||||
return NAN;
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
void DFM::decodeCFG(uint8_t *cfg)
|
||||
{
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
// new ID
|
||||
finddfname(cfg);
|
||||
// get meas
|
||||
uint8_t conf_id = (*cfg)>>4;
|
||||
if(conf_id<=6) {
|
||||
uint32_t val = (cfg[1]<<12) | (cfg[2]<<4) | cfg[3];
|
||||
uint8_t exp = cfg[0] & 0xF;
|
||||
dfmstate.meas[conf_id] = val / (float)(1<<exp);
|
||||
Serial.printf("meas %d is %f (%d,%d)\n", conf_id, dfmstate.meas[conf_id], val, exp);
|
||||
}
|
||||
// get batt
|
||||
if(si->validID && si->subtype>=0x0A) {
|
||||
// otherwise don't try, as we might not have the right type yet...
|
||||
int cid = (si->subtype >= 0x0C) ? 0x7 : 0x5;
|
||||
if(conf_id == cid) {
|
||||
uint16_t val = cfg[1]<<8 | cfg[2];
|
||||
si->batteryVoltage = val / 1000.0;
|
||||
Serial.printf("battery: %f\n", si->batteryVoltage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// not used any more
|
||||
static int bitCount(int x) {
|
||||
int m4 = 0x1 | (0x1<<8) | (0x1<<16) | (0x1<<24);
|
||||
int m1 = 0xFF;
|
||||
int s4 = (x&m4) + ((x>>1)&m4) + ((x>>2)&m4) + ((x>>3)&m4) + ((x>>4)&m4) + ((x>>5)&m4) + ((x>>6)&m4) + ((x>>7)&m4);
|
||||
int s1 = (s4&m1) + ((s4>>8)&m1) + ((s4>>16)&m1) + ((s4>>24)&m1);
|
||||
return s1;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t MON[]={0,0,31,59,90,120,151,181,212,243,273,304,334};
|
||||
|
||||
void DFM::decodeDAT(uint8_t *dat)
|
||||
{
|
||||
// TODO: Here we need to work on a shadow copy of SondeData in order to prevent concurrent changes while using data in main loop
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
Serial.print(" DAT["); Serial.print(dat[6]); Serial.print("]: ");
|
||||
|
||||
// We handle this case already here, because we need to update dfmstate.datesec before the cycle complete handling
|
||||
if( dat[6]==8 ) {
|
||||
int y = (dat[0]<<4) + (dat[1]>>4);
|
||||
int m = dat[1]&0x0F;
|
||||
int d = dat[2]>>3;
|
||||
int h = ((dat[2]&0x07)<<2) + (dat[3]>>6);
|
||||
int mi = (dat[3]&0x3F);
|
||||
Serial.printf("Date: %04d-%02d-%02d %02d:%02dz ", y, m, d, h, mi);
|
||||
si->sats = dat[4];
|
||||
si->validPos |= 0x40;
|
||||
// convert to unix time
|
||||
int tt = (y-1970)*365 + (y-1969)/4; // days since 1970
|
||||
if(m<=12) { tt += MON[m]; if((y%4)==0 && m>2) tt++; }
|
||||
tt = (tt+d-1)*(60*60*24) + h*3600 + mi*60;
|
||||
// If we get a time stamp much different to the previously received one, kill the ID.
|
||||
// most likely, we have a new sonde now, so wait for the new ID.
|
||||
if(tt-dfmstate.datesec > MAXIDAGE) killid();
|
||||
dfmstate.datesec = tt;
|
||||
dfmstate.good |= 0x100;
|
||||
}
|
||||
else if( dat[6]>8 ) return; // we ignore those...
|
||||
|
||||
/* Here we update data that should be updated only after receiving a "complete" frame (mainly for consistent SondeHub exports)
|
||||
* We do this (a) when there is a DAT8 block and (b) when there is wrap from DAT7 to DAT0, for these fields:
|
||||
* => frame
|
||||
* => vframe (only used for SondeHub as virtual frame number)
|
||||
* => time (calculated with using date and msec)
|
||||
* [assuming that if there is no DAT8, then the date value did not change.]
|
||||
*/
|
||||
|
||||
if( dat[6]==8 || dat[6] < dfmstate.lastdat) { // After DAT8, or after a "warp around"
|
||||
if( dfmstate.good&1 ) si->frame = dfmstate.frame;
|
||||
if( (dfmstate.good&0x102)==0x102 ) {
|
||||
si->time = dfmstate.datesec + dfmstate.msec/1000;
|
||||
// Lets be consistent with autorx: the timestamp uses the msec value truncated to seconds,
|
||||
// whereas the virtual frame number for DFM uses the msec value rounded to full seconds.
|
||||
// Actually, tt is real UTC, and the transformation to GPS seconds lacks adjusting for leap seconds
|
||||
si->vframe = dfmstate.datesec + (dfmstate.msec+500)/1000 - 315964800;
|
||||
}
|
||||
// All fields updated? 1=OK, 2=with errors
|
||||
Serial.printf("Cycle done: good is %x\n", dfmstate.good);
|
||||
si->temperature = get_Temp();
|
||||
Serial.printf("Temp: %f\n", si->temperature);
|
||||
dfmstate.cycledone = ((dfmstate.good&0x11F)==0x11F) ? 1 : 2;
|
||||
dfmstate.good = 0;
|
||||
dfmstate.lastdat = 0;
|
||||
} else {
|
||||
dfmstate.lastdat = dat[6];
|
||||
}
|
||||
dfmstate.good |= (1<<dat[6]);
|
||||
switch(dat[6]) {
|
||||
case 0:
|
||||
Serial.print("Packet counter: "); Serial.print(dat[3]);
|
||||
dfmstate.frame = dat[3];
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
int val = (((uint16_t)dat[4])<<8) + (uint16_t)dat[5];
|
||||
Serial.print("UTC-msec: "); Serial.print(val);
|
||||
dfmstate.msec = val;
|
||||
//uint32_t tmp = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + ((uint32_t)dat[3]);
|
||||
//si->sats = bitCount(tmp);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
float lat, vh;
|
||||
lat = (int32_t)(((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + ((uint32_t)dat[3]));
|
||||
vh = ((uint16_t)dat[4]<<8) + dat[5];
|
||||
Serial.print("GPS-lat: "); Serial.print(lat*0.0000001);
|
||||
Serial.print(", hor-V: "); Serial.print(vh*0.01);
|
||||
lat = lat*0.0000001;
|
||||
if( lat!=0 && si->lat!=0 && abs(lat-si->lat)>.25 ) killid();
|
||||
si->lat = lat;
|
||||
si->hs = vh*0.01;
|
||||
if(lat!=0 || vh!=0) si->validPos |= 0x11; else si->validPos &= ~0x11;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
float lon, dir;
|
||||
lon = (int32_t)(((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + (uint32_t)dat[3]);
|
||||
dir = ((uint16_t)dat[4]<<8) + dat[5];
|
||||
lon = lon*0.0000001;
|
||||
if( lon!=0 && si->lon!=0 && abs(lon-si->lon)>.25 ) killid();
|
||||
si->lon = lon;
|
||||
si->dir = dir*0.01;
|
||||
Serial.print("GPS-lon: "); Serial.print(si->lon);
|
||||
Serial.print(", dir: "); Serial.print(si->dir);
|
||||
if(lon != 0 || dir != 0) si->validPos |= 0x22; else si->validPos &= ~0x22;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
float alt, vv;
|
||||
alt = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + dat[3];
|
||||
vv = (int16_t)( ((int16_t)dat[4]<<8) | dat[5] );
|
||||
Serial.print("GPS-height: "); Serial.print(alt*0.01);
|
||||
Serial.print(", vv: "); Serial.print(vv*0.01);
|
||||
si->alt = alt*0.01;
|
||||
si->vs = vv*0.01;
|
||||
if(alt!=0 || vv != 0) si->validPos |= 0x0C; else si->validPos &= ~0x0C;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
// handled above
|
||||
break;
|
||||
default:
|
||||
Serial.print("(?)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DFM::bitsToBytes(uint8_t *bits, uint8_t *bytes, int len)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<len*4; i++) {
|
||||
//Serial.print(bits[i]?"1":"0");
|
||||
bytes[i/8] = (bytes[i/8]<<1) | (bits[i]?1:0);
|
||||
}
|
||||
bytes[(i-1)/8] &= 0x0F;
|
||||
}
|
||||
|
||||
static int haveNewFrame = 0;
|
||||
|
||||
int DFM::processDFMdata(uint8_t dt) {
|
||||
static uint8_t data[1024];
|
||||
static uint32_t rxdata = 0;
|
||||
static uint8_t rxbitc = 0;
|
||||
static uint8_t rxbyte = 0;
|
||||
static uint8_t rxsearching = 1;
|
||||
static uint8_t rxp;
|
||||
static int rssi=0, fei=0, afc=0;
|
||||
static uint8_t invers = 0;
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
uint8_t d = (dt&0x80)?1:0;
|
||||
dt <<= 1;
|
||||
rxdata = (rxdata<<1) | d;
|
||||
if( (rxbitc&1)==0 ) {
|
||||
// "bit1"
|
||||
rxbyte = (rxbyte<<1) | d;
|
||||
} else {
|
||||
// "bit2" ==> 01 or 10 => 1, otherweise => 0
|
||||
// not here: (10=>1, 01=>0)!!! rxbyte = rxbyte ^ d;
|
||||
}
|
||||
//
|
||||
if(rxsearching) {
|
||||
if( rxdata == 0x6566A5AA || rxdata == 0x9A995A55 ) {
|
||||
rxsearching = false;
|
||||
rxbitc = 0;
|
||||
rxp = 0;
|
||||
rxbyte = 0;
|
||||
rssi=sx1278.getRSSI();
|
||||
fei=sx1278.getFEI();
|
||||
afc=sx1278.getAFC();
|
||||
sonde.si()->rssi = rssi;
|
||||
sonde.si()->afc = afc;
|
||||
invers = (rxdata == 0x6566A5AA)?1:0;
|
||||
}
|
||||
} else {
|
||||
rxbitc = (rxbitc+1)%16; // 16;
|
||||
if(rxbitc == 0) { // got 8 data bit
|
||||
if(invers) rxbyte=~rxbyte;
|
||||
data[rxp++] = rxbyte&0xff; // (rxbyte>>1)&0xff;
|
||||
if(rxp>=DFM_FRAMELEN) {
|
||||
rxsearching = true;
|
||||
//Serial.println("Got a DFM frame!");
|
||||
Serial.print("[RSSI="); Serial.print(rssi);
|
||||
Serial.print(" FEI="); Serial.print(fei);
|
||||
Serial.print(" AFC="); Serial.print(afc); Serial.print("] ");
|
||||
decodeFrameDFM(data);
|
||||
haveNewFrame = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DFM::receive() {
|
||||
int rxframes = 5; // UP TO 5 frames, stop at type 8 frame
|
||||
|
||||
// tentative continuous RX version...
|
||||
unsigned long t0 = millis();
|
||||
dfmstate.cycledone = 0;
|
||||
while( ( millis() - t0 ) < 1300 ) {
|
||||
uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
if ( bitRead(value, 7) ) {
|
||||
Serial.println("FIFO full");
|
||||
}
|
||||
if ( bitRead(value, 4) ) {
|
||||
Serial.println("FIFO overflow");
|
||||
// new: (maybe clear only overflow??) TODO
|
||||
sx1278.clearIRQFlags();
|
||||
}
|
||||
if ( bitRead(value, 2) == 1 ) {
|
||||
Serial.println("FIFO: payload ready()");
|
||||
// does not make much sence? (from m10): TODO
|
||||
// ??????? sx1278.clearIRQFlags();
|
||||
}
|
||||
if(bitRead(value, 6) == 0) { // while FIFO not empty
|
||||
byte data = sx1278.readRegister(REG_FIFO);
|
||||
processDFMdata(data);
|
||||
value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
} else {
|
||||
if(haveNewFrame) {
|
||||
//Serial.printf("DFM::receive(): new frame complete after %ldms\n", millis()-t0);
|
||||
haveNewFrame = 0;
|
||||
rxframes--;
|
||||
// OK: All DAT frames (0/1/2/3/4/8) have been received in the last cycle
|
||||
if(dfmstate.cycledone==1) return RX_OK;
|
||||
if(dfmstate.cycledone>1 || rxframes==0) return RX_ERROR;
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
return rxframes == 5 ? RX_TIMEOUT : RX_ERROR;
|
||||
}
|
||||
|
||||
int DFM::decodeFrameDFM(uint8_t *data) {
|
||||
deinterleave(data, 7, hamming_conf);
|
||||
deinterleave(data+7, 13, hamming_dat1);
|
||||
deinterleave(data+20, 13, hamming_dat2);
|
||||
|
||||
int ret0 = hamming(hamming_conf, 7, block_conf);
|
||||
int ret1 = hamming(hamming_dat1, 13, block_dat1);
|
||||
int ret2 = hamming(hamming_dat2, 13, block_dat2);
|
||||
//Serial.printf("Hamming returns %d %d %d -- %d\n", ret0, ret1, ret2, ret0|ret1|ret2);
|
||||
|
||||
byte byte_conf[4], byte_dat1[7], byte_dat2[7];
|
||||
bitsToBytes(block_conf, byte_conf, 7);
|
||||
bitsToBytes(block_dat1, byte_dat1, 13);
|
||||
bitsToBytes(block_dat2, byte_dat2, 13);
|
||||
|
||||
printRaw("CFG", 7, ret0, byte_conf);
|
||||
printRaw("DAT", 13, ret1, byte_dat1);
|
||||
printRaw("DAT", 13, ret2, byte_dat2);
|
||||
if (ret0>=0) decodeCFG(byte_conf);
|
||||
if (ret1>=0 && ret1<=4) decodeDAT(byte_dat1);
|
||||
if (ret2>=0 && ret2<=4) decodeDAT(byte_dat2);
|
||||
Serial.println("");
|
||||
// Consistent with autorx: If more than 4 corrected bit errors in DAT block, assume it is possibly corrupt and
|
||||
// don't treat it as a correct frame (ttgo display shows data anyway, but it is not sent to external sites)
|
||||
if(ret1>4 || ret2>4) return RX_ERROR;
|
||||
return (ret0|ret1|ret2)>=0 ? RX_OK : RX_ERROR;
|
||||
}
|
||||
|
||||
// moved to a single function in Sonde(). This function can be used for additional
|
||||
// processing here, that takes too long for doing in the RX task loop
|
||||
int DFM::waitRXcomplete() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DFM dfm = DFM();
|
13
libraries/SondeLib/DFM.h → RX_FSK/src/DFM.h
Executable file → Normal file
13
libraries/SondeLib/DFM.h → RX_FSK/src/DFM.h
Executable file → Normal file
|
@ -15,24 +15,31 @@
|
|||
#ifndef inttypes_h
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include "DecoderBase.h"
|
||||
|
||||
#define DFM_NORMAL 0
|
||||
#define DFM_INVERSE 1
|
||||
|
||||
/* Main class */
|
||||
class DFM
|
||||
class DFM : public DecoderBase
|
||||
{
|
||||
private:
|
||||
int inverse=0;
|
||||
int stype;
|
||||
char *stypename=NULL;
|
||||
|
||||
void deinterleave(uint8_t *str, int L, uint8_t *block);
|
||||
uint32_t bits2val(const uint8_t *bits, int len);
|
||||
int check(uint8_t code[8]);
|
||||
int hamming(uint8_t *ham, int L, uint8_t *sym);
|
||||
void printRaw(const char *prefix, int len, int ret, const uint8_t* data);
|
||||
void finddfname(uint8_t *cfg);
|
||||
void decodeCFG(uint8_t *cfg);
|
||||
void decodeDAT(uint8_t *dat);
|
||||
void bitsToBytes(uint8_t *bits, uint8_t *bytes, int len);
|
||||
int processDFMdata(uint8_t dt);
|
||||
int decodeFrameDFM(uint8_t *data);
|
||||
void killid();
|
||||
|
||||
|
||||
#define B 8
|
||||
#define S 4
|
||||
|
@ -55,7 +62,7 @@ private:
|
|||
public:
|
||||
DFM();
|
||||
// main decoder API
|
||||
int setup(float frequency, int inverse);
|
||||
int setup(float frequency, int type);
|
||||
int receive();
|
||||
int waitRXcomplete();
|
||||
|
51
RX_FSK/src/DecoderBase.cpp
Normal file
51
RX_FSK/src/DecoderBase.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "DecoderBase.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
#define DECODERBASE_DEBUG 1
|
||||
|
||||
#if DECODERBASE_DEBUG
|
||||
#define DBG(x) x
|
||||
#else
|
||||
#define DBG(x)
|
||||
#endif
|
||||
|
||||
|
||||
int DecoderBase::setup(decoderSetupCfg &setupcfg, uint16_t agcbw, uint16_t rxbw) {
|
||||
if(sx1278.setFSK()!=0) {
|
||||
DBG(Serial.println("Setting FSK mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setBitrate(setupcfg.bitrate)!=0) {
|
||||
DBG(Serial.println("Setting bitrate FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#if DECODERBASE_DEBUG
|
||||
float br = sx1278.getBitrate();
|
||||
Serial.print("Exact bitrate is ");
|
||||
Serial.println(br);
|
||||
#endif
|
||||
if(sx1278.setAFCBandwidth(agcbw)!=0) {
|
||||
DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(rxbw)!=0) {
|
||||
DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", rxbw));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(sx1278.setRxConf(setupcfg.rx_cfg)!=0) {
|
||||
DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setSyncConf(setupcfg.sync_cfg, setupcfg.sync_len, setupcfg.sync_data)!=0) {
|
||||
DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setPreambleDetect(setupcfg.preamble_cfg)!=0) {
|
||||
DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
38
RX_FSK/src/DecoderBase.h
Normal file
38
RX_FSK/src/DecoderBase.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
|
||||
#ifndef DECODER_BASE_H
|
||||
#define DECODER_BASE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
#ifndef inttypes_h
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include "Sonde.h"
|
||||
|
||||
typedef struct _decoderSetupCfg {
|
||||
uint16_t bitrate;
|
||||
//uint16_t agcbw;
|
||||
//uint16_t rxbw;
|
||||
uint8_t rx_cfg;
|
||||
uint8_t sync_cfg;
|
||||
uint8_t sync_len;
|
||||
const uint8_t *sync_data;
|
||||
uint8_t preamble_cfg;
|
||||
} decoderSetupCfg;
|
||||
|
||||
/* Generic base class for all sonde decoders */
|
||||
class DecoderBase
|
||||
{
|
||||
protected:
|
||||
|
||||
public:
|
||||
int setup(decoderSetupCfg &setupcfg, uint16_t agcbw, uint16_t rxbw);
|
||||
virtual int setup(float frequency, int type=0) = 0;
|
||||
|
||||
virtual int receive() = 0;
|
||||
virtual int waitRXcomplete() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
0
libraries/SondeLib/DefaultFonts.c → RX_FSK/src/DefaultFonts.c
Executable file → Normal file
0
libraries/SondeLib/DefaultFonts.c → RX_FSK/src/DefaultFonts.c
Executable file → Normal file
1329
libraries/SondeLib/Display.cpp → RX_FSK/src/Display.cpp
Executable file → Normal file
1329
libraries/SondeLib/Display.cpp → RX_FSK/src/Display.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
76
libraries/SondeLib/Display.h → RX_FSK/src/Display.h
Executable file → Normal file
76
libraries/SondeLib/Display.h → RX_FSK/src/Display.h
Executable file → Normal file
|
@ -1,14 +1,26 @@
|
|||
#ifndef Display_h
|
||||
#define Display_h
|
||||
|
||||
#define FONT_LARGE 1
|
||||
#define FONT_SMALL 0
|
||||
|
||||
#include <SPI.h>
|
||||
//#include <TFT22_ILI9225.h>
|
||||
#include "gfxfont.h"
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include <U8x8lib.h>
|
||||
#include <SPIFFS.h>
|
||||
|
||||
struct GpsPos {
|
||||
double lat;
|
||||
double lon;
|
||||
int alt;
|
||||
int course;
|
||||
float speed;
|
||||
int sat;
|
||||
int accuracy;
|
||||
int hdop;
|
||||
int valid;
|
||||
};
|
||||
extern struct GpsPos gpsPos;
|
||||
|
||||
#define WIDTH_AUTO 9999
|
||||
struct DispEntry {
|
||||
|
@ -36,44 +48,59 @@ struct StatInfo {
|
|||
uint8_t size;
|
||||
};
|
||||
|
||||
struct CircleInfo { // 3,5=g0NCS,50,ff0000,000033,5,ffff00,4,ffffff
|
||||
char type;
|
||||
char top,bul,arr; // what to point to with top, bullet, array
|
||||
uint16_t fgcol, bgcol;
|
||||
uint8_t radius;
|
||||
uint8_t brad;
|
||||
uint16_t bcol;
|
||||
uint8_t awidth;
|
||||
uint16_t acol;
|
||||
};
|
||||
|
||||
// Now starting towards supporting different Display types / libraries
|
||||
class RawDisplay {
|
||||
public:
|
||||
virtual void begin() = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void setContrast(uint8_t contrast) = 0;
|
||||
virtual void setFont(uint8_t fontindex) = 0;
|
||||
virtual void getDispSize(uint8_t *height, uint8_t *width, uint8_t *lineskip, uint8_t *colskip) = 0;
|
||||
virtual void drawString(uint8_t x, uint8_t y, const char *s, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0 ) = 0;
|
||||
virtual void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) = 0;
|
||||
virtual void drawString(uint16_t x, uint16_t y, const char *s, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0 ) = 0;
|
||||
virtual void drawTile(uint16_t x, uint16_t y, uint8_t cnt, uint8_t *tile_ptr) = 0;
|
||||
virtual void drawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color, bool fill) = 0;
|
||||
virtual void drawBitmap(uint16_t x1, uint16_t y1, const uint16_t* bitmap, int16_t w, int16_t h) = 0;
|
||||
virtual void welcome() = 0;
|
||||
virtual void drawIP(uint8_t x, uint8_t y, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0 ) = 0;
|
||||
virtual void drawQS(uint8_t x, uint8_t y, uint8_t len, uint8_t size, uint8_t *stat, uint16_t fg=0xffff, uint16_t bg=0) = 0;
|
||||
virtual void drawIP(uint16_t x, uint16_t y, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0 ) = 0;
|
||||
virtual void drawQS(uint16_t x, uint16_t y, uint8_t len, uint8_t size, uint8_t *stat, uint16_t fg=0xffff, uint16_t bg=0) = 0;
|
||||
};
|
||||
|
||||
class U8x8Display : public RawDisplay {
|
||||
private:
|
||||
U8X8 *u8x8 = NULL; // initialize later after reading config file
|
||||
int _type;
|
||||
uint8_t _type;
|
||||
const uint8_t **fontlist;
|
||||
int nfonts;
|
||||
|
||||
public:
|
||||
U8x8Display(int type = 0) { _type = type; }
|
||||
U8x8Display(uint8_t type = 0) { _type = type; }
|
||||
void begin();
|
||||
void clear();
|
||||
void setContrast(uint8_t contrast);
|
||||
void setFont(uint8_t fontindex);
|
||||
void getDispSize(uint8_t *height, uint8_t *width, uint8_t *lineskip, uint8_t *colskip);
|
||||
void drawString(uint8_t x, uint8_t y, const char *s, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0);
|
||||
void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr);
|
||||
void drawString(uint16_t x, uint16_t y, const char *s, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0);
|
||||
void drawTile(uint16_t x, uint16_t y, uint8_t cnt, uint8_t *tile_ptr);
|
||||
void drawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color, bool fill);
|
||||
void drawBitmap(uint16_t x1, uint16_t y1, const uint16_t* bitmap, int16_t w, int16_t h);
|
||||
void welcome();
|
||||
void drawIP(uint8_t x, uint8_t y, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0);
|
||||
void drawQS(uint8_t x, uint8_t y, uint8_t len, uint8_t size, uint8_t *stat, uint16_t fg=0xffff, uint16_t bg=0);
|
||||
void drawIP(uint16_t x, uint16_t y, int16_t width=WIDTH_AUTO, uint16_t fg=0xffff, uint16_t bg=0);
|
||||
void drawQS(uint16_t x, uint16_t y, uint8_t len, uint8_t size, uint8_t *stat, uint16_t fg=0xffff, uint16_t bg=0);
|
||||
};
|
||||
|
||||
typedef Arduino_GFX MY_ILI9225;
|
||||
|
||||
class Display {
|
||||
private:
|
||||
void replaceLayouts(DispInfo *newlayout, int nnew);
|
||||
|
@ -82,24 +109,19 @@ private:
|
|||
int xscale=13, yscale=22;
|
||||
int fontsma=0, fontlar=1;
|
||||
uint16_t colfg, colbg;
|
||||
static void circ(int x, int y);
|
||||
static void circ(uint16_t *bm, int16_t w, int16_t x0, int16_t y0, int16_t r, uint16_t fg, boolean fill, uint16_t bg);
|
||||
static int countEntries(File f);
|
||||
void calcGPS();
|
||||
void calcVbat();
|
||||
void calcDurVol();
|
||||
boolean gpsValid;
|
||||
float gpsLat, gpsLon;
|
||||
int gpsAlt;
|
||||
int gpsDist; // -1: invalid
|
||||
int gpsCourse, gpsDir, gpsBear; // 0..360; -1: invalid
|
||||
int gpsDir, gpsBear; // 0..360; -1: invalid
|
||||
boolean gpsCourseOld;
|
||||
static const int LINEBUFLEN{ 255 };
|
||||
static char lineBuf[LINEBUFLEN];
|
||||
static const char *trim(char *s) {
|
||||
char *ret = s;
|
||||
while(*ret && isspace(*ret)) { ret++; }
|
||||
int lastidx;
|
||||
while(1) {
|
||||
int lastidx;
|
||||
lastidx = strlen(ret)-1;
|
||||
if(lastidx>=0 && isspace(ret[lastidx]))
|
||||
ret[lastidx] = 0;
|
||||
|
@ -109,7 +131,8 @@ private:
|
|||
return ret;
|
||||
}
|
||||
public:
|
||||
void initFromFile();
|
||||
static int getScreenIndex(int index);
|
||||
void initFromFile(int index);
|
||||
|
||||
int layoutIdx;
|
||||
DispInfo *layout;
|
||||
|
@ -117,15 +140,13 @@ public:
|
|||
DispInfo *layouts;
|
||||
int nLayouts;
|
||||
static RawDisplay *rdis;
|
||||
uint16_t dispstate;
|
||||
|
||||
Display();
|
||||
void init();
|
||||
static char buf[17];
|
||||
static void drawLat(DispEntry *de);
|
||||
static void drawLon(DispEntry *de);
|
||||
static void drawAz(DispEntry *de);
|
||||
static void drawVBat(DispEntry *de);
|
||||
static void drawDurVol(DispEntry *de);
|
||||
static void drawAlt(DispEntry *de);
|
||||
static void drawHS(DispEntry *de);
|
||||
static void drawVS(DispEntry *de);
|
||||
|
@ -147,17 +168,16 @@ public:
|
|||
void setIP(const char *ip, bool AP);
|
||||
void updateDisplayPos();
|
||||
void updateDisplayPos2();
|
||||
void updateDisplayAz();
|
||||
void updateDisplayVBat();
|
||||
void updateDisplayID();
|
||||
void updateDisplayRSSI();
|
||||
void updateStat();
|
||||
void updateDisplayRXConfig();
|
||||
void updateDisplayIP();
|
||||
void updateDisplay();
|
||||
void updateDisplayVBatt();
|
||||
|
||||
void dispsavectlON();
|
||||
void dispsavectlOFF(int rxactive);
|
||||
void setLayout(int layout);
|
||||
void setContrast();
|
||||
};
|
||||
|
||||
extern Display disp;
|
652
RX_FSK/src/M10M20.cpp
Normal file
652
RX_FSK/src/M10M20.cpp
Normal file
|
@ -0,0 +1,652 @@
|
|||
|
||||
/* M10 and M20 decoder functions */
|
||||
|
||||
#include "M10M20.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "rsc.h"
|
||||
#include "Sonde.h"
|
||||
#include <SPIFFS.h>
|
||||
|
||||
#define M10M20_DEBUG 1
|
||||
|
||||
#if M10M20_DEBUG
|
||||
#define M10M20_DBG(x) x
|
||||
#else
|
||||
#define M10M20_DBG(x)
|
||||
#endif
|
||||
|
||||
|
||||
static byte data1[512];
|
||||
static byte *dataptr=data1;
|
||||
|
||||
static uint8_t rxbitc;
|
||||
static uint16_t rxbyte;
|
||||
static int rxp=0;
|
||||
static int haveNewFrame = 0;
|
||||
//static int lastFrame = 0;
|
||||
static int headerDetected = 0;
|
||||
|
||||
|
||||
decoderSetupCfg m10m20SetupCfg = {
|
||||
.bitrate = 9600,
|
||||
//// Disable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
.rx_cfg = 0x00,
|
||||
.sync_cfg = 0x70,
|
||||
.sync_len = 1,
|
||||
.sync_data = (const uint8_t *)"\x66\x66",
|
||||
// Preamble detection off (+ size 1 byte, maximum tolerance; should not matter for "off"?)
|
||||
.preamble_cfg = 0x00 | 0x00 | 0x1F,
|
||||
};
|
||||
|
||||
int M10M20::setup(float frequency, int /*type*/)
|
||||
{
|
||||
M10M20_DBG(Serial.println("Setup sx1278 for M10/M20 sonde"));;
|
||||
if(sx1278.ON()!=0) {
|
||||
M10M20_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// setFSK: switches to FSK standby mode
|
||||
if(sx1278.setFSK()!=0) {
|
||||
M10M20_DBG(Serial.println("Setting FSK mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
Serial.print("M10/M20: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
int res = sx1278.setFrequency(frequency);
|
||||
// Test: maybe fix issue after spectrum display?
|
||||
sx1278.writeRegister(REG_PLL_HOP, 0);
|
||||
|
||||
if(sx1278.setAFCBandwidth(sonde.config.m10m20.agcbw)!=0) {
|
||||
M10M20_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.m10m20.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.m10m20.rxbw)!=0) {
|
||||
M10M20_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.m10m20.rxbw));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// TODO: Maybe do this conditionally? -- maybe skip if afc if agcbw set to 0 or -1?
|
||||
//// Step 1: Tentative AFC mode
|
||||
sx1278.clearIRQFlags();
|
||||
// preamble detector + AFC + AGC on
|
||||
// wait for preamble interrupt within 2sec
|
||||
sx1278.setBitrate(4800);
|
||||
// DetectorOn=1, Preamble detector size 01, preamble tol 0x0A (10)
|
||||
sx1278.setPreambleDetect(0x80 | 0x20 | 0x0A);
|
||||
// Manual start RX, Enable Auto-AFC, Auto-AGC, RX Trigger (AGC+AFC)by preamble
|
||||
sx1278.setRxConf(0x20 | 0x10 | 0x08 | 0x06);
|
||||
// Packet config 1: fixed len, no mancecer, no crc, no address filter
|
||||
// Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0)
|
||||
if(sx1278.setPacketConfig(0x08, 0x40)!=0) {
|
||||
M10M20_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// enable RX
|
||||
sx1278.setPayloadLength(0);
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
unsigned long t0 = millis();
|
||||
M10M20_DBG(Serial.printf("M10M20::setup() AFC preamble search start at %ld\n",t0));
|
||||
while( millis() - t0 < 1000 ) {
|
||||
uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS1);
|
||||
if(value & 2) {
|
||||
int32_t afc = sx1278.getAFC();
|
||||
int16_t rssi = sx1278.getRSSI();
|
||||
Serial.printf("M10M20::setup: preamble: AFC is %d, RSSI is %.1f\n", afc, rssi/2.0);
|
||||
sonde.sondeList[rxtask.currentSonde].rssi = rssi;
|
||||
sonde.sondeList[rxtask.currentSonde].afc = afc;
|
||||
break;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
if( millis() - t0 >= 1000) {
|
||||
Serial.println("Preamble scan for AFC: TIMEOUT\n");
|
||||
return 1; // no preamble, so we may fail fast....
|
||||
}
|
||||
|
||||
//// Step 2: Real reception
|
||||
if( DecoderBase::setup(m10m20SetupCfg, sonde.config.m10m20.agcbw, sonde.config.m10m20.rxbw)!=0 ) {
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
// Now all done in DecoderBase::setup
|
||||
// FSK standby mode, seems like otherweise baudrate cannot be changed?
|
||||
sx1278.setFSK();
|
||||
if(sx1278.setBitrate(9600)!=0) {
|
||||
M10M20_DBG(Serial.println("Setting bitrate 9600bit/s FAILED"));
|
||||
return 1;
|
||||
}
|
||||
M10M20_DBG(Serial.printf("Exact bitrate is %f\n", sx1278.getBitrate()));
|
||||
// Probably not necessary, as this was set before
|
||||
if(sx1278.setAFCBandwidth(sonde.config.m10m20.agcbw)!=0) {
|
||||
M10M20_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.m10m20.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.m10m20.rxbw)!=0) {
|
||||
M10M20_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.m10m20.rxbw));
|
||||
return 1;
|
||||
}
|
||||
|
||||
///// Enable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
//if(sx1278.setRxConf(0x1E)!=0) {
|
||||
// Disable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
if(sx1278.setRxConf(0x00)!=0) {
|
||||
M10M20_DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// version 1, working with continuous RX
|
||||
const char *SYNC="\x66\x66";
|
||||
if(sx1278.setSyncConf(0x70, 1, (const uint8_t *)SYNC)!=0) {
|
||||
M10M20_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// Preamble detection off (+ size 1 byte, maximum tolerance; should not matter for "off"?)
|
||||
if(sx1278.setPreambleDetect(0x00 | 0x00 | 0x1F)!=0) {
|
||||
M10M20_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Packet config 1: fixed len, no mancecer, no crc, no address filter
|
||||
// Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0)
|
||||
if(sx1278.setPacketConfig(0x08, 0x40)!=0) {
|
||||
M10M20_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// enable RX
|
||||
sx1278.setPayloadLength(0); // infinite for now...
|
||||
sx1278.setRxConf(0x20);
|
||||
uint16_t afc = sx1278.getRawAFC();
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
delay(50);
|
||||
sx1278.setRawAFC(afc);
|
||||
delay(50);
|
||||
Serial.printf("after RX_MODE: AFC is %d\n", sx1278.getAFC());
|
||||
|
||||
#if M10M20_DEBUG
|
||||
M10M20_DBG(Serial.println("Setting SX1278 config for M10 finished\n"); Serial.println());
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
M10M20::M10M20() {
|
||||
}
|
||||
|
||||
#define M10_FRAMELEN 101
|
||||
#define M10_CRCPOS 99
|
||||
|
||||
#define M20_FRAMELEN 88
|
||||
#define M20_CRCPOSB 22
|
||||
|
||||
void M10M20::printRaw(uint8_t *data, int len)
|
||||
{
|
||||
char buf[3];
|
||||
int i;
|
||||
for(i=0; i<len; i++) {
|
||||
snprintf(buf, 3, "%02X ", data[i]);
|
||||
Serial.print(buf);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
static uint16_t update_checkM10M20(int c, uint8_t b) {
|
||||
int c0, c1, t, t6, t7, s;
|
||||
c1 = c & 0xFF;
|
||||
// B
|
||||
b = (b >> 1) | ((b & 1) << 7);
|
||||
b ^= (b >> 2) & 0xFF;
|
||||
// A1
|
||||
t6 = ( c & 1) ^ ((c >> 2) & 1) ^ ((c >> 4) & 1);
|
||||
t7 = ((c >> 1) & 1) ^ ((c >> 3) & 1) ^ ((c >> 5) & 1);
|
||||
t = (c & 0x3F) | (t6 << 6) | (t7 << 7);
|
||||
// A2
|
||||
s = (c >> 7) & 0xFF;
|
||||
s ^= (s >> 2) & 0xFF;
|
||||
c0 = b ^ t ^ s;
|
||||
return ((c1 << 8) | c0) & 0xFFFF;
|
||||
}
|
||||
static uint16_t crc_M10M20(int len, uint8_t *msg) {
|
||||
uint16_t cs = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
cs = update_checkM10M20(cs, msg[i]);
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
static bool checkM10M20crc(int crcpos, uint8_t *msg) {
|
||||
uint16_t cs, cs1;
|
||||
cs = crc_M10M20(crcpos, msg);
|
||||
cs1 = (msg[crcpos] << 8) | msg[crcpos+1];
|
||||
return (cs1 == cs);
|
||||
}
|
||||
|
||||
typedef uint32_t SET256[8];
|
||||
static SET256 sondeudp_VARSET = {0x03BBBBF0UL,0x80600000UL,0x06A001A0UL,
|
||||
0x0000001CUL,0x00000000UL,0x00000000UL,0x00000000UL,
|
||||
0x00000000UL};
|
||||
// VARSET=SET256{4..9,11..13,15..17,19..21,23..25,53..54,63,69,71,72,85,87,89,90,98..100};
|
||||
static SET256 sondeudp_VARSETM20 = {0xF3E27F54UL,0x0000000FUL,0x00000030UL,
|
||||
0x00000000UL, 0x00444C39UL, 0x53445A00UL, 0x00000000UL,
|
||||
0x00000000UL};
|
||||
// VARSET=SET256{2,4,6,8..10,11..14,17,21..25,28..35,68,69}; (* known as variable *)
|
||||
|
||||
static uint8_t fixcnt[M10_FRAMELEN];
|
||||
static uint8_t fixbytes[M10_FRAMELEN];
|
||||
|
||||
static int32_t getint32(uint8_t *data) {
|
||||
return (int32_t)( data[3]|(data[2]<<8)|(data[1]<<16)|(data[0]<<24) );
|
||||
}
|
||||
|
||||
static int32_t getint24(uint8_t *data) {
|
||||
return (int32_t)(data[2]|(data[1]<<8)|(data[0]<<16) );
|
||||
}
|
||||
|
||||
static int32_t getint24_r(uint8_t *data) {
|
||||
return (int32_t)(data[0]|(data[1]<<8)|(data[2]<<16) );
|
||||
}
|
||||
|
||||
static int16_t getint16(uint8_t *data) {
|
||||
return (int16_t)(data[1]|((uint16_t)data[0]<<8));
|
||||
}
|
||||
|
||||
static int16_t getint16_r(uint8_t *data) {
|
||||
return (int16_t)(((uint16_t)data[1]<<8) |data[0]);
|
||||
}
|
||||
|
||||
static char dez(uint8_t nr) {
|
||||
nr = nr%10;
|
||||
return '0'+nr;
|
||||
}
|
||||
static char hex(uint8_t nr) {
|
||||
nr = nr&0x0f;
|
||||
if(nr<10) return '0'+nr;
|
||||
else return 'A'+nr-10;
|
||||
}
|
||||
const static float DEGMUL = 1.0/0xB60B60;
|
||||
|
||||
#define VMUL 0.005
|
||||
#define VMUL_M20 0.01
|
||||
#ifndef PI
|
||||
#define PI (3.1415926535897932384626433832795)
|
||||
#endif
|
||||
#define RAD (PI/180)
|
||||
|
||||
|
||||
// ret: 1=frame ok; 2=frame with errors; 0=ignored frame (m10dop-alternativ)
|
||||
int M10M20::decodeframeM10(uint8_t *data) {
|
||||
int repairstep = 16;
|
||||
int repl = 0;
|
||||
bool crcok;
|
||||
// error correction, inspired by oe5dxl's sondeudp
|
||||
do {
|
||||
crcok = checkM10M20crc(M10_CRCPOS, data);
|
||||
if(crcok || repairstep==0) break;
|
||||
repl = 0;
|
||||
for(int i=0; i<M10_CRCPOS; i++) {
|
||||
if( ((sondeudp_VARSET[i/32]&(1<<(i%32))) == 0) && (fixcnt[i]>=repairstep) ) {
|
||||
repl++;
|
||||
data[i] = fixbytes[i];
|
||||
}
|
||||
}
|
||||
repairstep >>= 1;
|
||||
} while(true);
|
||||
if(crcok) {
|
||||
for(int i=0; i<M10_CRCPOS; i++) {
|
||||
if(fixbytes[i]==data[i] &&fixcnt[i]<255) fixcnt[i]++;
|
||||
else { fixcnt[i]=0; fixbytes[i]=data[i]; }
|
||||
}
|
||||
}
|
||||
Serial.println(crcok?"CRC OK":"CRC NOT OK");
|
||||
Serial.printf(" repair: %d/%d\n", repl, repairstep);
|
||||
if(!crcok) return 2;
|
||||
|
||||
if(data[1]==0x9F && data[2]==0x20) {
|
||||
Serial.println("Decoding...");
|
||||
//SondeInfo *si = sonde.si();
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
|
||||
// Its a M10
|
||||
// getid...
|
||||
char ids[12];
|
||||
ids[0] = 'M';
|
||||
ids[1] = 'E';
|
||||
ids[2] = hex(data[95]/16);
|
||||
ids[3] = hex(data[95]);
|
||||
ids[4] = hex(data[93]);
|
||||
uint32_t id = data[96] + data[97]*256;
|
||||
ids[5] = hex(id/4096);
|
||||
ids[6] = hex(id/256);
|
||||
ids[7] = hex(id/16);
|
||||
ids[8] = hex(id);
|
||||
ids[9] = 0;
|
||||
strncpy(si->id, ids, 10);
|
||||
ids[0] = hex(data[95]/16);
|
||||
ids[1] = dez((data[95]&0x0f)/10);
|
||||
ids[2] = dez((data[95]&0x0f));
|
||||
ids[3] = '-';
|
||||
ids[4] = dez(data[93]);
|
||||
ids[5] = '-';
|
||||
ids[6] = dez(id>>13);
|
||||
id &= 0x1fff;
|
||||
ids[7] = dez(id/1000);
|
||||
ids[8] = dez((id/100)%10);
|
||||
ids[9] = dez((id/10)%10);
|
||||
ids[10] = dez(id%10);
|
||||
ids[11] = 0;
|
||||
strncpy(si->ser, ids, 12);
|
||||
si->validID = true;
|
||||
Serial.printf("ID is %s [%02x %02x %d]\n", ids, data[95], data[93], id);
|
||||
// ID printed on sonde is ...-.-abbbb, with a=id>>13, bbbb=id&0x1fff in decimal
|
||||
// position data
|
||||
si->lat = getint32(data+14) * DEGMUL;
|
||||
si->lon = getint32(data+18) * DEGMUL;
|
||||
si->alt = getint32(data+22) * 0.001;
|
||||
float ve = getint16(data+4)*VMUL;
|
||||
float vn = getint16(data+6)*VMUL;
|
||||
si->vs = getint16(data+8) * VMUL;
|
||||
si->hs = sqrt(ve*ve+vn*vn);
|
||||
si->sats = data[30];
|
||||
float dir = atan2(ve, vn)*(1.0/RAD);
|
||||
if(dir<0) dir+=360;
|
||||
si->dir = dir;
|
||||
si->validPos = 0x3f;
|
||||
// m10 temp
|
||||
float T = NAN;
|
||||
{
|
||||
const float p0 = 1.07303516e-03, p1 = 2.41296733e-04, p2 = 2.26744154e-06, p3 = 6.52855181e-08;
|
||||
const float Rs[3] = { 12.1e3 , 36.5e3 , 475.0e3 };
|
||||
const float Rp[3] = { 1e20 , 330.0e3 , 2000.0e3 };
|
||||
uint8_t sct = data[62];
|
||||
float rt = getint16_r(data+63) & (0xFFF);
|
||||
if(rt!=0 && sct<3) {
|
||||
rt = (4095-rt)/rt - (Rs[sct]/Rp[sct]);
|
||||
if(rt>0) {
|
||||
rt = Rs[sct] / rt;
|
||||
if(rt>0) {
|
||||
rt = log(rt);
|
||||
rt = 1/( p0 + p1*rt + p2*rt*rt + p3*rt*rt*rt ) - 273.15;
|
||||
if(rt>-99 && rt<50) { T = rt; }
|
||||
}
|
||||
}
|
||||
}
|
||||
si->temperature = T;
|
||||
}
|
||||
|
||||
// m10 battery
|
||||
uint16_t batADC = (uint16_t)getint16_r(data+0x45);
|
||||
si->batteryVoltage = 2.709 * batADC * 2.5/1023.0;
|
||||
|
||||
// m10 humidity
|
||||
{
|
||||
float cRHc55 = ((float)(uint32_t)getint24_r(data+0x35)) / (uint32_t)getint24_r(data+0x32);
|
||||
float TH = -273.15;
|
||||
const float huRs = 22.1e3;
|
||||
const float p0 = 4.42606809e-03, p1 = -6.58184309e-04, p2 = 8.95735557e-05, p3 = -2.84347503e-06;
|
||||
float R = huRs / ( (4095.0/getint16_r(data+0x59)) - 1 );
|
||||
if(R>0) TH += 1/( p0 + p1*log(R) + p2*log(R)*log(R) + p3*log(R)*log(R)*log(R) );
|
||||
//float Tc = T;
|
||||
float rh = (cRHc55-0.8955)/0.002;
|
||||
const float T0=0.0, T1=-30.0;
|
||||
//float T = Tc;
|
||||
if(T<T0) rh += T0 - T/5.5;
|
||||
if(T<T1) rh *= 1.0 + (T1-T)/75.0;
|
||||
if(rh<0.0) rh=0.0;
|
||||
if(rh>100.0) rh=100.0;
|
||||
si->relativeHumidity = rh;
|
||||
}
|
||||
Serial.printf("hum: %.2f batt: %.2f\n", si->relativeHumidity, si->batteryVoltage);
|
||||
|
||||
uint32_t gpstime = getint32(data+10);
|
||||
uint16_t gpsweek = getint16(data+32);
|
||||
// UTC is GPSTIME - 18s (24*60*60-18 = 86382)
|
||||
// one week = 7*24*60*60 = 604800 seconds
|
||||
// unix epoch starts jan 1st 1970 0:00
|
||||
// gps time starts jan 6, 1980 0:00. thats 315964800 epoch seconds.
|
||||
// subtracting 86400 yields 315878400UL
|
||||
si->time = (gpstime/1000) + 86382 + gpsweek*604800 + 315878400UL;
|
||||
// consistent with autorx, vframe is based on GPS time without the -18 seconds adjustment
|
||||
// for the GPS time / UTC time difference (included in 86382 above)
|
||||
si->vframe = si->time - 315964800 + 18;
|
||||
si->validTime = true;
|
||||
} else {
|
||||
Serial.printf("data is %02x %02x %02x\n", data[0], data[1], data[2]);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t rxdata;
|
||||
static bool rxsearching=true;
|
||||
static bool isM20=false;
|
||||
|
||||
// search for
|
||||
// //101001100110011010011010011001100110100110101010100110101001
|
||||
// //1010011001100110100110100110 0110.0110 1001.1010 1010.1001 1010.1001 => 0x669AA9A9
|
||||
void M10M20::processM10data(uint8_t dt)
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
uint8_t d = (dt&0x80)?1:0;
|
||||
dt <<= 1;
|
||||
rxdata = (rxdata<<1) | d;
|
||||
if( (rxbitc&1)==0 ) {
|
||||
// "bit1"
|
||||
rxbyte = (rxbyte<<1) | d;
|
||||
} else {
|
||||
// "bit2" ==> 01 or 10 => 1, otherweise => 0
|
||||
rxbyte = rxbyte ^ d;
|
||||
}
|
||||
//
|
||||
if(rxsearching) {
|
||||
if( rxdata == 0xcccca64c || rxdata == 0x333359b3 ) {
|
||||
rxsearching = false;
|
||||
rxbitc = 0;
|
||||
rxp = 0;
|
||||
isM20 = false;
|
||||
headerDetected = 1;
|
||||
#if 1
|
||||
int rssi=sx1278.getRSSI();
|
||||
int fei=sx1278.getFEI();
|
||||
int afc=sx1278.getAFC();
|
||||
Serial.print("SYNC!!! Test: RSSI="); Serial.print(rssi);
|
||||
Serial.print(" FEI="); Serial.print(fei);
|
||||
Serial.print(" AFC="); Serial.println(afc);
|
||||
sonde.si()->rssi = rssi;
|
||||
sonde.si()->afc = afc;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
rxbitc = (rxbitc+1)%16; // 16;
|
||||
if(rxbitc == 0) { // got 8 data bit
|
||||
//Serial.printf("%03x ",rxbyte);
|
||||
dataptr[rxp++] = rxbyte&0xff; // (rxbyte>>1)&0xff;
|
||||
// detect type of sonde:
|
||||
// 64 9F 20 => M10
|
||||
// 64 49 0x => M10 (?) -- not used here
|
||||
// 45 20 7x => M20
|
||||
if(rxp==2 && dataptr[0]==0x45 && dataptr[1]==0x20) { isM20 = true; }
|
||||
if(isM20) {
|
||||
memcpy(sonde.si()->d.typestr, "M20 ", 5);
|
||||
sonde.si()->d.subtype = 2;
|
||||
if(rxp>=M20_FRAMELEN) {
|
||||
rxsearching = true;
|
||||
haveNewFrame = decodeframeM20(dataptr);
|
||||
}
|
||||
} else {
|
||||
memcpy(sonde.si()->d.typestr, "M10 ", 5);
|
||||
sonde.si()->d.subtype = 1;
|
||||
if(rxp>=M10_FRAMELEN) {
|
||||
rxsearching = true;
|
||||
haveNewFrame = decodeframeM10(dataptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int M10M20::receive() {
|
||||
unsigned long t0 = millis();
|
||||
Serial.printf("M10M20::receive() start at %ld\n",t0);
|
||||
while( millis() - t0 < 1100 ) {
|
||||
uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
if ( bitRead(value, 7) ) {
|
||||
Serial.println("FIFO full");
|
||||
}
|
||||
if ( bitRead(value, 4) ) {
|
||||
Serial.println("FIFO overflow");
|
||||
}
|
||||
if ( bitRead(value, 2) == 1 ) {
|
||||
Serial.println("FIFO: ready()");
|
||||
sx1278.clearIRQFlags();
|
||||
}
|
||||
if(bitRead(value, 6) == 0) { // while FIFO not empty
|
||||
byte data = sx1278.readRegister(REG_FIFO);
|
||||
//Serial.printf("%02x:",data);
|
||||
processM10data(data);
|
||||
value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
} else {
|
||||
if(headerDetected) {
|
||||
t0 = millis(); // restart timer... don't time out if header detected...
|
||||
headerDetected = 0;
|
||||
}
|
||||
if(haveNewFrame) {
|
||||
Serial.printf("M10M20::receive(): new frame complete after %ldms\n", millis()-t0);
|
||||
printRaw(dataptr, M10_FRAMELEN);
|
||||
int retval = haveNewFrame==1 ? RX_OK: RX_ERROR;
|
||||
haveNewFrame = 0;
|
||||
return retval;
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
int32_t afc = sx1278.getAFC();
|
||||
int16_t rssi = sx1278.getRSSI();
|
||||
Serial.printf("receive: AFC is %d, RSSI is %.1f\n", afc, rssi/2.0);
|
||||
Serial.printf("M10M20::receive() timed out\n");
|
||||
return RX_TIMEOUT; // TODO RX_OK;
|
||||
}
|
||||
|
||||
#define M10MAXLEN (240)
|
||||
|
||||
int M10M20::waitRXcomplete() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ret: 1=frame ok; 2=frame with errors; 0=ignored frame (m20dop-alternativ)
|
||||
int M10M20::decodeframeM20(uint8_t *data) {
|
||||
int repairstep = 16;
|
||||
int frl;
|
||||
int repl = 0;
|
||||
bool crcok = false;
|
||||
bool crcbok = false;
|
||||
//SondeInfo *si = sonde.si();
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
// error correction, inspired by oe5dxl's sondeudp
|
||||
// check first block
|
||||
uint8_t s[200];
|
||||
s[0] = 0x16;
|
||||
for(int i=1; i<=M20_CRCPOSB-1; i++) { s[i] = data[i+1]; }
|
||||
crcbok = (crc_M10M20(M20_CRCPOSB-1, s) ==
|
||||
((data[M20_CRCPOSB] << 8) | data[M20_CRCPOSB+1]));
|
||||
|
||||
frl = data[0] + 1; // frame len? (0x45+1 => 70)
|
||||
if(frl>M20_FRAMELEN) { frl = M20_FRAMELEN; }
|
||||
do {
|
||||
crcok = checkM10M20crc(frl-2, data);
|
||||
if(crcok || repairstep == 0) break;
|
||||
repl = 0;
|
||||
for(int i=crcbok?M20_CRCPOSB+2:0; i<frl-2; i++) {
|
||||
if( ((sondeudp_VARSETM20[i/32]&(1<<(i%32))) == 0) && (fixcnt[i]>=repairstep) ) {
|
||||
repl++;
|
||||
data[i] = fixbytes[i];
|
||||
}
|
||||
}
|
||||
repairstep >>= 1;
|
||||
} while(true);
|
||||
if(crcbok) {
|
||||
int oklen = crcok ? frl-2 : 21;
|
||||
for(int i=0; i<oklen; i++) {
|
||||
if(fixbytes[i]==data[i]) { if(fixcnt[i]<255) fixcnt[i]++; }
|
||||
else { fixcnt[i]=0; fixbytes[i]=data[i]; }
|
||||
}
|
||||
}
|
||||
Serial.println(crcok?"CRC OK":"CRC NOT OK");
|
||||
Serial.printf(" repair: %d/%d\n", repl, repairstep);
|
||||
if(!crcok) return 2;
|
||||
|
||||
Serial.println("Decoding...");
|
||||
// Its a M20
|
||||
// getid...
|
||||
// TODO: Adjust ID calculation and serial number reconstruction
|
||||
char ids[11]={'M','E','0','0','0','0','0','0','0','0','0'};
|
||||
|
||||
ids[0] = 'M';
|
||||
ids[1] = 'E';
|
||||
uint32_t id = data[18]; // getint16(data+18);
|
||||
ids[2] = hex(id/16);
|
||||
ids[3] = hex(id);
|
||||
//
|
||||
id = getint16_r(data+19)/4;
|
||||
ids[4] = (char)((id/10000)%10+48);
|
||||
ids[5] = (char)((id/1000)%10+48);
|
||||
ids[6] = (char)((id/100)%10+48);
|
||||
ids[7] = (char)((id/10)%10+48);
|
||||
ids[8] = (char)(id%10+48);
|
||||
ids[9] = 0;
|
||||
strncpy(si->id, ids, 10);
|
||||
// Serial: AAB-C-DDEEE
|
||||
char *ser = si->ser;
|
||||
uint8_t tmp = data[18] & 0x7F;
|
||||
ser[0] = (tmp/12) + '0';
|
||||
ser[1] = ((tmp%12 + 1) / 10 ) + '0';
|
||||
ser[2] = ((tmp%12 + 1) % 10 ) + '0';
|
||||
ser[3] = '-';
|
||||
ser[4] = ((data[19]&0x03)<<1) + (data[18]/128) + 1 + '0';
|
||||
ser[5] = '-';
|
||||
ser[6] = ids[4];
|
||||
ser[7] = ids[5];
|
||||
ser[8] = ids[6];
|
||||
ser[9] = ids[7];
|
||||
ser[10] = ids[8];
|
||||
ser[11] = 0;
|
||||
|
||||
// TODO
|
||||
if(crcok) {
|
||||
si->validID = true;
|
||||
//Serial.printf("ID is %s [%02x %02x %d]\n", ids, data[95], data[93], id);
|
||||
// ID printed on sonde is ...-.-abbbb, with a=id>>13, bbbb=id&0x1fff in decimal
|
||||
// position data
|
||||
// 0x1C 4 byte
|
||||
si->lat = getint32(data+28) * 1e-6;
|
||||
//0x20 4 byte
|
||||
si->lon = getint32(data+32) * 1e-6;
|
||||
//0x08 3 byte
|
||||
si->alt = getint24(data+8) * VMUL_M20;
|
||||
//0x0B 2 byte
|
||||
//VMUL_M20 specific
|
||||
float ve = getint16(data+11)*VMUL_M20;
|
||||
//0x0D 2 byte
|
||||
float vn = getint16(data+13)*VMUL_M20;
|
||||
//0x18 2 byte
|
||||
si->vs = getint16(data+24) * VMUL_M20;
|
||||
si->hs = sqrt(ve*ve+vn*vn);
|
||||
float dir = atan2(ve, vn)*(1.0/RAD);
|
||||
if(dir<0) dir+=360;
|
||||
si->dir = dir;
|
||||
si->validPos = 0x3f;
|
||||
|
||||
//0x0F 3 byte
|
||||
uint32_t tow = getint24(data+15);
|
||||
uint16_t week = getint16(data+26);
|
||||
si->time = (tow+week*604800+315964800)-18;
|
||||
si->vframe =si->time - 315964800;
|
||||
|
||||
si->validTime = true;
|
||||
}
|
||||
return crcok?1:2;
|
||||
}
|
||||
|
||||
|
||||
M10M20 m10m20 = M10M20();
|
50
libraries/SondeLib/M10.h → RX_FSK/src/M10M20.h
Executable file → Normal file
50
libraries/SondeLib/M10.h → RX_FSK/src/M10M20.h
Executable file → Normal file
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
* M10.h
|
||||
* Functions for decoding Meteomodem M10 sondes with SX127x chips
|
||||
* M10M20.h
|
||||
* Functions for decoding Meteomodem M10M20 sondes with SX127x chips
|
||||
* Copyright (C) 2019 Hansi Reiser, dl9rdz
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef M10_h
|
||||
#define M10_h
|
||||
#ifndef M10M20_h
|
||||
#define M10M20_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -15,46 +15,16 @@
|
|||
#ifndef inttypes_h
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
struct CONTEXTR9 {
|
||||
char calibdata[512];
|
||||
uint32_t calibok;
|
||||
char mesok;
|
||||
char posok;
|
||||
char framesent;
|
||||
double lat;
|
||||
double lon;
|
||||
double heig;
|
||||
double speed;
|
||||
double dir;
|
||||
double climb;
|
||||
double lastlat;
|
||||
double laslong;
|
||||
double lastalt;
|
||||
double lastspeed;
|
||||
double lastdir;
|
||||
double lastclb;
|
||||
float hrmsc;
|
||||
float vrmsc;
|
||||
double hp;
|
||||
double hyg;
|
||||
double temp;
|
||||
double ozontemp;
|
||||
double ozon;
|
||||
uint32_t goodsats;
|
||||
uint32_t timems;
|
||||
uint32_t framenum;
|
||||
};
|
||||
#endif
|
||||
#include "DecoderBase.h"
|
||||
|
||||
/* Main class */
|
||||
class M10
|
||||
class M10M20 : public DecoderBase
|
||||
{
|
||||
private:
|
||||
void printRaw(uint8_t *data, int len);
|
||||
void processM10data(uint8_t data);
|
||||
int decodeframeM10(uint8_t *data);
|
||||
int decodeframeM20(uint8_t *data);
|
||||
#if 0
|
||||
void stobyte92(uint8_t byte);
|
||||
void dogps(const uint8_t *sf, int sf_len,
|
||||
|
@ -83,14 +53,14 @@ private:
|
|||
#endif
|
||||
|
||||
public:
|
||||
M10();
|
||||
int setup(float frequency);
|
||||
M10M20();
|
||||
int setup(float frequency, int type = 0);
|
||||
int receive();
|
||||
int waitRXcomplete();
|
||||
|
||||
//int use_ecc = 1;
|
||||
};
|
||||
|
||||
extern M10 m10;
|
||||
extern M10M20 m10m20;
|
||||
|
||||
#endif
|
559
RX_FSK/src/MP3H.cpp
Normal file
559
RX_FSK/src/MP3H.cpp
Normal file
|
@ -0,0 +1,559 @@
|
|||
|
||||
/* MP3H decoder functions */
|
||||
|
||||
#include "MP3H.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "rsc.h"
|
||||
#include "Sonde.h"
|
||||
#include <SPIFFS.h>
|
||||
|
||||
#define MP3H_DEBUG 1
|
||||
|
||||
#if MP3H_DEBUG
|
||||
#define MP3H_DBG(x) x
|
||||
#else
|
||||
#define MP3H_DBG(x)
|
||||
#endif
|
||||
|
||||
static struct st_mp3hstate {
|
||||
uint32_t id1, id2;
|
||||
uint8_t idok;
|
||||
uint32_t gpsdate;
|
||||
uint32_t gpsdatetime;
|
||||
bool dateok;
|
||||
} mp3hstate;
|
||||
|
||||
static byte data1[512];
|
||||
static byte *dataptr=data1;
|
||||
|
||||
static uint8_t rxbitc;
|
||||
static uint16_t rxbyte;
|
||||
static int rxp=0;
|
||||
static int haveNewFrame = 0;
|
||||
//static int lastFrame = 0;
|
||||
static int headerDetected = 0;
|
||||
|
||||
extern uint16_t MON[];
|
||||
|
||||
decoderSetupCfg mp3hSetupCfg = {
|
||||
.bitrate = 2400,
|
||||
.rx_cfg = 0x00,
|
||||
.sync_cfg = 0x70,
|
||||
.sync_len = 1,
|
||||
.sync_data = (const uint8_t *)"\x66\x66",
|
||||
.preamble_cfg = 0x00 | 0x00 | 0x1F
|
||||
};
|
||||
|
||||
int MP3H::setup(float frequency, int /*type*/)
|
||||
{
|
||||
MP3H_DBG(Serial.println("Setup sx1278 for MP3H sonde"));;
|
||||
if(sx1278.ON()!=0) {
|
||||
MP3H_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// setFSK: switches to FSK standby mode
|
||||
if(sx1278.setFSK()!=0) {
|
||||
MP3H_DBG(Serial.println("Setting FSK mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
Serial.print("MP3H: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
int res = sx1278.setFrequency(frequency);
|
||||
// Test: maybe fix issue after spectrum display?
|
||||
sx1278.writeRegister(REG_PLL_HOP, 0);
|
||||
|
||||
if(sx1278.setAFCBandwidth(sonde.config.mp3h.agcbw)!=0) {
|
||||
MP3H_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.mp3h.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.mp3h.rxbw)!=0) {
|
||||
MP3H_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.mp3h.rxbw));
|
||||
return 1;
|
||||
}
|
||||
|
||||
//// Step 2: Real reception
|
||||
if(DecoderBase::setup(mp3hSetupCfg, sonde.config.mp3h.agcbw, sonde.config.mp3h.rxbw)!=0) {
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
// Now all done in Decoderbase
|
||||
// FSK standby mode, seems like otherweise baudrate cannot be changed?
|
||||
sx1278.setFSK();
|
||||
if(sx1278.setBitrate(2400)!=0) {
|
||||
MP3H_DBG(Serial.println("Setting bitrate 2400bit/s FAILED"));
|
||||
return 1;
|
||||
}
|
||||
MP3H_DBG(Serial.printf("Exact bitrate is %f\n", sx1278.getBitrate()));
|
||||
// Probably not necessary, as this was set before
|
||||
if(sx1278.setAFCBandwidth(sonde.config.mp3h.agcbw)!=0) {
|
||||
MP3H_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.mp3h.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.mp3h.rxbw)!=0) {
|
||||
MP3H_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.mp3h.rxbw));
|
||||
return 1;
|
||||
}
|
||||
|
||||
///// Enable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
//if(sx1278.setRxConf(0x1E)!=0) {
|
||||
// Disable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
if(sx1278.setRxConf(0x00)!=0) {
|
||||
MP3H_DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// version 1, working with continuous RX
|
||||
const char *SYNC="\x66\x66";
|
||||
if(sx1278.setSyncConf(0x70, 1, (const uint8_t *)SYNC)!=0) {
|
||||
MP3H_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// Preamble detection off (+ size 1 byte, maximum tolerance; should not matter for "off"?)
|
||||
if(sx1278.setPreambleDetect(0x00 | 0x00 | 0x1F)!=0) {
|
||||
MP3H_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Packet config 1: fixed len, no mancecer, no crc, no address filter
|
||||
// Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0)
|
||||
if(sx1278.setPacketConfig(0x08, 0x40)!=0) {
|
||||
MP3H_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// enable RX
|
||||
sx1278.setPayloadLength(0); // infinite for now...
|
||||
//sx1278.setRxConf(0x20);
|
||||
uint16_t afc = sx1278.getRawAFC();
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
delay(50);
|
||||
sx1278.setRawAFC(afc);
|
||||
delay(50);
|
||||
Serial.printf("after RX_MODE: AFC is %d\n", sx1278.getAFC());
|
||||
|
||||
memset((void *)&mp3hstate, 0, sizeof(mp3hstate));
|
||||
#if MP3H_DEBUG
|
||||
MP3H_DBG(Serial.println("Setting SX1278 config for MP3H finished\n"); Serial.println());
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
MP3H::MP3H() {
|
||||
}
|
||||
|
||||
#define MP3H_FRAMELEN 49
|
||||
|
||||
// offsets from zilog
|
||||
// https://github.com/rs1729/RS/blob/master/demod/mod/mp3h1mod.c
|
||||
#define OFS -3
|
||||
#define pos_CNT1 (OFS+ 3) // 1 nibble (0x80..0x8F ?)
|
||||
#define pos_TIME (OFS+ 4) // 3*1 byte
|
||||
#define pos_GPSecefX (OFS+ 8) // 4 byte
|
||||
#define pos_GPSecefY (OFS+12) // 4 byte
|
||||
#define pos_GPSecefZ (OFS+16) // 4 byte
|
||||
#define pos_GPSecefV (OFS+20) // 3*2 byte
|
||||
#define pos_GPSnSats (OFS+26) // 1 byte (num Sats ?)
|
||||
#define pos_PTU1 (OFS+35) // 4 byte
|
||||
#define pos_PTU2 (OFS+39) // 4 byte
|
||||
#define pos_CNT2 (OFS+43) // 1 byte (0x01..0x10 ?)
|
||||
#define pos_CFG (OFS+44) // 2/4 byte
|
||||
#define pos_CRC (OFS+48) // 2 byte
|
||||
|
||||
|
||||
#define crc16poly 0xA001
|
||||
static bool checkMP3CRC(uint8_t *data)
|
||||
{
|
||||
int start = pos_CNT1;
|
||||
int len = 45;
|
||||
uint16_t rem = 0xffff;
|
||||
for(int i=0; i<len; i++) {
|
||||
rem ^= data[start+i];
|
||||
for(int j=0; j<8; j++) {
|
||||
if(rem&0x1) rem = (rem>>1) ^ crc16poly;
|
||||
else rem = rem>>1;
|
||||
}
|
||||
}
|
||||
uint16_t crcdat = data[pos_CRC] | (data[pos_CRC+1]<<8);
|
||||
return rem == crcdat ? true : false;
|
||||
}
|
||||
|
||||
void MP3H::printRaw(uint8_t *data, int len)
|
||||
{
|
||||
char buf[3];
|
||||
int i;
|
||||
for(i=0; i<len; i++) {
|
||||
snprintf(buf, 3, "%02X ", data[i]);
|
||||
Serial.print(buf);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
#ifndef PI
|
||||
#define PI (3.1415926535897932384626433832795)
|
||||
#endif
|
||||
#define RAD (PI/180)
|
||||
#define DEG (180/PI)
|
||||
|
||||
static uint32_t u4(uint8_t *d)
|
||||
{
|
||||
return d[0] | (d[1]<<8) | (d[2]<<16) | (d[3]<<24);
|
||||
}
|
||||
#define i4(d) ((int32_t)u4(d))
|
||||
|
||||
static uint16_t u2(uint8_t *d)
|
||||
{
|
||||
return d[0] | (d[1]<<8);
|
||||
}
|
||||
#define i2(d) ((int16_t)u2(d))
|
||||
|
||||
|
||||
// defined in RS41.cpp
|
||||
extern void wgs84r(double x, double y, double z, double * lat, double * long0, double * heig);
|
||||
extern double atang2(double x, double y);
|
||||
|
||||
|
||||
void calcgps(uint8_t *buf) {
|
||||
//SondeInfo *si = sonde.si();
|
||||
SondeData *si =&(sonde.si()->d);
|
||||
double wx = i4(buf+pos_GPSecefX) * 0.01;
|
||||
double wy = i4(buf+pos_GPSecefY) * 0.01;
|
||||
double wz = i4(buf+pos_GPSecefZ) * 0.01;
|
||||
double vx = i2(buf+pos_GPSecefV) * 0.01;
|
||||
double vy = i2(buf+pos_GPSecefV+2) * 0.01;
|
||||
double vz = i2(buf+pos_GPSecefV+4) * 0.01;
|
||||
if(wx==0 && wy==0 && wz==0) { if(si->validPos&0x7f) { si->validPos |= 0x80; } return; }
|
||||
// wgs84r
|
||||
double lat, lng, alt;
|
||||
wgs84r(wx, wy, wz, &lat, &lng, &alt);
|
||||
if(alt<-1000 || alt>80000) { if(si->validPos&0x7f) { si->validPos |= 0x80; } return; }
|
||||
si->lat = (float)(lat*DEG);
|
||||
si->lon = (float)(lng*DEG);
|
||||
si->alt = alt;
|
||||
// speeddir
|
||||
double sinlat = sin(lat);
|
||||
double coslat = cos(lat);
|
||||
double sinlng = sin(lng);
|
||||
double coslng = cos(lng);
|
||||
double vn = -vx*sinlat*coslng - vy*sinlat*sinlng + vz*coslat;
|
||||
double ve = -vx*sinlng + vy*coslng;
|
||||
double clb = vx*coslat*coslng + vy*coslat*sinlng + vz*sinlat;
|
||||
double dir = atang2(vn, ve)/RAD;
|
||||
if(dir<0.0) dir+=360.0;
|
||||
si->dir = dir;
|
||||
si->vs = clb;
|
||||
si->hs = sqrt(vn*vn + ve*ve);
|
||||
si->sats = buf[pos_GPSnSats];
|
||||
|
||||
Serial.printf("Pos: %f %f alt %f dir %f vs %f hs %f sats %d\n", si->lat, si->lon, si->alt, si->dir, si->vs, si->hs, si->sats);
|
||||
si->validPos = 0x7f;
|
||||
}
|
||||
static uint32_t getgpstime(uint8_t *buf) {
|
||||
return buf[pos_TIME] * 60*60 + buf[pos_TIME+1] * 60 + buf[pos_TIME+2];
|
||||
}
|
||||
// unix time stamp from date and time info in frame.
|
||||
static void getmp3htime(uint8_t *buf) {
|
||||
//SondeInfo *si = sonde.si();
|
||||
SondeData *si =&(sonde.si()->d);
|
||||
|
||||
// gpsdate from CFG frame 15 (0 if not yet received)
|
||||
uint32_t gpsdate = mp3hstate.gpsdate;
|
||||
uint32_t gpstime = getgpstime(buf);
|
||||
int tt = 0;
|
||||
if(gpsdate) {
|
||||
uint16_t year = (gpsdate%100)+2000;
|
||||
gpsdate /= 100;
|
||||
uint8_t month = gpsdate%100;
|
||||
gpsdate /= 100;
|
||||
uint8_t day = gpsdate % 100;
|
||||
// year-month-day to unix time
|
||||
tt = (year-1970)*365 + (year-1969)/4; // days since 1970
|
||||
if(month<=12) { tt += MON[month]; if((year%4)==0 && month>2) tt++; }
|
||||
tt = (tt+day-1)*(60*60*24);
|
||||
if(gpstime < mp3hstate.gpsdatetime) tt += 60*60*24; // time wrapped since last date tx
|
||||
Serial.printf("date: %04d-%02d-%02d t%d ", year, month, day, gpstime);
|
||||
}
|
||||
tt += gpstime;
|
||||
si->time = tt;
|
||||
si->vframe = tt - 315964800;
|
||||
Serial.printf(" mp3h TIMESTAMP: %d\n", tt);
|
||||
}
|
||||
|
||||
static uint8_t hex(uint32_t n) {
|
||||
n = n % 16;
|
||||
return (n<10) ? (n+'0') : (n-10+'A');
|
||||
}
|
||||
|
||||
static void resetmp3h() {
|
||||
mp3hstate.id1 = mp3hstate.id2 = 0;
|
||||
mp3hstate.idok = 0;
|
||||
mp3hstate.gpsdate = 0;
|
||||
mp3hstate.dateok = 0;
|
||||
}
|
||||
|
||||
// ret: 1=frame ok; 2=frame with errors; 0=ignored frame (m10dop-alternativ)
|
||||
int MP3H::decodeframeMP3H(uint8_t *data) {
|
||||
printRaw(data, MP3H_FRAMELEN);
|
||||
|
||||
//
|
||||
if(!checkMP3CRC(data)) {
|
||||
// maybe add repairing frames later...
|
||||
return 2;
|
||||
}
|
||||
|
||||
// data is a frame with correct CRC
|
||||
//SondeInfo *si = sonde.si();
|
||||
SondeData *si =&(sonde.si()->d);
|
||||
uint8_t cnt = data[pos_CNT1] & 0x0F;
|
||||
uint32_t cfg = u4(data+pos_CFG);
|
||||
if(cnt==15) {
|
||||
// date
|
||||
mp3hstate.gpsdate = cfg;
|
||||
mp3hstate.gpsdatetime = getgpstime(data);
|
||||
mp3hstate.dateok = true;
|
||||
} else if(cnt==13) {
|
||||
// id2
|
||||
if(mp3hstate.id2 > 0 && mp3hstate.id2 != cfg) { resetmp3h(); }
|
||||
mp3hstate.id2 = cfg;
|
||||
mp3hstate.idok |= 2;
|
||||
} else if(cnt==12) {
|
||||
// id1
|
||||
if(mp3hstate.id1 > 0 && mp3hstate.id1 != cfg) { resetmp3h(); }
|
||||
mp3hstate.id1 = cfg;
|
||||
mp3hstate.idok |= 1;
|
||||
}
|
||||
// get id
|
||||
if((mp3hstate.idok&3) == 3) {
|
||||
//...
|
||||
//si->type = STYPE_MP3H;
|
||||
uint32_t n = mp3hstate.id1*100000 + mp3hstate.id2;
|
||||
si->id[0] = 'M';
|
||||
si->id[1] = 'R';
|
||||
si->id[2] = 'Z';
|
||||
si->id[3] = hex(n/0x100000);
|
||||
si->id[4] = hex(n/0x10000);
|
||||
si->id[5] = hex(n/0x1000);
|
||||
si->id[6] = hex(n/0x100);
|
||||
si->id[7] = hex(n/0x10);
|
||||
si->id[8] = hex(n);
|
||||
si->id[9] = 0;
|
||||
snprintf(si->ser, 12, "%u-%u", mp3hstate.id1, mp3hstate.id2);
|
||||
si->validID = true;
|
||||
}
|
||||
|
||||
// position
|
||||
calcgps(data);
|
||||
// time
|
||||
getmp3htime(data);
|
||||
return 1;
|
||||
#if 0
|
||||
int repairstep = 16;
|
||||
int repl = 0;
|
||||
bool crcok;
|
||||
// error correction, inspired by oe5dxl's sondeudp
|
||||
do {
|
||||
crcok = checkMP3Hcrc(M10_CRCPOS, data);
|
||||
if(crcok || repairstep==0) break;
|
||||
repl = 0;
|
||||
for(int i=0; i<M10_CRCPOS; i++) {
|
||||
if( ((sondeudp_VARSET[i/32]&(1<<(i%32))) == 0) && (fixcnt[i]>=repairstep) ) {
|
||||
repl++;
|
||||
data[i] = fixbytes[i];
|
||||
}
|
||||
}
|
||||
repairstep >>= 1;
|
||||
} while(true);
|
||||
if(crcok) {
|
||||
for(int i=0; i<M10_CRCPOS; i++) {
|
||||
if(fixbytes[i]==data[i] &&fixcnt[i]<255) fixcnt[i]++;
|
||||
else { fixcnt[i]=0; fixbytes[i]=data[i]; }
|
||||
}
|
||||
}
|
||||
Serial.println(crcok?"CRC OK":"CRC NOT OK");
|
||||
Serial.printf(" repair: %d/%d\n", repl, repairstep);
|
||||
|
||||
if(data[1]==0x9F && data[2]==0x20) {
|
||||
Serial.println("Decoding...");
|
||||
// Its a M10
|
||||
// getid...
|
||||
char ids[11];
|
||||
ids[0] = 'M';
|
||||
ids[1] = 'E';
|
||||
ids[2] = hex(data[95]/16);
|
||||
ids[3] = hex(data[95]);
|
||||
ids[4] = hex(data[93]);
|
||||
uint32_t id = data[96] + data[97]*256;
|
||||
ids[5] = hex(id/4096);
|
||||
ids[6] = hex(id/256);
|
||||
ids[7] = hex(id/16);
|
||||
ids[8] = hex(id);
|
||||
ids[9] = 0;
|
||||
strncpy(sonde.si()->id, ids, 10);
|
||||
ids[0] = hex(data[95]/16);
|
||||
ids[1] = dez((data[95]&0x0f)/10);
|
||||
ids[2] = dez((data[95]&0x0f));
|
||||
ids[3] = dez(data[93]);
|
||||
ids[4] = dez(id>>13);
|
||||
id &= 0x1fff;
|
||||
ids[5] = dez(id/1000);
|
||||
ids[6] = dez((id/100)%10);
|
||||
ids[7] = dez((id/10)%10);
|
||||
ids[8] = dez(id%10);
|
||||
strncpy(sonde.si()->ser, ids, 10);
|
||||
sonde.si()->validID = true;
|
||||
Serial.printf("ID is %s [%02x %02x %d]\n", ids, data[95], data[93], id);
|
||||
// ID printed on sonde is ...-.-abbbb, with a=id>>13, bbbb=id&0x1fff in decimal
|
||||
// position data
|
||||
sonde.si()->lat = getint32(data+14) * DEGMUL;
|
||||
sonde.si()->lon = getint32(data+18) * DEGMUL;
|
||||
sonde.si()->alt = getint32(data+22) * 0.001;
|
||||
float ve = getint16(data+4)*VMUL;
|
||||
float vn = getint16(data+6)*VMUL;
|
||||
sonde.si()->vs = getint16(data+8) * VMUL;
|
||||
sonde.si()->hs = sqrt(ve*ve+vn*vn);
|
||||
float dir = atan2(vn, ve)*(1.0/RAD);
|
||||
if(dir<0) dir+=360;
|
||||
sonde.si()->dir = dir;
|
||||
sonde.si()->validPos = 0x3f;
|
||||
|
||||
uint32_t gpstime = getint32(data+10);
|
||||
uint16_t gpsweek = getint16(data+32);
|
||||
// UTC is GPSTIME - 18s (24*60*60-18 = 86382)
|
||||
// one week = 7*24*60*60 = 604800 seconds
|
||||
// unix epoch starts jan 1st 1970 0:00
|
||||
// gps time starts jan 6, 1980 0:00. thats 315964800 epoch seconds.
|
||||
// subtracting 86400 yields 315878400UL
|
||||
sonde.si()->time = (gpstime/1000) + 86382 + gpsweek*604800 + 315878400UL;
|
||||
sonde.si()->validTime = true;
|
||||
} else {
|
||||
Serial.printf("data is %02x %02x %02x\n", data[0], data[1], data[2]);
|
||||
return 0;
|
||||
}
|
||||
return crcok?1:2;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t rxdata;
|
||||
static bool rxsearching=true;
|
||||
|
||||
// search for
|
||||
// 0xBF3H (or inverse)
|
||||
void MP3H::processMP3Hdata(uint8_t dt)
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
uint8_t d = (dt&0x80)?1:0;
|
||||
dt <<= 1;
|
||||
rxdata = (rxdata<<1) | d;
|
||||
if( (rxbitc&1)==0 ) {
|
||||
// "bit1"
|
||||
rxbyte = (rxbyte<<1) | d;
|
||||
} else {
|
||||
// "bit2" ==> 01 or 10 => 1, otherweise => 0
|
||||
// rxbyte = rxbyte ^ d;
|
||||
}
|
||||
// BF3H => 1011 1111 0011 0101 => 10011010 10101010 01011010 01100110 => 9AAA5A66 // 6555a599
|
||||
if(rxsearching) {
|
||||
if( rxdata == 0x9AAA5A66 || rxdata == 0x6555a599 ) {
|
||||
rxsearching = false;
|
||||
rxbitc = 0;
|
||||
rxp = 0;
|
||||
headerDetected = 1;
|
||||
Serial.print("SYNC\n");
|
||||
int rssi=sx1278.getRSSI();
|
||||
int fei=sx1278.getFEI();
|
||||
int afc=sx1278.getAFC();
|
||||
Serial.print("SYNC!!! Test: RSSI="); Serial.print(rssi);
|
||||
Serial.print(" FEI="); Serial.print(fei);
|
||||
Serial.print(" AFC="); Serial.println(afc);
|
||||
sonde.si()->rssi = rssi;
|
||||
sonde.si()->afc = afc;
|
||||
}
|
||||
} else {
|
||||
rxbitc = (rxbitc+1)%16; // 16;
|
||||
if(rxbitc == 0) { // got 8 data bit
|
||||
dataptr[rxp++] = rxbyte&0xff; // (rxbyte>>1)&0xff;
|
||||
//if(rxp==2 && dataptr[0]==0x45 && dataptr[1]==0x20) { isM20 = true; }
|
||||
if(rxp>=MP3H_FRAMELEN) {
|
||||
rxsearching = true;
|
||||
haveNewFrame = decodeframeMP3H(dataptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MAXFRAMES 6
|
||||
int MP3H::receive() {
|
||||
// we wait for at most 6 frames or until a new seq nr.
|
||||
uint8_t nFrames = MAXFRAMES; // MP3H sends every frame 6x
|
||||
static uint32_t lastFrame = 0;
|
||||
uint8_t retval = RX_TIMEOUT;
|
||||
|
||||
unsigned long t0 = millis();
|
||||
Serial.printf("MP3H::receive() start at %ld\n",t0);
|
||||
while( millis() - t0 < 1100 + (retval!=RX_TIMEOUT)?1000:0 ) {
|
||||
uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
if ( bitRead(value, 7) ) {
|
||||
Serial.println("FIFO full");
|
||||
}
|
||||
if ( bitRead(value, 4) ) {
|
||||
Serial.println("FIFO overflow");
|
||||
}
|
||||
if ( bitRead(value, 2) == 1 ) {
|
||||
Serial.println("FIFO: ready()");
|
||||
sx1278.clearIRQFlags();
|
||||
}
|
||||
if(bitRead(value, 6) == 0) { // while FIFO not empty
|
||||
byte data = sx1278.readRegister(REG_FIFO);
|
||||
Serial.printf("%02x:",data);
|
||||
processMP3Hdata(data);
|
||||
value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
} else {
|
||||
if(headerDetected) {
|
||||
t0 = millis(); // restart timer... don't time out if header detected...
|
||||
headerDetected = 0;
|
||||
}
|
||||
if(haveNewFrame) {
|
||||
Serial.printf("MP3H::receive(): new frame complete after %ldms\n", millis()-t0);
|
||||
printRaw(dataptr, MP3H_FRAMELEN);
|
||||
nFrames--;
|
||||
// frame with CRC error: just skip and retry (unless we have waited for 6 frames alred)
|
||||
if(haveNewFrame != 1) {
|
||||
Serial.printf("hNF: %d (ERROR)\n", haveNewFrame);
|
||||
retval = RX_ERROR;
|
||||
} else if (sonde.si()->d.time == lastFrame) { // same frame number as seen before => skip
|
||||
Serial.printf("Skipping frame with frame# %d\n", lastFrame);
|
||||
// nothing, wait for next, "new" frame
|
||||
} else { // good and new frame, return it.
|
||||
Serial.println("Good frame");
|
||||
haveNewFrame = 0;
|
||||
lastFrame = sonde.si()->d.time;
|
||||
return RX_OK;
|
||||
}
|
||||
haveNewFrame = 0;
|
||||
#if 0
|
||||
if(nFrames <= 0) {
|
||||
// up to 6 old or erronous frames received => break out
|
||||
Serial.printf("nFrames is %di, giving up\n", nFrames);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
int32_t afc = sx1278.getAFC();
|
||||
int16_t rssi = sx1278.getRSSI();
|
||||
Serial.printf("receive: AFC is %d, RSSI is %.1f\n", afc, rssi/2.0);
|
||||
Serial.printf("MP3H::receive() timed out\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
int MP3H::waitRXcomplete() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
MP3H mp3h = MP3H();
|
||||
|
36
RX_FSK/src/MP3H.h
Normal file
36
RX_FSK/src/MP3H.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* MP3H.h
|
||||
* Functions for decoding MP3H radiosonde
|
||||
* Copyright (C) 2021 Hansi Reiser, dl9rdz
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef MP3H_h
|
||||
#define MP3H_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
#ifndef inttypes_h
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include "DecoderBase.h"
|
||||
|
||||
/* Main class */
|
||||
class MP3H : public DecoderBase
|
||||
{
|
||||
private:
|
||||
void printRaw(uint8_t *data, int len);
|
||||
void processMP3Hdata(uint8_t data);
|
||||
int decodeframeMP3H(uint8_t *data);
|
||||
public:
|
||||
MP3H();
|
||||
int setup(float frequency, int type = 0);
|
||||
int receive();
|
||||
int waitRXcomplete();
|
||||
};
|
||||
|
||||
extern MP3H mp3h;
|
||||
|
||||
#endif
|
934
RX_FSK/src/RS41.cpp
Normal file
934
RX_FSK/src/RS41.cpp
Normal file
|
@ -0,0 +1,934 @@
|
|||
|
||||
/* RS41 decoder functions */
|
||||
#include "RS41.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "rsc.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
#define RS41_DEBUG 1
|
||||
|
||||
#if RS41_DEBUG
|
||||
#define RS41_DBG(x) x
|
||||
#else
|
||||
#define RS41_DBG(x)
|
||||
#endif
|
||||
|
||||
#define RS41MAXLEN (320)
|
||||
static byte data[800];
|
||||
static int dpos = 0;
|
||||
|
||||
|
||||
// whole 51 row frame as C structure
|
||||
// taken from https://github.com/einergehtnochrein/ra-firmware
|
||||
struct subframeBuffer {
|
||||
uint64_t valid; // bitmask for subframe valid; lsb=frame 0, etc.
|
||||
union {
|
||||
byte rawData[51*16];
|
||||
struct __attribute__((__packed__)) {
|
||||
uint16_t crc16; /* CRC16 CCITT Checksum over range 0x002...0x31F */
|
||||
uint16_t frequency; /* 0x002: TX is on 400 MHz + (frequency / 64) * 10 kHz */
|
||||
uint8_t startupTxPower; /* 0x004: TX power level at startup (1...7) */
|
||||
uint8_t reserved005;
|
||||
uint8_t reserved006;
|
||||
uint16_t reserved007; /* 0x007: ?? (some bitfield) [0],[1],[2],[3]. Init value = 0xE */
|
||||
uint16_t reserved009; /* 0x009: ? */
|
||||
uint8_t reserved00B;
|
||||
uint8_t reserved00C;
|
||||
uint8_t serial[8]; /* 0x00D: Sonde ID, 8 char, not terminated */
|
||||
uint16_t firmwareVersion; /* 0x015: 10000*major + 100*minor + patch*/
|
||||
uint16_t reserved017;
|
||||
uint16_t minHeight4Flight; /* 0x019: Height (meter above ground) where flight mode begins */
|
||||
uint8_t lowBatteryThreshold100mV; /* 0x01B: (Default=18) Shutdown if battery voltage below this
|
||||
threshold for some time (10s ?)
|
||||
*/
|
||||
uint8_t nfcDetectorThreshold; /* 0x01C: NFC detector threshold [25mV] (Default: 0x05 = 125mV) */
|
||||
uint8_t reserved01D; /* 0x01D: ?? (Init value = 0xB4) */
|
||||
uint8_t reserved01E; /* 0x01E: ?? (Init value = 0x3C) */
|
||||
uint16_t reserved01F;
|
||||
int8_t refTemperatureThreshold; /* 0x021: Reference temperature threshold [°C] */
|
||||
uint8_t reserved022;
|
||||
uint16_t reserved023;
|
||||
uint16_t reserved025;
|
||||
int16_t flightKillFrames; /* 0x027: Number of frames in flight until kill (-1 = disabled) */
|
||||
uint16_t reserved029; /* 0x029: ? (Init value = 0) */
|
||||
uint8_t burstKill; /* 0x02B: Burst kill (0=disabled, 1=enabled) */
|
||||
uint8_t reserved02C;
|
||||
uint8_t reserved02D;
|
||||
uint16_t reserved02E;
|
||||
uint16_t reserved030;
|
||||
uint8_t reserved032;
|
||||
uint16_t reserved033;
|
||||
uint16_t reserved035;
|
||||
uint16_t reserved037;
|
||||
uint16_t reserved039; /* 0x039: */
|
||||
uint8_t reserved03B; /* 0x03B: */
|
||||
uint8_t reserved03C; /* 0x03C: */
|
||||
float refResistorLow; /* 0x03D: Reference resistor low (750 Ohms) */
|
||||
float refResistorHigh; /* 0x041: Reference resistor high (1100 Ohms) */
|
||||
float refCapLow; /* 0x045: Reference capacitance low (0) */
|
||||
float refCapHigh; /* 0x049: Reference capacitance high (47 pF) */
|
||||
float taylorT[3]; /* 0x04D: Tayor coefficients for main temperature calculation */
|
||||
float calT; /* 0x059: Calibration factor for main sensor */
|
||||
float polyT[6]; /* 0x05D: */
|
||||
float calibU[2]; /* 0x075: Calibration coefficients for humidity sensor */
|
||||
|
||||
float matrixU[7][6]; /* 0x07D: Matrix for humidity sensor RH calculation */
|
||||
float taylorTU[3]; /* 0x125: Coefficients for U sensor temperature calculation */
|
||||
float calTU; /* 0x131: Calibration factor for U temperature sensor */
|
||||
float polyTrh[6]; /* 0x135: */
|
||||
|
||||
uint8_t reserved14D; /* 0x14D: */
|
||||
uint32_t reserved14E; /* 0x14E: */
|
||||
|
||||
float f152;
|
||||
uint8_t u156;
|
||||
float f157; /* 0x157: ?? (Initialized by same value as calibU[0]) */
|
||||
uint8_t reserved15B; /* 0x15B: */
|
||||
uint32_t reserved15C; /* 0x15C: */
|
||||
float f160[35];
|
||||
uint8_t startIWDG; /* 0x1EC: If ==1 or ==2: Watchdog IWDG will not be started */
|
||||
uint8_t parameterSetupDone; /* 0x1ED: Set (!=0) if parameter setup was done */
|
||||
uint8_t enableTestMode; /* 0x1EE: Test mode (service menu) (0=disabled, 1=enabled) */
|
||||
uint8_t enableTX; /* 0x1EF: 0=TX disabled, 1=TX enabled (maybe this is autostart?) */
|
||||
float f1F0[8];
|
||||
float pressureLaunchSite[2]; /* 0x210: Pressure [hPa] at launch site */
|
||||
struct __attribute__((__packed__)){
|
||||
char variant[10]; /* 0x218: Sonde variant (e.g. "RS41-SG") */
|
||||
uint8_t mainboard[10]; /* 0x222: Name of mainboard (e.g. "RSM412") */
|
||||
} names;
|
||||
struct __attribute__((__packed__)){
|
||||
uint8_t mainboard[9]; /* 0x22C: Serial number of mainboard (e.g. "L1123553") */
|
||||
uint8_t text235[12]; /* 0x235: "0000000000" */
|
||||
uint16_t reserved241; /* 0x241: */
|
||||
uint8_t pressureSensor[8]; /* 0x243: Serial number of pressure sensor (e.g. "N1310487") */
|
||||
uint16_t reserved24B; /* 0x24B: */
|
||||
} serials;
|
||||
uint16_t reserved24D; /* 0x24D: */
|
||||
uint16_t reserved24F; /* 0x24F: */
|
||||
uint16_t reserved251; /* 0x251: (Init value = 0x21A = 538) */
|
||||
uint8_t xdataUartBaud; /* 0x253: 1=9k6, 2=19k2, 3=38k4, 4=57k6, 5=115k2 */
|
||||
uint8_t reserved254;
|
||||
float cpuTempSensorVoltageAt25deg; /* 0x255: CPU temperature sensor voltage at 25°C */
|
||||
uint8_t reserved259;
|
||||
uint8_t reserved25A[0x25E -0x25A];
|
||||
float matrixP[18]; /* 0x25E: Coefficients for pressure sensor polynomial */
|
||||
float vectorBp[3]; /* 0x2A6: */
|
||||
uint8_t reserved2B2[8]; /* 0x2B2: */
|
||||
float matrixBt[12]; /* 0x2BA: */
|
||||
uint8_t reserved2EA[0x2FA-0x2EA];
|
||||
uint16_t halfword2FA[9];
|
||||
float reserved30C;
|
||||
float reserved310; /* 0x310: */
|
||||
uint8_t reserved314; /* 0x314: */
|
||||
uint8_t reserved315; /* 0x315: */
|
||||
int16_t burstKillFrames; /* 0x316: Number of active frames after burst kill */
|
||||
uint8_t reserved318[0x320-0x318];
|
||||
|
||||
/* This is fragment 50. It only uses 14 valid bytes! */
|
||||
int16_t killCountdown; /* 0x320: Counts frames remaining until kill (-1 = inactive) */
|
||||
uint8_t reserved322[6];
|
||||
int8_t intTemperatureCpu; /* 0x328: Temperature [°C] of CPU */
|
||||
int8_t intTemperatureRadio; /* 0x329: Temperature [°C] of radio chip */
|
||||
int8_t reserved32A; /* 0x32A: */
|
||||
uint8_t reserved32B; /* 0x32B: */
|
||||
uint8_t reserved32C; /* 0x32C: ? (the sum of two slow 8-bit counters) */
|
||||
uint8_t reserved32D; /* 0x32D: ? (the sum of two slow 8-bit counters) */
|
||||
} value;
|
||||
};
|
||||
};
|
||||
// moved global variable "calibration" to sondeInfo->extra
|
||||
|
||||
static uint16_t CRCTAB[256];
|
||||
|
||||
#define X2C_DIVR(a, b) ((b) != 0.0f ? (a)/(b) : (a))
|
||||
#define X2C_DIVL(a, b) ((a)/(b))
|
||||
static uint32_t X2C_LSH(uint32_t a, int32_t length, int32_t n)
|
||||
{
|
||||
uint32_t m;
|
||||
|
||||
m = 0;
|
||||
m = (length == 32) ? 0xFFFFFFFFl : (1 << length) - 1;
|
||||
if (n > 0) {
|
||||
if (n >= (int32_t)length)
|
||||
return 0;
|
||||
return (a << n) & m;
|
||||
}
|
||||
|
||||
if (n <= (int32_t)-length)
|
||||
return 0;
|
||||
return (a >> -n) & m;
|
||||
}
|
||||
|
||||
double atang2(double x, double y)
|
||||
{
|
||||
double w;
|
||||
if (fabs(x)>fabs(y)) {
|
||||
w = (double)atan(X2C_DIVL(y,x));
|
||||
if (x<0.0) {
|
||||
if (y>0.0) w = 3.1415926535898+w;
|
||||
else w = w-3.1415926535898;
|
||||
}
|
||||
}
|
||||
else if (y!=0.0) {
|
||||
w = (double)(1.5707963267949f-atan(X2C_DIVL(x, y)));
|
||||
if (y<0.0) w = w-3.1415926535898;
|
||||
}
|
||||
else w = 0.0;
|
||||
return w;
|
||||
} /* end atang2() */
|
||||
|
||||
|
||||
static void Gencrctab(void)
|
||||
{
|
||||
uint16_t j;
|
||||
uint16_t i;
|
||||
uint16_t crc;
|
||||
for (i = 0U; i<=255U; i++) {
|
||||
crc = (uint16_t)(i*256U);
|
||||
for (j = 0U; j<=7U; j++) {
|
||||
if ((0x8000U & crc)) crc = X2C_LSH(crc,16,1)^0x1021U;
|
||||
else crc = X2C_LSH(crc,16,1);
|
||||
} /* end for */
|
||||
CRCTAB[i] = X2C_LSH(crc,16,-8)|X2C_LSH(crc,16,8);
|
||||
} /* end for */
|
||||
} /* end Gencrctab() */
|
||||
|
||||
decoderSetupCfg rs41SetupCfg = {
|
||||
.bitrate = 4800,
|
||||
.rx_cfg = 0x1E, // Enable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
.sync_cfg = 0x57, // Set autostart_RX to 01, preamble 0, SYNC detect==on, syncsize=3 (==4 byte
|
||||
.sync_len = 8,
|
||||
.sync_data = (const uint8_t *)"\x08\x6D\x53\x88\x44\x69\x48\x1F",
|
||||
.preamble_cfg = 0xA8,
|
||||
};
|
||||
|
||||
|
||||
int RS41::setup(float frequency, int /*type*/)
|
||||
{
|
||||
if(!initialized) {
|
||||
Gencrctab();
|
||||
initrsc();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if(sx1278.ON()!=0) {
|
||||
RS41_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(DecoderBase::setup(rs41SetupCfg, sonde.config.rs41.agcbw, sonde.config.rs41.rxbw)!=0 ) {
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
// all moved to DecoderBase now
|
||||
if(sx1278.setFSK()!=0) {
|
||||
RS41_DBG(Serial.println("Setting FSK mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setBitrate(4800)!=0) {
|
||||
RS41_DBG(Serial.println("Setting bitrate 4800bit/s FAILED"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(sx1278.setAFCBandwidth(sonde.config.rs41.agcbw)!=0) {
|
||||
RS41_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.rs41.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.rs41.rxbw)!=0) {
|
||||
RS41_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.rs41.rxbw));
|
||||
return 1;
|
||||
}
|
||||
// Enable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
if(sx1278.setRxConf(0x1E)!=0) {
|
||||
RS41_DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// Set autostart_RX to 01, preamble 0, SYNC detect==on, syncsize=3 (==4 byte
|
||||
//char header[] = "0110.0101 0110.0110 1010.0101 1010.1010";
|
||||
|
||||
//const char *SYNC="\x10\xB6\xCA\x11\x22\x96\x12\xF8";
|
||||
const char *SYNC="\x08\x6D\x53\x88\x44\x69\x48\x1F";
|
||||
if(sx1278.setSyncConf(0x57, 8, (const uint8_t *)SYNC)!=0) {
|
||||
RS41_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setPreambleDetect(0xA8)!=0) {
|
||||
RS41_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Packet config 1: fixed len, no mancecer, no crc, no address filter
|
||||
// Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0)
|
||||
if(sx1278.setPacketConfig(0x08, 0x40)!=0) {
|
||||
RS41_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
int retval = sx1278.setFrequency(frequency);
|
||||
dpos = 0;
|
||||
|
||||
sx1278.clearIRQFlags();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint32_t RS41::bits2val(const uint8_t *bits, int len) {
|
||||
uint32_t val = 0;
|
||||
for (int j = 0; j < len; j++) {
|
||||
val |= (bits[j] << (len-1-j));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
RS41::RS41() {
|
||||
}
|
||||
|
||||
/* RS41 reed solomon decoder, from dxlAPRS
|
||||
*/
|
||||
static int32_t reedsolomon41(byte buf[], uint32_t buf_len, uint32_t len2)
|
||||
{
|
||||
uint32_t i;
|
||||
int32_t res1;
|
||||
/*tb1, */
|
||||
int32_t res;
|
||||
char b1[256];
|
||||
char b[256];
|
||||
uint32_t eraspos[24];
|
||||
uint32_t tmp;
|
||||
for (i = 0UL; i<=255UL; i++) {
|
||||
b[i] = 0;
|
||||
b1[i] = 0;
|
||||
} /* end for */
|
||||
tmp = len2;
|
||||
i = 0UL;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
b[230UL-i] = buf[i*2UL+56UL];
|
||||
b1[230UL-i] = buf[i*2UL+57UL];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
for (i = 0UL; i<=23UL; i++) {
|
||||
b[254UL-i] = buf[i+8UL];
|
||||
b1[254UL-i] = buf[i+32UL];
|
||||
} /* end for */
|
||||
res = decodersc(b, eraspos, 0);
|
||||
res1 = decodersc(b1, eraspos, 0);
|
||||
if (res>0L && res<=12L) {
|
||||
tmp = len2;
|
||||
i = 0UL;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
buf[i*2UL+56UL] = b[230UL-i];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
for (i = 0UL; i<=23UL; i++) {
|
||||
buf[i+8UL] = b[254UL-i];
|
||||
} /* end for */
|
||||
}
|
||||
if (res1>0L && res1<=12L) {
|
||||
tmp = len2;
|
||||
i = 0UL;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
buf[i*2UL+57UL] = b1[230UL-i];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
for (i = 0UL; i<=23UL; i++) {
|
||||
buf[i+32UL] = b1[254UL-i];
|
||||
} /* end for */
|
||||
}
|
||||
if (res<0L || res1<0L) return -1L;
|
||||
else return res+res1;
|
||||
return 0;
|
||||
} /* end reedsolomon41() */
|
||||
|
||||
|
||||
|
||||
|
||||
static char crcrs(const byte frame[], uint32_t frame_len,
|
||||
int32_t from, int32_t to)
|
||||
{
|
||||
uint16_t crc;
|
||||
int32_t i;
|
||||
int32_t tmp;
|
||||
crc = 0xFFFFU;
|
||||
tmp = to-3L;
|
||||
i = from;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
crc = X2C_LSH(crc,16,-8)^CRCTAB[(uint32_t)((crc^(uint16_t)(uint8_t)frame[i])&0xFFU)];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
return frame[to-1L]==(char)crc && frame[to-2L]==(char)X2C_LSH(crc,
|
||||
16,-8);
|
||||
} /* end crcrs() */
|
||||
|
||||
static int32_t getint32(const byte frame[], uint32_t frame_len,
|
||||
uint32_t p)
|
||||
{
|
||||
uint32_t n;
|
||||
uint32_t i;
|
||||
n = 0UL;
|
||||
for (i = 3UL;; i--) {
|
||||
n = n*256UL+(uint32_t)(uint8_t)frame[p+i];
|
||||
if (i==0UL) break;
|
||||
} /* end for */
|
||||
return (int32_t)n;
|
||||
} /* end getint32() */
|
||||
|
||||
static uint32_t getint24(const byte frame[], uint32_t frame_len, uint32_t p) { // 24bit unsigned int
|
||||
uint32_t val24 = 0;
|
||||
val24 = frame[p] | (frame[p+1]<<8) | (frame[p+2]<<16);
|
||||
return val24;
|
||||
}
|
||||
|
||||
static uint32_t getcard16(const byte frame[], uint32_t frame_len,
|
||||
uint32_t p)
|
||||
{
|
||||
return (uint32_t)(uint8_t)frame[p]+256UL*(uint32_t)(uint8_t)
|
||||
frame[p+1UL];
|
||||
} /* end getcard16() */
|
||||
|
||||
|
||||
static int32_t getint16(const byte frame[], uint32_t frame_len,
|
||||
uint32_t p)
|
||||
{
|
||||
uint32_t n;
|
||||
n = (uint32_t)(uint8_t)frame[p]+256UL*(uint32_t)(uint8_t)
|
||||
frame[p+1UL];
|
||||
if (n>=32768UL) return (int32_t)(n-65536UL);
|
||||
return (int32_t)n;
|
||||
} /* end getint16() */
|
||||
|
||||
// also used by MP3H.cpp
|
||||
void wgs84r(double x, double y, double z,
|
||||
double * lat, double * long0,
|
||||
double * heig)
|
||||
{
|
||||
double sl;
|
||||
double ct;
|
||||
double st;
|
||||
double t;
|
||||
double rh;
|
||||
double xh;
|
||||
double h;
|
||||
h = x*x+y*y;
|
||||
if (h>0.0) {
|
||||
rh = sqrt(h);
|
||||
xh = x+rh;
|
||||
*long0 = atang2(xh, y)*2.0;
|
||||
if (*long0>3.1415926535898) *long0 = *long0-6.2831853071796;
|
||||
t = atan(X2C_DIVL(z*1.003364089821, rh));
|
||||
st = sin(t);
|
||||
ct = cos(t);
|
||||
*lat = atan((X2C_DIVL(z+4.2841311513312E+4*st*st*st,
|
||||
rh-4.269767270718E+4*ct*ct*ct)));
|
||||
sl = sin(*lat);
|
||||
*heig = X2C_DIVL(rh,cos(*lat))-(X2C_DIVR(6.378137E+6f,
|
||||
sqrt((1.0-6.6943799901413E-3*sl*sl))));
|
||||
}
|
||||
else {
|
||||
*lat = 0.0;
|
||||
*long0 = 0.0;
|
||||
*heig = 0.0;
|
||||
}
|
||||
/* lat:=atan(z/(rh*(1.0 - E2))); */
|
||||
/* heig:=sqrt(h + z*z) - EARTHA; */
|
||||
} /* end wgs84r() */
|
||||
|
||||
// returns: 0=ok, -1=error
|
||||
static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
||||
{
|
||||
double dir;
|
||||
double vu;
|
||||
double ve;
|
||||
double vn;
|
||||
double vz;
|
||||
double vy;
|
||||
double vx;
|
||||
double heig;
|
||||
double long0;
|
||||
double lat;
|
||||
double z;
|
||||
double y;
|
||||
double x;
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
x = (double)getint32(b, b_len, p)*0.01;
|
||||
y = (double)getint32(b, b_len, p+4UL)*0.01;
|
||||
z = (double)getint32(b, b_len, p+8UL)*0.01;
|
||||
uint8_t sats = getcard16(b, b_len, p+18UL)&255UL;
|
||||
Serial.printf("x:%g, y:%g, z:%g sats:%d\n", x, y, z, sats);
|
||||
if( sats<4 || (x==0 && y==0 && z==0) ) {
|
||||
// RS41 sometimes sends frame with all 0
|
||||
// or, if sats<4, data is simply garbage. do not use.
|
||||
if(si->validPos) si->validPos |= 0x80; // flag as old
|
||||
return;
|
||||
}
|
||||
si->sats = sats;
|
||||
wgs84r(x, y, z, &lat, &long0, &heig);
|
||||
Serial.print(" ");
|
||||
si->lat = (float)(X2C_DIVL(lat,1.7453292519943E-2));
|
||||
Serial.print(si->lat);
|
||||
Serial.print(" ");
|
||||
si->lon = (float)(X2C_DIVL(long0,1.7453292519943E-2));
|
||||
Serial.print(si->lon);
|
||||
if (heig<1.E+5 && heig>(-1.E+5)) {
|
||||
Serial.print(" ");
|
||||
Serial.print((uint32_t)heig);
|
||||
Serial.print("m");
|
||||
}
|
||||
/*speed */
|
||||
vx = (double)getint16(b, b_len, p+12UL)*0.01;
|
||||
vy = (double)getint16(b, b_len, p+14UL)*0.01;
|
||||
vz = (double)getint16(b, b_len, p+16UL)*0.01;
|
||||
vn = (-(vx*sin(lat)*cos(long0))-vy*sin(lat)*sin(long0))+vz*cos(lat);
|
||||
ve = -(vx*sin(long0))+vy*cos(long0);
|
||||
vu = vx*cos(lat)*cos(long0)+vy*cos(lat)*sin(long0)+vz*sin(lat);
|
||||
dir = X2C_DIVL(atang2(vn, ve),1.7453292519943E-2);
|
||||
if (dir<0.0) dir = 360.0+dir;
|
||||
si->dir = dir;
|
||||
Serial.print(" ");
|
||||
si->hs = sqrt(vn*vn+ve*ve);
|
||||
Serial.print(si->hs*3.6);
|
||||
Serial.print("km/h ");
|
||||
Serial.print(dir);
|
||||
Serial.print("deg ");
|
||||
Serial.print((float)vu);
|
||||
si->vs = vu;
|
||||
Serial.print("m/s ");
|
||||
si->alt = heig;
|
||||
if( 0==(int)(lat*10000) && 0==(int)(long0*10000) ) {
|
||||
if(si->validPos) {
|
||||
// we have an old position, so keep previous position and mark it as old
|
||||
si->validPos |= 0x80;
|
||||
}
|
||||
}
|
||||
else
|
||||
si->validPos = 0x7f;
|
||||
} /* end posrs41() */
|
||||
|
||||
void ProcessSubframe( byte *subframeBytes, int subframeNumber ) {
|
||||
// the total subframe consists of 51 rows, each row 16 bytes
|
||||
// based on https://github.com/bazjo/RS41_Decoding/tree/master/RS41-SGP#Subframe
|
||||
struct subframeBuffer *s = (struct subframeBuffer *)sonde.si()->extra;
|
||||
// Allocate on demand
|
||||
if(!s) {
|
||||
s = (struct subframeBuffer *)malloc( sizeof(struct subframeBuffer) );
|
||||
if(!s) { Serial.println("ProcessSubframe: out of memory"); return; }
|
||||
sonde.si()->extra = s;
|
||||
s->valid = 0;
|
||||
}
|
||||
memcpy( s->rawData+16*subframeNumber, subframeBytes, 16);
|
||||
s->valid |= (1ULL << subframeNumber);
|
||||
Serial.printf("subframe %d; valid: %x%08x\n", subframeNumber, (uint32_t)(s->valid>>32), (uint32_t)s->valid);
|
||||
for(int i=0; i<16; i++) { Serial.printf("%02x[%c]", subframeBytes[i],( subframeBytes[i]>20 && subframeBytes[i]<127)? subframeBytes[i] : '.'); }
|
||||
Serial.println("");
|
||||
// subframeReceived[subframeNumber] = true; // mark this row of the total subframe as complete
|
||||
|
||||
#if 0
|
||||
Serial.printf("subframe number: 0x%02X\n", subframeNumber );
|
||||
Serial.print("subframe values: ");
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
Serial.printf( "%02X ", subframeBytes[i] );
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println("Full subframe");
|
||||
for ( int j = 0; j<51; j++ ) {
|
||||
Serial.printf("%03X ", j*16);
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
Serial.printf( "%02X ", s.rawData[j*16+i] );
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Find the water vapor saturation pressure for a given temperature.
|
||||
* Uses the Hyland and Wexler equation with coefficients for T < 0°C.
|
||||
*/
|
||||
// taken from https://github.com/einergehtnochrein/ra-firmware
|
||||
static float _RS41_waterVaporSaturationPressure (float Tcelsius)
|
||||
{
|
||||
/* Convert to Kelvin */
|
||||
float T = Tcelsius + 273.15f;
|
||||
|
||||
/* Apply some correction magic */
|
||||
T = 0
|
||||
- 0.4931358f
|
||||
+ (1.0f + 4.61e-3f) * T
|
||||
- 1.3746454e-5f * T * T
|
||||
+ 1.2743214e-8f * T * T * T
|
||||
;
|
||||
|
||||
/* Plug into H+W equation */
|
||||
float p = expf(-5800.2206f / T
|
||||
+ 1.3914993f
|
||||
+ 6.5459673f * logf(T)
|
||||
- 4.8640239e-2f * T
|
||||
+ 4.1764768e-5f * T * T
|
||||
- 1.4452093e-8f * T * T * T
|
||||
);
|
||||
|
||||
/* Scale result to hPa */
|
||||
return p / 100.0f;
|
||||
}
|
||||
|
||||
#define PM(x) calibration->value.matrixP[x]
|
||||
// CALIB_P: matrixP (frames 0x25..0x2A) and type (frame 0x21)
|
||||
#define CALIB_P ((0x3Fll<<0x25)|(1ll<<0x21))
|
||||
float GetRAP( uint32_t m, uint32_t m1, uint32_t m2, int16_t ptraw) {
|
||||
struct subframeBuffer *calibration = (struct subframeBuffer *)sonde.si()->extra;
|
||||
float pt = (float)ptraw*0.01;
|
||||
float pw[6];
|
||||
pw[0] = PM(0) + pt*PM(7) + pt*pt*PM(11) + pt*pt*pt*PM(15);
|
||||
pw[1] = PM(1) + pt*PM(8) + pt*pt*PM(12) + pt*pt*pt*PM(16);
|
||||
pw[2] = PM(2) + pt*PM(9) + pt*pt*PM(13) + pt*pt*pt*PM(17);
|
||||
pw[3] = PM(3) + pt*PM(10)+ pt*pt*PM(14);
|
||||
pw[4] = PM(4);
|
||||
pw[5] = PM(5);
|
||||
float f = (float)m; //meas[9];
|
||||
float f1 = (float)m1; //meas[10];
|
||||
float f2 = (float)m2; //meas[11];
|
||||
float r = f-f1;
|
||||
if(r!=0.0) {
|
||||
r = (f2-f1) * PM(6) / r;
|
||||
float xx = 1.0;
|
||||
float p = 0.0;
|
||||
for(int i=0; i<=5; i++) {
|
||||
p += pw[i] * xx;
|
||||
xx = xx * r;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
return NAN;
|
||||
}
|
||||
|
||||
// taken from https://github.com/einergehtnochrein/ra-firmware
|
||||
float GetRATemp( uint32_t measuredCurrent, uint32_t refMin, uint32_t refMax, float calT, float taylorT[3], float polyT[6] ) {
|
||||
struct subframeBuffer *calibration = (struct subframeBuffer *)sonde.si()->extra;
|
||||
/* Reference values for temperature are two known resistors.
|
||||
* From that we can derive the resistance of the sensor.
|
||||
*/
|
||||
float current = ( float(measuredCurrent) - float(refMin) ) / float(refMax - refMin);
|
||||
float res = calibration->value.refResistorLow
|
||||
+ (calibration->value.refResistorHigh - calibration->value.refResistorLow) * current;
|
||||
float x = res * calT;
|
||||
|
||||
float Tuncal = 0
|
||||
+ taylorT[0]
|
||||
+ taylorT[1] * x
|
||||
+ taylorT[2] * x * x;
|
||||
|
||||
/* Apply calibration polynomial */
|
||||
float temperature =
|
||||
Tuncal + polyT[0]
|
||||
+ polyT[1] * Tuncal
|
||||
+ polyT[2] * Tuncal * Tuncal
|
||||
+ polyT[3] * Tuncal * Tuncal * Tuncal
|
||||
+ polyT[4] * Tuncal * Tuncal * Tuncal * Tuncal
|
||||
+ polyT[5] * Tuncal * Tuncal * Tuncal * Tuncal * Tuncal;
|
||||
|
||||
return temperature;
|
||||
}
|
||||
|
||||
// taken from https://github.com/einergehtnochrein/ra-firmware
|
||||
float GetRAHumidity( uint32_t humCurrent, uint32_t humMin, uint32_t humMax, float sensorTemp, float externalTemp, float pressure ) {
|
||||
struct subframeBuffer *calibration = (struct subframeBuffer *)sonde.si()->extra;
|
||||
float current = float( humCurrent - humMin) / float( humMax - humMin );
|
||||
/* Compute absolute capacitance from the known references */
|
||||
float C = calibration->value.refCapLow
|
||||
+ (calibration->value.refCapHigh - calibration->value.refCapLow) * current;
|
||||
|
||||
/* Apply calibration */
|
||||
float Cp = ( C / calibration->value.calibU[0] - 1.0f) * calibration->value.calibU[1];
|
||||
|
||||
/* Compensation for low temperature and pressure at altitude */
|
||||
if(isnan(pressure)) {
|
||||
// if no pressure is available (non-SGP), estimate based on altitude
|
||||
pressure = 1013.25f * expf(-1.18575919e-4f * sonde.si()->d.alt );
|
||||
}
|
||||
|
||||
float Tp = (sensorTemp - 20.0f) / 180.0f;
|
||||
float sum = 0;
|
||||
float powc = 1.0f;
|
||||
float p = pressure / 1000.0f;
|
||||
for ( int i = 0; i < 3; i++) {
|
||||
float l = 0;
|
||||
float powt = 1.0f;
|
||||
for ( int j = 0; j < 4; j++) {
|
||||
l += calibration->value.matrixBt[4*i+j] * powt;
|
||||
powt *= Tp;
|
||||
}
|
||||
float x = calibration->value.vectorBp[i];
|
||||
sum += l * (x * p / (1.0f + x * p) - x * powc / (1.0f + x));
|
||||
powc *= Cp;
|
||||
}
|
||||
Cp -= sum;
|
||||
|
||||
float xj = 1.0f;
|
||||
for ( int j = 0; j < 7; j++) {
|
||||
float yk = 1.0f;
|
||||
for ( int k = 0; k < 6; k++) {
|
||||
sum += xj * yk * calibration->value.matrixU[j][k];
|
||||
yk *= Tp;
|
||||
}
|
||||
xj *= Cp;
|
||||
}
|
||||
|
||||
/* Since there is always a small difference between the temperature readings for
|
||||
* the atmospheric (main) tempoerature sensor and the temperature sensor inside
|
||||
* the humidity sensor device, transform the humidity value to the atmospheric conditions
|
||||
* with its different water vapor saturation pressure.
|
||||
*/
|
||||
float RH = sum
|
||||
* _RS41_waterVaporSaturationPressure(sensorTemp)
|
||||
/ _RS41_waterVaporSaturationPressure(externalTemp);
|
||||
|
||||
return RH;
|
||||
}
|
||||
|
||||
// returns: 0: ok, -1: rs or crc error
|
||||
int RS41::decode41(byte *data, int maxlen)
|
||||
{
|
||||
char buf[128];
|
||||
int crcok = 1;
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
|
||||
int32_t corr = reedsolomon41(data, 560, 131); // try short frame first
|
||||
if(corr<0) {
|
||||
corr = reedsolomon41(data, 560, 230); // try long frame
|
||||
}
|
||||
#if 0
|
||||
Serial.print("RS result:");
|
||||
Serial.print(corr);
|
||||
Serial.println();
|
||||
#endif
|
||||
int p = 57; // 8 byte header, 48 byte RS
|
||||
while(p<maxlen) { /* why 555? */
|
||||
uint8_t typ = data[p++];
|
||||
uint32_t len = data[p++]+2UL;
|
||||
if(p+len>maxlen) break;
|
||||
|
||||
#if 0
|
||||
// DEBUG OUTPUT
|
||||
Serial.print("@");
|
||||
Serial.print(p-2);
|
||||
Serial.print(": ID:");
|
||||
Serial.print(typ, HEX);
|
||||
Serial.print(", len=");
|
||||
Serial.print(len);
|
||||
Serial.print(": ");
|
||||
for(int i=0; i<len-1; i++) {
|
||||
char buf[3];
|
||||
snprintf(buf, 4, "%02X|", data[p+i]);
|
||||
Serial.print(buf);
|
||||
}
|
||||
#endif
|
||||
// check CRC
|
||||
if(!crcrs(data, 560, p, p+len)) {
|
||||
Serial.println("###CRC ERROR###");
|
||||
crcok = 0;
|
||||
} else {
|
||||
switch(typ) {
|
||||
case 'y': // name
|
||||
{
|
||||
if(strncmp(si->id, (const char *)(data+p+2), 8)) {
|
||||
// ID changed, i.e. new sonde on same frequency. clear calibration and all other data
|
||||
sonde.clearAllData(sonde.si());
|
||||
struct subframeBuffer *sub = (struct subframeBuffer *)sonde.si()->extra;
|
||||
if(sub) { sub->valid = 0; }
|
||||
}
|
||||
Serial.print("#");
|
||||
uint16_t fnr = data[p]+(data[p+1]<<8);
|
||||
Serial.print(fnr);
|
||||
si->vframe = si->frame = fnr;
|
||||
Serial.print("; RS41 ID ");
|
||||
snprintf(buf, 10, "%.8s ", data+p+2);
|
||||
Serial.print(buf);
|
||||
si->batteryVoltage = data[p+10] / 10.0f;
|
||||
// not needed, if we end up here, the type has to be RS41.... si->type=STYPE_RS41;
|
||||
strncpy(si->id, (const char *)(data+p+2), 8);
|
||||
si->id[8]=0;
|
||||
strncpy(si->ser, (const char *)(data+p+2), 8);
|
||||
si->ser[8]=0;
|
||||
si->validID=true;
|
||||
int calnr = data[p+23];
|
||||
// not sure about this
|
||||
if(calnr==0x31) {
|
||||
uint16_t bt = data[p+30] + 256*data[p+31];
|
||||
si->burstKT = bt;
|
||||
}
|
||||
// this should be right...
|
||||
if(calnr==0x02) {
|
||||
uint16_t kt = data[p+31] + 256*data[p+32];
|
||||
si->launchKT = kt;
|
||||
}
|
||||
// and this seems fine as well...
|
||||
if(calnr==0x32) {
|
||||
uint16_t cntdown = data[p+24] + (data[p+25]<<8);
|
||||
uint16_t min = cntdown - (cntdown/3600)*3600;
|
||||
Serial.printf("Countdown value: %d\n [%2d:%02d:%02d]", cntdown, cntdown/3600, min/60, min-(min/60)*60);
|
||||
si->countKT = cntdown;
|
||||
si->crefKT = fnr;
|
||||
}
|
||||
ProcessSubframe( data+p+24, calnr );
|
||||
|
||||
}
|
||||
// TODO: some more data
|
||||
break;
|
||||
case '|': // date
|
||||
{
|
||||
uint32_t gpstime = getint32(data, 560, p+2);
|
||||
uint16_t gpsweek = getint16(data, 560, p);
|
||||
// UTC is GPSTIME - 18s (24*60*60-18 = 86382)
|
||||
// one week = 7*24*60*60 = 604800 seconds
|
||||
// unix epoch starts jan 1st 1970 0:00
|
||||
// gps time starts jan 6, 1980 0:00. thats 315964800 epoch seconds.
|
||||
// subtracting 86400 yields 315878400UL
|
||||
si->time = (gpstime/1000) + 86382 + gpsweek*604800 + 315878400UL;
|
||||
si->validTime = true;
|
||||
}
|
||||
break;
|
||||
case '{': // pos
|
||||
posrs41(data+p, len, 0);
|
||||
break;
|
||||
case 'z': // 0x7a is character z - 7A-MEAS temperature and humidity frame
|
||||
{
|
||||
uint32_t tempMeasMain = getint24(data, 560, p+0);
|
||||
uint32_t tempMeasRef1 = getint24(data, 560, p+3);
|
||||
uint32_t tempMeasRef2 = getint24(data, 560, p+6);
|
||||
uint32_t humidityMain = getint24(data, 560, p+9);
|
||||
uint32_t humidityRef1 = getint24(data, 560, p+12);
|
||||
uint32_t humidityRef2 = getint24(data, 560, p+15);
|
||||
uint32_t tempHumiMain = getint24(data, 560, p+18);
|
||||
uint32_t tempHumiRef1 = getint24(data, 560, p+21);
|
||||
uint32_t tempHumiRef2 = getint24(data, 560, p+24);
|
||||
uint32_t pressureMain = getint24(data, 560, p+27);
|
||||
uint32_t pressureRef1 = getint24(data, 560, p+30);
|
||||
uint32_t pressureRef2 = getint24(data, 560, p+33);
|
||||
int16_t ptraw = getint16(data, 560, p+38);
|
||||
#if 0
|
||||
Serial.printf( "External temp: tempMeasMain = %ld, tempMeasRef1 = %ld, tempMeasRef2 = %ld\n", tempMeasMain, tempMeasRef1, tempMeasRef2 );
|
||||
Serial.printf( "Rel Humidity: humidityMain = %ld, humidityRef1 = %ld, humidityRef2 = %ld\n", humidityMain, humidityRef1, humidityRef2 );
|
||||
Serial.printf( "Humid sensor: tempHumiMain = %ld, tempHumiRef1 = %ld, tempHumiRef2 = %ld\n", tempHumiMain, tempHumiRef1, tempHumiRef2 );
|
||||
Serial.printf( "Pressure sens: pressureMain = %ld, pressureRef1 = %ld, pressureRef2 = %ld\n", pressureMain, pressureRef1, pressureRef2 );
|
||||
#endif
|
||||
struct subframeBuffer *calibration = (struct subframeBuffer *)(sonde.si()->extra);
|
||||
// temp: 0xF8==bits 3..7 : we need refResistorlow/high, taylorT, polyT
|
||||
bool validExternalTemperature = calibration!=NULL && (calibration->valid & 0xF8) == 0xF8;
|
||||
|
||||
// humidity: bits 3..20 and 37..46. and bit 33 (variant)
|
||||
bool validHumidity = calibration!=NULL && (calibration->valid & 0x7FE2001FFFF8) == 0x7FE2001FFFF8;
|
||||
|
||||
// pressure: bits 33 and 37..42 (variant; x25..x2a: matrixP) /// CALIB_P is 0x7E200000000)
|
||||
bool validPressure = calibration!=NULL && (calibration->valid & CALIB_P)==CALIB_P && calibration->value.names.variant[7]=='P';
|
||||
|
||||
if ( validPressure ) {
|
||||
si->pressure = GetRAP( pressureMain, pressureRef1, pressureRef2, ptraw );
|
||||
Serial.printf("Pressure sensor = %f\n", si->pressure);
|
||||
}
|
||||
|
||||
if ( validExternalTemperature ) {
|
||||
si->temperature = GetRATemp( tempMeasMain, tempMeasRef1, tempMeasRef2,
|
||||
calibration->value.calT, calibration->value.taylorT, calibration->value.polyT );
|
||||
Serial.printf("External temperature = %f\n", si->temperature );
|
||||
}
|
||||
|
||||
if ( validHumidity && validExternalTemperature ) {
|
||||
si->tempRHSensor = GetRATemp( tempHumiMain, tempHumiRef1, tempHumiRef2,
|
||||
calibration->value.calTU, calibration->value.taylorTU, calibration->value.polyTrh );
|
||||
Serial.printf("Humidity Sensor temperature = %f\n", si->tempRHSensor );
|
||||
si->relativeHumidity = GetRAHumidity( humidityMain, humidityRef1, humidityRef2, si->tempRHSensor, si->temperature, si->pressure );
|
||||
Serial.printf("Relative humidity = %f\n", si->relativeHumidity );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}}
|
||||
p += len;
|
||||
Serial.println();
|
||||
}
|
||||
return crcok ? 0 : RX_ERROR;
|
||||
}
|
||||
void RS41::printRaw(uint8_t *data, int len)
|
||||
{
|
||||
char buf[3];
|
||||
int i;
|
||||
for(i=0; i<len; i++) {
|
||||
snprintf(buf, 3, "%02X", data[i]);
|
||||
Serial.print(buf);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void RS41::bitsToBytes(uint8_t *bits, uint8_t *bytes, int len)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<len*4; i++) {
|
||||
bytes[i/8] = (bytes[i/8]<<1) | (bits[i]?1:0);
|
||||
}
|
||||
bytes[(i-1)/8] &= 0x0F;
|
||||
}
|
||||
|
||||
static unsigned char lookup[16] = {
|
||||
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
|
||||
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
|
||||
|
||||
static uint8_t reverse(uint8_t n) {
|
||||
return (lookup[n&0x0f] << 4) | lookup[n>>4];
|
||||
}
|
||||
|
||||
|
||||
static uint8_t scramble[64] = {150U,131U,62U,81U,177U,73U,8U,152U,50U,5U,89U,
|
||||
14U,249U,68U,198U,38U,33U,96U,194U,234U,121U,93U,109U,161U,
|
||||
84U,105U,71U,12U,220U,232U,92U,241U,247U,118U,130U,127U,7U,
|
||||
153U,162U,44U,147U,124U,48U,99U,245U,16U,46U,97U,208U,188U,
|
||||
180U,182U,6U,170U,244U,35U,120U,110U,59U,174U,191U,123U,76U,
|
||||
193U};
|
||||
|
||||
|
||||
int RS41::receive() {
|
||||
sx1278.setPayloadLength(RS41MAXLEN-8);
|
||||
int e = sx1278.receivePacketTimeout(1000, data+8);
|
||||
#if 1
|
||||
if(e) { /*Serial.println("TIMEOUT");*/ return RX_TIMEOUT; }
|
||||
|
||||
for(int i=0; i<RS41MAXLEN; i++) { data[i] = reverse(data[i]); }
|
||||
for(int i=0; i<RS41MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
|
||||
return decode41(data, RS41MAXLEN);
|
||||
#else
|
||||
// FAKE testing data
|
||||
SondeInfo *si = sonde.si();
|
||||
si->lat = 48;
|
||||
si->lon = -100;
|
||||
si->alt = 30000;
|
||||
si->vs = 3.4;
|
||||
si->validPos = 0x7f;
|
||||
si->validID = 1;
|
||||
strcpy(si->id, "A1234");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int RS41::waitRXcomplete() {
|
||||
// Currently not used. can be used for additinoal post-processing
|
||||
// (required for RS92 to avoid FIFO overrun in rx task)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// copy variant string to buf (max buflen chars; buflen should be 11
|
||||
// return 0 if subtype is available, -1 if not
|
||||
int RS41::getSubtype(char *buf, int buflen, SondeInfo *si) {
|
||||
struct subframeBuffer *sf = (struct subframeBuffer *)si->extra;
|
||||
if(!sf) return -1;
|
||||
if( ( (sf->valid>>0x21) &3) != 3 ) return -1; // or 1 instead of 3 for the first 8 chars only, as in autorx?
|
||||
if(buflen>11) buflen=11; // then buflen should be capped at 9 (8+trailing \0)
|
||||
strncpy(buf, sf->value.names.variant, buflen);
|
||||
buf[buflen-1]=0;
|
||||
if(*buf==0) return -1;
|
||||
Serial.printf("subframe valid: %x%08x; subtype=%s\n", (uint32_t)(sf->valid>>32), (uint32_t)sf->valid, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RS41 rs41 = RS41();
|
10
libraries/SondeLib/RS41.h → RX_FSK/src/RS41.h
Executable file → Normal file
10
libraries/SondeLib/RS41.h → RX_FSK/src/RS41.h
Executable file → Normal file
|
@ -15,9 +15,11 @@
|
|||
#ifndef inttypes_h
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include "Sonde.h"
|
||||
#include "DecoderBase.h"
|
||||
|
||||
/* Main class */
|
||||
class RS41
|
||||
class RS41 : public DecoderBase
|
||||
{
|
||||
private:
|
||||
uint32_t bits2val(const uint8_t *bits, int len);
|
||||
|
@ -25,6 +27,7 @@ private:
|
|||
void bitsToBytes(uint8_t *bits, uint8_t *bytes, int len);
|
||||
int decode41(byte *data, int maxlen);
|
||||
|
||||
#if 0
|
||||
#define B 8
|
||||
#define S 4
|
||||
uint8_t hamming_conf[ 7*B]; // 7*8=56
|
||||
|
@ -41,6 +44,7 @@ private:
|
|||
{ 1, 1, 0, 1, 0, 0, 1, 0},
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 1}};
|
||||
uint8_t He[8] = { 0x7, 0xB, 0xD, 0xE, 0x8, 0x4, 0x2, 0x1}; // Spalten von H:
|
||||
#endif
|
||||
// 1-bit-error-Syndrome
|
||||
boolean initialized = false;
|
||||
|
||||
|
@ -48,7 +52,7 @@ public:
|
|||
RS41();
|
||||
// New interface:
|
||||
// setup() is called when channel is activated (sets mode and frequency and activates receiver)
|
||||
int setup(float frequency);
|
||||
int setup(float frequency, int type = 0);
|
||||
// processRXbyte is called by background task for each received byte
|
||||
// should be fast enough to not cause sx127x fifo buffer overflow
|
||||
// void processRXbyte(uint8_t data);
|
||||
|
@ -59,6 +63,8 @@ public:
|
|||
int waitRXcomplete();
|
||||
//int receiveFrame();
|
||||
|
||||
static int getSubtype(char *buf, int buflen, SondeInfo *si);
|
||||
|
||||
int use_ecc = 1;
|
||||
};
|
||||
|
172
libraries/SondeLib/RS92.cpp → RX_FSK/src/RS92.cpp
Executable file → Normal file
172
libraries/SondeLib/RS92.cpp → RX_FSK/src/RS92.cpp
Executable file → Normal file
|
@ -17,7 +17,6 @@
|
|||
#define RS92_DBG(x)
|
||||
#endif
|
||||
|
||||
//static uint16_t CRCTAB[256];
|
||||
uint16_t *CRCTAB = NULL;
|
||||
|
||||
#define X2C_DIVR(a, b) ((b) != 0.0f ? (a)/(b) : (a))
|
||||
|
@ -39,27 +38,6 @@ static uint32_t X2C_LSH(uint32_t a, int32_t length, int32_t n)
|
|||
return (a >> -n) & m;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static double atang2(double x, double y)
|
||||
{
|
||||
double w;
|
||||
if (fabs(x)>fabs(y)) {
|
||||
w = (double)atan((float)(X2C_DIVL(y,x)));
|
||||
if (x<0.0) {
|
||||
if (y>0.0) w = 3.1415926535898+w;
|
||||
else w = w-3.1415926535898;
|
||||
}
|
||||
}
|
||||
else if (y!=0.0) {
|
||||
w = (double)(1.5707963267949f-atan((float)(X2C_DIVL(x,
|
||||
y))));
|
||||
if (y<0.0) w = w-3.1415926535898;
|
||||
}
|
||||
else w = 0.0;
|
||||
return w;
|
||||
} /* end atang2() */
|
||||
#endif
|
||||
|
||||
static void Gencrctab(void)
|
||||
{
|
||||
uint16_t j;
|
||||
|
@ -90,7 +68,16 @@ static int haveNewFrame = 0;
|
|||
static int lastFrame = 0;
|
||||
static int headerDetected = 0;
|
||||
|
||||
int RS92::setup(float frequency)
|
||||
decoderSetupCfg rs92SetupCfg = {
|
||||
.bitrate = 4800,
|
||||
.rx_cfg = 0x1E,
|
||||
.sync_cfg = 0x70,
|
||||
.sync_len = 2,
|
||||
.sync_data = (const uint8_t *)"\x66\x65",
|
||||
.preamble_cfg = 0xA8,
|
||||
};
|
||||
|
||||
int RS92::setup(float frequency, int /*type*/)
|
||||
{
|
||||
#if RS92_DEBUG
|
||||
Serial.println("Setup sx1278 for RS92 sonde");
|
||||
|
@ -106,6 +93,10 @@ int RS92::setup(float frequency)
|
|||
RS92_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(DecoderBase::setup(rs92SetupCfg, sonde.config.rs92.rxbw, sonde.config.rs92.rxbw)!=0) {
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
if(sx1278.setFSK()!=0) {
|
||||
RS92_DBG(Serial.println("Setting FSJ mode FAILED"));
|
||||
return 1;
|
||||
|
@ -140,7 +131,6 @@ int RS92::setup(float frequency)
|
|||
//const char *SYNC="\x08\x6D\x53\x88\x44\x69\x48\x1F";
|
||||
// was 0x57
|
||||
//const char *SYNC="\x99\x9A";
|
||||
#if 1
|
||||
// version 1, working with continuous RX
|
||||
const char *SYNC="\x66\x65";
|
||||
if(sx1278.setSyncConf(0x70, 2, (const uint8_t *)SYNC)!=0) {
|
||||
|
@ -152,6 +142,7 @@ int RS92::setup(float frequency)
|
|||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// version 2, with per-packet rx start, untested
|
||||
// header is 2a 10 65, i.e. with lsb first
|
||||
|
@ -196,19 +187,6 @@ int RS92::setup(float frequency)
|
|||
return res;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int RS92::setFrequency(float frequency) {
|
||||
Serial.print("RS92: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
int res = sx1278.setFrequency(frequency);
|
||||
// enable RX
|
||||
sx1278.setPayloadLength(0); // infinite for now...
|
||||
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t RS92::bits2val(const uint8_t *bits, int len) {
|
||||
uint32_t val = 0;
|
||||
for (int j = 0; j < len; j++) {
|
||||
|
@ -448,34 +426,6 @@ void RS92::printRaw(uint8_t *data, int len)
|
|||
Serial.println();
|
||||
}
|
||||
|
||||
#if 0
|
||||
// I guess this is old copy&paste stuff from RS41??
|
||||
int RS92::bitsToBytes(uint8_t *bits, uint8_t *bytes, int len)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<len*4; i++) {
|
||||
bytes[i/8] = (bytes[i/8]<<1) | (bits[i]?1:0);
|
||||
}
|
||||
bytes[(i-1)/8] &= 0x0F;
|
||||
}
|
||||
|
||||
static unsigned char lookup[16] = {
|
||||
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
|
||||
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
|
||||
|
||||
static uint8_t reverse(uint8_t n) {
|
||||
return (lookup[n&0x0f] << 4) | lookup[n>>4];
|
||||
}
|
||||
|
||||
|
||||
static uint8_t scramble[64] = {150U,131U,62U,81U,177U,73U,8U,152U,50U,5U,89U,
|
||||
14U,249U,68U,198U,38U,33U,96U,194U,234U,121U,93U,109U,161U,
|
||||
84U,105U,71U,12U,220U,232U,92U,241U,247U,118U,130U,127U,7U,
|
||||
153U,162U,44U,147U,124U,48U,99U,245U,16U,46U,97U,208U,188U,
|
||||
180U,182U,6U,170U,244U,35U,120U,110U,59U,174U,191U,123U,76U,
|
||||
193U};
|
||||
#endif
|
||||
|
||||
|
||||
void RS92::stobyte92(uint8_t b)
|
||||
{
|
||||
|
@ -615,7 +565,7 @@ int RS92::waitRXcomplete() {
|
|||
Serial.printf("decoding frame %d\n", lastFrame);
|
||||
print_frame(lastFrame==1?data1:data2, 240);
|
||||
|
||||
SondeInfo *si = sonde.sondeList+rxtask.receiveSonde;
|
||||
SondeData *si = &( (sonde.sondeList+rxtask.receiveSonde)->d );
|
||||
si->lat = gpx.lat;
|
||||
si->lon = gpx.lon;
|
||||
si->alt = gpx.alt;
|
||||
|
@ -626,102 +576,14 @@ int RS92::waitRXcomplete() {
|
|||
memcpy(si->id, gpx.id, 9);
|
||||
memcpy(si->ser, gpx.id, 9);
|
||||
si->validID = true;
|
||||
si->frame = gpx.frnr;
|
||||
si->vframe = si->frame = gpx.frnr;
|
||||
si->sats = gpx.k;
|
||||
si->time = (gpx.gpssec/1000) + 86382 + gpx.week*604800 + 315878400UL;
|
||||
si->validTime = true;
|
||||
|
||||
#if 0
|
||||
int res=0;
|
||||
uint32_t t0 = millis();
|
||||
while( rxtask.receiveResult == 0xFFFF && millis()-t0 < 2000) { delay(20); }
|
||||
|
||||
if( rxtask.receiveResult<0 || rxtask.receiveResult==RX_TIMEOUT) {
|
||||
res = RX_TIMEOUT;
|
||||
} else if ( rxtask.receiveResult==0) {
|
||||
res = RX_OK;
|
||||
} else {
|
||||
res = RX_ERROR;
|
||||
}
|
||||
rxtask.receiveResult = 0xFFFF;
|
||||
Serial.printf("RS92::waitRXcomplete returning %d (%s)\n", res, RXstr[res]);
|
||||
return res;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int oldwaitRXcomplete() {
|
||||
Serial.println("RS92: receive frame...\n");
|
||||
sx1278receiveData = true;
|
||||
delay(6000); // done in other task....
|
||||
//sx1278receiveData = false;
|
||||
#if 0
|
||||
//sx1278.setPayloadLength(518-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
|
||||
//sx1278.setPayloadLength(0); // infinite for now...
|
||||
|
||||
////// test code for continuous reception
|
||||
// sx1278.receive(); /// active FSK RX mode -- already done above...
|
||||
uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
unsigned long previous = millis();
|
||||
|
||||
byte ready=0;
|
||||
uint32_t wait = 8000;
|
||||
// while not yet done or FIFO not yet empty
|
||||
// bit 6: FIFO Empty
|
||||
// bit 2 payload ready
|
||||
int by=0;
|
||||
while( (!ready || bitRead(value,6)==0) && (millis() - previous < wait) )
|
||||
{
|
||||
if( bitRead(value, 7) ) { Serial.println("FIFO full"); }
|
||||
if( bitRead(value, 4) ) { Serial.println("FIFO overflow"); }
|
||||
if( bitRead(value,2)==1 ) ready=1;
|
||||
if( bitRead(value, 6) == 0 ) { // FIFO not empty
|
||||
byte data = sx1278.readRegister(REG_FIFO);
|
||||
process8N1data(data);
|
||||
by++;
|
||||
#if 0
|
||||
if(di==1) {
|
||||
int rssi=getRSSI();
|
||||
int fei=getFEI();
|
||||
int afc=getAFC();
|
||||
Serial.print("Test: RSSI="); Serial.println(rssi);
|
||||
Serial.print("Test: FEI="); Serial.println(fei);
|
||||
Serial.print("Test: AFC="); Serial.println(afc);
|
||||
sonde.si()->rssi = rssi;
|
||||
sonde.si()->afc = afc;
|
||||
}
|
||||
if(di>520) {
|
||||
// TODO
|
||||
Serial.println("TOO MUCH DATA");
|
||||
break;
|
||||
}
|
||||
previous = millis(); // reset timeout after receiving data
|
||||
#endif
|
||||
}
|
||||
value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
}
|
||||
Serial.printf("processed %d bytes before end/timeout\n", by);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/////
|
||||
#if 0
|
||||
int e = sx1278.receivePacketTimeout(1000, data+8);
|
||||
if(e) { Serial.println("TIMEOUT"); return RX_TIMEOUT; } //if timeout... return 1
|
||||
|
||||
printRaw(data, RS92MAXLEN);
|
||||
//for(int i=0; i<RS92MAXLEN; i++) { data[i] = reverse(data[i]); }
|
||||
//printRaw(data, MAXLEN);
|
||||
//for(int i=0; i<RS92MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
|
||||
//printRaw(data, MAXLEN);
|
||||
//int res = decode41(data, RS92MAXLEN);
|
||||
#endif
|
||||
int res=0;
|
||||
return res==0 ? RX_OK : RX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
RS92 rs92 = RS92();
|
10
libraries/SondeLib/RS92.h → RX_FSK/src/RS92.h
Executable file → Normal file
10
libraries/SondeLib/RS92.h → RX_FSK/src/RS92.h
Executable file → Normal file
|
@ -15,6 +15,7 @@
|
|||
#ifndef inttypes_h
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include "DecoderBase.h"
|
||||
|
||||
|
||||
struct CONTEXTR9 {
|
||||
|
@ -49,17 +50,12 @@ struct CONTEXTR9 {
|
|||
|
||||
|
||||
/* Main class */
|
||||
class RS92
|
||||
class RS92 : public DecoderBase
|
||||
{
|
||||
private:
|
||||
void process8N1data(uint8_t data);
|
||||
void stobyte92(uint8_t byte);
|
||||
void decodeframe92(uint8_t *data);
|
||||
#if 0
|
||||
void dogps(const uint8_t *sf, int sf_len,
|
||||
struct CONTEXTR9 * cont, uint32_t * timems,
|
||||
uint32_t * gpstime);
|
||||
#endif
|
||||
uint32_t bits2val(const uint8_t *bits, int len);
|
||||
void printRaw(uint8_t *data, int len);
|
||||
int bitsToBytes(uint8_t *bits, uint8_t *bytes, int len);
|
||||
|
@ -84,7 +80,7 @@ private:
|
|||
|
||||
public:
|
||||
RS92();
|
||||
int setup(float frequency);
|
||||
int setup(float frequency, int type = 0);
|
||||
int receive();
|
||||
int waitRXcomplete();
|
||||
|
85
libraries/SX1278FSK/SX1278FSK.cpp → RX_FSK/src/SX1278FSK.cpp
Executable file → Normal file
85
libraries/SX1278FSK/SX1278FSK.cpp → RX_FSK/src/SX1278FSK.cpp
Executable file → Normal file
|
@ -11,16 +11,41 @@
|
|||
|
||||
#include "SX1278FSK.h"
|
||||
#include "SPI.h"
|
||||
#include <Sonde.h>
|
||||
#include <Display.h>
|
||||
#include "Sonde.h"
|
||||
#include "Display.h"
|
||||
|
||||
SX1278FSK::SX1278FSK()
|
||||
|
||||
#define SPI_MUTEX_LOCK() \
|
||||
do \
|
||||
{ \
|
||||
} while (xSemaphoreTake(_lock, portMAX_DELAY) != pdPASS)
|
||||
#define SPI_MUTEX_UNLOCK() xSemaphoreGive(_lock)
|
||||
|
||||
SX1278FSK::SX1278FSK() {}
|
||||
|
||||
void SX1278FSK::setup(xSemaphoreHandle lock)
|
||||
{
|
||||
// Initialize class variables
|
||||
_lock = lock;
|
||||
Serial.println("Setup sx1278");
|
||||
if(_lock) SPI_MUTEX_LOCK();
|
||||
digitalWrite(sonde.config.sx1278_ss, HIGH);
|
||||
pinMode(sonde.config.sx1278_ss, OUTPUT);
|
||||
Serial.printf("Configuing SX1278FSK SPI with miso=%d, mosi=%d, sck=%d, ss=%d\n", sonde.config.sx1278_miso,
|
||||
sonde.config.sx1278_mosi, sonde.config.sx1278_sck, sonde.config.sx1278_ss);
|
||||
SPI.begin(sonde.config.sx1278_sck, sonde.config.sx1278_miso, sonde.config.sx1278_mosi, -1); // no hardware CS
|
||||
// was: SPI.begin();
|
||||
|
||||
//Set most significant bit first
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
//Divide the clock frequency
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV2);
|
||||
//Set data mode
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
if(_lock) SPI_MUTEX_UNLOCK();
|
||||
};
|
||||
|
||||
|
||||
static SPISettings spiset = SPISettings(40000000L, MSBFIRST, SPI_MODE0);
|
||||
static SPISettings spiset = SPISettings(10000000L, MSBFIRST, SPI_MODE0);
|
||||
|
||||
/*
|
||||
Function: Turns the module ON.
|
||||
|
@ -34,19 +59,6 @@ uint8_t SX1278FSK::ON()
|
|||
Serial.println(F("Starting 'ON'"));
|
||||
#endif
|
||||
|
||||
// Powering the module
|
||||
pinMode(SX1278_SS, OUTPUT);
|
||||
digitalWrite(SX1278_SS, HIGH);
|
||||
|
||||
//Configure the MISO, MOSI, CS, SPCR.
|
||||
SPI.begin();
|
||||
//Set most significant bit first
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
//Divide the clock frequency
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV2);
|
||||
//Set data mode
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
|
||||
// Set Maximum Over Current Protection
|
||||
state = setMaxCurrent(0x1B);
|
||||
if( state == 0 )
|
||||
|
@ -60,7 +72,6 @@ uint8_t SX1278FSK::ON()
|
|||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set FSK mode
|
||||
state = setFSK();
|
||||
return state;
|
||||
|
@ -77,10 +88,12 @@ void SX1278FSK::OFF()
|
|||
Serial.println(F("Starting 'OFF'"));
|
||||
#endif
|
||||
|
||||
SPI.end();
|
||||
//SPI.end();
|
||||
#if 0
|
||||
// Powering the module
|
||||
pinMode(SX1278_SS,OUTPUT);
|
||||
digitalWrite(SX1278_SS,LOW);
|
||||
#endif
|
||||
|
||||
#if (SX1278FSK_debug_mode > 1)
|
||||
Serial.println(F("## Setting OFF ##"));
|
||||
|
@ -98,15 +111,16 @@ byte SX1278FSK::readRegister(byte address)
|
|||
{
|
||||
byte value = 0x00;
|
||||
|
||||
if(_lock) SPI_MUTEX_LOCK();
|
||||
digitalWrite(sonde.config.sx1278_ss,LOW);
|
||||
SPI.beginTransaction(spiset);
|
||||
digitalWrite(SX1278_SS,LOW);
|
||||
|
||||
//delay(1);
|
||||
bitClear(address, 7); // Bit 7 cleared to write in registers
|
||||
SPI.transfer(address);
|
||||
value = SPI.transfer(0x00);
|
||||
digitalWrite(SX1278_SS,HIGH);
|
||||
SPI.endTransaction();
|
||||
digitalWrite(sonde.config.sx1278_ss,HIGH);
|
||||
|
||||
#if (SX1278FSK_debug_mode > 1)
|
||||
if(address!=0x3F) {
|
||||
|
@ -118,7 +132,7 @@ byte SX1278FSK::readRegister(byte address)
|
|||
Serial.println();
|
||||
}
|
||||
#endif
|
||||
|
||||
if(_lock) SPI_MUTEX_UNLOCK();
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -131,15 +145,16 @@ Parameters:
|
|||
*/
|
||||
void SX1278FSK::writeRegister(byte address, byte data)
|
||||
{
|
||||
if(_lock) SPI_MUTEX_LOCK();
|
||||
digitalWrite(sonde.config.sx1278_ss,LOW);
|
||||
SPI.beginTransaction(spiset);
|
||||
digitalWrite(SX1278_SS,LOW);
|
||||
|
||||
//delay(1);
|
||||
bitSet(address, 7); // Bit 7 set to read from registers
|
||||
SPI.transfer(address);
|
||||
SPI.transfer(data);
|
||||
digitalWrite(SX1278_SS,HIGH);
|
||||
SPI.endTransaction();
|
||||
digitalWrite(sonde.config.sx1278_ss,HIGH);
|
||||
|
||||
#if (SX1278FSK_debug_mode > 1)
|
||||
Serial.print(F("## Writing: ##\t"));
|
||||
|
@ -150,7 +165,7 @@ void SX1278FSK::writeRegister(byte address, byte data)
|
|||
Serial.print(data, HEX);
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
if(_lock) SPI_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -164,20 +179,23 @@ void SX1278FSK::writeRegister(byte address, byte data)
|
|||
*/
|
||||
void SX1278FSK::clearIRQFlags()
|
||||
{
|
||||
#if 0
|
||||
byte st0;
|
||||
|
||||
// Save the previous status
|
||||
st0 = readRegister(REG_OP_MODE);
|
||||
// Stdby mode to write in registers
|
||||
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE);
|
||||
#endif
|
||||
// FSK mode flags1 register
|
||||
writeRegister(REG_IRQ_FLAGS1, 0xFF);
|
||||
// FSK mode flags2 register
|
||||
writeRegister(REG_IRQ_FLAGS2, 0xFF);
|
||||
#if 0
|
||||
// Getting back to previous status
|
||||
if(st0 != FSK_STANDBY_MODE) {
|
||||
writeRegister(REG_OP_MODE, st0);
|
||||
}
|
||||
#endif
|
||||
#if (SX1278FSK_debug_mode > 1)
|
||||
Serial.println(F("## FSK flags cleared ##"));
|
||||
#endif
|
||||
|
@ -194,7 +212,7 @@ uint8_t SX1278FSK::setFSK()
|
|||
{
|
||||
uint8_t state = 2;
|
||||
byte st0;
|
||||
byte config1;
|
||||
//byte config1;
|
||||
|
||||
#if (SX1278FSK_debug_mode > 1)
|
||||
Serial.println();
|
||||
|
@ -563,6 +581,13 @@ int32_t SX1278FSK::getAFC()
|
|||
AFC = (int32_t)(regval * SX127X_FSTEP);
|
||||
return AFC;
|
||||
}
|
||||
uint16_t SX1278FSK::getRawAFC() {
|
||||
return (readRegister(REG_AFC_MSB)<<8) | readRegister(REG_AFC_LSB);
|
||||
}
|
||||
void SX1278FSK::setRawAFC(uint16_t afc) {
|
||||
writeRegister(REG_AFC_MSB, afc>>8);
|
||||
writeRegister(REG_AFC_LSB, afc&0xFF);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: Gets the current supply limit of the power amplifier, protecting battery chemistries.
|
||||
|
@ -642,7 +667,7 @@ int8_t SX1278FSK::setMaxCurrent(uint8_t rate)
|
|||
// Enable Over Current Protection
|
||||
rate |= B00100000;
|
||||
|
||||
state = 1;
|
||||
//state = 1;
|
||||
st0 = readRegister(REG_OP_MODE); // Save the previous status
|
||||
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); // Set FSK Standby mode to write in registers
|
||||
writeRegister(REG_OCP, rate); // Modifying maximum current supply
|
||||
|
@ -719,7 +744,6 @@ uint8_t SX1278FSK::receivePacketTimeout(uint32_t wait, byte *data)
|
|||
// It's a bit of a hack.... get RSSI and AFC (a) at beginning of packet and
|
||||
// for RS41 after about 0.5 sec. It might be more logical to put this decoder-specific
|
||||
// code into RS41.cpp instead of this file... (maybe TODO?)
|
||||
|
||||
if(di==1 || di==290 ) {
|
||||
int rssi=getRSSI();
|
||||
int afc=getAFC();
|
||||
|
@ -858,4 +882,5 @@ void SX1278FSK::showRxRegisters()
|
|||
}
|
||||
#endif
|
||||
|
||||
xSemaphoreHandle globalLock =xSemaphoreCreateMutex();
|
||||
SX1278FSK sx1278 = SX1278FSK();
|
10
libraries/SX1278FSK/SX1278FSK.h → RX_FSK/src/SX1278FSK.h
Executable file → Normal file
10
libraries/SX1278FSK/SX1278FSK.h → RX_FSK/src/SX1278FSK.h
Executable file → Normal file
|
@ -35,8 +35,6 @@
|
|||
|
||||
#define SX1278FSK_debug_mode 0
|
||||
|
||||
#define SX1278_SS SS
|
||||
|
||||
//! MACROS //
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01) // read a bit
|
||||
#define bitSet(value, bit) ((value) |= (1UL << (bit))) // set bit to '1'
|
||||
|
@ -171,7 +169,9 @@ class SX1278FSK
|
|||
{
|
||||
public:
|
||||
// class constructor
|
||||
SX1278FSK();
|
||||
SX1278FSK();
|
||||
|
||||
void setup(xSemaphoreHandle lock);
|
||||
|
||||
// Turn on SX1278 module (return 0 on sucess, 1 otherwise)
|
||||
uint8_t ON();
|
||||
|
@ -240,6 +240,8 @@ public:
|
|||
|
||||
// Get current AFC value
|
||||
int32_t getAFC();
|
||||
uint16_t getRawAFC();
|
||||
void setRawAFC(uint16_t afc);
|
||||
|
||||
// Get the maximum current supply by the module.
|
||||
int getMaxCurrent();
|
||||
|
@ -254,7 +256,7 @@ public:
|
|||
// Receive a packet
|
||||
uint8_t receivePacketTimeout(uint32_t wait, byte *data);
|
||||
|
||||
|
||||
xSemaphoreHandle _lock = NULL;
|
||||
|
||||
#if 0
|
||||
//! It gets the internal temperature of the module.
|
207
RX_FSK/src/Scanner.cpp
Normal file
207
RX_FSK/src/Scanner.cpp
Normal file
|
@ -0,0 +1,207 @@
|
|||
#include "Scanner.h"
|
||||
|
||||
#include <U8x8lib.h>
|
||||
|
||||
#include "SX1278FSK.h"
|
||||
#include "Sonde.h"
|
||||
#include "Display.h"
|
||||
|
||||
|
||||
double STARTF;
|
||||
|
||||
|
||||
struct scancfg {
|
||||
int PLOT_W; // Width of plot, in pixel
|
||||
int PLOT_H8; // Height of plot, in 8 pixel units
|
||||
int TICK1; // Pixel per MHz marker
|
||||
int TICK2; // Pixel per sub-Mhz marker (250k or 200k)
|
||||
double CHANSTEP; // Scanner frequenz steps
|
||||
int SMPL_PIX; // Frequency steps per pixel
|
||||
int NCHAN; // number of channels to scan, PLOT_W * SMPL_PIX
|
||||
int SMOOTH;
|
||||
int ADDWAIT;
|
||||
int VSCALE;
|
||||
};
|
||||
|
||||
//struct scancfg scanLCD={ 121, 7, 120/6, 120/6/4, 6000.0/120.0/20.0, 20, 120*20, 1 };
|
||||
struct scancfg scanLCD={ 121, 7, 120/6, 120/6/4, 6000.0/120.0/10.0, 10, 120*10, 2, 40, 1 };
|
||||
struct scancfg scanTFT={ 210, 16, 210/6, 210/6/5, 6000.0/210.0/10.0, 10, 210*10, 1, 0, 1 };
|
||||
struct scancfg scan934x={ 300, 22, 300/6, 300/6/5, 6000.0/300.0/7.0, 7, 300*5, 1, 10, 2 };
|
||||
|
||||
struct scancfg &scanconfig = scanTFT;
|
||||
|
||||
#define CHANBW 12500
|
||||
//#define PIXSAMPL (50/CHANBW)
|
||||
//#define STARTF 401000000
|
||||
|
||||
// max of 120*5 and 210*3
|
||||
//#define MAXN 210*10
|
||||
//#define MAXN 120*20
|
||||
#define MAXN 300*10
|
||||
|
||||
// max of 120 and 210 (ceil(210/8)*8)) -- now ceil(300/8)*8
|
||||
//#define MAXDISP 216
|
||||
#define MAXDISP 304
|
||||
|
||||
int scanresult[MAXN];
|
||||
int scandisp[MAXDISP];
|
||||
double peakf=0;
|
||||
|
||||
//#define PLOT_MIN -250
|
||||
#define PLOT_MIN (sonde.config.noisefloor*2)
|
||||
#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<scanconfig.PLOT_H8; y++) {
|
||||
int nbits = scanconfig.VSCALE*value - 8*(scanconfig.PLOT_H8-1-y);
|
||||
if(nbits<0) { row[8*y]=0; continue; }
|
||||
if(nbits>=8) { row[8*y]=255; continue; }
|
||||
row[8*y] = tilepatterns[nbits];
|
||||
}
|
||||
}
|
||||
/* LCD:
|
||||
* There are 16*8 columns to plot, NPLOT must be lower than that
|
||||
* currently, we use 128 * 50kHz channels
|
||||
* There are 8*8 values to plot; MIN is bottom end,
|
||||
* TFT:
|
||||
* There are 210 columns to plot
|
||||
* Currently we use 210 * (6000/120)kHz channels, i.e. 28.5714kHz
|
||||
*/
|
||||
///// unused???? uint8_t tiles[16] = { 0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0, 1, 3, 7, 15, 31, 63, 127, 255};
|
||||
|
||||
// type 0: lcd, 1: tft(ILI9225), 2: lcd(sh1106) 3:TFT(ili9341), 4: TFT(ili9342)
|
||||
#define ISTFT (sonde.config.disptype!=0 && sonde.config.disptype!=2)
|
||||
void Scanner::plotResult()
|
||||
{
|
||||
int yofs = 0;
|
||||
char buf[30];
|
||||
if(ISTFT) {
|
||||
yofs = 2;
|
||||
if (sonde.config.marker != 0) {
|
||||
itoa((sonde.config.startfreq), buf, 10);
|
||||
disp.rdis->drawString(0, 1, buf);
|
||||
disp.rdis->drawString(scanconfig.PLOT_W/2-10, 1, "MHz");
|
||||
itoa((sonde.config.startfreq + 6), buf, 10);
|
||||
disp.rdis->drawString(scanconfig.PLOT_W-15, 1, buf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sonde.config.marker != 0) {
|
||||
itoa((sonde.config.startfreq), buf, 10);
|
||||
disp.rdis->drawString(0, 1, buf);
|
||||
disp.rdis->drawString(7, 1, "MHz");
|
||||
itoa((sonde.config.startfreq + 6), buf, 10);
|
||||
disp.rdis->drawString(13, 1, buf);
|
||||
}
|
||||
}
|
||||
uint8_t row[scanconfig.PLOT_H8*8];
|
||||
for(int i=0; i<scanconfig.PLOT_W; i+=8) {
|
||||
for(int j=0; j<8; j++) {
|
||||
fillTiles(row+j, PLOT_SCALE(scandisp[i+j]));
|
||||
if( (i+j)>=scanconfig.PLOT_W ) { for(int y=0; y<scanconfig.PLOT_H8; y++) row[j+8*y]=0; }
|
||||
if( ((i+j)%scanconfig.TICK1)==0) { row[j] |= 0x07; }
|
||||
if( ((i+j)%scanconfig.TICK2)==0) { row[j] |= 0x01; }
|
||||
}
|
||||
for(int y=0; y<scanconfig.PLOT_H8; y++) {
|
||||
if(sonde.config.marker && y==1 && !ISTFT ) {
|
||||
// don't overwrite MHz marker text
|
||||
if(i<3*8 || (i>=7*8&&i<10*8) || i>=13*8) continue;
|
||||
}
|
||||
disp.rdis->drawTile(i/8, y+yofs, 1, row+8*y);
|
||||
}
|
||||
}
|
||||
if(ISTFT) { // large TFT
|
||||
sprintf(buf, "Peak: %03.3f MHz", peakf*0.000001);
|
||||
disp.rdis->drawString(0, (yofs+scanconfig.PLOT_H8+1)*8, buf);
|
||||
} else {
|
||||
sprintf(buf, "Peak: %03.3fMHz", peakf*0.000001);
|
||||
disp.rdis->drawString(0, 7, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void Scanner::scan()
|
||||
{
|
||||
if(!ISTFT) { // LCD small
|
||||
scanconfig = scanLCD;
|
||||
} else if (sonde.config.disptype==1) {
|
||||
scanconfig = scanTFT;
|
||||
} else {
|
||||
scanconfig = scan934x;
|
||||
}
|
||||
// Configure
|
||||
STARTF = (sonde.config.startfreq * 1000000);
|
||||
sx1278.writeRegister(REG_PLL_HOP, 0x80); // FastHopOn
|
||||
sx1278.setRxBandwidth((int)(scanconfig.CHANSTEP*1000));
|
||||
double bw = sx1278.getRxBandwidth();
|
||||
Serial.print("RX Bandwith for scan: "); Serial.println(bw);
|
||||
sx1278.writeRegister(REG_RSSI_CONFIG, scanconfig.SMOOTH&0x07);
|
||||
sx1278.setFrequency(STARTF);
|
||||
Serial.print("Start freq = "); Serial.println(STARTF);
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
|
||||
unsigned long start = millis();
|
||||
uint32_t lastfrf= STARTF * (1<<19) / SX127X_CRYSTAL_FREQ;
|
||||
float freq = STARTF;
|
||||
int wait = scanconfig.ADDWAIT + 20 + 1000*(1<<(scanconfig.SMOOTH+1))/4/(0.001*CHANBW);
|
||||
Serial.print("wait time (us) is: "); Serial.println(wait);
|
||||
for(int iter=0; iter<3; iter++) { // three interations, to catch all RS41 transmissions
|
||||
delayMicroseconds(20000); yield();
|
||||
for(int i=0; i<scanconfig.PLOT_W*scanconfig.SMPL_PIX; i++) {
|
||||
freq = STARTF + 1000.0*i*scanconfig.CHANSTEP;
|
||||
//freq = 404000000 + 100*i*scanconfig.CHANSTEP;
|
||||
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^(scacconfig.SMOOTH+1) / 4 / CHANBW us)
|
||||
delayMicroseconds(wait);
|
||||
int rssi = -(int)sx1278.readRegister(REG_RSSI_VALUE_FSK);
|
||||
if(iter==0) { scanresult[i] = rssi; } else {
|
||||
if(rssi>scanresult[i]) scanresult[i]=rssi;
|
||||
}
|
||||
}
|
||||
}
|
||||
yield();
|
||||
unsigned long duration = millis()-start;
|
||||
Serial.print("wait: ");
|
||||
Serial.println(wait);
|
||||
Serial.print("Scan time: ");
|
||||
Serial.println(duration);
|
||||
Serial.print("Final freq: ");
|
||||
Serial.println(freq);
|
||||
int peakidx=-1;
|
||||
int peakres=-9999;
|
||||
for(int i=0; i<scanconfig.PLOT_W; i+=1) {
|
||||
int r=scanresult[i*scanconfig.SMPL_PIX];
|
||||
if(r>peakres+1) { peakres=r; peakidx=i*scanconfig.SMPL_PIX; }
|
||||
scandisp[i] = r;
|
||||
for(int j=1; j<scanconfig.SMPL_PIX; j++) {
|
||||
r = scanresult[i*scanconfig.SMPL_PIX+j];
|
||||
scandisp[i]+=r;
|
||||
if(r>peakres+1) { peakres=r; peakidx=i*scanconfig.SMPL_PIX+j; }
|
||||
}
|
||||
//for(int j=1; j<PIXSAMPL; j++) { if(scanresult[i+j]>scandisp[i/PIXSAMPL]) scandisp[i/PIXSAMPL] = scanresult[i+j]; }
|
||||
Serial.print(scanresult[i]); Serial.print(", ");
|
||||
}
|
||||
peakidx--;
|
||||
double newpeakf = STARTF + scanconfig.CHANSTEP*1000.0*peakidx;
|
||||
if(newpeakf<peakf-20000 || newpeakf>peakf+20000) peakf=newpeakf; // different frequency
|
||||
else if (newpeakf < peakf) peakf = 0.75*newpeakf + 0.25*peakf; // averaging on frequency, some bias towards lower...
|
||||
else peakf = 0.25*newpeakf + 0.75*peakf;
|
||||
Serial.println("\n");
|
||||
for(int i=0; i<scanconfig.PLOT_W; i++) {
|
||||
scandisp[i]/=scanconfig.SMPL_PIX;
|
||||
Serial.print(scandisp[i]); Serial.print(", ");
|
||||
}
|
||||
Serial.println("\n");
|
||||
Serial.print("Peak: ");
|
||||
Serial.print(peakf);
|
||||
}
|
||||
|
||||
Scanner scanner = Scanner();
|
1
libraries/SondeLib/Scanner.h → RX_FSK/src/Scanner.h
Executable file → Normal file
1
libraries/SondeLib/Scanner.h → RX_FSK/src/Scanner.h
Executable file → Normal file
|
@ -9,7 +9,6 @@
|
|||
#ifndef inttypes_h
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
class Scanner
|
||||
{
|
||||
private:
|
247
RX_FSK/src/ShFreqImport.cpp
Normal file
247
RX_FSK/src/ShFreqImport.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "ShFreqImport.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
static int ppos;
|
||||
static int quotes;
|
||||
static char id[20];
|
||||
static int idpos;
|
||||
static float lat, lon, freq;
|
||||
static char type[20];
|
||||
|
||||
static uint8_t inuse[1+99/8]; // MAXSONDE is 99
|
||||
|
||||
static char keyword[40];
|
||||
static int keywordpos;
|
||||
static char value[40];
|
||||
static int valuepos;
|
||||
|
||||
static int importState;
|
||||
static float homelat, homelon;
|
||||
|
||||
|
||||
// Map SondeHub type string to Stype. -1 for not supported types.
|
||||
int ShFreqImport::stringToStype(const char *type) {
|
||||
if(type[2]=='4') return STYPE_RS41;
|
||||
if(type[2]=='9') return STYPE_RS92;
|
||||
if(type[1]=='1') return STYPE_M10M20;
|
||||
if(type[1]=='2') return STYPE_M10M20;
|
||||
if(type[0]=='D') return STYPE_DFM;
|
||||
if(type[2]=='3') return STYPE_MP3H; // TODO: check if '3' is correct
|
||||
return -1; // iMet is not supported
|
||||
}
|
||||
|
||||
// in Display.cpp
|
||||
extern float calcLatLonDist(float lat1, float lon1, float lat2, float lon2);
|
||||
|
||||
void ShFreqImport::setLabel(int idx, char *id, float lat, float lon) {
|
||||
snprintf(sonde.sondeList[idx].launchsite, 18, "@%s/%d", id, (int)(calcLatLonDist(homelat, homelon, lat, lon)/1000));
|
||||
sonde.sondeList[idx].launchsite[17] = 0;
|
||||
}
|
||||
|
||||
void ShFreqImport::usekeyvalue() {
|
||||
if(strcmp(keyword,"lat")==0) lat = atof(value);
|
||||
if(strcmp(keyword,"lon")==0) lon = atof(value);
|
||||
if(strcmp(keyword,"frequency")==0) { if(isnan(freq)) freq = atof(value); } // prefer tx_frequency if available
|
||||
if(strcmp(keyword,"tx_frequency")==0) freq = atof(value);
|
||||
if(strcmp(keyword,"type")==0) strcpy(type, value);
|
||||
}
|
||||
|
||||
/* populate qrg.txt with frequency of near sonde */
|
||||
void ShFreqImport::populate(char *id, float lat, float lon, float freq, const char *type)
|
||||
{
|
||||
//printf(" ID %s: %.5f, %.5f f=%.3f, type=%s \n", id, lat, lon, freq, type);
|
||||
// Skip if freq already exists
|
||||
int stype = stringToStype(type);
|
||||
if(stype<0) return; // unsupported type
|
||||
|
||||
// check if frequency exists already
|
||||
// don't do anything if its a static entry
|
||||
// update label if its a dynamic SH entry
|
||||
int i;
|
||||
for(i=0; i<sonde.config.maxsonde; i++) {
|
||||
if( abs(sonde.sondeList[i].freq-freq)<0.003 ) { // exists already, max error 3000 Hz
|
||||
Serial.printf("id %s close to %d\n", id, i);
|
||||
if( sonde.sondeList[i].type == stype) {
|
||||
char *l = sonde.sondeList[i].launchsite;
|
||||
if( *l=='@' || *l==' ' || *l==0 ) {
|
||||
setLabel(i, id, lat, lon);
|
||||
inuse[i/8] |= (1<<(i&7));
|
||||
}
|
||||
sonde.sondeList[i].active = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find slot
|
||||
// slots with empty launchsite are considered available for automated entries
|
||||
while(ppos < sonde.config.maxsonde) {
|
||||
if( *sonde.sondeList[ppos].launchsite==' ' || *sonde.sondeList[ppos].launchsite== 0 ) break;
|
||||
ppos++;
|
||||
}
|
||||
if(ppos >= sonde.config.maxsonde) {
|
||||
Serial.println("populate: out of free slots");
|
||||
return;
|
||||
} // no more free slots
|
||||
|
||||
sonde.clearAllData(&sonde.sondeList[ppos]);
|
||||
sonde.sondeList[ppos].active = 1;
|
||||
sonde.sondeList[ppos].freq = freq;
|
||||
sonde.sondeList[ppos].type = (SondeType)stype;
|
||||
setLabel(ppos, id, lat, lon);
|
||||
inuse[ppos/8] |= (1<<(ppos&7));
|
||||
ppos++;
|
||||
}
|
||||
|
||||
// clears all remaining automatically filled slots (no longer in SH data)
|
||||
void ShFreqImport::cleanup() {
|
||||
//Serial.println("Cleanup called ********");
|
||||
for(int i=0; i<sonde.config.maxsonde; i++) {
|
||||
if( (((inuse[i/8]>>(i&7))&1) == 0) && *sonde.sondeList[i].launchsite=='@' ) {
|
||||
// Don't remove the currently active entry
|
||||
if(i==sonde.currentSonde) continue;
|
||||
Serial.printf("removing #%d\n", i);
|
||||
sonde.sondeList[i].launchsite[0] = 0;
|
||||
sonde.sondeList[i].active = 0;
|
||||
sonde.sondeList[i].freq = 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BUFLEN 128
|
||||
#define VALLEN 20
|
||||
int ShFreqImport::handleChar(char c) {
|
||||
Serial.print(c);
|
||||
switch(importState) {
|
||||
case START:
|
||||
// wait for initial '{'
|
||||
if(c=='{') {
|
||||
Serial.println("{ found");
|
||||
importState++;
|
||||
}
|
||||
break;
|
||||
case BEFOREID:
|
||||
// what for first '"' in { "A1234567" : { ... } }; or detect end
|
||||
if(c=='"') { idpos = 0; lat = NAN; lon = NAN; freq = NAN; *type = 0; importState++; }
|
||||
if(c=='}') {
|
||||
importState = ENDREACHED;
|
||||
cleanup();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case COPYID:
|
||||
// copy ID "A1234567" until second '"' is earched
|
||||
if(c=='"') { id[idpos] = 0; importState++; }
|
||||
else id[idpos++] = c;
|
||||
break;
|
||||
case AFTERID:
|
||||
// wait for '{' in '"A1234567": { ...'
|
||||
if(c=='{') importState++;
|
||||
break;
|
||||
case BEFOREKEY:
|
||||
if(c=='"') { keywordpos = 0; importState++; }
|
||||
break;
|
||||
case COPYKEY:
|
||||
if(c=='"') { importState++; keyword[keywordpos] = 0; /* printf("Key: >%s<\n", keyword);*/ }
|
||||
else keyword[keywordpos++] = c;
|
||||
break;
|
||||
case AFTERKEY:
|
||||
if(c==':') {
|
||||
valuepos = 0;
|
||||
quotes = 0;
|
||||
if(strcmp(keyword,"lat")==0 || strcmp(keyword, "lon")==0 || strcmp(keyword, "frequency")==0 || strcmp(keyword, "tx_frequency")==0)
|
||||
importState = BEFORENUMVAL;
|
||||
else {
|
||||
if (strcmp(keyword, "type")==0)
|
||||
importState = BEFORESTRINGVAL;
|
||||
else
|
||||
importState = SKIPVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BEFORENUMVAL:
|
||||
if( (c>='0'&&c<='9') || c=='-') { value[0] = c; valuepos=1; importState++; }
|
||||
break;
|
||||
case COPYNUMVAL:
|
||||
if( !(c>='0'&&c<='9') && c!='-' && c!='.' ) {
|
||||
value[valuepos]=0; importState=SKIPVAL; usekeyvalue();
|
||||
if(c!=',' && c!='}') break;
|
||||
}
|
||||
else { value[valuepos++] = c; break; }
|
||||
// intenionall fall-through
|
||||
case SKIPVAL:
|
||||
// This is rather fragile, we *should* handle more escaping and so on but do not do so so far, only simple quotes
|
||||
if(c=='"') quotes = !quotes;
|
||||
if(quotes) break;
|
||||
if(c==',') importState = BEFOREKEY;
|
||||
if(c=='}') {
|
||||
// we have an ID and all key/value pairs, check if its good....
|
||||
if( !isnan(lat) && !isnan(lon) && !isnan(freq) && type[0] ) {
|
||||
printf("SondeHub import: populate %s %f %f %f %s\n", id, lat, lon, freq, type);
|
||||
populate(id, lat, lon, freq, type);
|
||||
} else {
|
||||
printf("Skipping incomplete %s\n", id);
|
||||
}
|
||||
importState = ENDORNEXT;
|
||||
}
|
||||
break;
|
||||
case BEFORESTRINGVAL:
|
||||
if(c=='"') importState++;
|
||||
break;
|
||||
case COPYSTRINGVAL:
|
||||
if(c=='"') { importState=SKIPVAL; value[valuepos]=0; usekeyvalue(); }
|
||||
else value[valuepos++] = c;
|
||||
break;
|
||||
case ENDORNEXT:
|
||||
// next we have to see either a final "}', or a comma before the next id
|
||||
if(c==',') importState = BEFOREID;
|
||||
else if (c=='}') { importState = ENDREACHED; cleanup(); return 1; }
|
||||
break;
|
||||
case ENDREACHED:
|
||||
Serial.println("REPLY: END REACHED");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lat lon in deg, dist in km, time in minutes
|
||||
int ShFreqImport::shImportSendRequest(WiFiClient *client, float lat, float lon, int dist, int time) {
|
||||
if(!client->connected()) {
|
||||
if(!client->connect(sonde.config.sondehub.host, 80)) {
|
||||
Serial.println("Connection FAILED");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Serial.println("Sending SondeHub import request");
|
||||
char req[300];
|
||||
snprintf(req, 200, "GET /sondes?lat=%f&lon=%f&distance=%d&last=%d HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Accept: application/json\r\n"
|
||||
"Cache-Control: no-cache\r\n\r\n",
|
||||
lat, lon, dist*1000, time*60, sonde.config.sondehub.host);
|
||||
client->print(req);
|
||||
Serial.print(req);
|
||||
importState = START;
|
||||
homelat = lat;
|
||||
homelon = lon;
|
||||
memset(inuse, 0, sizeof(inuse));
|
||||
ppos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return 0 if more data should be read (later), 1 if finished (close connection...)
|
||||
int ShFreqImport::shImportHandleReply(WiFiClient *client) {
|
||||
if(!client->connected()) return 1;
|
||||
while(client->available()) {
|
||||
int res = handleChar(client->read());
|
||||
if(res) return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
30
RX_FSK/src/ShFreqImport.h
Normal file
30
RX_FSK/src/ShFreqImport.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef SH_FREQ_IMPORT_
|
||||
#define SH_FREQ_IMPORT_H
|
||||
// Automated frequency import from SondeHub
|
||||
|
||||
#include <WiFi.h>
|
||||
|
||||
enum ImportState { START, BEFOREID, COPYID, AFTERID, BEFOREKEY, COPYKEY, AFTERKEY, SKIPVAL, BEFORENUMVAL, COPYNUMVAL, BEFORESTRINGVAL, COPYSTRINGVAL, AFTERPAYLOAD, ENDORNEXT, ENDREACHED };
|
||||
|
||||
class ShFreqImport {
|
||||
public:
|
||||
// Fetch data from sondehub and populate qrg.txt with result
|
||||
// return: 0: ok; 1: failure
|
||||
static int shImportSendRequest(WiFiClient *client, float lat, float lon, int dist, int time);
|
||||
|
||||
// return 0: ok, need more data; 1: finished/failure, close connection
|
||||
// Asynchronous I/O. Handle data if available
|
||||
static int shImportHandleReply(WiFiClient *client);
|
||||
|
||||
private:
|
||||
static int stringToStype(const char *type);
|
||||
static void setLabel(int idx, char *id, float lat, float lon);
|
||||
static void usekeyvalue();
|
||||
static int handleChar(char c);
|
||||
|
||||
// add one entry on available slot at or after ppos
|
||||
static void populate(char *id, float lat, float lon, float freq, const char *type);
|
||||
static void cleanup();
|
||||
};
|
||||
|
||||
#endif
|
522
libraries/SondeLib/Sonde.cpp → RX_FSK/src/Sonde.cpp
Executable file → Normal file
522
libraries/SondeLib/Sonde.cpp → RX_FSK/src/Sonde.cpp
Executable file → Normal file
|
@ -5,12 +5,13 @@
|
|||
#include "RS41.h"
|
||||
#include "RS92.h"
|
||||
#include "DFM.h"
|
||||
#include "M10.h"
|
||||
#include "M10M20.h"
|
||||
#include "MP3H.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "Display.h"
|
||||
#include <Wire.h>
|
||||
|
||||
extern SX1278FSK sx1278;
|
||||
uint8_t debug = 255-8-16;
|
||||
|
||||
RXTask rxtask = { -1, -1, -1, 0xFFFF, 0 };
|
||||
|
||||
|
@ -19,19 +20,31 @@ const char *evstring[]={"NONE", "KEY1S", "KEY1D", "KEY1M", "KEY1L", "KEY2S", "KE
|
|||
|
||||
const char *RXstr[]={"RX_OK", "RX_TIMEOUT", "RX_ERROR", "RX_UNKNOWN"};
|
||||
|
||||
int fingerprintValue[]={ 17, 31, 64, 4, 55, 48, 23, 128+23, -1 };
|
||||
// Dependency to enum SondeType
|
||||
const char *sondeTypeStr[NSondeTypes] = { "DFM ", "RS41", "RS92", "Mxx ", "M10 ", "M20 ", "MP3H" };
|
||||
const char *sondeTypeLongStr[NSondeTypes] = { "DFM (all)", "RS41", "RS92", "M10/M20", "M10 ", "M20 ", "MP3-H1" };
|
||||
const char sondeTypeChar[NSondeTypes] = { 'D', '4', 'R', 'M', 'M', '2', '3' };
|
||||
const char *manufacturer_string[]={"Graw", "Vaisala", "Vaisala", "Meteomodem", "Meteomodem", "Meteomodem", "Meteo-Radiy"};
|
||||
|
||||
int fingerprintValue[]={ 17, 31, 64, 4, 55, 48, 23, 128+23, 119, 128+119, -1 };
|
||||
const char *fingerprintText[]={
|
||||
"TTGO T-Beam (new version 1.0), I2C not working after powerup, assuming 0.9\" OLED@21,22",
|
||||
"TTGO LORA32 v2.1_1.6 (0.9\" OLED@21,22)",
|
||||
"TTGO LORA v1.0 (0.9\" OLED@4,15)",
|
||||
"Heltec v1/v2 (0.9\"OLED@4,15)",
|
||||
"TTGO T-Beam (old version), 0.9\" OLED@21,22",
|
||||
"TTGO T-Beam (old version), SPI TFT@4,21,22",
|
||||
"TTGO T-Beam (new version 1.0), 0.9\" OLED@21,22",
|
||||
"TTGO T-Beam (new version 1.0), SPI TFT@4,13,14",
|
||||
"TTGO T-Beam (V0.7), 0.9\" OLED@21,22",
|
||||
"TTGO T-Beam (V0.7), SPI TFT@4,21,22",
|
||||
"TTGO T-Beam (V1.0), 0.9\" OLED@21,22",
|
||||
"TTGO T-Beam (V1.0), SPI TFT@4,13,14",
|
||||
"TTGO T-Beam (V1.1), 0.9\" OLED@21,22",
|
||||
"TTGO T-Beam (V1.1), SPI TFT@4,13,14",
|
||||
};
|
||||
|
||||
int getKeyPressEvent(); /* in RX_FSK.ino */
|
||||
/* global variables from RX_FSK.ino */
|
||||
int getKeyPressEvent();
|
||||
int handlePMUirq();
|
||||
extern uint8_t pmu_irq;
|
||||
extern SX1278FSK sx1278;
|
||||
|
||||
/* Task model:
|
||||
* There is a background task for all SX1278 interaction.
|
||||
|
@ -41,7 +54,7 @@ int getKeyPressEvent(); /* in RX_FSK.ino */
|
|||
* - Periodically it calls Sonde::receive(), which calls the current decoder's receive()
|
||||
* function. It should return control to the SX1278 main loop at least once per second.
|
||||
* It will also set the internal variable receiveResult. The decoder's receive function
|
||||
* must make sure that there are no FIFI overflows in the SX1278.
|
||||
* must make sure that there are no FIFO overflows in the SX1278.
|
||||
* - the Arduino main loop will call the waitRXcomplete function, which should return as
|
||||
* soon as there is some new data to display, or no later than after 1s, returning the
|
||||
* value of receiveResult (or timeout, if receiveResult was not set within 1s). It
|
||||
|
@ -66,27 +79,35 @@ void Sonde::defaultConfig() {
|
|||
Serial.printf("Board fingerprint is %d\n", fingerprint);
|
||||
|
||||
sondeList = (SondeInfo *)malloc((MAXSONDE+1)*sizeof(SondeInfo));
|
||||
// addSonde should initialize everything anyway, so this should not strictly be necessary, but does no harm either
|
||||
memset(sondeList, 0, (MAXSONDE+1)*sizeof(SondeInfo));
|
||||
for(int i=0; i<(MAXSONDE+1); i++) {
|
||||
sondeList[i].freq=400;
|
||||
sondeList[i].type=STYPE_RS41;
|
||||
clearAllData(&sondeList[i]);
|
||||
}
|
||||
config.touch_thresh = 70;
|
||||
config.led_pout = -1;
|
||||
config.power_pout = -1;
|
||||
config.spectrum=10;
|
||||
// Try autodetecting board type
|
||||
config.type = TYPE_TTGO;
|
||||
// Seems like on startup, GPIO4 is 1 on v1 boards, 0 on v2.1 boards?
|
||||
config.gpsOn=0;
|
||||
config.gps_rxd = -1;
|
||||
config.gps_txd = -1;
|
||||
strcpy(config.gps_lat,"43.591");
|
||||
strcpy(config.gps_lon,"7.100");
|
||||
config.gps_alt=123;
|
||||
config.gps_Lat=0;
|
||||
config.gps_Lon=0;
|
||||
config.gps_Alt=0;
|
||||
config.batt_adc = -1;
|
||||
config.sx1278_ss = SS; // default SS pin, on all TTGOs
|
||||
config.sx1278_miso = MISO;
|
||||
config.sx1278_mosi = MOSI;
|
||||
config.sx1278_sck = SCK;
|
||||
config.oled_rst = 16;
|
||||
config.disptype = 0;
|
||||
config.dispcontrast = -1;
|
||||
config.oled_orient = 1;
|
||||
config.button2_axp = 0;
|
||||
config.norx_timeout = 20;
|
||||
config.screenfile = 1;
|
||||
|
||||
if(initlevels[16]==0) {
|
||||
config.oled_sda = 4;
|
||||
config.oled_scl = 15;
|
||||
|
@ -98,24 +119,58 @@ void Sonde::defaultConfig() {
|
|||
} else {
|
||||
config.oled_sda = 21;
|
||||
config.oled_scl = 22;
|
||||
if(initlevels[17]==0) { // T-Beam
|
||||
if(initlevels[12]==0) { // T-Beam v1.0
|
||||
Serial.println("Autoconfig: looks like T-Beam 1.0 board");
|
||||
config.button_pin = 38;
|
||||
config.button2_pin = 15 + 128; //T4 + 128; // T4 = GPIO13
|
||||
// Maybe in future use as default only PWR as button2?
|
||||
//config.button2_pin = 255;
|
||||
config.button2_axp = 1;
|
||||
config.gps_rxd = 34;
|
||||
// Check for I2C-Display@21,22
|
||||
#define SSD1306_ADDRESS 0x3c
|
||||
if(initlevels[17]==0) { // T-Beam or M5Stack Core2?
|
||||
int tbeam=7;
|
||||
if(initlevels[12]==0) {
|
||||
tbeam = 10;
|
||||
Serial.println("Autoconfig: looks like T-Beam 1.0 or M5Stack Core2 board");
|
||||
} else if ( initlevels[4]==1 && initlevels[12]==1 ) {
|
||||
tbeam = 11;
|
||||
Serial.println("Autoconfig: looks like T-Beam 1.1 board");
|
||||
}
|
||||
if(tbeam == 10 || tbeam == 11) { // T-Beam v1.0 or T-Beam v1.1
|
||||
Wire.begin(21, 22);
|
||||
Wire.beginTransmission(SSD1306_ADDRESS);
|
||||
byte err = Wire.endTransmission();
|
||||
delay(100); // otherwise its too fast?!
|
||||
Wire.beginTransmission(SSD1306_ADDRESS);
|
||||
err = Wire.endTransmission();
|
||||
if(err!=0 && fingerprint!=17) { // hmm. 17 after powerup with oled commected and no i2c answer!?!?
|
||||
#define BM8563_ADDRESS 0x51
|
||||
Wire.beginTransmission(BM8563_ADDRESS);
|
||||
byte err = Wire.endTransmission();
|
||||
if(err) { // try again
|
||||
delay(400);
|
||||
Wire.beginTransmission(BM8563_ADDRESS);
|
||||
err = Wire.endTransmission();
|
||||
}
|
||||
if(err==0) {
|
||||
Serial.println("M5stack Core2 board detected\n");
|
||||
config.type = TYPE_M5_CORE2;
|
||||
config.button_pin = 255;
|
||||
config.button2_pin = 255;
|
||||
config.button2_axp = 1;
|
||||
config.disptype = 4; // ILI9342
|
||||
config.oled_sda = 23;
|
||||
config.oled_scl = 18;
|
||||
config.oled_rst = -1;
|
||||
config.screenfile = 4;
|
||||
config.gps_rxd = 13;
|
||||
config.gps_txd = -1; // 14
|
||||
config.sx1278_ss = 33;
|
||||
config.sx1278_miso = 38;
|
||||
config.sx1278_mosi = 23; //MOSI;
|
||||
config.sx1278_sck = 18; // SCK;
|
||||
} else { // some t-beam...
|
||||
config.button_pin = 38;
|
||||
config.button2_pin = 15 + 128; //T4 + 128; // T4 = GPIO13
|
||||
// Maybe in future use as default only PWR as button2?
|
||||
//config.button2_pin = 255;
|
||||
config.button2_axp = 1;
|
||||
config.gps_rxd = 34;
|
||||
config.gps_txd = 12;
|
||||
// Check for I2C-Display@21,22
|
||||
#define SSD1306_ADDRESS 0x3c
|
||||
Wire.beginTransmission(SSD1306_ADDRESS);
|
||||
err = Wire.endTransmission();
|
||||
delay(100); // otherwise its too fast?!
|
||||
Wire.beginTransmission(SSD1306_ADDRESS);
|
||||
err = Wire.endTransmission();
|
||||
if(err!=0 && fingerprint!=17) { // hmm. 17 after powerup with oled commected and no i2c answer!?!?
|
||||
fingerprint |= 128;
|
||||
Serial.println("no I2C display found, assuming large TFT display\n");
|
||||
// CS=0, RST=14, RS=2, SDA=4, CLK=13
|
||||
|
@ -124,11 +179,14 @@ void Sonde::defaultConfig() {
|
|||
config.oled_sda = 4;
|
||||
config.oled_scl = 13;
|
||||
config.oled_rst = 14;
|
||||
|
||||
config.spectrum = -1; // no spectrum for now on large display
|
||||
} else {
|
||||
config.screenfile = 2;
|
||||
} else {
|
||||
// OLED display, pins 21,22 ok...
|
||||
config.disptype = 0;
|
||||
Serial.println("... with small OLED display\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Serial.println("Autoconfig: looks like T-Beam v0.7 board");
|
||||
|
@ -142,40 +200,38 @@ void Sonde::defaultConfig() {
|
|||
config.oled_sda = 4;
|
||||
config.oled_scl = 21;
|
||||
config.oled_rst = 22;
|
||||
|
||||
config.spectrum = -1; // no spectrum for now on large display
|
||||
config.screenfile = 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Likely a TTGO V2.1_1.6
|
||||
config.button_pin = 2 + 128; // GPIO2 / T2
|
||||
config.button2_pin = 14 + 128; // GPIO14 / T6
|
||||
config.led_pout = 25;
|
||||
config.batt_adc = 35;
|
||||
}
|
||||
}
|
||||
//
|
||||
config.noisefloor = -125;
|
||||
config.gainLNA=0;
|
||||
strcpy(config.call,"NOCALL");
|
||||
strcpy(config.passcode, "---");
|
||||
config.passcode = -1;
|
||||
strcpy(config.mdnsname, "radiosonde");
|
||||
strcpy(config.vbatmax,"1.84");
|
||||
strcpy(config.vbatmin,"1.64");
|
||||
config.telemetryOn=0;
|
||||
config.maxsonde=15;
|
||||
config.debug=0;
|
||||
config.wifi=1;
|
||||
config.buzzerOn=0;
|
||||
config.buzzerFreq=700;
|
||||
config.buzzerPort=12;
|
||||
config.dbsmetre=0;
|
||||
config.degdec=0;
|
||||
config.maxsonde=15;
|
||||
config.debug=0;
|
||||
config.wifi=1;
|
||||
config.wifiap=1;
|
||||
config.display[0]=0;
|
||||
config.display[1]=1;
|
||||
config.display[2]=-1;
|
||||
config.startfreq=400;
|
||||
config.channelbw=10;
|
||||
config.marker=0;
|
||||
config.showafc=0;
|
||||
config.freqofs=0;
|
||||
config.rs41.agcbw=12500;
|
||||
config.rs41.rxbw=6300;
|
||||
|
@ -183,23 +239,44 @@ void Sonde::defaultConfig() {
|
|||
config.rs92.alt2d=480;
|
||||
config.dfm.agcbw=20800;
|
||||
config.dfm.rxbw=10400;
|
||||
config.m10m20.agcbw=20800;
|
||||
config.m10m20.rxbw=12500;
|
||||
config.mp3h.agcbw=12500;
|
||||
config.mp3h.rxbw=12500;
|
||||
config.udpfeed.active = 1;
|
||||
config.udpfeed.type = 0;
|
||||
strcpy(config.udpfeed.host, "fra1od.fr.to");
|
||||
strcpy(config.udpfeed.host, "192.168.42.20");
|
||||
strcpy(config.udpfeed.symbol, "/O");
|
||||
config.udpfeed.port = 14580;
|
||||
config.udpfeed.port = 9002;
|
||||
config.udpfeed.highrate = 1;
|
||||
config.udpfeed.idformat = ID_DFMGRAW;
|
||||
config.tcpfeed.active = 0;
|
||||
config.tcpfeed.type = 1;
|
||||
strcpy(config.tcpfeed.host, "radiosondy.info");
|
||||
strcpy(config.tcpfeed.symbol, "/O");
|
||||
config.tcpfeed.port = 14580;
|
||||
config.tcpfeed.port = 12345;
|
||||
config.tcpfeed.highrate = 10;
|
||||
config.tcpfeed.idformat = ID_DFMDXL;
|
||||
config.kisstnc.active = 0;
|
||||
strcpy(config.ephftp,"igs.bkg.bund.de/IGS/BRDC/");
|
||||
|
||||
config.mqtt.active = 0;
|
||||
strcpy(config.mqtt.id, "rdz_sonde_server");
|
||||
config.mqtt.port = 1883;
|
||||
strcpy(config.mqtt.username, "/0");
|
||||
strcpy(config.mqtt.password, "/0");
|
||||
strcpy(config.mqtt.prefix, "rdz_sonde_server/");
|
||||
}
|
||||
|
||||
extern struct st_configitems config_list[];
|
||||
extern const int N_CONFIG;
|
||||
|
||||
void Sonde::checkConfig() {
|
||||
if(config.maxsonde > MAXSONDE) config.maxsonde = MAXSONDE;
|
||||
if(config.sondehub.fiinterval<5) config.sondehub.fiinterval = 5;
|
||||
if(config.sondehub.fimaxdist>700) config.sondehub.fimaxdist = 700;
|
||||
if(config.sondehub.fimaxage>48) config.sondehub.fimaxage = 48;
|
||||
if(config.sondehub.fimaxdist==0) config.sondehub.fimaxdist = 150;
|
||||
if(config.sondehub.fimaxage==0) config.sondehub.fimaxage = 2;
|
||||
}
|
||||
void Sonde::setConfig(const char *cfg) {
|
||||
while(*cfg==' '||*cfg=='\t') cfg++;
|
||||
if(*cfg=='#') return;
|
||||
|
@ -209,143 +286,52 @@ void Sonde::setConfig(const char *cfg) {
|
|||
*s=0; s--;
|
||||
while(s>cfg && (*s==' '||*s=='\t')) { *s=0; s--; }
|
||||
Serial.printf("configuration option '%s'=%s \n", cfg, val);
|
||||
if(strcmp(cfg,"noisefloor")==0) {
|
||||
config.noisefloor = atoi(val);
|
||||
if(config.noisefloor==0) config.noisefloor=-130;
|
||||
} else if(strcmp(cfg,"gainLNA")==0) {
|
||||
config.gainLNA = atoi(val);
|
||||
} else if(strcmp(cfg,"call")==0) {
|
||||
strncpy(config.call, val, 9);
|
||||
config.call[9]=0;
|
||||
} else if(strcmp(cfg,"passcode")==0) {
|
||||
strncpy(config.passcode, val, 9);
|
||||
} else if(strcmp(cfg,"button_pin")==0) {
|
||||
config.button_pin = atoi(val);
|
||||
} else if(strcmp(cfg,"button2_pin")==0) {
|
||||
config.button2_pin = atoi(val);
|
||||
} else if(strcmp(cfg,"button2_axp")==0) {
|
||||
config.button2_axp = atoi(val);
|
||||
} else if(strcmp(cfg,"touch_thresh")==0) {
|
||||
config.touch_thresh = atoi(val);
|
||||
} else if(strcmp(cfg,"led_pout")==0) {
|
||||
config.led_pout = atoi(val);
|
||||
} else if(strcmp(cfg,"power_pout")==0) {
|
||||
config.power_pout = atoi(val);
|
||||
} else if(strcmp(cfg,"disptype")==0) {
|
||||
config.disptype = atoi(val);
|
||||
} else if(strcmp(cfg,"oled_sda")==0) {
|
||||
config.oled_sda = atoi(val);
|
||||
} else if(strcmp(cfg,"oled_scl")==0) {
|
||||
config.oled_scl = atoi(val);
|
||||
} else if(strcmp(cfg,"oled_rst")==0) {
|
||||
config.oled_rst = atoi(val);
|
||||
} else if(strcmp(cfg,"oled_orient")==0) {
|
||||
config.oled_orient = atoi(val);
|
||||
} else if(strcmp(cfg,"gpsOn")==0) {
|
||||
config.gpsOn = atoi(val);
|
||||
} else if(strcmp(cfg,"gps_rxd")==0) {
|
||||
config.gps_rxd = atoi(val);
|
||||
} else if(strcmp(cfg,"gps_txd")==0) {
|
||||
config.gps_txd = atoi(val);
|
||||
} else if(strcmp(cfg,"gps_lat")==0) {
|
||||
strncpy(config.gps_lat, val, 8);
|
||||
} else if(strcmp(cfg,"gps_lon")==0) {
|
||||
strncpy(config.gps_lon, val, 8);
|
||||
} else if(strcmp(cfg,"gps_alt")==0) {
|
||||
config.gps_alt = atoi(val);
|
||||
} else if(strcmp(cfg,"maxsonde")==0) {
|
||||
config.maxsonde = atoi(val);
|
||||
if(config.maxsonde>MAXSONDE) config.maxsonde=MAXSONDE;
|
||||
} 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,"mdnsname")==0) {
|
||||
strncpy(config.mdnsname, val, 14);
|
||||
} else if(strcmp(cfg,"vbatmax")==0) {
|
||||
strncpy(config.vbatmax,val,5);
|
||||
} else if(strcmp(cfg,"vbatmin")==0) {
|
||||
strncpy(config.vbatmin,val,5);
|
||||
} else if(strcmp(cfg,"telemetryOn")==0) {
|
||||
config.telemetryOn=atoi(val);
|
||||
} else if(strcmp(cfg,"buzzerOn")==0) {
|
||||
config.buzzerOn=atoi(val);
|
||||
} else if(strcmp(cfg,"buzzerPort")==0) {
|
||||
config.buzzerPort=atoi(val);
|
||||
} else if(strcmp(cfg,"buzzerFreq")==0) {
|
||||
config.buzzerFreq=atoi(val);
|
||||
} else if(strcmp(cfg,"dbsmetre")==0) {
|
||||
config.dbsmetre=atoi(val);
|
||||
} else if(strcmp(cfg,"degdec")==0) {
|
||||
config.degdec=atoi(val);
|
||||
} else if(strcmp(cfg,"display")==0) {
|
||||
int i = 0;
|
||||
char *ptr;
|
||||
while(val) {
|
||||
ptr = strchr(val,',');
|
||||
if(ptr) *ptr = 0;
|
||||
config.display[i++] = atoi(val);
|
||||
val = ptr?ptr+1:NULL;
|
||||
Serial.printf("appending value %d next is %s\n", config.display[i-1], val?val:"");
|
||||
|
||||
// new code: use config_list to find config entry...
|
||||
int i;
|
||||
for(i=0; i<N_CONFIG; i++) {
|
||||
if(strcmp(cfg, config_list[i].name)!=0) continue;
|
||||
|
||||
if(config_list[i].type>0) { // string with that length
|
||||
strlcpy((char *)config_list[i].data, val, config_list[i].type+1);
|
||||
break;
|
||||
}
|
||||
config.display[i] = -1;
|
||||
} else if (strcmp(cfg, "norx_timeout")==0) {
|
||||
config.norx_timeout = 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,"marker")==0) {
|
||||
config.marker = atoi(val);
|
||||
} else if(strcmp(cfg,"showafc")==0) {
|
||||
config.showafc = atoi(val);
|
||||
} else if(strcmp(cfg,"freqofs")==0) {
|
||||
config.freqofs = atoi(val);
|
||||
} else if(strcmp(cfg,"rs41.agcbw")==0) {
|
||||
config.rs41.agcbw = atoi(val);
|
||||
} else if(strcmp(cfg,"rs41.rxbw")==0) {
|
||||
config.rs41.rxbw = atoi(val);
|
||||
} else if(strcmp(cfg,"dfm.agcbw")==0) {
|
||||
config.dfm.agcbw = atoi(val);
|
||||
} else if(strcmp(cfg,"dfm.rxbw")==0) {
|
||||
config.dfm.rxbw = atoi(val);
|
||||
} else if(strcmp(cfg,"rs92.alt2d")==0) {
|
||||
config.rs92.alt2d= atoi(val);
|
||||
} else if(strcmp(cfg,"kisstnc.active")==0) {
|
||||
config.kisstnc.active = atoi(val);
|
||||
} else if(strcmp(cfg,"kisstnc.idformat")==0) {
|
||||
config.kisstnc.idformat = atoi(val);
|
||||
} else if(strcmp(cfg,"rs92.rxbw")==0) {
|
||||
config.rs92.rxbw = atoi(val);
|
||||
} else if(strcmp(cfg,"axudp.active")==0) {
|
||||
config.udpfeed.active = atoi(val)>0;
|
||||
} else if(strcmp(cfg,"axudp.host")==0) {
|
||||
strncpy(config.udpfeed.host, val, 63);
|
||||
} else if(strcmp(cfg,"axudp.port")==0) {
|
||||
config.udpfeed.port = atoi(val);
|
||||
} else if(strcmp(cfg,"axudp.symbol")==0) {
|
||||
strncpy(config.udpfeed.symbol, val, 3);
|
||||
} else if(strcmp(cfg,"axudp.highrate")==0) {
|
||||
config.udpfeed.highrate = atoi(val);
|
||||
} else if(strcmp(cfg,"axudp.idformat")==0) {
|
||||
config.udpfeed.idformat = atoi(val);
|
||||
} else if(strcmp(cfg,"tcp.active")==0) {
|
||||
config.tcpfeed.active = atoi(val)>0;
|
||||
} else if(strcmp(cfg,"tcp.host")==0) {
|
||||
strncpy(config.tcpfeed.host, val, 63);
|
||||
} else if(strcmp(cfg,"tcp.port")==0) {
|
||||
config.tcpfeed.port = atoi(val);
|
||||
} else if(strcmp(cfg,"tcp.symbol")==0) {
|
||||
strncpy(config.tcpfeed.symbol, val, 3);
|
||||
} else if(strcmp(cfg,"tcp.highrate")==0) {
|
||||
config.tcpfeed.highrate = atoi(val);
|
||||
} else if(strcmp(cfg,"tcp.idformat")==0) {
|
||||
config.tcpfeed.idformat = atoi(val);
|
||||
} else {
|
||||
switch(config_list[i].type) {
|
||||
case 0: // integer
|
||||
case -4: // integer (with "touch button" checkbox in web form)
|
||||
case -3: // integer (boolean on/off swith in web form)
|
||||
case -2: // integer (ID type)
|
||||
*(int *)config_list[i].data = atoi(val);
|
||||
break;
|
||||
case -7: // double
|
||||
{
|
||||
double d = atof(val);
|
||||
if(*val == 0 || d==0) d = NAN;
|
||||
*(double *)config_list[i].data = d;
|
||||
break;
|
||||
}
|
||||
case -6: // display list
|
||||
{
|
||||
int idx = 0;
|
||||
char *ptr;
|
||||
while(val) {
|
||||
ptr = strchr(val,',');
|
||||
if(ptr) *ptr = 0;
|
||||
config.display[idx++] = atoi(val);
|
||||
val = ptr?ptr+1:NULL;
|
||||
Serial.printf("appending value %d next is %s\n", config.display[idx-1], val?val:"");
|
||||
}
|
||||
config.display[idx] = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// skipping non-supported types
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if(i==N_CONFIG) {
|
||||
Serial.printf("Invalid config option '%s'=%s \n", cfg, val);
|
||||
}
|
||||
}
|
||||
|
@ -364,40 +350,49 @@ void Sonde::addSonde(float frequency, SondeType type, int active, char *launchsi
|
|||
return;
|
||||
}
|
||||
Serial.printf("Adding %f - %d - %d - %s\n", frequency, type, active, launchsite);
|
||||
sondeList[nSonde].type = type;
|
||||
sondeList[nSonde].freq = frequency;
|
||||
// reset all data if type or frequency has changed
|
||||
if(type != sondeList[nSonde].type || frequency != sondeList[nSonde].freq) {
|
||||
//TODO: Check for potential race condition with decoders
|
||||
// do not clear extra while decoder is potentiall still accessing it!
|
||||
if(sondeList[nSonde].extra) free(sondeList[nSonde].extra);
|
||||
memset(&sondeList[nSonde], 0, sizeof(SondeInfo));
|
||||
sondeList[nSonde].type = type;
|
||||
sondeList[nSonde].d.typestr[0] = 0;
|
||||
sondeList[nSonde].freq = frequency;
|
||||
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
|
||||
clearAllData(sondeList+nSonde);
|
||||
}
|
||||
sondeList[nSonde].active = active;
|
||||
strncpy(sondeList[nSonde].launchsite, launchsite, 17);
|
||||
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++;
|
||||
}
|
||||
|
||||
// called by updateState (only)
|
||||
void Sonde::nextConfig() {
|
||||
currentSonde++;
|
||||
if(currentSonde>=nSonde) {
|
||||
if(currentSonde>=config.maxsonde) {
|
||||
currentSonde=0;
|
||||
}
|
||||
// Skip non-active entries (but don't loop forever if there are no active ones)
|
||||
for(int i=0; i<config.maxsonde; i++) {
|
||||
for(int i=0; i<config.maxsonde - 1; i++) {
|
||||
if(!sondeList[currentSonde].active) {
|
||||
currentSonde++;
|
||||
if(currentSonde>=nSonde) currentSonde=0;
|
||||
if(currentSonde>=config.maxsonde) currentSonde=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Sonde::nextRxSonde() {
|
||||
rxtask.currentSonde++;
|
||||
if(rxtask.currentSonde>=nSonde) {
|
||||
if(rxtask.currentSonde>=config.maxsonde) {
|
||||
rxtask.currentSonde=0;
|
||||
}
|
||||
for(int i=0; i<config.maxsonde; i++) {
|
||||
for(int i=0; i<config.maxsonde - 1; i++) {
|
||||
if(!sondeList[rxtask.currentSonde].active) {
|
||||
rxtask.currentSonde++;
|
||||
if(rxtask.currentSonde>=nSonde) rxtask.currentSonde=0;
|
||||
if(rxtask.currentSonde>=config.maxsonde) rxtask.currentSonde=0;
|
||||
}
|
||||
}
|
||||
Serial.printf("nextRxSonde: %d\n", rxtask.currentSonde);
|
||||
//Serial.printf("nextRxSonde: %d\n", rxtask.currentSonde);
|
||||
}
|
||||
void Sonde::nextRxFreq(int addkhz) {
|
||||
// last entry is for the variable frequency
|
||||
|
@ -417,34 +412,50 @@ void Sonde::setup() {
|
|||
Serial.print("Invalid rxtask.currentSonde: ");
|
||||
Serial.println(rxtask.currentSonde);
|
||||
rxtask.currentSonde = 0;
|
||||
for(int i=0; i<config.maxsonde - 1; i++) {
|
||||
if(!sondeList[rxtask.currentSonde].active) {
|
||||
rxtask.currentSonde++;
|
||||
if(rxtask.currentSonde>=config.maxsonde) rxtask.currentSonde=0;
|
||||
}
|
||||
}
|
||||
sonde.currentSonde = rxtask.currentSonde;
|
||||
}
|
||||
|
||||
// update receiver config
|
||||
Serial.print("\nSonde::setup() on sonde index ");
|
||||
Serial.print("Sonde::setup() start on index ");
|
||||
Serial.println(rxtask.currentSonde);
|
||||
switch(sondeList[rxtask.currentSonde].type) {
|
||||
case STYPE_RS41:
|
||||
rs41.setup(sondeList[rxtask.currentSonde].freq * 1000000);
|
||||
break;
|
||||
case STYPE_DFM06:
|
||||
case STYPE_DFM09:
|
||||
dfm.setup( sondeList[rxtask.currentSonde].freq * 1000000, sondeList[rxtask.currentSonde].type==STYPE_DFM06?0:1 );
|
||||
case STYPE_DFM:
|
||||
dfm.setup( sondeList[rxtask.currentSonde].freq * 1000000, sondeList[rxtask.currentSonde].type );
|
||||
break;
|
||||
case STYPE_RS92:
|
||||
rs92.setup( sondeList[rxtask.currentSonde].freq * 1000000);
|
||||
break;
|
||||
case STYPE_M10:
|
||||
m10.setup( sondeList[rxtask.currentSonde].freq * 1000000);
|
||||
case STYPE_M20:
|
||||
case STYPE_M10M20:
|
||||
m10m20.setup( sondeList[rxtask.currentSonde].freq * 1000000);
|
||||
break;
|
||||
case STYPE_MP3H:
|
||||
mp3h.setup( sondeList[rxtask.currentSonde].freq * 1000000);
|
||||
break;
|
||||
}
|
||||
// debug
|
||||
float afcbw = sx1278.getAFCBandwidth();
|
||||
float rxbw = sx1278.getRxBandwidth();
|
||||
Serial.printf("AFC BW: %f RX BW: %f\n", afcbw, rxbw);
|
||||
int freq = (int)sx1278.getFrequency();
|
||||
int afcbw = (int)sx1278.getAFCBandwidth();
|
||||
int rxbw = (int)sx1278.getRxBandwidth();
|
||||
Serial.printf("Sonde::setup() done: Type %s Freq %f, AFC BW: %d, RX BW: %d\n", sondeTypeStr[sondeList[rxtask.currentSonde].type], 0.000001*freq, afcbw, rxbw);
|
||||
|
||||
// reset rxtimer / norxtimer state
|
||||
sonde.sondeList[sonde.currentSonde].lastState = -1;
|
||||
}
|
||||
|
||||
extern void flashLed(int ms);
|
||||
extern void buzzerLed(int temps);
|
||||
|
||||
void Sonde::receive() {
|
||||
uint16_t res = 0;
|
||||
SondeInfo *si = &sondeList[rxtask.currentSonde];
|
||||
|
@ -456,16 +467,21 @@ void Sonde::receive() {
|
|||
res = rs92.receive();
|
||||
break;
|
||||
case STYPE_M10:
|
||||
res = m10.receive();
|
||||
case STYPE_M20:
|
||||
case STYPE_M10M20:
|
||||
res = m10m20.receive();
|
||||
break;
|
||||
case STYPE_DFM06:
|
||||
case STYPE_DFM09:
|
||||
case STYPE_DFM:
|
||||
res = dfm.receive();
|
||||
break;
|
||||
case STYPE_MP3H:
|
||||
res = mp3h.receive();
|
||||
break;
|
||||
}
|
||||
|
||||
// state information for RX_TIMER / NORX_TIMER events
|
||||
if(res==0) { // RX OK
|
||||
if(res==RX_OK || res==RX_ERROR) { // something was received...
|
||||
|
||||
flashLed(700);
|
||||
if(sonde.config.buzzerOn==1) {
|
||||
buzzerLed(500);
|
||||
|
@ -473,12 +489,12 @@ void Sonde::receive() {
|
|||
if(si->lastState != 1) {
|
||||
si->rxStart = millis();
|
||||
si->lastState = 1;
|
||||
sonde.dispsavectlON();
|
||||
}
|
||||
} else { // RX not ok
|
||||
if(res==RX_ERROR) {
|
||||
flashLed(100);
|
||||
}
|
||||
Serial.printf("RX result %d, laststate was %d\n", res, si->lastState);
|
||||
} else { // RX Timeout
|
||||
flashLed( (res==RX_OK)?700:100);
|
||||
ledcWriteTone(0, 0);
|
||||
//Serial.printf("Sonde::receive(): result %d (%s), laststate was %d\n", res, (res<=3)?RXstr[res]:"?", si->lastState);
|
||||
if(si->lastState != 0) {
|
||||
si->norxStart = millis();
|
||||
si->lastState = 0;
|
||||
|
@ -493,28 +509,33 @@ void Sonde::receive() {
|
|||
|
||||
int event = getKeyPressEvent();
|
||||
if (!event) event = timeoutEvent(si);
|
||||
else sonde.dispsavectlON();
|
||||
int action = (event==EVT_NONE) ? ACT_NONE : disp.layout->actions[event];
|
||||
Serial.printf("event %x: action is %x\n", event, action);
|
||||
//if(action!=ACT_NONE) { Serial.printf("event %x: action is %x\n", event, action); }
|
||||
// If action is to move to a different sonde index, we do update things here, set activate
|
||||
// to force the sx1278 task to call sonde.setup(), and pass information about sonde to
|
||||
// main loop (display update...)
|
||||
if(action == ACT_NEXTSONDE || action==ACT_PREVSONDE || (action>64&&action<128) ) {
|
||||
if(action == ACT_DISPLAY_SCANNER || action == ACT_NEXTSONDE || action==ACT_PREVSONDE || (action>64&&action<128) ) {
|
||||
// handled here...
|
||||
if(action==ACT_NEXTSONDE||action==ACT_PREVSONDE)
|
||||
nextRxSonde();
|
||||
else
|
||||
nextRxFreq( action-64 );
|
||||
action = ACT_SONDE(rxtask.currentSonde);
|
||||
if(action==ACT_DISPLAY_SCANNER) {
|
||||
// nothing to do here, be re-call setup() for M10/M20 for repeating AFC
|
||||
}
|
||||
else {
|
||||
if(action==ACT_NEXTSONDE||action==ACT_PREVSONDE)
|
||||
nextRxSonde();
|
||||
else
|
||||
nextRxFreq( action-64 );
|
||||
action = ACT_SONDE(rxtask.currentSonde);
|
||||
}
|
||||
if(rxtask.activate==-1) {
|
||||
// race condition here. maybe better use mutex. TODO
|
||||
rxtask.activate = action;
|
||||
rxtask.activate = ACT_SONDE(rxtask.currentSonde);
|
||||
}
|
||||
}
|
||||
Serial.printf("Sonde:receive(): result %d (%s), event %02x => action %02x\n", res, (res<=3)?RXstr[res]:"?", event, action);
|
||||
res = (action<<8) | (res&0xff);
|
||||
Serial.printf("receive Result is %04x\n", res);
|
||||
// let waitRXcomplete resume...
|
||||
rxtask.receiveResult = res;
|
||||
|
||||
}
|
||||
|
||||
// return (action<<8) | (rxresult)
|
||||
|
@ -522,10 +543,14 @@ uint16_t Sonde::waitRXcomplete() {
|
|||
uint16_t res=0;
|
||||
uint32_t t0 = millis();
|
||||
rxloop:
|
||||
while( rxtask.receiveResult==0xFFFF && millis()-t0 < 3000) { delay(50); }
|
||||
while( (pmu_irq!=1) && rxtask.receiveResult==0xFFFF && millis()-t0 < 3000) { delay(50); }
|
||||
if( pmu_irq ) {
|
||||
handlePMUirq();
|
||||
if(pmu_irq!=2) goto rxloop;
|
||||
}
|
||||
if( rxtask.receiveResult == RX_UPDATERSSI ) {
|
||||
rxtask.receiveResult = 0xFFFF;
|
||||
Serial.print("RSSI update: ");
|
||||
Serial.printf("RSSI update: %d/2\n", sonde.si()->rssi);
|
||||
disp.updateDisplayRSSI();
|
||||
goto rxloop;
|
||||
}
|
||||
|
@ -548,12 +573,16 @@ rxloop:
|
|||
rs92.waitRXcomplete();
|
||||
break;
|
||||
case STYPE_M10:
|
||||
m10.waitRXcomplete();
|
||||
case STYPE_M20:
|
||||
case STYPE_M10M20:
|
||||
m10m20.waitRXcomplete();
|
||||
break;
|
||||
case STYPE_DFM06:
|
||||
case STYPE_DFM09:
|
||||
case STYPE_DFM:
|
||||
dfm.waitRXcomplete();
|
||||
break;
|
||||
case STYPE_MP3H:
|
||||
mp3h.waitRXcomplete();
|
||||
break;
|
||||
}
|
||||
memmove(sonde.si()->rxStat+1, sonde.si()->rxStat, 17);
|
||||
sonde.si()->rxStat[0] = res;
|
||||
|
@ -562,30 +591,29 @@ rxloop:
|
|||
|
||||
uint8_t Sonde::timeoutEvent(SondeInfo *si) {
|
||||
uint32_t now = millis();
|
||||
#if 1
|
||||
Serial.printf("Timeout check: %d - %d vs %d; %d - %d vs %d; %d - %d vs %d\n",
|
||||
#if 0
|
||||
Serial.printf("Timeout check: %d - %d vs %d; %d - %d vs %d; %d - %d vs %d; lastState: %d\n",
|
||||
now, si->viewStart, disp.layout->timeouts[0],
|
||||
now, si->rxStart, disp.layout->timeouts[1],
|
||||
now, si->norxStart, disp.layout->timeouts[2]);
|
||||
now, si->norxStart, disp.layout->timeouts[2], si->lastState);
|
||||
#endif
|
||||
Serial.printf("lastState is %d\n", si->lastState);
|
||||
if(disp.layout->timeouts[0]>=0 && now - si->viewStart >= disp.layout->timeouts[0]) {
|
||||
Serial.println("View timer expired");
|
||||
Serial.println("Sonde::timeoutEvent: View");
|
||||
return EVT_VIEWTO;
|
||||
}
|
||||
if(si->lastState==1 && disp.layout->timeouts[1]>=0 && now - si->rxStart >= disp.layout->timeouts[1]) {
|
||||
Serial.println("RX timer expired");
|
||||
Serial.println("Sonde::timeoutEvent: RX");
|
||||
return EVT_RXTO;
|
||||
}
|
||||
if(si->lastState==0 && disp.layout->timeouts[2]>=0 && now - si->norxStart >= disp.layout->timeouts[2]) {
|
||||
Serial.println("NORX timer expired");
|
||||
Serial.println("Sonde::timeoutEvent: NORX");
|
||||
return EVT_NORXTO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t Sonde::updateState(uint8_t event) {
|
||||
Serial.printf("Sonde::updateState for event %d\n", event);
|
||||
//Serial.printf("Sonde::updateState for event %02x\n", event);
|
||||
// No change
|
||||
if(event==ACT_NONE) return 0xFF;
|
||||
|
||||
|
@ -646,6 +674,14 @@ uint8_t Sonde::updateState(uint8_t event) {
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
void Sonde::clearAllData(SondeInfo *si) {
|
||||
// set everything to 0
|
||||
memset(&(si->d), 0, sizeof(SondeData));
|
||||
// set floats to NaN
|
||||
si->d.lat = si->d.lon = si->d.alt = si->d.vs = si->d.hs = si->d.dir = NAN;
|
||||
si->d.temperature = si->d.tempRHSensor = si->d.relativeHumidity = si->d.pressure = si->d.batteryVoltage = NAN;
|
||||
}
|
||||
|
||||
void Sonde::updateDisplayPos() {
|
||||
disp.updateDisplayPos();
|
||||
}
|
||||
|
@ -676,13 +712,25 @@ void Sonde::updateDisplayIP() {
|
|||
|
||||
void Sonde::updateDisplay()
|
||||
{
|
||||
int t = millis();
|
||||
disp.updateDisplay();
|
||||
Serial.printf("updateDisplay took %d ms\n", (int)(millis()-t));
|
||||
}
|
||||
|
||||
void Sonde::clearDisplay() {
|
||||
disp.rdis->clear();
|
||||
}
|
||||
|
||||
void Sonde::dispsavectlON() {
|
||||
disp.dispsavectlON();
|
||||
}
|
||||
|
||||
void Sonde::dispsavectlOFF(int rxactive) {
|
||||
disp.dispsavectlOFF(rxactive);
|
||||
}
|
||||
|
||||
|
||||
SondeType Sonde::realType(SondeInfo *si) {
|
||||
if(TYPE_IS_METEO(si->type) && si->d.subtype>0 ) { return si->d.subtype==1 ? STYPE_M10:STYPE_M20; }
|
||||
else return si->type;
|
||||
}
|
||||
|
||||
Sonde sonde = Sonde();
|
216
libraries/SondeLib/Sonde.h → RX_FSK/src/Sonde.h
Executable file → Normal file
216
libraries/SondeLib/Sonde.h → RX_FSK/src/Sonde.h
Executable file → Normal file
|
@ -2,9 +2,25 @@
|
|||
#ifndef Sonde_h
|
||||
#define Sonde_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
enum DbgLevel { DEBUG_OFF=0, DEBUG_INFO=1, DEBUG_SPARSER=16, DEBUG_DISPLAY=8 }; // to be extended for configuring serial debug output
|
||||
extern uint8_t debug;
|
||||
|
||||
#define DebugPrint(l,x) if(debug&l) { Serial.print(x); }
|
||||
#define DebugPrintln(l,x) if(debug&l) { Serial.println(x); }
|
||||
#define DebugPrintf(l,...) if(debug&l) { Serial.printf(__VA_ARGS__); }
|
||||
|
||||
// RX_TIMEOUT: no header detected
|
||||
// RX_ERROR: header detected, but data not decoded (crc error, etc.)
|
||||
// RX_OK: header and data ok
|
||||
// RX_PARTIAL: header detected, some data ok, some with errors
|
||||
// For RS41: Some blocks with CRC error, some blocks ok in a single frame
|
||||
// For DFM: In +- 1s, some but not all DAT-subframes 1,2,3,4,5,6,7,8 received
|
||||
// For RS92 ??? unclear
|
||||
// For M10/M20 its always all or nothing, no PARTIAL data
|
||||
// For MP3H its alway all or nothing, no PARTIAL data
|
||||
// RX_OK: header and all data ok
|
||||
enum RxResult { RX_OK, RX_TIMEOUT, RX_ERROR, RX_UNKNOWN, RX_NOPOS };
|
||||
#define RX_UPDATERSSI 0xFFFE
|
||||
|
||||
|
@ -46,39 +62,66 @@ extern const char *RXstr[];
|
|||
// 01000000 => goto sonde -1
|
||||
// 01000001 => goto sonde +1
|
||||
|
||||
#define NSondeTypes 5
|
||||
enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41, STYPE_RS92, STYPE_M10 };
|
||||
#define NSondeTypes 7
|
||||
enum SondeType { STYPE_DFM, STYPE_RS41, STYPE_RS92, STYPE_M10M20, STYPE_M10, STYPE_M20, STYPE_MP3H };
|
||||
extern const char *sondeTypeStr[NSondeTypes];
|
||||
extern const char *sondeTypeLongStr[NSondeTypes];
|
||||
extern const char sondeTypeChar[NSondeTypes];
|
||||
extern const char *manufacturer_string[NSondeTypes];
|
||||
|
||||
typedef struct st_sondeinfo {
|
||||
// receiver configuration
|
||||
bool active;
|
||||
SondeType type;
|
||||
float freq;
|
||||
#define ISOLED(cfg) ((cfg).disptype==0 || (cfg).disptype==2)
|
||||
|
||||
#define TYPE_IS_DFM(t) ( (t)==STYPE_DFM )
|
||||
#define TYPE_IS_METEO(t) ( (t)==STYPE_M10M20 || (t)==STYPE_M10 || (t)==STYPE_M20 )
|
||||
|
||||
#define VALIDPOS(x) (((x)&0x03)==0x03)
|
||||
#define VALIDALT(x) ((x)&0x04)
|
||||
#define VALIDVS(x) ((x)&0x08)
|
||||
#define VALIDHS(x) ((x)&0x10)
|
||||
#define VALIDDIR(x) ((x)&0x20)
|
||||
#define VALIDSATS(x) ((x)&0x40)
|
||||
|
||||
typedef struct st_sondedata {
|
||||
// decoded ID
|
||||
char id[10];
|
||||
char ser[12];
|
||||
bool validID;
|
||||
char launchsite[18];
|
||||
char typestr[5]; // decoded type (use type if *typestr==0)
|
||||
int8_t subtype; /* 0 for none/unknown, hex type for dfm, 1/2 for M10/M20 */
|
||||
// decoded position
|
||||
float lat; // latitude
|
||||
float lon; // longitude
|
||||
float az; // azimut
|
||||
float vbat; // vbat %
|
||||
int durvolheure; // duree vol heure
|
||||
int durvolminute; // duree vol minute
|
||||
int durvolseconde; // duree vol seconde
|
||||
float alt; // altitude
|
||||
float vs; // vertical speed
|
||||
float hs; // horizontal speed
|
||||
float vs; // vertical speed in m/s
|
||||
float hs; // horizontal speed in m/s
|
||||
float dir; // 0..360
|
||||
uint8_t sats; // number of sats
|
||||
uint8_t validPos; // bit pattern for validity of above 7 fields; 0x80: position is old
|
||||
// decoded GPS time
|
||||
uint32_t time;
|
||||
uint16_t sec;
|
||||
uint32_t frame;
|
||||
uint32_t vframe; // vframe==frame if frame is unique/continous, otherweise vframe is derived from gps time
|
||||
bool validTime;
|
||||
// shut down timers, currently only for RS41; -1=disabled
|
||||
uint16_t launchKT, burstKT, countKT;
|
||||
uint16_t crefKT; // frame number in which countKT was last sent
|
||||
// sonde specific extra data, NULL if unused or not yet initialized, currently used for RS41 subframe data (calibration)
|
||||
float temperature; // platinum resistor temperature
|
||||
float tempRHSensor; // temperature of relative humidity sensor
|
||||
float relativeHumidity; // relative humidity
|
||||
float pressure;
|
||||
float batteryVoltage = -1;
|
||||
} SondeData;
|
||||
|
||||
typedef struct st_sondeinfo {
|
||||
// First part: static configuration, not decoded data.
|
||||
// receiver configuration
|
||||
bool active;
|
||||
SondeType type;
|
||||
float freq;
|
||||
char launchsite[18];
|
||||
|
||||
// Second part: internal decoder state. no need to clear this on new sonde
|
||||
// RSSI from receiver
|
||||
int rssi; // signal strength
|
||||
int32_t afc; // afc correction value
|
||||
|
@ -88,9 +131,11 @@ typedef struct st_sondeinfo {
|
|||
uint32_t norxStart; // millis() timestamp of continuous no rx start
|
||||
uint32_t viewStart; // millis() timestamp of viewinf this sonde with current display
|
||||
int8_t lastState; // -1: disabled; 0: norx; 1: rx
|
||||
// shut down timers, currently only for RS41; -1=disabled
|
||||
int16_t launchKT, burstKT, countKT;
|
||||
uint16_t crefKT; // frame number in which countKT was last sent
|
||||
// Third part: decoded data. Clear if reception of a new sonde has started
|
||||
SondeData d;
|
||||
|
||||
// Decoder-specific data, dynamically allocated (for RS41: calibration data)
|
||||
void *extra;
|
||||
} SondeInfo;
|
||||
// rxStat: 3=undef[empty] 1=timeout[.] 2=errro[E] 0=ok[|] 4=no valid position[°]
|
||||
|
||||
|
@ -126,10 +171,16 @@ struct st_dfmconfig {
|
|||
int agcbw;
|
||||
int rxbw;
|
||||
};
|
||||
struct st_m10m20config {
|
||||
int agcbw;
|
||||
int rxbw;
|
||||
};
|
||||
struct st_mp3hconfig {
|
||||
int agcbw;
|
||||
int rxbw;
|
||||
};
|
||||
|
||||
|
||||
enum IDTYPE { ID_DFMDXL, ID_DFMGRAW, ID_DFMAUTO };
|
||||
|
||||
struct st_feedinfo {
|
||||
bool active;
|
||||
int type; // 0:UDP(axudp), 1:TCP(aprs.fi)
|
||||
|
@ -139,76 +190,130 @@ struct st_feedinfo {
|
|||
int lowrate;
|
||||
int highrate;
|
||||
int lowlimit;
|
||||
int idformat; // 0: dxl 1: real 2: auto
|
||||
};
|
||||
|
||||
// maybe extend for external Bluetooth interface?
|
||||
// internal bluetooth consumes too much memory
|
||||
struct st_kisstnc {
|
||||
bool active;
|
||||
int idformat;
|
||||
};
|
||||
|
||||
struct st_mqtt {
|
||||
int active;
|
||||
char id[64];
|
||||
char host[64];
|
||||
int port;
|
||||
char username[64];
|
||||
char password[64];
|
||||
char prefix[64];
|
||||
};
|
||||
|
||||
struct st_cm {
|
||||
int active;
|
||||
char host[64];
|
||||
int port;
|
||||
};
|
||||
|
||||
struct st_sondehub {
|
||||
int active;
|
||||
int chase;
|
||||
char host[64];
|
||||
char callsign[64];
|
||||
char antenna[64];
|
||||
char email[64];
|
||||
int fiactive;
|
||||
int fiinterval;
|
||||
int fimaxdist;
|
||||
double fimaxage;
|
||||
};
|
||||
|
||||
// to be extended
|
||||
enum { TYPE_TTGO, TYPE_M5_CORE2 };
|
||||
|
||||
typedef struct st_rdzconfig {
|
||||
int type; // autodetected type, TTGO or M5_CORE2
|
||||
// hardware configuration
|
||||
int button_pin; // PIN port number menu button (+128 for touch mode)
|
||||
int button_pin; // PIN port number menu button (+128 for touch mode)
|
||||
int button2_pin; // PIN port number menu button (+128 for touch mode)
|
||||
int button2_axp; // Use AXP192 power button as button2
|
||||
int touch_thresh; // Threshold value (0..100) for touch input button
|
||||
int led_pout; // POUT port number of LED (used as serial monitor)
|
||||
int power_pout; // Power control pin (for Heltec v2)
|
||||
int disptype; // 0=OLED; 1=ILI9225
|
||||
int oled_sda; // OLED data pin
|
||||
int oled_scl; // OLED clock pin
|
||||
int oled_rst; // OLED reset pin
|
||||
int oled_orient; // OLED orientation (default: 1)
|
||||
int gpsOn; // GPS Active On=1/Off=0
|
||||
int oled_sda; // OLED/TFT data pin
|
||||
int oled_scl; // OLED/TFT clock pin
|
||||
int oled_rst; // OLED/TFT reset pin
|
||||
int oled_orient; // OLED/TFT orientation (default: 1)
|
||||
int gps_rxd; // GPS module RXD pin. We expect 9600 baud NMEA data.
|
||||
int gps_txd; // GPS module TXD pin
|
||||
char gps_lat[20]; // QTH no gps latitude
|
||||
char gps_lon[20]; // QTH no gps longitude
|
||||
int gps_alt; // QTH no gps altitude
|
||||
float gps_Lat,gps_Lon, gps_Alt; // QTH gps OM lat, lon, alt
|
||||
int batt_adc; // Pin for ADC battery measurement (GPIO35 on TTGO V2.1_1.6)
|
||||
int sx1278_ss; // SPI slave select for sx1278
|
||||
int sx1278_miso; // SPI MISO for sx1278
|
||||
int sx1278_mosi; // SPI MOSI for sx1278
|
||||
int sx1278_sck; // SPI SCK for sx1278
|
||||
// software configuration
|
||||
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
|
||||
int8_t display[30]; // list of display mode (0:scanner, 1:default, 2,... additional modes)
|
||||
int debug; // show port and config options after reboot
|
||||
double rxlat;
|
||||
double rxlon;
|
||||
double rxalt;
|
||||
int wifi; // connect to known WLAN 0=skip
|
||||
int screenfile;
|
||||
int8_t display[30]; // list of display mode (0:scanner, 1:default, 2,... additional modes)
|
||||
int dispsaver; // Turn display on/off (0=always on, 10*n+1: off after n seconds,
|
||||
// 10*n+2: scanner off after n seconds, RX always shown)
|
||||
int dispcontrast; // For OLED: set contrast to 0..255 (-1: don't set/leave at factory default)
|
||||
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 -1=disable; 0=forever
|
||||
int marker; // show freq marker 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 norx_timeout; // Time after which rx mode switches to scan mode (without rx signal)
|
||||
int noisefloor; // for spectrum display
|
||||
int gainLNA;
|
||||
char mdnsname[15]; // mDNS-Name, defaults to radiosonde
|
||||
char vbatmax[5]; // Vbat maxi when bat charged
|
||||
char vbatmin[5]; // Vbat minimum discharged
|
||||
int telemetryOn; // Active Save information telemetry
|
||||
int buzzerPort; // Buzzer port
|
||||
int buzzerFreq; // Buzzer Frequency
|
||||
int noisefloor; // for spectrum display
|
||||
char mdnsname[15]; // mDNS-Name, defaults to rdzsonde
|
||||
// Add f4IYT
|
||||
int buzzerPort; // Buzzer port
|
||||
int buzzerFreq; // Buzzer Frequency
|
||||
int buzzerOn; // Buzzer On
|
||||
int dbsmetre; // Db or Smetre display
|
||||
int degdec; // Degres or Decimal 0=decimal 1=degres
|
||||
// receiver configuration
|
||||
int showafc; // show afc value in rx screen
|
||||
int freqofs; // frequency offset (tuner config = rx frequency + freqofs) in Hz
|
||||
struct st_rs41config rs41; // configuration options specific for RS41 receiver
|
||||
struct st_rs92config rs92;
|
||||
struct st_dfmconfig dfm;
|
||||
struct st_m10m20config m10m20;
|
||||
struct st_mp3hconfig mp3h;
|
||||
char ephftp[40];
|
||||
// data feed configuration
|
||||
// for now, one feed for each type is enough, but might get extended to more?
|
||||
char call[10]; // APRS callsign
|
||||
char passcode[9]; // APRS passcode
|
||||
int passcode; // APRS passcode
|
||||
int chase;
|
||||
char objcall[10]; // APRS object call (for wettersonde.net)
|
||||
char beaconsym[5]; // APRS beacon symbol
|
||||
char comment[32];
|
||||
struct st_feedinfo udpfeed; // target for AXUDP messages
|
||||
struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections
|
||||
struct st_kisstnc kisstnc; // target for KISS TNC (via TCP, mainly for APRSdroid)
|
||||
struct st_mqtt mqtt;
|
||||
struct st_sondehub sondehub;
|
||||
struct st_cm cm;
|
||||
} RDZConfig;
|
||||
|
||||
|
||||
#define MAXSONDE 99
|
||||
struct st_configitems {
|
||||
const char *name;
|
||||
// const char *label; => now handled in JS
|
||||
int type; // 0: numeric; i>0 string of length i; -1: separator; -2: type selector
|
||||
void *data;
|
||||
};
|
||||
|
||||
// defined in RX_FSK.ino
|
||||
extern struct st_configitems config_list[];
|
||||
extern const int N_CONFIG;
|
||||
|
||||
|
||||
#define MAXSONDE 50
|
||||
|
||||
extern int fingerprintValue[];
|
||||
extern const char *fingerprintText[];
|
||||
|
@ -226,9 +331,12 @@ public:
|
|||
// moved to heap, saving space in .bss
|
||||
//SondeInfo sondeList[MAXSONDE+1];
|
||||
SondeInfo *sondeList;
|
||||
// helper function for type string
|
||||
static SondeType realType(SondeInfo *si);
|
||||
|
||||
Sonde();
|
||||
void defaultConfig();
|
||||
void checkConfig();
|
||||
void setConfig(const char *str);
|
||||
|
||||
void clearSonde();
|
||||
|
@ -241,13 +349,9 @@ public:
|
|||
void setup();
|
||||
void receive();
|
||||
uint16_t waitRXcomplete();
|
||||
/* old and temp interface */
|
||||
#if 0
|
||||
void processRXbyte(uint8_t data);
|
||||
int receiveFrame();
|
||||
#endif
|
||||
|
||||
SondeInfo *si();
|
||||
void clearAllData(SondeInfo *si);
|
||||
|
||||
uint8_t timeoutEvent(SondeInfo *si);
|
||||
uint8_t updateState(uint8_t event);
|
||||
|
@ -261,6 +365,8 @@ public:
|
|||
void updateDisplayIP();
|
||||
void updateDisplay();
|
||||
void clearDisplay();
|
||||
void dispsavectlON();
|
||||
void dispsavectlOFF(int rxactive);
|
||||
|
||||
void setIP(String ip, bool isAP);
|
||||
};
|
117
libraries/SondeLib/aprs.cpp → RX_FSK/src/aprs.cpp
Executable file → Normal file
117
libraries/SondeLib/aprs.cpp → RX_FSK/src/aprs.cpp
Executable file → Normal file
|
@ -17,6 +17,8 @@
|
|||
#include <inttypes.h>
|
||||
#include "aprs.h"
|
||||
|
||||
extern const char *version_name;
|
||||
extern const char *version_id;
|
||||
#if 0
|
||||
int openudp(const char *ip, int port, struct sockaddr_in *si) {
|
||||
int fd;
|
||||
|
@ -204,7 +206,7 @@ extern int aprsstr_mon2raw(const char *mon, char raw[], int raw_len)
|
|||
--n;
|
||||
}
|
||||
aprsstr_appcrc(raw, raw_len, p);
|
||||
fprintf(stderr,"results in %s\n",raw);
|
||||
//fprintf(stderr,"results in %s\n",raw);
|
||||
return p+2;
|
||||
} /* end mon2raw() */
|
||||
|
||||
|
@ -215,6 +217,7 @@ extern int aprsstr_mon2kiss(const char *mon, char raw[], int raw_len)
|
|||
if(len==0) return 0;
|
||||
int idx=0;
|
||||
raw[idx++] = '\xC0';
|
||||
raw[idx++] = 0; // channel 0
|
||||
for(int i=0; i<len-2; i++) { // -2: discard CRC, not used in KISS
|
||||
if(tmp[i]=='\xC0') {
|
||||
raw[idx++] = '\xDB';
|
||||
|
@ -234,28 +237,11 @@ extern int aprsstr_mon2kiss(const char *mon, char raw[], int raw_len)
|
|||
#define FEET (1.0/0.3048)
|
||||
#define KNOTS (1.851984)
|
||||
|
||||
#define X2C_max_longcard 0xFFFFFFFFUL
|
||||
static uint32_t X2C_TRUNCC(double x, uint32_t min0, uint32_t max0)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (x < (double)min0)
|
||||
i = (uint32_t)min0;
|
||||
if (x > (double)max0)
|
||||
i = (uint32_t)max0;
|
||||
|
||||
i = (uint32_t)x;
|
||||
if ((double)i > x)
|
||||
--i;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t truncc(double r)
|
||||
{
|
||||
if (r<=0.0) return 0UL;
|
||||
else if (r>=2.E+9) return 2000000000UL;
|
||||
else return (uint32_t)X2C_TRUNCC(r,0UL,X2C_max_longcard);
|
||||
else return (uint32_t)r;
|
||||
return 0;
|
||||
} /* end truncc() */
|
||||
|
||||
|
@ -271,16 +257,53 @@ static uint32_t dao91(double x)
|
|||
} /* end dao91() */
|
||||
|
||||
|
||||
char b[201];
|
||||
char raw[201];
|
||||
char b[251];
|
||||
//char raw[201];
|
||||
const char *destcall="APRRDZ";
|
||||
|
||||
char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) {
|
||||
// float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym, const char *comm)
|
||||
*b=0;
|
||||
char *aprs_send_beacon(const char *usercall, float lat, float lon, const char *sym, const char *comment) {
|
||||
*b = 0;
|
||||
aprsstr_append(b, usercall);
|
||||
aprsstr_append(b, ">");
|
||||
const char *destcall="APZRDZ";
|
||||
aprsstr_append(b, destcall);
|
||||
#if 0
|
||||
aprsstr_append(b, ":/"); // / is report with timestamp
|
||||
int i = strlen(b);
|
||||
int sec = 0; // TODO: NOW!!!
|
||||
snprintf(b+i, APRS_MAXLEN, "%02d%02d%02dh", sec/(60*60), (sec%(60*60))/60, sec%60);
|
||||
#else
|
||||
// report without timestamp
|
||||
aprsstr_append(b, ":!"); // ! is report w/p timestamp
|
||||
#endif
|
||||
// lat
|
||||
int i = strlen(b);
|
||||
int lati = abs((int)lat);
|
||||
int latm = (fabs(lat)-lati)*6000;
|
||||
snprintf(b+i, APRS_MAXLEN-i, "%02d%02d.%02d%c%c", lati, latm/100, latm%100, lat<0?'S':'N', sym[0]);
|
||||
// lon
|
||||
i = strlen(b);
|
||||
int loni = abs((int)lon);
|
||||
int lonm = (fabs(lon)-loni)*6000;
|
||||
snprintf(b+i, APRS_MAXLEN-i, "%03d%02d.%02d%c%c", loni, lonm/100, lonm%100, lon<0?'W':'E', sym[1]);
|
||||
// maybe add alt
|
||||
// maybe add DAO?
|
||||
i = strlen(b);
|
||||
snprintf(b+i, APRS_MAXLEN-i, "%s", comment);
|
||||
|
||||
i = strlen(b);
|
||||
snprintf(b+i, APRS_MAXLEN-i, " %s-%s", version_name, version_id);
|
||||
//sprintf(b + strlen(b), "%s", version_name);
|
||||
return b;
|
||||
}
|
||||
|
||||
char *aprs_senddata(SondeInfo *si, const char *usercall, const char *objcall, const char *sym) {
|
||||
SondeData *s = &(si->d);
|
||||
*b=0;
|
||||
aprsstr_append(b, *objcall ? objcall : usercall);
|
||||
aprsstr_append(b, ">");
|
||||
// const char *destcall="APRARX,SONDEGATE,TCPIP,qAR,oh3bsg";
|
||||
aprsstr_append(b, destcall);
|
||||
// if(*objcall) { aprsstr_append(b, ","); aprsstr_append(b, usercall); }
|
||||
// uncompressed
|
||||
aprsstr_append(b, ":;");
|
||||
char tmp[10];
|
||||
|
@ -290,7 +313,7 @@ char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) {
|
|||
// time
|
||||
int i = strlen(b);
|
||||
int sec = s->time % 86400;
|
||||
snprintf(b+i, APRS_MAXLEN-1, "%02d%02d%02dz", sec/(60*60), (sec%(60*60))/60, sec%60);
|
||||
snprintf(b+i, APRS_MAXLEN-1, "%02d%02d%02dh", sec/(60*60), (sec%(60*60))/60, sec%60);
|
||||
i = strlen(b);
|
||||
//aprsstr_append_data(time, ds);
|
||||
int lati = abs((int)s->lat);
|
||||
|
@ -302,25 +325,43 @@ char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) {
|
|||
snprintf(b+i, APRS_MAXLEN-i, "%03d%02d.%02d%c%c", loni, lonm/100, lonm%100, s->lon<0?'W':'E', sym[1]);
|
||||
if(s->hs>0.5) {
|
||||
i=strlen(b);
|
||||
snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(s->dir+1.5), realcard(s->hs*1.0/KNOTS+0.5));
|
||||
snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(s->dir+1.5), realcard(s->hs*3.6/KNOTS+0.5));
|
||||
}
|
||||
if(s->alt>0.5) {
|
||||
i=strlen(b);
|
||||
snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(s->alt*FEET+0.5));
|
||||
}
|
||||
int dao=1;
|
||||
if(dao) {
|
||||
i=strlen(b);
|
||||
snprintf(b+i, APRS_MAXLEN-i, "!w%c%c!", 33+dao91(s->lat), 33+dao91(s->lon));
|
||||
// always use DAO
|
||||
i=strlen(b);
|
||||
snprintf(b+i, APRS_MAXLEN-i, "!w%c%c!", 33+dao91(s->lat), 33+dao91(s->lon));
|
||||
|
||||
// ??? strcat(b, "&");
|
||||
i=strlen(b);
|
||||
i += snprintf(b+i, APRS_MAXLEN-i, "Clb=%.1fm/s ", s->vs );
|
||||
if( !isnan(s->pressure) ) {
|
||||
sprintf(b+strlen(b), "p=%.1fhPa ", s->pressure);
|
||||
}
|
||||
strcat(b, "&");
|
||||
char comm[100];
|
||||
snprintf(comm, 100, "Clb=%.1fm/s %.3fMHz Type=%s", s->vs, s->freq, sondeTypeStr[s->type]);
|
||||
strcat(b, comm);
|
||||
if(s->type==STYPE_M10||s->type==STYPE_DFM06||s->type==STYPE_DFM09) {
|
||||
snprintf(comm, 100, " ser=%s", s->ser);
|
||||
strcat(b, comm);
|
||||
if( !isnan(s->temperature) ) {
|
||||
sprintf(b+strlen(b), "t=%.1fC ", s->temperature);
|
||||
}
|
||||
if( !isnan(s->relativeHumidity) ) {
|
||||
sprintf(b+strlen(b), "h=%.1f%% ", s->relativeHumidity);
|
||||
}
|
||||
char type[12];
|
||||
if ( si->type == STYPE_RS41 && RS41::getSubtype(type, 11, si) == 0 ) {
|
||||
// type was copied to type
|
||||
} else {
|
||||
strncpy(type, sondeTypeStr[sonde.realType(si)], 11); type[11]=0;
|
||||
}
|
||||
|
||||
sprintf(b+strlen(b), "%.3fMHz Type=%s ", si->freq, type /* sondeTypeStr[sonde.realType(si)] */ );
|
||||
if( s->countKT != 0xffff && s->vframe - s->crefKT < 51 ) {
|
||||
sprintf(b+strlen(b), "TxOff=%dh%dm ", s->countKT/3600, (s->countKT-s->countKT/3600*3600)/60);
|
||||
}
|
||||
if( TYPE_IS_DFM(si->type) || TYPE_IS_METEO(si->type) ) {
|
||||
sprintf(b + strlen(b), "ser=%s ", s->ser);
|
||||
}
|
||||
sprintf(b + strlen(b), "%s", version_name);
|
||||
return b;
|
||||
}
|
||||
|
4
libraries/SondeLib/aprs.h → RX_FSK/src/aprs.h
Executable file → Normal file
4
libraries/SondeLib/aprs.h → RX_FSK/src/aprs.h
Executable file → Normal file
|
@ -2,13 +2,15 @@
|
|||
#ifndef _aprs_h
|
||||
#define _aprs_h
|
||||
#include "Sonde.h"
|
||||
#include "RS41.h"
|
||||
|
||||
|
||||
#define APRS_MAXLEN 201
|
||||
void aprs_gencrctab(void);
|
||||
int aprsstr_mon2raw(const char *mon, char raw[], int raw_len);
|
||||
int aprsstr_mon2kiss(const char *mon, char raw[], int raw_len);
|
||||
char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym);
|
||||
char *aprs_send_beacon(const char *call, float lat, float lon, const char *sym, const char *comment);
|
||||
char *aprs_senddata(SondeInfo *s, const char *usercall, const char *objcall, const char *sym);
|
||||
|
||||
|
||||
#endif
|
19
libraries/SondeLib/autodetect-infos → RX_FSK/src/autodetect-infos
Executable file → Normal file
19
libraries/SondeLib/autodetect-infos → RX_FSK/src/autodetect-infos
Executable file → Normal file
|
@ -30,6 +30,25 @@ TTGO T-Beam 1.0 with OLED display => fingerprint 0010111 => 23
|
|||
0:1 1:0 2:0 3:1 4:0 5:1 6:0 7:1 8:0 9:1 10:1 11:1 12:0 13:0 14:1 15:1 16:1 17:0 18:0 19:0 20:0 21:1 22:1 23:1 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0
|
||||
0:4 1:4 2:0 3:4 4:0 5:4 6:0 7:4 8:0 9:4 10:4 11:4 12:0 13:0 14:4 15:4 16:4 17:0 18:0 19:0 20:0 21:4 22:4 23:4 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0 (before setup)
|
||||
|
||||
TTGO T-Team 1.0 with IL9225 TFT => fingerprint 23
|
||||
0:1 1:0 2:0 3:1 4:0 5:1 6:0 7:1 8:0 9:1 10:1 11:1 12:0 13:0 14:1 15:1 16:1 17:0 18:0 19:0 20:0 21:1 22:1 23:1 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0
|
||||
0:1 1:1 2:0 3:1 4:0 5:1 6:0 7:1 8:0 9:1 10:1 11:1 12:0 13:0 14:1 15:1 16:1 17:0 18:0 19:0 20:0 21:1 22:1 23:1 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0 (before setup)
|
||||
|
||||
M5Stack Core2
|
||||
0:1 1:0 2:0 3:1 4:1 5:1 6:0 7:1 8:0 9:1 10:1 11:1 12:0 13:1 14:1 15:1 16:1 17:0 18:1 19:0 20:0 21:1 22:1 23:1 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0
|
||||
0:1 1:1 2:0 3:1 4:1 5:1 6:0 7:1 8:0 9:1 10:1 11:1 12:0 13:1 14:1 15:1 16:1 17:0 18:1 19:0 20:0 21:1 22:1 23:1 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0 (before setup)
|
||||
Board fingerprint is 87 (nach power on)
|
||||
0:1 1:0 2:0 3:1 4:0 5:0 6:0 7:1 8:0 9:1 10:1 11:1 12:0 13:0 14:1 15:0 16:1 17:0 18:0 19:0 20:0 21:1 22:1 23:0 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0
|
||||
0:1 1:1 2:0 3:1 4:0 5:0 6:0 7:1 8:0 9:1 10:1 11:1 12:0 13:0 14:1 15:0 16:1 17:0 18:0 19:0 20:0 21:1 22:1 23:0 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0 (before setup)
|
||||
Board fingerprint is 22 (nach reset)
|
||||
Autoconfig: looks like T-Beam 1.0 board
|
||||
|
||||
|
||||
vs 0010111
|
||||
T-Beam 1.1 seems to be different: 1110111
|
||||
GPIO4 = 1 (additional pullup) => +64
|
||||
GPIO12 = 1 (maybe additional pullup) => +32
|
||||
|
||||
1
|
||||
|
||||
Fingerprint GPIOs: 4, 12, 16, 17, 21, 22, 23,
|
0
libraries/fonts/FreeMono12pt7b.h → RX_FSK/src/fonts/FreeMono12pt7b.h
Executable file → Normal file
0
libraries/fonts/FreeMono12pt7b.h → RX_FSK/src/fonts/FreeMono12pt7b.h
Executable file → Normal file
495
RX_FSK/src/fonts/FreeMono12pt8b.h
Normal file
495
RX_FSK/src/fonts/FreeMono12pt8b.h
Normal file
|
@ -0,0 +1,495 @@
|
|||
const uint8_t FreeMono12pt8bBitmaps[] PROGMEM = {
|
||||
0x00, 0xDB, 0x6D, 0x92, 0x48, 0x01, 0xB8, 0xF7, 0x67, 0x67, 0x67, 0x66,
|
||||
0x66, 0x62, 0x00, 0x02, 0x40, 0x90, 0x44, 0x11, 0x04, 0x87, 0xFC, 0x48,
|
||||
0x12, 0x04, 0x87, 0xF8, 0x48, 0x12, 0x04, 0x81, 0x20, 0x48, 0x12, 0x00,
|
||||
0x08, 0x04, 0x0F, 0x0C, 0x6C, 0x14, 0x02, 0x00, 0xC0, 0x1E, 0x00, 0x80,
|
||||
0x30, 0x18, 0x17, 0x18, 0x70, 0x10, 0x08, 0x04, 0x00, 0x18, 0x19, 0x04,
|
||||
0x21, 0x08, 0x44, 0x0F, 0x00, 0x0C, 0x1C, 0x78, 0x20, 0xC0, 0xC8, 0x22,
|
||||
0x08, 0x42, 0x20, 0x78, 0x3E, 0x40, 0x40, 0x40, 0x20, 0x60, 0x91, 0x8A,
|
||||
0x8A, 0x86, 0x86, 0x7B, 0xFF, 0x6D, 0xB0, 0x01, 0x26, 0x44, 0xCC, 0xCC,
|
||||
0xCC, 0x44, 0x62, 0x31, 0x13, 0x24, 0xC9, 0x24, 0x92, 0xD6, 0x90, 0x00,
|
||||
0x04, 0x02, 0x11, 0x17, 0xF0, 0xC0, 0x50, 0x4C, 0x42, 0x00, 0x04, 0x00,
|
||||
0x80, 0x10, 0x02, 0x00, 0x40, 0x08, 0x3F, 0xF8, 0x20, 0x04, 0x00, 0x80,
|
||||
0x10, 0x02, 0x00, 0x3B, 0x9C, 0xC4, 0x60, 0xFF, 0xE0, 0x6F, 0x70, 0x00,
|
||||
0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x06,
|
||||
0x02, 0x01, 0x01, 0x00, 0x80, 0x80, 0x40, 0x00, 0x1C, 0x33, 0x10, 0x50,
|
||||
0x28, 0x14, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x2C, 0x12, 0x18,
|
||||
0xF8, 0x18, 0x1C, 0x1A, 0x19, 0x08, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04,
|
||||
0x02, 0x01, 0x00, 0x80, 0x43, 0xFE, 0x1E, 0x11, 0x90, 0x38, 0x10, 0x08,
|
||||
0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x04, 0x07, 0xFE, 0x1E,
|
||||
0x08, 0x64, 0x08, 0x02, 0x00, 0x80, 0x20, 0x70, 0x1C, 0x00, 0x80, 0x10,
|
||||
0x04, 0x01, 0x00, 0x70, 0x23, 0xF0, 0x06, 0x0A, 0x0A, 0x12, 0x12, 0x22,
|
||||
0x62, 0x42, 0x82, 0x82, 0xFF, 0x02, 0x02, 0x02, 0x0F, 0x3F, 0x08, 0x22,
|
||||
0x00, 0x80, 0x20, 0x08, 0x03, 0xF0, 0x02, 0x00, 0x40, 0x10, 0x04, 0x01,
|
||||
0x00, 0xD0, 0x23, 0xF0, 0x07, 0x8E, 0x0C, 0x0C, 0x04, 0x02, 0x02, 0x31,
|
||||
0x66, 0xA0, 0xE0, 0x60, 0x28, 0x14, 0x09, 0x08, 0x7C, 0xFF, 0x81, 0x81,
|
||||
0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08,
|
||||
0x1C, 0x31, 0x20, 0x50, 0x28, 0x14, 0x09, 0x08, 0x78, 0x43, 0x40, 0xA0,
|
||||
0x30, 0x18, 0x16, 0x09, 0xF8, 0x1C, 0x31, 0x10, 0x50, 0x18, 0x0C, 0x05,
|
||||
0x06, 0x87, 0x3E, 0x80, 0x40, 0x20, 0x20, 0x30, 0x33, 0xF0, 0x7F, 0x70,
|
||||
0x00, 0x06, 0xF7, 0x39, 0xCE, 0x00, 0x00, 0x07, 0x73, 0x98, 0xCC, 0x00,
|
||||
0x00, 0xC0, 0x60, 0x18, 0x0C, 0x06, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03,
|
||||
0x00, 0x30, 0x01, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x06,
|
||||
0x00, 0x30, 0x01, 0x80, 0x18, 0x01, 0x80, 0xC0, 0x30, 0x18, 0x0C, 0x02,
|
||||
0x00, 0x00, 0x3C, 0x61, 0xA0, 0x40, 0x10, 0x08, 0x08, 0x08, 0x18, 0x08,
|
||||
0x04, 0x00, 0x00, 0x01, 0xC0, 0xE0, 0x3C, 0x62, 0xC1, 0x81, 0x81, 0x87,
|
||||
0x99, 0x91, 0x91, 0x91, 0x8F, 0x81, 0x80, 0x80, 0x40, 0x3F, 0x1F, 0x00,
|
||||
0x0C, 0x00, 0x48, 0x01, 0x20, 0x04, 0x80, 0x21, 0x00, 0x84, 0x02, 0x08,
|
||||
0x1F, 0xE0, 0x40, 0x81, 0x01, 0x08, 0x04, 0x20, 0x13, 0xE1, 0xF0, 0x7E,
|
||||
0x02, 0x1C, 0x20, 0x62, 0x02, 0x20, 0x22, 0x06, 0x3F, 0x82, 0x1C, 0x20,
|
||||
0x22, 0x01, 0x20, 0x12, 0x01, 0x20, 0x2F, 0xFC, 0x1E, 0x06, 0x39, 0x01,
|
||||
0x40, 0x28, 0x01, 0x00, 0x20, 0x04, 0x00, 0x80, 0x10, 0x02, 0x00, 0x20,
|
||||
0x16, 0x04, 0x3F, 0x00, 0x7C, 0x08, 0x71, 0x01, 0x20, 0x14, 0x02, 0x80,
|
||||
0x50, 0x0A, 0x01, 0x40, 0x28, 0x05, 0x00, 0xA0, 0x24, 0x0D, 0xFE, 0x00,
|
||||
0x7F, 0xE4, 0x04, 0x80, 0x90, 0x12, 0x00, 0x44, 0x0F, 0x81, 0x10, 0x22,
|
||||
0x04, 0x00, 0x80, 0x90, 0x12, 0x03, 0xFF, 0xC0, 0x7F, 0xE4, 0x04, 0x80,
|
||||
0x90, 0x12, 0x00, 0x44, 0x0F, 0x81, 0x10, 0x22, 0x04, 0x00, 0x80, 0x10,
|
||||
0x02, 0x01, 0xFC, 0x00, 0x0F, 0x06, 0x39, 0x01, 0x40, 0x08, 0x01, 0x00,
|
||||
0x20, 0x04, 0x00, 0x83, 0xF0, 0x0A, 0x01, 0x60, 0x26, 0x04, 0x7F, 0x80,
|
||||
0x70, 0xE2, 0x04, 0x20, 0x42, 0x04, 0x20, 0x42, 0x04, 0x3F, 0xC2, 0x04,
|
||||
0x20, 0x42, 0x04, 0x20, 0x42, 0x04, 0x20, 0x4F, 0x8F, 0xFF, 0x04, 0x02,
|
||||
0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x87,
|
||||
0xFC, 0x0F, 0xE0, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80,
|
||||
0x08, 0x80, 0x88, 0x08, 0x80, 0x88, 0x08, 0xC1, 0x03, 0xE0, 0x78, 0xF1,
|
||||
0x01, 0x08, 0x10, 0x43, 0x02, 0x30, 0x13, 0x00, 0xB0, 0x06, 0x60, 0x21,
|
||||
0x81, 0x04, 0x08, 0x10, 0x40, 0x82, 0x06, 0x7C, 0x1C, 0xFC, 0x04, 0x00,
|
||||
0x80, 0x10, 0x02, 0x00, 0x40, 0x08, 0x01, 0x00, 0x20, 0x04, 0x04, 0x80,
|
||||
0x90, 0x12, 0x03, 0xFF, 0xC0, 0x70, 0x18, 0xC0, 0x73, 0x02, 0x8A, 0x0A,
|
||||
0x28, 0x48, 0x91, 0x22, 0x48, 0x88, 0xA2, 0x23, 0x08, 0x84, 0x22, 0x00,
|
||||
0x88, 0x02, 0x20, 0x0B, 0xE1, 0xF0, 0xE0, 0xF6, 0x02, 0x50, 0x25, 0x82,
|
||||
0x48, 0x24, 0x42, 0x44, 0x24, 0x22, 0x43, 0x24, 0x12, 0x40, 0xA4, 0x0A,
|
||||
0x40, 0x6F, 0x86, 0x0F, 0x01, 0x8C, 0x20, 0x64, 0x02, 0x40, 0x18, 0x01,
|
||||
0x80, 0x18, 0x01, 0x80, 0x1C, 0x01, 0x40, 0x36, 0x02, 0x30, 0x41, 0xF8,
|
||||
0x7E, 0x04, 0x38, 0x81, 0x10, 0x12, 0x02, 0x40, 0x48, 0x11, 0xFC, 0x20,
|
||||
0x04, 0x00, 0x80, 0x10, 0x02, 0x01, 0xFC, 0x00, 0x0F, 0x01, 0x8C, 0x20,
|
||||
0x64, 0x02, 0x40, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x40,
|
||||
0x36, 0x02, 0x30, 0x41, 0xF8, 0x04, 0x01, 0xF9, 0x10, 0xE0, 0x7E, 0x01,
|
||||
0x0E, 0x08, 0x10, 0x40, 0x42, 0x02, 0x10, 0x30, 0x83, 0x07, 0xE0, 0x21,
|
||||
0x81, 0x06, 0x08, 0x10, 0x40, 0x42, 0x02, 0x7C, 0x0C, 0x1E, 0x0C, 0x74,
|
||||
0x0D, 0x01, 0x40, 0x18, 0x03, 0x80, 0x1E, 0x00, 0xC0, 0x18, 0x06, 0x01,
|
||||
0xC0, 0xEF, 0xC0, 0xFF, 0xF0, 0x86, 0x10, 0xC2, 0x10, 0x40, 0x08, 0x01,
|
||||
0x00, 0x20, 0x04, 0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0x7F, 0x00, 0xF0,
|
||||
0xF4, 0x02, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x40,
|
||||
0x24, 0x02, 0x60, 0x22, 0x06, 0x30, 0x41, 0xF8, 0x78, 0x3C, 0x80, 0x22,
|
||||
0x01, 0x08, 0x04, 0x10, 0x10, 0x40, 0x80, 0x82, 0x02, 0x10, 0x08, 0x40,
|
||||
0x11, 0x00, 0x48, 0x01, 0xA0, 0x03, 0x00, 0x0C, 0x00, 0x78, 0x39, 0x00,
|
||||
0x22, 0x00, 0x88, 0xC2, 0x23, 0x08, 0x8A, 0x42, 0x29, 0x09, 0x24, 0x24,
|
||||
0x90, 0x91, 0x41, 0x85, 0x06, 0x14, 0x18, 0x50, 0x60, 0xC0, 0x70, 0x76,
|
||||
0x02, 0x20, 0x41, 0x0C, 0x08, 0x80, 0xD0, 0x06, 0x00, 0x60, 0x0D, 0x00,
|
||||
0x98, 0x10, 0x82, 0x04, 0x60, 0x2F, 0x0F, 0x70, 0x76, 0x02, 0x20, 0x41,
|
||||
0x0C, 0x18, 0x80, 0x90, 0x05, 0x00, 0x60, 0x02, 0x00, 0x20, 0x02, 0x00,
|
||||
0x20, 0x02, 0x01, 0xFC, 0x7F, 0x90, 0x24, 0x09, 0x04, 0x42, 0x00, 0x80,
|
||||
0x40, 0x20, 0x18, 0x04, 0x12, 0x05, 0x01, 0x40, 0x7F, 0xF0, 0xE8, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8F, 0x80, 0x40, 0x10, 0x08, 0x02,
|
||||
0x01, 0x00, 0x40, 0x20, 0x18, 0x04, 0x02, 0x00, 0x80, 0x40, 0x10, 0x08,
|
||||
0x02, 0x01, 0x00, 0x40, 0xF1, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x1F, 0x00, 0x0C, 0x0D, 0x04, 0x44, 0x34, 0x08, 0x00, 0xFF, 0xFC, 0x84,
|
||||
0x30, 0x7F, 0x00, 0x10, 0x02, 0x00, 0x43, 0xF9, 0x81, 0x20, 0x24, 0x04,
|
||||
0x81, 0x8F, 0xDC, 0xC0, 0x04, 0x00, 0x40, 0x04, 0x00, 0x40, 0x04, 0xFC,
|
||||
0x50, 0x66, 0x02, 0x60, 0x14, 0x01, 0x40, 0x16, 0x01, 0x60, 0x25, 0x06,
|
||||
0xCF, 0xC0, 0x3F, 0xCC, 0x19, 0x01, 0x40, 0x08, 0x01, 0x00, 0x20, 0x02,
|
||||
0x01, 0x60, 0x47, 0xF0, 0x00, 0xC0, 0x04, 0x00, 0x40, 0x04, 0x00, 0x43,
|
||||
0xE4, 0x41, 0xC8, 0x0C, 0x80, 0x48, 0x04, 0x80, 0x48, 0x04, 0x80, 0xC4,
|
||||
0x1C, 0x3E, 0x70, 0x3F, 0x10, 0x28, 0x06, 0x01, 0xFF, 0xE0, 0x08, 0x02,
|
||||
0x00, 0x40, 0x4F, 0xE0, 0x00, 0x07, 0xF1, 0x00, 0x40, 0x10, 0x3F, 0xE1,
|
||||
0x00, 0x40, 0x10, 0x04, 0x01, 0x00, 0x40, 0x10, 0x04, 0x0F, 0xF0, 0x3E,
|
||||
0x68, 0x2A, 0x03, 0x40, 0x68, 0x05, 0x01, 0xA0, 0x36, 0x0E, 0x63, 0x43,
|
||||
0x88, 0x01, 0x00, 0x40, 0x08, 0x3E, 0x00, 0x60, 0x02, 0x00, 0x20, 0x02,
|
||||
0x00, 0x20, 0x02, 0xF8, 0x30, 0x42, 0x04, 0x20, 0x42, 0x04, 0x20, 0x42,
|
||||
0x04, 0x20, 0x42, 0x04, 0xF8, 0xF0, 0x0C, 0x03, 0x00, 0xC0, 0x00, 0x00,
|
||||
0x1F, 0x00, 0x40, 0x10, 0x04, 0x01, 0x00, 0x40, 0x10, 0x04, 0x01, 0x0F,
|
||||
0xFC, 0x04, 0x08, 0x10, 0x00, 0x1F, 0xC0, 0x81, 0x02, 0x04, 0x08, 0x10,
|
||||
0x20, 0x40, 0x81, 0x02, 0x0F, 0xF0, 0xC0, 0x08, 0x01, 0x00, 0x20, 0x04,
|
||||
0x00, 0x8F, 0x90, 0x82, 0x20, 0x48, 0x0F, 0x01, 0xB0, 0x23, 0x04, 0x30,
|
||||
0x83, 0x30, 0x78, 0x3C, 0x01, 0x00, 0x40, 0x10, 0x04, 0x01, 0x00, 0x40,
|
||||
0x10, 0x04, 0x01, 0x00, 0x40, 0x10, 0x04, 0x01, 0x0F, 0xFC, 0xFE, 0xF0,
|
||||
0xC6, 0x22, 0x10, 0x88, 0x42, 0x21, 0x08, 0x84, 0x22, 0x10, 0x88, 0x42,
|
||||
0x21, 0x0B, 0xC6, 0x30, 0x6F, 0x83, 0x04, 0x20, 0x42, 0x02, 0x20, 0x22,
|
||||
0x02, 0x20, 0x22, 0x02, 0x20, 0x2F, 0x8F, 0x3F, 0x0C, 0x13, 0x01, 0x40,
|
||||
0x28, 0x03, 0x00, 0x60, 0x14, 0x02, 0x40, 0x87, 0xE0, 0xCF, 0xC5, 0x06,
|
||||
0x60, 0x26, 0x01, 0x40, 0x16, 0x01, 0x60, 0x17, 0x02, 0x58, 0xC4, 0x70,
|
||||
0x40, 0x04, 0x00, 0x40, 0x0F, 0x80, 0x3F, 0x74, 0x1C, 0x80, 0xC8, 0x04,
|
||||
0x80, 0x48, 0x04, 0x80, 0x4C, 0x0C, 0x63, 0x41, 0xC4, 0x00, 0x40, 0x04,
|
||||
0x00, 0x40, 0x1E, 0x73, 0xC2, 0xC4, 0x60, 0x08, 0x01, 0x00, 0x20, 0x04,
|
||||
0x00, 0x80, 0x10, 0x1F, 0xF0, 0x3F, 0x90, 0x24, 0x09, 0x80, 0x1E, 0x00,
|
||||
0x60, 0x06, 0x01, 0xC0, 0xEF, 0xE0, 0x00, 0x04, 0x00, 0x80, 0x10, 0x0F,
|
||||
0xF8, 0x40, 0x08, 0x01, 0x00, 0x20, 0x04, 0x00, 0x80, 0x10, 0x01, 0x02,
|
||||
0x3F, 0x80, 0xE1, 0xE2, 0x02, 0x20, 0x22, 0x02, 0x20, 0x22, 0x02, 0x20,
|
||||
0x22, 0x06, 0x20, 0xA1, 0xF3, 0xF8, 0xF9, 0x01, 0x08, 0x10, 0x60, 0x81,
|
||||
0x0C, 0x08, 0x40, 0x22, 0x01, 0x20, 0x05, 0x00, 0x30, 0x00, 0xF0, 0x7A,
|
||||
0x01, 0x10, 0x08, 0x8C, 0x42, 0x62, 0x12, 0x90, 0xA5, 0x05, 0x18, 0x28,
|
||||
0xC0, 0x86, 0x00, 0x78, 0xF3, 0x04, 0x18, 0x80, 0xD0, 0x06, 0x00, 0x70,
|
||||
0x09, 0x81, 0x0C, 0x20, 0x6F, 0x8F, 0xF0, 0xF2, 0x02, 0x20, 0x41, 0x04,
|
||||
0x10, 0x80, 0x88, 0x09, 0x00, 0x50, 0x05, 0x00, 0x20, 0x02, 0x00, 0x40,
|
||||
0x04, 0x07, 0xE0, 0xFF, 0x41, 0xA0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81,
|
||||
0xC0, 0xFF, 0xC0, 0x00, 0x61, 0x04, 0x10, 0x41, 0x04, 0x63, 0x02, 0x04,
|
||||
0x10, 0x41, 0x04, 0x10, 0x30, 0x7F, 0xFF, 0xC0, 0x03, 0x02, 0x08, 0x20,
|
||||
0x82, 0x08, 0x30, 0x72, 0x08, 0x20, 0x82, 0x08, 0x43, 0x00, 0x78, 0x71,
|
||||
0x30, 0x30, 0xFF, 0xFE, 0x00, 0x18, 0x00, 0x61, 0xE1, 0x98, 0x66, 0x40,
|
||||
0x98, 0x01, 0x60, 0x05, 0x80, 0x26, 0x01, 0x18, 0x18, 0x60, 0x41, 0x81,
|
||||
0x06, 0x00, 0x18, 0x00, 0x60, 0xE1, 0x83, 0x86, 0x00, 0x1F, 0xFF, 0xC0,
|
||||
0x00, 0xFC, 0x00, 0x92, 0x4B, 0x6D, 0xB0, 0x08, 0x08, 0x08, 0x3E, 0x63,
|
||||
0x81, 0x80, 0x80, 0x80, 0x80, 0x41, 0x3E, 0x08, 0x08, 0x08, 0x0E, 0x0C,
|
||||
0xC2, 0x00, 0x80, 0x20, 0x08, 0x0F, 0xC0, 0x40, 0x10, 0x04, 0x01, 0x00,
|
||||
0x80, 0x20, 0x7F, 0xF0, 0x07, 0x81, 0x87, 0x30, 0x32, 0x02, 0x40, 0x04,
|
||||
0x00, 0xFF, 0x84, 0x00, 0xFF, 0x84, 0x00, 0x60, 0x02, 0x00, 0x10, 0x30,
|
||||
0xFC, 0x70, 0x76, 0x02, 0x20, 0x41, 0x0C, 0x18, 0x80, 0x90, 0x07, 0x03,
|
||||
0xFC, 0x02, 0x00, 0x20, 0x3F, 0xC0, 0x20, 0x02, 0x01, 0xF8, 0x20, 0x84,
|
||||
0xC0, 0xE0, 0x10, 0x1E, 0x0C, 0x74, 0x0D, 0x01, 0x40, 0x18, 0x03, 0x80,
|
||||
0x1E, 0x00, 0xC0, 0x18, 0x06, 0x01, 0xC0, 0xEF, 0xC0, 0x1F, 0xC4, 0x08,
|
||||
0x81, 0x10, 0x0D, 0x81, 0x18, 0x20, 0xC3, 0x06, 0x30, 0x61, 0x84, 0x0B,
|
||||
0x80, 0xC0, 0x08, 0x83, 0x1F, 0xC0, 0x31, 0x86, 0x80, 0xC0, 0x00, 0x00,
|
||||
0x0F, 0xE4, 0x09, 0x02, 0x60, 0x07, 0x80, 0x18, 0x01, 0x80, 0x70, 0x3B,
|
||||
0xF8, 0x07, 0x80, 0x61, 0x82, 0x01, 0x10, 0xD2, 0x4C, 0xC6, 0x21, 0x18,
|
||||
0x80, 0x62, 0x01, 0x88, 0x06, 0x21, 0x14, 0x7C, 0xD8, 0x02, 0x30, 0x30,
|
||||
0x3F, 0x80, 0x30, 0x90, 0x13, 0xE8, 0x50, 0xBF, 0x80, 0x08, 0x23, 0x08,
|
||||
0xC2, 0x30, 0xCC, 0x31, 0x86, 0x18, 0x61, 0x84, 0x18, 0x41, 0x04, 0xFF,
|
||||
0xE0, 0x04, 0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0x08, 0xFF, 0xE0, 0x07,
|
||||
0x80, 0x61, 0x82, 0x01, 0x13, 0xC2, 0x44, 0xC6, 0x11, 0x18, 0x44, 0x61,
|
||||
0xE1, 0x84, 0x86, 0x11, 0x14, 0xE6, 0xD8, 0x02, 0x30, 0x30, 0x3F, 0x80,
|
||||
0xFE, 0x79, 0x0A, 0x0C, 0x18, 0x49, 0x8C, 0x00, 0x04, 0x00, 0x80, 0x10,
|
||||
0x02, 0x00, 0x41, 0xFF, 0xC1, 0x00, 0x20, 0x04, 0x00, 0x80, 0x00, 0x00,
|
||||
0x0F, 0xFE, 0x31, 0x28, 0x41, 0x08, 0x42, 0x30, 0xFC, 0x31, 0x20, 0x42,
|
||||
0x18, 0x10, 0x61, 0x78, 0x21, 0x84, 0xC0, 0xC0, 0x00, 0x7F, 0x90, 0x24,
|
||||
0x09, 0x04, 0x42, 0x00, 0x80, 0x40, 0x20, 0x18, 0x04, 0x12, 0x05, 0x01,
|
||||
0x40, 0x7F, 0xF0, 0xE1, 0xE2, 0x02, 0x20, 0x22, 0x02, 0x20, 0x22, 0x02,
|
||||
0x20, 0x22, 0x06, 0x20, 0xE3, 0xF3, 0x20, 0x02, 0x00, 0x20, 0x02, 0x00,
|
||||
0x20, 0x00, 0x07, 0xCF, 0xA3, 0x14, 0x62, 0x8C, 0x51, 0x8A, 0x31, 0x43,
|
||||
0xA8, 0x1D, 0x00, 0xA0, 0x14, 0x02, 0x80, 0x50, 0x0A, 0x01, 0x41, 0xE6,
|
||||
0x74, 0x42, 0x1A, 0x06, 0x00, 0x00, 0x07, 0xFA, 0x0D, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x0E, 0x07, 0xFE, 0x27, 0x08, 0x42, 0x10, 0x84, 0xF8,
|
||||
0x39, 0x8A, 0x0C, 0x18, 0x30, 0x9E, 0x00, 0x84, 0x18, 0x41, 0x84, 0x18,
|
||||
0xC1, 0x8C, 0x31, 0x8C, 0x63, 0x08, 0xC2, 0x10, 0x80, 0x03, 0xFC, 0x74,
|
||||
0x12, 0x10, 0x50, 0x41, 0x41, 0x06, 0x04, 0x88, 0x1E, 0x20, 0x48, 0x81,
|
||||
0x23, 0x04, 0x04, 0x10, 0x58, 0x41, 0x31, 0x04, 0x3F, 0xF0, 0x3C, 0xF1,
|
||||
0x0A, 0x24, 0x30, 0xE0, 0x41, 0x81, 0xFE, 0x04, 0x08, 0x10, 0x10, 0xC0,
|
||||
0x42, 0x84, 0xF1, 0xE0, 0x38, 0xC1, 0x8C, 0x00, 0x07, 0x07, 0x60, 0x22,
|
||||
0x04, 0x10, 0xC1, 0x88, 0x09, 0x00, 0x50, 0x06, 0x00, 0x20, 0x02, 0x00,
|
||||
0x20, 0x02, 0x00, 0x20, 0x1F, 0xC0, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x08,
|
||||
0x18, 0x60, 0xC0, 0x80, 0x80, 0x81, 0xC1, 0x7E, 0x08, 0x00, 0x30, 0x00,
|
||||
0x20, 0x00, 0x40, 0x00, 0x00, 0x7C, 0x00, 0x30, 0x01, 0x20, 0x04, 0x80,
|
||||
0x12, 0x00, 0x84, 0x02, 0x10, 0x08, 0x20, 0x7F, 0x81, 0x02, 0x04, 0x04,
|
||||
0x20, 0x10, 0x80, 0x4F, 0x87, 0xC0, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00,
|
||||
0x80, 0x00, 0x00, 0x7C, 0x00, 0x30, 0x01, 0x20, 0x04, 0x80, 0x12, 0x00,
|
||||
0x84, 0x02, 0x10, 0x08, 0x20, 0x7F, 0x81, 0x02, 0x04, 0x04, 0x20, 0x10,
|
||||
0x80, 0x4F, 0x87, 0xC0, 0x03, 0x00, 0x1A, 0x00, 0x84, 0x00, 0x00, 0x1F,
|
||||
0x00, 0x0C, 0x00, 0x48, 0x01, 0x20, 0x04, 0x80, 0x21, 0x00, 0x84, 0x02,
|
||||
0x08, 0x1F, 0xE0, 0x40, 0x81, 0x01, 0x08, 0x04, 0x20, 0x13, 0xE1, 0xF0,
|
||||
0x06, 0x20, 0x27, 0x00, 0x00, 0x07, 0xC0, 0x03, 0x00, 0x12, 0x00, 0x48,
|
||||
0x01, 0x20, 0x08, 0x40, 0x21, 0x00, 0x82, 0x07, 0xF8, 0x10, 0x20, 0x40,
|
||||
0x42, 0x01, 0x08, 0x04, 0xF8, 0x7C, 0x08, 0x60, 0x71, 0x80, 0x00, 0x07,
|
||||
0xC0, 0x03, 0x00, 0x12, 0x00, 0x48, 0x01, 0x20, 0x08, 0x40, 0x21, 0x00,
|
||||
0x82, 0x07, 0xF8, 0x10, 0x20, 0x40, 0x42, 0x01, 0x08, 0x04, 0xF8, 0x7C,
|
||||
0x03, 0x80, 0x12, 0x00, 0x48, 0x01, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x30,
|
||||
0x01, 0x20, 0x04, 0x80, 0x12, 0x00, 0x84, 0x02, 0x10, 0x08, 0x20, 0x7F,
|
||||
0x81, 0x02, 0x04, 0x04, 0x20, 0x10, 0x80, 0x4F, 0x87, 0xC0, 0x1F, 0xFC,
|
||||
0x14, 0x10, 0x50, 0x42, 0x41, 0x09, 0x04, 0x24, 0x80, 0x9E, 0x04, 0x48,
|
||||
0x1F, 0x20, 0x44, 0x02, 0x10, 0x48, 0x41, 0x21, 0x07, 0xDF, 0xF0, 0x1E,
|
||||
0x06, 0x39, 0x01, 0x40, 0x28, 0x01, 0x00, 0x20, 0x04, 0x00, 0x80, 0x10,
|
||||
0x02, 0x00, 0x20, 0x16, 0x04, 0x3F, 0x01, 0x00, 0x30, 0x02, 0x03, 0xC0,
|
||||
0x10, 0x01, 0x00, 0x10, 0x01, 0x00, 0x00, 0xFF, 0xC8, 0x09, 0x01, 0x20,
|
||||
0x24, 0x00, 0x88, 0x1F, 0x02, 0x20, 0x44, 0x08, 0x01, 0x01, 0x20, 0x24,
|
||||
0x07, 0xFF, 0x80, 0x00, 0x00, 0x60, 0x18, 0x06, 0x00, 0x00, 0xFF, 0xC8,
|
||||
0x09, 0x01, 0x20, 0x24, 0x00, 0x88, 0x1F, 0x02, 0x20, 0x44, 0x08, 0x01,
|
||||
0x01, 0x20, 0x24, 0x07, 0xFF, 0x80, 0x06, 0x01, 0xE0, 0x42, 0x00, 0x07,
|
||||
0xFE, 0x40, 0x48, 0x09, 0x01, 0x20, 0x04, 0x40, 0xF8, 0x11, 0x02, 0x20,
|
||||
0x40, 0x08, 0x09, 0x01, 0x20, 0x3F, 0xFC, 0x30, 0xC6, 0x38, 0x00, 0x3F,
|
||||
0xF2, 0x02, 0x40, 0x48, 0x09, 0x00, 0x22, 0x07, 0xC0, 0x88, 0x11, 0x02,
|
||||
0x00, 0x40, 0x48, 0x09, 0x01, 0xFF, 0xE0, 0x00, 0x18, 0x06, 0x01, 0x80,
|
||||
0x07, 0xF8, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20,
|
||||
0x10, 0x08, 0x04, 0x3F, 0xE0, 0x00, 0x01, 0x03, 0x03, 0x00, 0x07, 0xF8,
|
||||
0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08,
|
||||
0x04, 0x3F, 0xE0, 0x18, 0x1A, 0x10, 0xC0, 0x0F, 0xF0, 0x40, 0x20, 0x10,
|
||||
0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x7F, 0xC0,
|
||||
0x43, 0x71, 0x80, 0x1F, 0xE0, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02,
|
||||
0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0xFF, 0x80, 0x3E, 0x02, 0x1C, 0x20,
|
||||
0x22, 0x01, 0x20, 0x12, 0x01, 0x7E, 0x1A, 0x11, 0x20, 0x12, 0x01, 0x20,
|
||||
0x12, 0x02, 0x20, 0x67, 0xF8, 0x1C, 0x43, 0x38, 0x00, 0x0E, 0x0F, 0x60,
|
||||
0x25, 0x02, 0x58, 0x24, 0x82, 0x44, 0x24, 0x42, 0x42, 0x24, 0x32, 0x41,
|
||||
0x24, 0x0A, 0x40, 0xA4, 0x06, 0xF8, 0x60, 0x00, 0x00, 0x80, 0x06, 0x00,
|
||||
0x20, 0x00, 0x00, 0xF0, 0x18, 0xC2, 0x06, 0x40, 0x24, 0x01, 0x80, 0x18,
|
||||
0x01, 0x80, 0x18, 0x01, 0xC0, 0x14, 0x03, 0x60, 0x23, 0x04, 0x1F, 0x80,
|
||||
0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0x00, 0x00, 0xF0, 0x18, 0xC2, 0x06,
|
||||
0x40, 0x24, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0xC0, 0x14, 0x03,
|
||||
0x60, 0x23, 0x04, 0x1F, 0x80, 0x06, 0x00, 0xD0, 0x10, 0x80, 0x00, 0x0F,
|
||||
0x01, 0x8C, 0x20, 0x64, 0x02, 0x40, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80,
|
||||
0x1C, 0x01, 0x40, 0x36, 0x02, 0x30, 0x41, 0xF8, 0x0C, 0x41, 0x38, 0x00,
|
||||
0x00, 0xF0, 0x18, 0xC2, 0x06, 0x40, 0x24, 0x01, 0x80, 0x18, 0x01, 0x80,
|
||||
0x18, 0x01, 0xC0, 0x14, 0x03, 0x60, 0x23, 0x04, 0x1F, 0x80, 0x10, 0xC3,
|
||||
0x8C, 0x00, 0x00, 0xF0, 0x18, 0xC2, 0x06, 0x40, 0x24, 0x01, 0x80, 0x18,
|
||||
0x01, 0x80, 0x18, 0x01, 0xC0, 0x14, 0x03, 0x60, 0x23, 0x04, 0x1F, 0x80,
|
||||
0x81, 0xA1, 0x89, 0x83, 0x81, 0x81, 0xA1, 0x89, 0x82, 0x80, 0x00, 0x00,
|
||||
0x00, 0xF1, 0x18, 0xE2, 0x06, 0x40, 0x64, 0x09, 0x81, 0x18, 0x21, 0x86,
|
||||
0x18, 0x41, 0xC8, 0x15, 0x03, 0x60, 0x27, 0x04, 0x5F, 0x88, 0x00, 0x00,
|
||||
0x00, 0x80, 0x06, 0x00, 0x20, 0x00, 0x0F, 0x0F, 0x40, 0x24, 0x02, 0x40,
|
||||
0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x26, 0x02, 0x20,
|
||||
0x63, 0x04, 0x1F, 0x80, 0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0x00, 0x0F,
|
||||
0x0F, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x24,
|
||||
0x02, 0x40, 0x26, 0x02, 0x20, 0x63, 0x04, 0x1F, 0x80, 0x06, 0x00, 0xD0,
|
||||
0x10, 0x80, 0x00, 0xF0, 0xF4, 0x02, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02,
|
||||
0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x60, 0x22, 0x06, 0x30, 0x41, 0xF8,
|
||||
0x10, 0xC3, 0x8C, 0x00, 0x0F, 0x0F, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02,
|
||||
0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x26, 0x02, 0x20, 0x63, 0x04,
|
||||
0x1F, 0x80, 0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0x00, 0x07, 0x07, 0x60,
|
||||
0x22, 0x04, 0x10, 0xC1, 0x88, 0x09, 0x00, 0x50, 0x06, 0x00, 0x20, 0x02,
|
||||
0x00, 0x20, 0x02, 0x00, 0x20, 0x1F, 0xC0, 0x7E, 0x04, 0x00, 0x80, 0x1F,
|
||||
0x02, 0x1C, 0x40, 0x88, 0x09, 0x01, 0x20, 0x24, 0x08, 0xFE, 0x10, 0x02,
|
||||
0x01, 0xFC, 0x00, 0x00, 0x03, 0xE0, 0x84, 0x30, 0x44, 0x08, 0x82, 0x11,
|
||||
0xC2, 0x0C, 0x40, 0x48, 0x05, 0x00, 0xA0, 0x14, 0x42, 0x88, 0xF8, 0xF0,
|
||||
0x30, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x20, 0x04, 0x00,
|
||||
0x87, 0xF3, 0x02, 0x40, 0x48, 0x09, 0x03, 0x1F, 0xB8, 0x02, 0x00, 0x80,
|
||||
0x20, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x20, 0x04, 0x00, 0x87, 0xF3, 0x02,
|
||||
0x40, 0x48, 0x09, 0x03, 0x1F, 0xB8, 0x0C, 0x03, 0xC0, 0x8C, 0x00, 0x00,
|
||||
0x00, 0xFE, 0x00, 0x20, 0x04, 0x00, 0x87, 0xF3, 0x02, 0x40, 0x48, 0x09,
|
||||
0x03, 0x1F, 0xB8, 0x18, 0x84, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x01, 0x00,
|
||||
0x20, 0x04, 0x3F, 0x98, 0x12, 0x02, 0x40, 0x48, 0x18, 0xFD, 0xC0, 0x63,
|
||||
0x8C, 0x70, 0x00, 0x00, 0x07, 0xF0, 0x01, 0x00, 0x20, 0x04, 0x3F, 0x98,
|
||||
0x12, 0x02, 0x40, 0x48, 0x18, 0xFD, 0xC0, 0x0E, 0x02, 0x40, 0x48, 0x07,
|
||||
0x00, 0x00, 0x00, 0x1F, 0xC0, 0x04, 0x00, 0x80, 0x10, 0xFE, 0x60, 0x48,
|
||||
0x09, 0x01, 0x20, 0x63, 0xF7, 0x3E, 0xF0, 0x0A, 0x20, 0x10, 0x80, 0x41,
|
||||
0x3F, 0xFD, 0x04, 0x08, 0x10, 0x20, 0x40, 0x43, 0x85, 0xF7, 0xE0, 0x3F,
|
||||
0xCC, 0x19, 0x01, 0x40, 0x08, 0x01, 0x00, 0x20, 0x02, 0x01, 0x60, 0x47,
|
||||
0xF0, 0x10, 0x03, 0x00, 0x20, 0x3C, 0x00, 0x10, 0x02, 0x00, 0x40, 0x00,
|
||||
0x00, 0x0F, 0xC4, 0x0A, 0x01, 0x80, 0x7F, 0xF8, 0x02, 0x00, 0x80, 0x10,
|
||||
0x13, 0xF8, 0x03, 0x01, 0x00, 0x80, 0x00, 0x00, 0x0F, 0xC4, 0x0A, 0x01,
|
||||
0x80, 0x7F, 0xF8, 0x02, 0x00, 0x80, 0x10, 0x13, 0xF8, 0x04, 0x06, 0x83,
|
||||
0x10, 0x82, 0x00, 0x0F, 0xC4, 0x0A, 0x01, 0x80, 0x7F, 0xF8, 0x02, 0x00,
|
||||
0x80, 0x10, 0x13, 0xF8, 0x31, 0x8C, 0x60, 0x00, 0x00, 0x3F, 0x10, 0x28,
|
||||
0x06, 0x01, 0xFF, 0xE0, 0x08, 0x02, 0x00, 0x40, 0x4F, 0xE0, 0x30, 0x02,
|
||||
0x00, 0x40, 0x00, 0x00, 0x1F, 0x00, 0x40, 0x10, 0x04, 0x01, 0x00, 0x40,
|
||||
0x10, 0x04, 0x01, 0x0F, 0xFC, 0x02, 0x01, 0x00, 0x80, 0x00, 0x00, 0x1F,
|
||||
0x00, 0x40, 0x10, 0x04, 0x01, 0x00, 0x40, 0x10, 0x04, 0x01, 0x0F, 0xFC,
|
||||
0x08, 0x05, 0x82, 0x30, 0x00, 0x00, 0x1F, 0x00, 0x40, 0x10, 0x04, 0x01,
|
||||
0x00, 0x40, 0x10, 0x04, 0x01, 0x0F, 0xFC, 0x63, 0x98, 0xE0, 0x00, 0x00,
|
||||
0x7C, 0x01, 0x00, 0x40, 0x10, 0x04, 0x01, 0x00, 0x40, 0x10, 0x04, 0x3F,
|
||||
0xF0, 0x30, 0x81, 0xE0, 0x78, 0x00, 0x80, 0x08, 0x7F, 0x98, 0x36, 0x02,
|
||||
0x80, 0x70, 0x06, 0x00, 0xC0, 0x2C, 0x04, 0xC1, 0x0F, 0xC0, 0x1C, 0x43,
|
||||
0x38, 0x00, 0x00, 0x00, 0x6F, 0x83, 0x04, 0x20, 0x42, 0x02, 0x20, 0x22,
|
||||
0x02, 0x20, 0x22, 0x02, 0x20, 0x2F, 0x8F, 0x10, 0x01, 0x00, 0x10, 0x00,
|
||||
0x00, 0x00, 0x7E, 0x18, 0x26, 0x02, 0x80, 0x50, 0x06, 0x00, 0xC0, 0x28,
|
||||
0x04, 0x81, 0x0F, 0xC0, 0x02, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x7E,
|
||||
0x18, 0x26, 0x02, 0x80, 0x50, 0x06, 0x00, 0xC0, 0x28, 0x04, 0x81, 0x0F,
|
||||
0xC0, 0x0C, 0x03, 0x40, 0xC4, 0x00, 0x00, 0x00, 0x7E, 0x18, 0x26, 0x02,
|
||||
0x80, 0x50, 0x06, 0x00, 0xC0, 0x28, 0x04, 0x81, 0x0F, 0xC0, 0x18, 0x84,
|
||||
0xE0, 0x00, 0x00, 0x03, 0xF0, 0xC1, 0x30, 0x14, 0x02, 0x80, 0x30, 0x06,
|
||||
0x01, 0x40, 0x24, 0x08, 0x7E, 0x00, 0x71, 0x8E, 0x30, 0x00, 0x00, 0x03,
|
||||
0xF0, 0xC1, 0x30, 0x14, 0x02, 0x80, 0x30, 0x06, 0x01, 0x40, 0x24, 0x08,
|
||||
0x7E, 0x00, 0x0C, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x11, 0xFA, 0x30, 0x46,
|
||||
0x0A, 0x41, 0x24, 0x21, 0x44, 0x14, 0x82, 0x70, 0x22, 0x04, 0x5F, 0x88,
|
||||
0x00, 0x08, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x0E, 0x1E, 0x20, 0x22,
|
||||
0x02, 0x20, 0x22, 0x02, 0x20, 0x22, 0x02, 0x20, 0x62, 0x0A, 0x1F, 0x30,
|
||||
0x01, 0x00, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x1E, 0x20, 0x22, 0x02,
|
||||
0x20, 0x22, 0x02, 0x20, 0x22, 0x02, 0x20, 0x62, 0x0A, 0x1F, 0x30, 0x06,
|
||||
0x00, 0xF0, 0x18, 0x80, 0x00, 0x00, 0x0E, 0x1E, 0x20, 0x22, 0x02, 0x20,
|
||||
0x22, 0x02, 0x20, 0x22, 0x02, 0x20, 0x62, 0x0A, 0x1F, 0x30, 0x30, 0xC3,
|
||||
0x0C, 0x00, 0x00, 0x00, 0xE1, 0xE2, 0x02, 0x20, 0x22, 0x02, 0x20, 0x22,
|
||||
0x02, 0x20, 0x22, 0x06, 0x20, 0xA1, 0xF3, 0x00, 0x80, 0x10, 0x02, 0x00,
|
||||
0x00, 0x00, 0x0F, 0x0F, 0x20, 0x22, 0x04, 0x10, 0x41, 0x08, 0x08, 0x80,
|
||||
0x90, 0x05, 0x00, 0x50, 0x02, 0x00, 0x20, 0x04, 0x00, 0x40, 0x7E, 0x00,
|
||||
0xC0, 0x04, 0x00, 0x40, 0x04, 0x00, 0x4F, 0xC5, 0x06, 0x60, 0x26, 0x01,
|
||||
0x40, 0x16, 0x01, 0x60, 0x17, 0x02, 0x58, 0xC4, 0x70, 0x40, 0x04, 0x00,
|
||||
0x40, 0x0F, 0x80, 0x38, 0xC3, 0x8C, 0x00, 0x00, 0x00, 0xF0, 0xF2, 0x02,
|
||||
0x20, 0x41, 0x04, 0x10, 0x80, 0x88, 0x09, 0x00, 0x50, 0x05, 0x00, 0x20,
|
||||
0x02, 0x00, 0x40, 0x04, 0x07, 0xE0 };
|
||||
|
||||
const GFXglyph FreeMono12pt8bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 14, 0, 0 }, // 0x20 ' ' U+0020
|
||||
{ 1, 3, 15, 14, 6, -14 }, // 0x21 '!' U+0021
|
||||
{ 7, 8, 7, 14, 3, -14 }, // 0x22 '"' U+0022
|
||||
{ 14, 10, 17, 14, 2, -15 }, // 0x23 '#' U+0023
|
||||
{ 36, 9, 18, 14, 3, -15 }, // 0x24 '$' U+0024
|
||||
{ 57, 10, 15, 14, 2, -14 }, // 0x25 '%' U+0025
|
||||
{ 76, 8, 12, 14, 3, -11 }, // 0x26 '&' U+0026
|
||||
{ 88, 3, 7, 14, 6, -14 }, // 0x27 ''' U+0027
|
||||
{ 91, 4, 18, 14, 7, -14 }, // 0x28 '(' U+0028
|
||||
{ 100, 3, 18, 14, 4, -14 }, // 0x29 ')' U+0029
|
||||
{ 107, 9, 9, 14, 3, -14 }, // 0x2a '*' U+002A
|
||||
{ 118, 11, 12, 14, 2, -12 }, // 0x2b '+' U+002B
|
||||
{ 135, 5, 6, 14, 3, -2 }, // 0x2c ',' U+002C
|
||||
{ 139, 11, 1, 14, 2, -6 }, // 0x2d '-' U+002D
|
||||
{ 141, 4, 3, 14, 5, -2 }, // 0x2e '.' U+002E
|
||||
{ 143, 9, 18, 14, 3, -15 }, // 0x2f '/' U+002F
|
||||
{ 164, 9, 15, 14, 3, -14 }, // 0x30 '0' U+0030
|
||||
{ 181, 9, 15, 14, 3, -14 }, // 0x31 '1' U+0031
|
||||
{ 198, 9, 15, 14, 2, -14 }, // 0x32 '2' U+0032
|
||||
{ 215, 10, 15, 14, 2, -14 }, // 0x33 '3' U+0033
|
||||
{ 234, 8, 15, 14, 3, -14 }, // 0x34 '4' U+0034
|
||||
{ 249, 10, 15, 14, 2, -14 }, // 0x35 '5' U+0035
|
||||
{ 268, 9, 15, 14, 3, -14 }, // 0x36 '6' U+0036
|
||||
{ 285, 8, 15, 14, 3, -14 }, // 0x37 '7' U+0037
|
||||
{ 300, 9, 15, 14, 3, -14 }, // 0x38 '8' U+0038
|
||||
{ 317, 9, 15, 14, 3, -14 }, // 0x39 '9' U+0039
|
||||
{ 334, 4, 10, 14, 5, -9 }, // 0x3a ':' U+003A
|
||||
{ 339, 5, 13, 14, 3, -9 }, // 0x3b ';' U+003B
|
||||
{ 348, 11, 11, 14, 2, -11 }, // 0x3c '<' U+003C
|
||||
{ 364, 12, 4, 14, 1, -8 }, // 0x3d '=' U+003D
|
||||
{ 370, 11, 11, 14, 2, -11 }, // 0x3e '>' U+003E
|
||||
{ 386, 9, 14, 14, 3, -13 }, // 0x3f '?' U+003F
|
||||
{ 402, 8, 16, 14, 3, -14 }, // 0x40 '@' U+0040
|
||||
{ 418, 14, 14, 14, 0, -13 }, // 0x41 'A' U+0041
|
||||
{ 443, 12, 14, 14, 1, -13 }, // 0x42 'B' U+0042
|
||||
{ 464, 11, 14, 14, 2, -13 }, // 0x43 'C' U+0043
|
||||
{ 484, 11, 14, 14, 1, -13 }, // 0x44 'D' U+0044
|
||||
{ 504, 11, 14, 14, 1, -13 }, // 0x45 'E' U+0045
|
||||
{ 524, 11, 14, 14, 1, -13 }, // 0x46 'F' U+0046
|
||||
{ 544, 11, 14, 14, 2, -13 }, // 0x47 'G' U+0047
|
||||
{ 564, 12, 14, 14, 1, -13 }, // 0x48 'H' U+0048
|
||||
{ 585, 9, 14, 14, 3, -13 }, // 0x49 'I' U+0049
|
||||
{ 601, 12, 14, 14, 2, -13 }, // 0x4a 'J' U+004A
|
||||
{ 622, 13, 14, 14, 1, -13 }, // 0x4b 'K' U+004B
|
||||
{ 645, 11, 14, 14, 2, -13 }, // 0x4c 'L' U+004C
|
||||
{ 665, 14, 14, 14, 0, -13 }, // 0x4d 'M' U+004D
|
||||
{ 690, 12, 14, 14, 1, -13 }, // 0x4e 'N' U+004E
|
||||
{ 711, 12, 14, 14, 1, -13 }, // 0x4f 'O' U+004F
|
||||
{ 732, 11, 14, 14, 1, -13 }, // 0x50 'P' U+0050
|
||||
{ 752, 12, 17, 14, 1, -13 }, // 0x51 'Q' U+0051
|
||||
{ 778, 13, 14, 14, 1, -13 }, // 0x52 'R' U+0052
|
||||
{ 801, 10, 14, 14, 2, -13 }, // 0x53 'S' U+0053
|
||||
{ 819, 11, 14, 14, 2, -13 }, // 0x54 'T' U+0054
|
||||
{ 839, 12, 14, 14, 1, -13 }, // 0x55 'U' U+0055
|
||||
{ 860, 14, 14, 14, 0, -13 }, // 0x56 'V' U+0056
|
||||
{ 885, 14, 14, 14, 0, -13 }, // 0x57 'W' U+0057
|
||||
{ 910, 12, 14, 14, 1, -13 }, // 0x58 'X' U+0058
|
||||
{ 931, 12, 14, 14, 1, -13 }, // 0x59 'Y' U+0059
|
||||
{ 952, 10, 14, 14, 2, -13 }, // 0x5a 'Z' U+005A
|
||||
{ 970, 4, 18, 14, 7, -14 }, // 0x5b '[' U+005B
|
||||
{ 979, 9, 18, 14, 3, -15 }, // 0x5c '\' U+005C
|
||||
{ 1000, 4, 18, 14, 4, -14 }, // 0x5d ']' U+005D
|
||||
{ 1009, 9, 7, 14, 3, -14 }, // 0x5e '^' U+005E
|
||||
{ 1017, 14, 1, 14, 0, 3 }, // 0x5f '_' U+005F
|
||||
{ 1019, 4, 3, 14, 4, -14 }, // 0x60 '`' U+0060
|
||||
{ 1021, 11, 10, 14, 2, -9 }, // 0x61 'a' U+0061
|
||||
{ 1035, 12, 15, 14, 1, -14 }, // 0x62 'b' U+0062
|
||||
{ 1058, 11, 10, 14, 2, -9 }, // 0x63 'c' U+0063
|
||||
{ 1072, 12, 15, 14, 2, -14 }, // 0x64 'd' U+0064
|
||||
{ 1095, 10, 10, 14, 2, -9 }, // 0x65 'e' U+0065
|
||||
{ 1108, 10, 15, 14, 3, -14 }, // 0x66 'f' U+0066
|
||||
{ 1127, 11, 14, 14, 2, -9 }, // 0x67 'g' U+0067
|
||||
{ 1147, 12, 15, 14, 1, -14 }, // 0x68 'h' U+0068
|
||||
{ 1170, 10, 15, 14, 2, -14 }, // 0x69 'i' U+0069
|
||||
{ 1189, 7, 19, 14, 4, -14 }, // 0x6a 'j' U+006A
|
||||
{ 1206, 11, 15, 14, 2, -14 }, // 0x6b 'k' U+006B
|
||||
{ 1227, 10, 15, 14, 2, -14 }, // 0x6c 'l' U+006C
|
||||
{ 1246, 14, 10, 14, 0, -9 }, // 0x6d 'm' U+006D
|
||||
{ 1264, 12, 10, 14, 1, -9 }, // 0x6e 'n' U+006E
|
||||
{ 1279, 11, 10, 14, 2, -9 }, // 0x6f 'o' U+006F
|
||||
{ 1293, 12, 14, 14, 1, -9 }, // 0x70 'p' U+0070
|
||||
{ 1314, 12, 14, 14, 2, -9 }, // 0x71 'q' U+0071
|
||||
{ 1335, 11, 10, 14, 2, -9 }, // 0x72 'r' U+0072
|
||||
{ 1349, 10, 10, 14, 2, -9 }, // 0x73 's' U+0073
|
||||
{ 1362, 11, 14, 14, 1, -13 }, // 0x74 't' U+0074
|
||||
{ 1382, 12, 10, 14, 1, -9 }, // 0x75 'u' U+0075
|
||||
{ 1397, 13, 10, 14, 1, -9 }, // 0x76 'v' U+0076
|
||||
{ 1414, 13, 10, 14, 1, -9 }, // 0x77 'w' U+0077
|
||||
{ 1431, 12, 10, 14, 1, -9 }, // 0x78 'x' U+0078
|
||||
{ 1446, 12, 14, 14, 1, -9 }, // 0x79 'y' U+0079
|
||||
{ 1467, 9, 10, 14, 3, -9 }, // 0x7a 'z' U+007A
|
||||
{ 1479, 6, 18, 14, 4, -14 }, // 0x7b '{' U+007B
|
||||
{ 1493, 1, 18, 14, 7, -14 }, // 0x7c '|' U+007C
|
||||
{ 1496, 6, 18, 14, 5, -14 }, // 0x7d '}' U+007D
|
||||
{ 1510, 10, 3, 14, 2, -7 }, // 0x7e '~' U+007E
|
||||
{ 1514, 14, 19, 14, 0, -16 }, // 0x7f 'REPLACEMENT CHARACTER *' U+2370
|
||||
{ 1548, 1, 1, 14, 0, 0 }, // 0x80 'NO-BREAK SPACE' U+00A0
|
||||
{ 1549, 3, 15, 14, 6, -10 }, // 0x81 'INVERTED EXCLAMATION MARK' U+00A1
|
||||
{ 1555, 8, 15, 14, 3, -14 }, // 0x82 'CENT SIGN' U+00A2
|
||||
{ 1570, 10, 14, 14, 2, -13 }, // 0x83 'POUND SIGN' U+00A3
|
||||
{ 1588, 12, 14, 14, 1, -13 }, // 0x84 'EURO SIGN *' U+20AC
|
||||
{ 1609, 12, 14, 14, 1, -13 }, // 0x85 'YEN SIGN' U+00A5
|
||||
{ 1630, 10, 18, 14, 2, -17 }, // 0x86 'LATIN CAPITAL LETTER S WITH CARON *' U+0160
|
||||
{ 1653, 11, 15, 14, 2, -13 }, // 0x87 'SECTION SIGN' U+00A7
|
||||
{ 1674, 10, 15, 14, 2, -14 }, // 0x88 'LATIN SMALL LETTER S WITH CARON *' U+0161
|
||||
{ 1693, 14, 14, 14, 0, -13 }, // 0x89 'COPYRIGHT SIGN' U+00A9
|
||||
{ 1718, 7, 7, 14, 4, -13 }, // 0x8a 'FEMININE ORDINAL INDICATOR' U+00AA
|
||||
{ 1725, 11, 10, 14, 2, -9 }, // 0x8b 'LEFT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00AB
|
||||
{ 1739, 11, 7, 14, 2, -10 }, // 0x8c 'NOT SIGN' U+00AC
|
||||
{ 1749, 11, 1, 14, 2, -6 }, // 0x8d 'SOFT HYPHEN' U+00AD
|
||||
{ 1751, 14, 14, 14, 0, -13 }, // 0x8e 'REGISTERED SIGN' U+00AE
|
||||
{ 1776, 7, 1, 14, 4, -13 }, // 0x8f 'MACRON' U+00AF
|
||||
{ 1777, 7, 7, 14, 4, -14 }, // 0x90 'DEGREE SIGN' U+00B0
|
||||
{ 1784, 11, 13, 14, 2, -12 }, // 0x91 'PLUS-MINUS SIGN' U+00B1
|
||||
{ 1802, 6, 9, 14, 4, -14 }, // 0x92 'SUPERSCRIPT TWO' U+00B2
|
||||
{ 1809, 6, 9, 14, 4, -14 }, // 0x93 'SUPERSCRIPT THREE' U+00B3
|
||||
{ 1816, 10, 18, 14, 2, -17 }, // 0x94 'LATIN CAPITAL LETTER Z WITH CARON *' U+017D
|
||||
{ 1839, 12, 15, 14, 1, -9 }, // 0x95 'MICRO SIGN' U+00B5
|
||||
{ 1862, 11, 16, 14, 2, -14 }, // 0x96 'PILCROW SIGN' U+00B6
|
||||
{ 1884, 2, 3, 14, 6, -6 }, // 0x97 'MIDDLE DOT' U+00B7
|
||||
{ 1885, 9, 15, 14, 3, -14 }, // 0x98 'LATIN SMALL LETTER Z WITH CARON *' U+017E
|
||||
{ 1902, 5, 9, 14, 5, -14 }, // 0x99 'SUPERSCRIPT ONE' U+00B9
|
||||
{ 1908, 7, 7, 14, 4, -13 }, // 0x9a 'MASCULINE ORDINAL INDICATOR' U+00BA
|
||||
{ 1915, 11, 10, 14, 2, -9 }, // 0x9b 'RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00BB
|
||||
{ 1929, 14, 14, 14, 0, -13 }, // 0x9c 'LATIN CAPITAL LIGATURE OE *' U+0152
|
||||
{ 1954, 14, 10, 14, 0, -9 }, // 0x9d 'LATIN SMALL LIGATURE OE *' U+0153
|
||||
{ 1972, 12, 17, 14, 1, -16 }, // 0x9e 'LATIN CAPITAL LETTER Y WITH DIAERESIS *' U+0178
|
||||
{ 1998, 8, 14, 14, 3, -9 }, // 0x9f 'INVERTED QUESTION MARK' U+00BF
|
||||
{ 2012, 14, 19, 14, 0, -18 }, // 0xa0 'LATIN CAPITAL LETTER A WITH GRAVE' U+00C0
|
||||
{ 2046, 14, 19, 14, 0, -18 }, // 0xa1 'LATIN CAPITAL LETTER A WITH ACUTE' U+00C1
|
||||
{ 2080, 14, 18, 14, 0, -17 }, // 0xa2 'LATIN CAPITAL LETTER A WITH CIRCUMFLEX' U+00C2
|
||||
{ 2112, 14, 17, 14, 0, -16 }, // 0xa3 'LATIN CAPITAL LETTER A WITH TILDE' U+00C3
|
||||
{ 2142, 14, 17, 14, 0, -16 }, // 0xa4 'LATIN CAPITAL LETTER A WITH DIAERESIS' U+00C4
|
||||
{ 2172, 14, 19, 14, 0, -18 }, // 0xa5 'LATIN CAPITAL LETTER A WITH RING ABOVE' U+00C5
|
||||
{ 2206, 14, 14, 14, 0, -13 }, // 0xa6 'LATIN CAPITAL LETTER AE' U+00C6
|
||||
{ 2231, 11, 18, 14, 2, -13 }, // 0xa7 'LATIN CAPITAL LETTER C WITH CEDILLA' U+00C7
|
||||
{ 2256, 11, 19, 14, 1, -18 }, // 0xa8 'LATIN CAPITAL LETTER E WITH GRAVE' U+00C8
|
||||
{ 2283, 11, 19, 14, 1, -18 }, // 0xa9 'LATIN CAPITAL LETTER E WITH ACUTE' U+00C9
|
||||
{ 2310, 11, 18, 14, 1, -17 }, // 0xaa 'LATIN CAPITAL LETTER E WITH CIRCUMFLEX' U+00CA
|
||||
{ 2335, 11, 17, 14, 1, -16 }, // 0xab 'LATIN CAPITAL LETTER E WITH DIAERESIS' U+00CB
|
||||
{ 2359, 9, 19, 14, 3, -18 }, // 0xac 'LATIN CAPITAL LETTER I WITH GRAVE' U+00CC
|
||||
{ 2381, 9, 19, 14, 3, -18 }, // 0xad 'LATIN CAPITAL LETTER I WITH ACUTE' U+00CD
|
||||
{ 2403, 9, 18, 14, 3, -17 }, // 0xae 'LATIN CAPITAL LETTER I WITH CIRCUMFLEX' U+00CE
|
||||
{ 2424, 9, 17, 14, 3, -16 }, // 0xaf 'LATIN CAPITAL LETTER I WITH DIAERESIS' U+00CF
|
||||
{ 2444, 12, 14, 14, 0, -13 }, // 0xb0 'LATIN CAPITAL LETTER ETH' U+00D0
|
||||
{ 2465, 12, 17, 14, 1, -16 }, // 0xb1 'LATIN CAPITAL LETTER N WITH TILDE' U+00D1
|
||||
{ 2491, 12, 19, 14, 1, -18 }, // 0xb2 'LATIN CAPITAL LETTER O WITH GRAVE' U+00D2
|
||||
{ 2520, 12, 19, 14, 1, -18 }, // 0xb3 'LATIN CAPITAL LETTER O WITH ACUTE' U+00D3
|
||||
{ 2549, 12, 18, 14, 1, -17 }, // 0xb4 'LATIN CAPITAL LETTER O WITH CIRCUMFLEX' U+00D4
|
||||
{ 2576, 12, 17, 14, 1, -16 }, // 0xb5 'LATIN CAPITAL LETTER O WITH TILDE' U+00D5
|
||||
{ 2602, 12, 17, 14, 1, -16 }, // 0xb6 'LATIN CAPITAL LETTER O WITH DIAERESIS' U+00D6
|
||||
{ 2628, 9, 9, 14, 3, -10 }, // 0xb7 'MULTIPLICATION SIGN' U+00D7
|
||||
{ 2639, 12, 16, 14, 1, -14 }, // 0xb8 'LATIN CAPITAL LETTER O WITH STROKE' U+00D8
|
||||
{ 2663, 12, 19, 14, 1, -18 }, // 0xb9 'LATIN CAPITAL LETTER U WITH GRAVE' U+00D9
|
||||
{ 2692, 12, 19, 14, 1, -18 }, // 0xba 'LATIN CAPITAL LETTER U WITH ACUTE' U+00DA
|
||||
{ 2721, 12, 18, 14, 1, -17 }, // 0xbb 'LATIN CAPITAL LETTER U WITH CIRCUMFLEX' U+00DB
|
||||
{ 2748, 12, 17, 14, 1, -16 }, // 0xbc 'LATIN CAPITAL LETTER U WITH DIAERESIS' U+00DC
|
||||
{ 2774, 12, 19, 14, 1, -18 }, // 0xbd 'LATIN CAPITAL LETTER Y WITH ACUTE' U+00DD
|
||||
{ 2803, 11, 14, 14, 1, -13 }, // 0xbe 'LATIN CAPITAL LETTER THORN' U+00DE
|
||||
{ 2823, 11, 15, 14, 1, -14 }, // 0xbf 'LATIN SMALL LETTER SHARP S' U+00DF
|
||||
{ 2844, 11, 15, 14, 2, -14 }, // 0xc0 'LATIN SMALL LETTER A WITH GRAVE' U+00E0
|
||||
{ 2865, 11, 15, 14, 2, -14 }, // 0xc1 'LATIN SMALL LETTER A WITH ACUTE' U+00E1
|
||||
{ 2886, 11, 15, 14, 2, -14 }, // 0xc2 'LATIN SMALL LETTER A WITH CIRCUMFLEX' U+00E2
|
||||
{ 2907, 11, 14, 14, 2, -13 }, // 0xc3 'LATIN SMALL LETTER A WITH TILDE' U+00E3
|
||||
{ 2927, 11, 14, 14, 2, -13 }, // 0xc4 'LATIN SMALL LETTER A WITH DIAERESIS' U+00E4
|
||||
{ 2947, 11, 16, 14, 2, -15 }, // 0xc5 'LATIN SMALL LETTER A WITH RING ABOVE' U+00E5
|
||||
{ 2969, 14, 10, 14, 0, -9 }, // 0xc6 'LATIN SMALL LETTER AE' U+00E6
|
||||
{ 2987, 11, 14, 14, 2, -9 }, // 0xc7 'LATIN SMALL LETTER C WITH CEDILLA' U+00E7
|
||||
{ 3007, 10, 15, 14, 2, -14 }, // 0xc8 'LATIN SMALL LETTER E WITH GRAVE' U+00E8
|
||||
{ 3026, 10, 15, 14, 2, -14 }, // 0xc9 'LATIN SMALL LETTER E WITH ACUTE' U+00E9
|
||||
{ 3045, 10, 15, 14, 2, -14 }, // 0xca 'LATIN SMALL LETTER E WITH CIRCUMFLEX' U+00EA
|
||||
{ 3064, 10, 14, 14, 2, -13 }, // 0xcb 'LATIN SMALL LETTER E WITH DIAERESIS' U+00EB
|
||||
{ 3082, 10, 15, 14, 2, -14 }, // 0xcc 'LATIN SMALL LETTER I WITH GRAVE' U+00EC
|
||||
{ 3101, 10, 15, 14, 2, -14 }, // 0xcd 'LATIN SMALL LETTER I WITH ACUTE' U+00ED
|
||||
{ 3120, 10, 15, 14, 2, -14 }, // 0xce 'LATIN SMALL LETTER I WITH CIRCUMFLEX' U+00EE
|
||||
{ 3139, 10, 14, 14, 2, -13 }, // 0xcf 'LATIN SMALL LETTER I WITH DIAERESIS' U+00EF
|
||||
{ 3157, 11, 15, 14, 2, -14 }, // 0xd0 'LATIN SMALL LETTER ETH' U+00F0
|
||||
{ 3178, 12, 14, 14, 1, -13 }, // 0xd1 'LATIN SMALL LETTER N WITH TILDE' U+00F1
|
||||
{ 3199, 11, 15, 14, 2, -14 }, // 0xd2 'LATIN SMALL LETTER O WITH GRAVE' U+00F2
|
||||
{ 3220, 11, 15, 14, 2, -14 }, // 0xd3 'LATIN SMALL LETTER O WITH ACUTE' U+00F3
|
||||
{ 3241, 11, 15, 14, 2, -14 }, // 0xd4 'LATIN SMALL LETTER O WITH CIRCUMFLEX' U+00F4
|
||||
{ 3262, 11, 14, 14, 2, -13 }, // 0xd5 'LATIN SMALL LETTER O WITH TILDE' U+00F5
|
||||
{ 3282, 11, 14, 14, 2, -13 }, // 0xd6 'LATIN SMALL LETTER O WITH DIAERESIS' U+00F6
|
||||
{ 3302, 11, 12, 14, 2, -12 }, // 0xd7 'DIVISION SIGN' U+00F7
|
||||
{ 3319, 12, 12, 14, 1, -10 }, // 0xd8 'LATIN SMALL LETTER O WITH STROKE' U+00F8
|
||||
{ 3337, 12, 15, 14, 1, -14 }, // 0xd9 'LATIN SMALL LETTER U WITH GRAVE' U+00F9
|
||||
{ 3360, 12, 15, 14, 1, -14 }, // 0xda 'LATIN SMALL LETTER U WITH ACUTE' U+00FA
|
||||
{ 3383, 12, 15, 14, 1, -14 }, // 0xdb 'LATIN SMALL LETTER U WITH CIRCUMFLEX' U+00FB
|
||||
{ 3406, 12, 14, 14, 1, -13 }, // 0xdc 'LATIN SMALL LETTER U WITH DIAERESIS' U+00FC
|
||||
{ 3427, 12, 19, 14, 1, -14 }, // 0xdd 'LATIN SMALL LETTER Y WITH ACUTE' U+00FD
|
||||
{ 3456, 12, 18, 14, 1, -13 }, // 0xde 'LATIN SMALL LETTER THORN' U+00FE
|
||||
{ 3483, 12, 18, 14, 1, -13 } }; // 0xdf 'LATIN SMALL LETTER Y WITH DIAERESIS' U+000FF
|
||||
|
||||
const GFXfont FreeMono12pt8b PROGMEM = {
|
||||
(uint8_t *)FreeMono12pt8bBitmaps,
|
||||
(GFXglyph *)FreeMono12pt8bGlyphs,
|
||||
0x20, 0xDF, 26 };
|
||||
|
||||
// Approx. 4861 bytes
|
0
libraries/fonts/FreeMono9pt7b.h → RX_FSK/src/fonts/FreeMono9pt7b.h
Executable file → Normal file
0
libraries/fonts/FreeMono9pt7b.h → RX_FSK/src/fonts/FreeMono9pt7b.h
Executable file → Normal file
374
RX_FSK/src/fonts/FreeMono9pt8b.h
Normal file
374
RX_FSK/src/fonts/FreeMono9pt8b.h
Normal file
|
@ -0,0 +1,374 @@
|
|||
const uint8_t FreeMono9pt8bBitmaps[] PROGMEM = {
|
||||
0x00, 0x55, 0x54, 0x1C, 0xDE, 0xF7, 0x39, 0x80, 0x20, 0x50, 0xA1, 0x42,
|
||||
0x9F, 0xCA, 0x14, 0xFE, 0x91, 0x22, 0x44, 0x80, 0x10, 0x21, 0xB4, 0x08,
|
||||
0x08, 0x0F, 0x01, 0x83, 0x0B, 0xE0, 0x81, 0x02, 0x00, 0x71, 0x22, 0x44,
|
||||
0x86, 0x23, 0xB8, 0x0E, 0x22, 0x44, 0x70, 0x78, 0x81, 0x02, 0x06, 0x12,
|
||||
0xA6, 0x44, 0x76, 0xD9, 0x24, 0x25, 0x25, 0x24, 0x49, 0x12, 0x91, 0x24,
|
||||
0x9B, 0x49, 0x48, 0x10, 0x22, 0x4B, 0xE2, 0x89, 0x00, 0x00, 0x08, 0x04,
|
||||
0x02, 0x01, 0x00, 0x83, 0xF8, 0x20, 0x10, 0x08, 0x00, 0x37, 0x64, 0x40,
|
||||
0x7F, 0x00, 0xFC, 0x02, 0x08, 0x10, 0x40, 0x82, 0x04, 0x10, 0x20, 0x41,
|
||||
0x02, 0x08, 0x00, 0x38, 0x8A, 0x14, 0x18, 0x30, 0x60, 0xC1, 0x82, 0x89,
|
||||
0xE0, 0x30, 0xA2, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x23, 0xF8, 0x79,
|
||||
0x0A, 0x10, 0x20, 0x41, 0x04, 0x10, 0x41, 0x07, 0xF8, 0x79, 0x08, 0x08,
|
||||
0x20, 0xC3, 0x80, 0x81, 0x02, 0x07, 0xF0, 0x0C, 0x28, 0x91, 0x24, 0x48,
|
||||
0xA1, 0x7F, 0x04, 0x08, 0x78, 0x7D, 0x02, 0x04, 0x07, 0xC0, 0x40, 0x81,
|
||||
0x03, 0x09, 0xF0, 0x1E, 0x41, 0x02, 0x08, 0x96, 0xB0, 0xC1, 0x42, 0x84,
|
||||
0xF0, 0xFF, 0x04, 0x10, 0x20, 0x41, 0x02, 0x04, 0x10, 0x20, 0x40, 0x79,
|
||||
0x0A, 0x0C, 0x14, 0x47, 0x31, 0x41, 0x83, 0x09, 0xF0, 0x38, 0x8A, 0x0C,
|
||||
0x18, 0x28, 0xCE, 0x81, 0x04, 0x09, 0xE0, 0x1F, 0x00, 0x3F, 0x03, 0x30,
|
||||
0x03, 0x76, 0x44, 0x00, 0x03, 0x04, 0x18, 0x60, 0x60, 0x18, 0x04, 0x03,
|
||||
0xFF, 0x80, 0x00, 0x1F, 0xF0, 0x40, 0x18, 0x03, 0x00, 0x60, 0x20, 0x60,
|
||||
0xC0, 0x80, 0xFD, 0x04, 0x08, 0x10, 0xC2, 0x04, 0x00, 0x10, 0x70, 0x78,
|
||||
0x8A, 0x14, 0x29, 0xD4, 0xA9, 0x4A, 0x89, 0x01, 0x01, 0xE0, 0x3C, 0x01,
|
||||
0x40, 0x48, 0x09, 0x01, 0x10, 0x42, 0x0F, 0xC1, 0x04, 0x40, 0x9E, 0x3C,
|
||||
0xFE, 0x20, 0x90, 0x48, 0x27, 0xE2, 0x09, 0x02, 0x81, 0x41, 0x7F, 0x00,
|
||||
0x3F, 0x20, 0xA0, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x41, 0x1F, 0x00,
|
||||
0xFC, 0x42, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0xFC, 0xFF, 0x41,
|
||||
0x41, 0x40, 0x78, 0x48, 0x40, 0x41, 0x41, 0xFF, 0xFF, 0x41, 0x40, 0x40,
|
||||
0x78, 0x48, 0x40, 0x40, 0x40, 0xF8, 0x3F, 0x20, 0xA0, 0x10, 0x08, 0x04,
|
||||
0x3E, 0x05, 0x02, 0x41, 0x1F, 0x80, 0xE3, 0x20, 0x90, 0x48, 0x27, 0xF2,
|
||||
0x09, 0x04, 0x82, 0x41, 0x73, 0xC0, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04,
|
||||
0x08, 0x11, 0xFC, 0x3F, 0x02, 0x01, 0x00, 0x80, 0x40, 0x22, 0x11, 0x08,
|
||||
0x84, 0x3C, 0x00, 0xF3, 0xA1, 0x11, 0x09, 0x05, 0x83, 0x21, 0x08, 0x84,
|
||||
0x42, 0x78, 0xC0, 0xF8, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x82, 0x41,
|
||||
0x20, 0xFF, 0xC0, 0xE0, 0xCC, 0x29, 0x45, 0x29, 0x24, 0xA4, 0x94, 0x91,
|
||||
0x12, 0x02, 0x40, 0x5E, 0x3C, 0x61, 0xCC, 0x23, 0x08, 0xA2, 0x24, 0x89,
|
||||
0x22, 0x28, 0x8A, 0x21, 0x9C, 0x20, 0x3E, 0x20, 0xA0, 0x50, 0x18, 0x0C,
|
||||
0x06, 0x03, 0x02, 0x41, 0x1F, 0x00, 0xFE, 0x41, 0x41, 0x41, 0x42, 0x7C,
|
||||
0x40, 0x40, 0x40, 0xF8, 0x3E, 0x20, 0xA0, 0x50, 0x18, 0x0C, 0x06, 0x03,
|
||||
0x02, 0x41, 0x1B, 0x06, 0x07, 0xF0, 0xFE, 0x10, 0x44, 0x11, 0x04, 0x42,
|
||||
0x1F, 0x04, 0x21, 0x08, 0x41, 0x3C, 0x30, 0x7F, 0x06, 0x0C, 0x07, 0x01,
|
||||
0x80, 0x81, 0x83, 0xF8, 0xFF, 0xC4, 0x42, 0x01, 0x00, 0x80, 0x40, 0x20,
|
||||
0x10, 0x08, 0x1F, 0x00, 0xE3, 0xA0, 0x90, 0x48, 0x24, 0x12, 0x09, 0x04,
|
||||
0x82, 0x41, 0x1F, 0x00, 0xF1, 0xE8, 0x10, 0x82, 0x10, 0x82, 0x10, 0x22,
|
||||
0x04, 0x80, 0x50, 0x0C, 0x00, 0x80, 0xF1, 0xD0, 0x14, 0x49, 0x32, 0x4A,
|
||||
0x92, 0xA3, 0x28, 0xCA, 0x31, 0x88, 0x60, 0xE3, 0xA1, 0x08, 0x82, 0x80,
|
||||
0x80, 0xC0, 0x50, 0x44, 0x41, 0x71, 0xC0, 0xE3, 0xA1, 0x08, 0x82, 0x81,
|
||||
0x80, 0x40, 0x20, 0x10, 0x08, 0x1F, 0x00, 0xFD, 0x0A, 0x20, 0x41, 0x04,
|
||||
0x10, 0xA1, 0x83, 0xFC, 0xF2, 0x49, 0x24, 0x92, 0x4E, 0x81, 0x01, 0x02,
|
||||
0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0xE4, 0x92, 0x49,
|
||||
0x24, 0x9E, 0x10, 0x51, 0x24, 0x28, 0x20, 0xFF, 0xE0, 0x11, 0x80, 0x1C,
|
||||
0x31, 0x00, 0x83, 0xC6, 0x24, 0x12, 0x08, 0xFB, 0xE0, 0x08, 0x02, 0x00,
|
||||
0xB8, 0x31, 0x88, 0x22, 0x04, 0x81, 0x20, 0x48, 0x2F, 0xF0, 0x38, 0x46,
|
||||
0x82, 0x80, 0x80, 0x80, 0x81, 0x7E, 0x03, 0x00, 0x40, 0x10, 0x64, 0x67,
|
||||
0x20, 0x48, 0x12, 0x04, 0x81, 0x10, 0xC3, 0xD8, 0x1C, 0x62, 0x81, 0x81,
|
||||
0xFE, 0x80, 0x40, 0x3F, 0x1F, 0x20, 0x20, 0x7C, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0xFE, 0x39, 0xA3, 0xA0, 0x50, 0x28, 0x14, 0x09, 0x0C, 0x7A,
|
||||
0x01, 0x01, 0x07, 0x80, 0xC0, 0x20, 0x10, 0x0B, 0x86, 0x22, 0x09, 0x04,
|
||||
0x82, 0x41, 0x20, 0xB8, 0xE0, 0x10, 0x20, 0x03, 0x81, 0x02, 0x04, 0x08,
|
||||
0x10, 0x23, 0xF8, 0x10, 0x81, 0xF0, 0x84, 0x21, 0x08, 0x42, 0x10, 0xFC,
|
||||
0xC0, 0x20, 0x10, 0x08, 0xC4, 0x42, 0x41, 0x40, 0x50, 0x44, 0x21, 0x31,
|
||||
0xE0, 0xF0, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x23, 0xF8, 0x59,
|
||||
0x8C, 0xD1, 0x11, 0x22, 0x24, 0x44, 0x88, 0x91, 0x17, 0x33, 0x5C, 0x31,
|
||||
0x10, 0x48, 0x24, 0x12, 0x09, 0x05, 0xC7, 0x1C, 0x31, 0x10, 0x50, 0x28,
|
||||
0x14, 0x09, 0x04, 0x7C, 0x6E, 0x0C, 0x62, 0x08, 0x81, 0x20, 0x48, 0x23,
|
||||
0x08, 0xBC, 0x20, 0x08, 0x07, 0x00, 0x1D, 0x98, 0xC8, 0x12, 0x04, 0x81,
|
||||
0x20, 0x44, 0x30, 0xF4, 0x01, 0x00, 0x40, 0x38, 0xC6, 0x59, 0x20, 0x40,
|
||||
0x40, 0x40, 0x40, 0xFC, 0x39, 0x8E, 0x03, 0x01, 0xC0, 0x60, 0xFE, 0x40,
|
||||
0x40, 0xFC, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x3F, 0xC3, 0x20, 0x90,
|
||||
0x48, 0x24, 0x12, 0x09, 0x0C, 0x7B, 0xE3, 0xA0, 0x90, 0x84, 0x42, 0x21,
|
||||
0x20, 0x50, 0x10, 0xC1, 0xC0, 0xA2, 0x49, 0x25, 0x52, 0xB1, 0x98, 0x44,
|
||||
0x63, 0x20, 0x88, 0x83, 0x81, 0x81, 0x21, 0x09, 0xC7, 0xC3, 0x20, 0x90,
|
||||
0x44, 0x42, 0x20, 0xA0, 0x50, 0x10, 0x08, 0x08, 0x1E, 0x00, 0xFF, 0x0A,
|
||||
0x20, 0x81, 0x04, 0x10, 0xFF, 0x12, 0x22, 0x22, 0xC2, 0x22, 0x22, 0x30,
|
||||
0xFF, 0xF8, 0xC1, 0x08, 0x42, 0x10, 0x64, 0x21, 0x08, 0x44, 0x00, 0xE2,
|
||||
0x38, 0xFF, 0xF0, 0x06, 0xFC, 0xD0, 0x58, 0x0B, 0x01, 0x60, 0xCC, 0x21,
|
||||
0x84, 0x30, 0x06, 0x10, 0xC7, 0x18, 0x03, 0xFF, 0xC0, 0x00, 0xC0, 0x55,
|
||||
0x54, 0x10, 0x43, 0x91, 0x82, 0x08, 0x11, 0x38, 0x41, 0x00, 0x3C, 0x20,
|
||||
0x20, 0x20, 0xF8, 0x20, 0x20, 0x20, 0x21, 0x7F, 0x3F, 0xA0, 0x90, 0x10,
|
||||
0x0F, 0xE7, 0xE2, 0x00, 0x80, 0x20, 0x8F, 0x80, 0xE3, 0xA1, 0x08, 0x82,
|
||||
0x81, 0x83, 0xF8, 0x20, 0x7C, 0x08, 0x1F, 0x00, 0x6C, 0x20, 0x03, 0xF8,
|
||||
0x30, 0x60, 0x38, 0x0C, 0x04, 0x0C, 0x1F, 0xC0, 0x1F, 0x10, 0x88, 0x4C,
|
||||
0x09, 0x82, 0x30, 0x84, 0x31, 0x07, 0x01, 0x10, 0x8F, 0x80, 0x00, 0xD8,
|
||||
0x40, 0x03, 0x98, 0xE0, 0x30, 0x1C, 0x06, 0x0F, 0xE0, 0x3F, 0x08, 0x12,
|
||||
0x3D, 0x48, 0x9A, 0x03, 0x40, 0x64, 0x4A, 0x72, 0x40, 0x87, 0xE0, 0xF0,
|
||||
0xBD, 0x2F, 0x80, 0x00, 0x08, 0x88, 0x88, 0xCC, 0x43, 0x10, 0x44, 0x11,
|
||||
0xFF, 0x80, 0x40, 0x20, 0x10, 0x00, 0x7F, 0x00, 0x3F, 0x08, 0x12, 0x79,
|
||||
0x49, 0x19, 0x23, 0x3C, 0x64, 0x8A, 0xCA, 0x40, 0x87, 0xE0, 0xF8, 0xF4,
|
||||
0x63, 0x17, 0x00, 0x00, 0x04, 0x02, 0x01, 0x0F, 0xF0, 0x40, 0x20, 0x10,
|
||||
0x00, 0x7F, 0x80, 0x79, 0x12, 0x4F, 0x71, 0x13, 0x1F, 0x04, 0xD0, 0x40,
|
||||
0x0F, 0xD0, 0xA2, 0x04, 0x10, 0x41, 0x0A, 0x18, 0x3F, 0xC0, 0xC3, 0x20,
|
||||
0x90, 0x48, 0x24, 0x12, 0x09, 0x0C, 0xDB, 0x50, 0x20, 0x10, 0x08, 0x00,
|
||||
0x3F, 0x6A, 0xCA, 0xCA, 0x4A, 0x7A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x3B,
|
||||
0x50, 0x00, 0xD8, 0x40, 0x0F, 0xF0, 0xA2, 0x08, 0x10, 0x41, 0x0F, 0xF0,
|
||||
0x62, 0x22, 0x27, 0xF4, 0x63, 0x17, 0x00, 0x00, 0x22, 0x18, 0x86, 0x61,
|
||||
0x11, 0x11, 0x11, 0x10, 0x3F, 0xC8, 0x8A, 0x11, 0x42, 0x08, 0x71, 0x0A,
|
||||
0x21, 0x02, 0x21, 0x44, 0x27, 0xFC, 0x31, 0x92, 0x98, 0x46, 0x11, 0x87,
|
||||
0xA1, 0x04, 0xC1, 0xEF, 0x22, 0x11, 0x00, 0x1C, 0x74, 0x21, 0x10, 0x50,
|
||||
0x30, 0x08, 0x04, 0x02, 0x01, 0x03, 0xE0, 0x10, 0xE0, 0x00, 0x10, 0xC4,
|
||||
0x20, 0x82, 0x17, 0xC0, 0x10, 0x01, 0x00, 0x10, 0x00, 0x03, 0xC0, 0x14,
|
||||
0x04, 0x80, 0x90, 0x11, 0x04, 0x20, 0xFC, 0x10, 0x44, 0x09, 0xE3, 0xC0,
|
||||
0x02, 0x00, 0x80, 0x20, 0x00, 0x03, 0xC0, 0x14, 0x04, 0x80, 0x90, 0x11,
|
||||
0x04, 0x20, 0xFC, 0x10, 0x44, 0x09, 0xE3, 0xC0, 0x04, 0x01, 0x40, 0x44,
|
||||
0x00, 0x03, 0xC0, 0x14, 0x04, 0x80, 0x90, 0x11, 0x04, 0x20, 0xFC, 0x10,
|
||||
0x44, 0x09, 0xE3, 0xC0, 0x08, 0x02, 0xE0, 0x00, 0x1E, 0x00, 0xA0, 0x24,
|
||||
0x04, 0x80, 0x88, 0x21, 0x07, 0xE0, 0x82, 0x20, 0x4F, 0x1E, 0x11, 0x02,
|
||||
0x20, 0x00, 0x1E, 0x00, 0xA0, 0x24, 0x04, 0x80, 0x88, 0x21, 0x07, 0xE0,
|
||||
0x82, 0x20, 0x4F, 0x1E, 0x0E, 0x02, 0x40, 0x30, 0x00, 0x03, 0xC0, 0x14,
|
||||
0x04, 0x80, 0x90, 0x11, 0x04, 0x20, 0xFC, 0x10, 0x44, 0x09, 0xE3, 0xC0,
|
||||
0x3F, 0xC2, 0x88, 0x51, 0x0A, 0x02, 0x70, 0x4A, 0x0F, 0x01, 0x21, 0x44,
|
||||
0x3D, 0xFC, 0x3F, 0x20, 0xA0, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x41,
|
||||
0x1B, 0x02, 0x00, 0x81, 0xC0, 0x20, 0x10, 0x08, 0x00, 0xFF, 0x41, 0x41,
|
||||
0x40, 0x78, 0x48, 0x40, 0x41, 0x41, 0xFF, 0x04, 0x08, 0x10, 0x00, 0xFF,
|
||||
0x41, 0x41, 0x40, 0x78, 0x48, 0x40, 0x41, 0x41, 0xFF, 0x00, 0x1C, 0x22,
|
||||
0x00, 0xFF, 0x41, 0x41, 0x40, 0x78, 0x48, 0x40, 0x41, 0x41, 0xFF, 0x22,
|
||||
0x66, 0x00, 0xFF, 0x41, 0x41, 0x40, 0x78, 0x48, 0x40, 0x41, 0x41, 0xFF,
|
||||
0x20, 0x20, 0x00, 0x0F, 0xE2, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81, 0x1F,
|
||||
0xC0, 0x04, 0x10, 0x40, 0x0F, 0xE2, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81,
|
||||
0x1F, 0xC0, 0x10, 0x51, 0x10, 0x0F, 0xE2, 0x04, 0x08, 0x10, 0x20, 0x40,
|
||||
0x81, 0x1F, 0xC0, 0x44, 0x88, 0x07, 0xF1, 0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x40, 0x8F, 0xE0, 0x7E, 0x10, 0x88, 0x24, 0x1F, 0xC9, 0x04, 0x82, 0x41,
|
||||
0x21, 0x3F, 0x00, 0x19, 0x09, 0x80, 0x01, 0x87, 0x30, 0x8C, 0x22, 0x88,
|
||||
0x92, 0x24, 0x88, 0xA2, 0x28, 0x86, 0x70, 0x80, 0x20, 0x0C, 0x00, 0x00,
|
||||
0x03, 0xE2, 0x0A, 0x05, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x24, 0x11, 0xF0,
|
||||
0x04, 0x04, 0x04, 0x00, 0x03, 0xE2, 0x0A, 0x05, 0x01, 0x80, 0xC0, 0x60,
|
||||
0x30, 0x24, 0x11, 0xF0, 0x08, 0x0A, 0x08, 0x80, 0x03, 0xE2, 0x0A, 0x05,
|
||||
0x01, 0x80, 0xC0, 0x60, 0x30, 0x24, 0x11, 0xF0, 0x10, 0x17, 0x00, 0x07,
|
||||
0xC4, 0x14, 0x0A, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x48, 0x23, 0xE0, 0x22,
|
||||
0x11, 0x00, 0x07, 0xC4, 0x14, 0x0A, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x48,
|
||||
0x23, 0xE0, 0x84, 0x90, 0xC1, 0x84, 0x90, 0x80, 0x00, 0x9F, 0x90, 0x50,
|
||||
0x68, 0x4C, 0x46, 0x43, 0x21, 0xA1, 0x20, 0xAD, 0x81, 0x00, 0x20, 0x0C,
|
||||
0x00, 0x00, 0x0E, 0x3A, 0x09, 0x04, 0x82, 0x41, 0x20, 0x90, 0x48, 0x24,
|
||||
0x11, 0xF0, 0x04, 0x04, 0x04, 0x00, 0x0E, 0x3A, 0x09, 0x04, 0x82, 0x41,
|
||||
0x20, 0x90, 0x48, 0x24, 0x11, 0xF0, 0x08, 0x0A, 0x08, 0x80, 0x0E, 0x3A,
|
||||
0x09, 0x04, 0x82, 0x41, 0x20, 0x90, 0x48, 0x24, 0x11, 0xF0, 0x22, 0x11,
|
||||
0x00, 0x1C, 0x74, 0x12, 0x09, 0x04, 0x82, 0x41, 0x20, 0x90, 0x48, 0x23,
|
||||
0xE0, 0x04, 0x04, 0x04, 0x00, 0x0E, 0x3A, 0x10, 0x88, 0x28, 0x18, 0x04,
|
||||
0x02, 0x01, 0x00, 0x81, 0xF0, 0xF8, 0x40, 0x7C, 0x43, 0x41, 0x41, 0x41,
|
||||
0x7E, 0x40, 0xF8, 0x1C, 0x11, 0x08, 0x84, 0x42, 0xC1, 0x18, 0x82, 0x41,
|
||||
0x20, 0x94, 0x79, 0xC0, 0x20, 0x08, 0x02, 0x00, 0x01, 0xC3, 0x10, 0x08,
|
||||
0x3C, 0x62, 0x41, 0x20, 0x8F, 0xB0, 0x00, 0x06, 0x04, 0x00, 0x01, 0xC3,
|
||||
0x10, 0x08, 0x3C, 0x62, 0x41, 0x20, 0x8F, 0xB0, 0x18, 0x12, 0x00, 0x03,
|
||||
0x86, 0x20, 0x10, 0x78, 0xC4, 0x82, 0x41, 0x1F, 0x60, 0x3E, 0x00, 0x07,
|
||||
0x0C, 0x40, 0x20, 0xF1, 0x89, 0x04, 0x82, 0x3E, 0xC0, 0x22, 0x33, 0x00,
|
||||
0x03, 0x86, 0x20, 0x10, 0x78, 0xC4, 0x82, 0x41, 0x1F, 0x60, 0x1C, 0x12,
|
||||
0x05, 0x01, 0x01, 0xC3, 0x10, 0x08, 0x3C, 0x62, 0x41, 0x20, 0x8F, 0xB0,
|
||||
0x39, 0x91, 0x90, 0x44, 0xF1, 0x47, 0xA1, 0x08, 0x41, 0xFF, 0x38, 0x46,
|
||||
0x82, 0x80, 0x80, 0x80, 0x81, 0x6E, 0x10, 0x08, 0x38, 0x00, 0x10, 0x08,
|
||||
0x00, 0x1C, 0x62, 0x81, 0x81, 0xFE, 0x80, 0x40, 0x3F, 0x00, 0x04, 0x18,
|
||||
0x00, 0x1C, 0x62, 0x81, 0x81, 0xFE, 0x80, 0x40, 0x3F, 0x08, 0x36, 0x00,
|
||||
0x1C, 0x62, 0x81, 0x81, 0xFE, 0x80, 0x40, 0x3F, 0x22, 0x22, 0x00, 0x1C,
|
||||
0x62, 0x81, 0x81, 0xFE, 0x80, 0x40, 0x3F, 0x40, 0x40, 0x40, 0x07, 0x02,
|
||||
0x04, 0x08, 0x10, 0x20, 0x47, 0xF0, 0x00, 0x30, 0x80, 0x07, 0x02, 0x04,
|
||||
0x08, 0x10, 0x20, 0x47, 0xF0, 0x30, 0x90, 0x03, 0x81, 0x02, 0x04, 0x08,
|
||||
0x10, 0x23, 0xF8, 0x45, 0x98, 0x03, 0x81, 0x02, 0x04, 0x08, 0x10, 0x23,
|
||||
0xF8, 0x36, 0x0E, 0x00, 0x83, 0xC6, 0x32, 0x0A, 0x05, 0x02, 0x81, 0x20,
|
||||
0x8F, 0x80, 0x3E, 0x00, 0x17, 0x0C, 0x44, 0x12, 0x09, 0x04, 0x82, 0x41,
|
||||
0x71, 0xC0, 0x00, 0x08, 0x02, 0x00, 0x01, 0xC3, 0x11, 0x05, 0x02, 0x81,
|
||||
0x40, 0x90, 0x47, 0xC0, 0x00, 0x02, 0x06, 0x00, 0x01, 0xC3, 0x11, 0x05,
|
||||
0x02, 0x81, 0x40, 0x90, 0x47, 0xC0, 0x18, 0x13, 0x00, 0x03, 0x86, 0x22,
|
||||
0x0A, 0x05, 0x02, 0x81, 0x20, 0x8F, 0x80, 0x3E, 0x00, 0x07, 0x0C, 0x44,
|
||||
0x14, 0x0A, 0x05, 0x02, 0x41, 0x1F, 0x00, 0x22, 0x11, 0x00, 0x03, 0x86,
|
||||
0x22, 0x0A, 0x05, 0x02, 0x81, 0x20, 0x8F, 0x80, 0x08, 0x04, 0x00, 0x00,
|
||||
0x00, 0x03, 0xF8, 0x00, 0x00, 0x08, 0x04, 0x00, 0x1D, 0x31, 0x10, 0xD0,
|
||||
0xA8, 0x94, 0x89, 0x84, 0xEC, 0x88, 0x00, 0x00, 0x08, 0x02, 0x00, 0x0C,
|
||||
0x32, 0x09, 0x04, 0x82, 0x41, 0x20, 0x90, 0xC7, 0xB0, 0x04, 0x04, 0x04,
|
||||
0x00, 0x0C, 0x32, 0x09, 0x04, 0x82, 0x41, 0x20, 0x90, 0xC7, 0xB0, 0x18,
|
||||
0x12, 0x00, 0x18, 0x64, 0x12, 0x09, 0x04, 0x82, 0x41, 0x21, 0x8F, 0x60,
|
||||
0x22, 0x33, 0x00, 0x18, 0x64, 0x12, 0x09, 0x04, 0x82, 0x41, 0x21, 0x8F,
|
||||
0x60, 0x02, 0x02, 0x02, 0x00, 0x0C, 0x32, 0x09, 0x04, 0x44, 0x22, 0x0A,
|
||||
0x05, 0x01, 0x00, 0x80, 0x81, 0xE0, 0xE0, 0x08, 0x02, 0x00, 0xB8, 0x31,
|
||||
0x88, 0x22, 0x04, 0x81, 0x20, 0x8C, 0x22, 0xF0, 0x80, 0x20, 0x1C, 0x00,
|
||||
0x22, 0x11, 0x00, 0x18, 0x64, 0x12, 0x08, 0x88, 0x44, 0x14, 0x0A, 0x02,
|
||||
0x01, 0x01, 0x03, 0xC0 };
|
||||
|
||||
const GFXglyph FreeMono9pt8bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 11, 0, 0 }, // 0x20 ' ' U+0020
|
||||
{ 1, 2, 11, 11, 4, -10 }, // 0x21 '!' U+0021
|
||||
{ 4, 5, 5, 11, 3, -10 }, // 0x22 '"' U+0022
|
||||
{ 8, 7, 13, 11, 2, -11 }, // 0x23 '#' U+0023
|
||||
{ 20, 7, 14, 11, 2, -11 }, // 0x24 '$' U+0024
|
||||
{ 33, 7, 11, 11, 2, -10 }, // 0x25 '%' U+0025
|
||||
{ 43, 7, 9, 11, 2, -8 }, // 0x26 '&' U+0026
|
||||
{ 51, 3, 5, 11, 4, -10 }, // 0x27 ''' U+0027
|
||||
{ 53, 3, 13, 11, 5, -10 }, // 0x28 '(' U+0028
|
||||
{ 58, 3, 13, 11, 3, -10 }, // 0x29 ')' U+0029
|
||||
{ 63, 7, 7, 11, 2, -10 }, // 0x2a '*' U+002A
|
||||
{ 70, 9, 9, 11, 1, -9 }, // 0x2b '+' U+002B
|
||||
{ 81, 4, 6, 11, 2, -2 }, // 0x2c ',' U+002C
|
||||
{ 84, 9, 1, 11, 1, -5 }, // 0x2d '-' U+002D
|
||||
{ 86, 3, 2, 11, 4, -1 }, // 0x2e '.' U+002E
|
||||
{ 87, 7, 13, 11, 2, -11 }, // 0x2f '/' U+002F
|
||||
{ 99, 7, 11, 11, 2, -10 }, // 0x30 '0' U+0030
|
||||
{ 109, 7, 11, 11, 2, -10 }, // 0x31 '1' U+0031
|
||||
{ 119, 7, 11, 11, 2, -10 }, // 0x32 '2' U+0032
|
||||
{ 129, 7, 11, 11, 2, -10 }, // 0x33 '3' U+0033
|
||||
{ 139, 7, 11, 11, 2, -10 }, // 0x34 '4' U+0034
|
||||
{ 149, 7, 11, 11, 2, -10 }, // 0x35 '5' U+0035
|
||||
{ 159, 7, 11, 11, 2, -10 }, // 0x36 '6' U+0036
|
||||
{ 169, 7, 11, 11, 2, -10 }, // 0x37 '7' U+0037
|
||||
{ 179, 7, 11, 11, 2, -10 }, // 0x38 '8' U+0038
|
||||
{ 189, 7, 11, 11, 2, -10 }, // 0x39 '9' U+0039
|
||||
{ 199, 3, 8, 11, 4, -7 }, // 0x3a ':' U+003A
|
||||
{ 202, 4, 11, 11, 2, -7 }, // 0x3b ';' U+003B
|
||||
{ 208, 8, 8, 11, 1, -8 }, // 0x3c '<' U+003C
|
||||
{ 216, 9, 4, 11, 1, -6 }, // 0x3d '=' U+003D
|
||||
{ 221, 9, 8, 11, 1, -8 }, // 0x3e '>' U+003E
|
||||
{ 230, 7, 10, 11, 2, -9 }, // 0x3f '?' U+003F
|
||||
{ 239, 7, 12, 11, 2, -10 }, // 0x40 '@' U+0040
|
||||
{ 250, 11, 10, 11, 0, -9 }, // 0x41 'A' U+0041
|
||||
{ 264, 9, 10, 11, 1, -9 }, // 0x42 'B' U+0042
|
||||
{ 276, 9, 10, 11, 1, -9 }, // 0x43 'C' U+0043
|
||||
{ 288, 8, 10, 11, 1, -9 }, // 0x44 'D' U+0044
|
||||
{ 298, 8, 10, 11, 1, -9 }, // 0x45 'E' U+0045
|
||||
{ 308, 8, 10, 11, 1, -9 }, // 0x46 'F' U+0046
|
||||
{ 318, 9, 10, 11, 1, -9 }, // 0x47 'G' U+0047
|
||||
{ 330, 9, 10, 11, 1, -9 }, // 0x48 'H' U+0048
|
||||
{ 342, 7, 10, 11, 2, -9 }, // 0x49 'I' U+0049
|
||||
{ 351, 9, 10, 11, 2, -9 }, // 0x4a 'J' U+004A
|
||||
{ 363, 9, 10, 11, 1, -9 }, // 0x4b 'K' U+004B
|
||||
{ 375, 9, 10, 11, 1, -9 }, // 0x4c 'L' U+004C
|
||||
{ 387, 11, 10, 11, 0, -9 }, // 0x4d 'M' U+004D
|
||||
{ 401, 10, 10, 11, 0, -9 }, // 0x4e 'N' U+004E
|
||||
{ 414, 9, 10, 11, 1, -9 }, // 0x4f 'O' U+004F
|
||||
{ 426, 8, 10, 11, 1, -9 }, // 0x50 'P' U+0050
|
||||
{ 436, 9, 12, 11, 1, -9 }, // 0x51 'Q' U+0051
|
||||
{ 450, 10, 10, 11, 1, -9 }, // 0x52 'R' U+0052
|
||||
{ 463, 7, 10, 11, 2, -9 }, // 0x53 'S' U+0053
|
||||
{ 472, 9, 10, 11, 1, -9 }, // 0x54 'T' U+0054
|
||||
{ 484, 9, 10, 11, 1, -9 }, // 0x55 'U' U+0055
|
||||
{ 496, 11, 10, 11, 0, -9 }, // 0x56 'V' U+0056
|
||||
{ 510, 10, 10, 11, 0, -9 }, // 0x57 'W' U+0057
|
||||
{ 523, 9, 10, 11, 1, -9 }, // 0x58 'X' U+0058
|
||||
{ 535, 9, 10, 11, 1, -9 }, // 0x59 'Y' U+0059
|
||||
{ 547, 7, 10, 11, 2, -9 }, // 0x5a 'Z' U+005A
|
||||
{ 556, 3, 13, 11, 5, -10 }, // 0x5b '[' U+005B
|
||||
{ 561, 7, 13, 11, 2, -11 }, // 0x5c '\' U+005C
|
||||
{ 573, 3, 13, 11, 3, -10 }, // 0x5d ']' U+005D
|
||||
{ 578, 7, 5, 11, 2, -10 }, // 0x5e '^' U+005E
|
||||
{ 583, 11, 1, 11, 0, 2 }, // 0x5f '_' U+005F
|
||||
{ 585, 3, 3, 11, 3, -11 }, // 0x60 '`' U+0060
|
||||
{ 587, 9, 8, 11, 1, -7 }, // 0x61 'a' U+0061
|
||||
{ 596, 10, 11, 11, 0, -10 }, // 0x62 'b' U+0062
|
||||
{ 610, 8, 8, 11, 2, -7 }, // 0x63 'c' U+0063
|
||||
{ 618, 10, 11, 11, 1, -10 }, // 0x64 'd' U+0064
|
||||
{ 632, 8, 8, 11, 1, -7 }, // 0x65 'e' U+0065
|
||||
{ 640, 8, 11, 11, 2, -10 }, // 0x66 'f' U+0066
|
||||
{ 651, 9, 11, 11, 1, -7 }, // 0x67 'g' U+0067
|
||||
{ 664, 9, 11, 11, 1, -10 }, // 0x68 'h' U+0068
|
||||
{ 677, 7, 11, 11, 2, -10 }, // 0x69 'i' U+0069
|
||||
{ 687, 5, 14, 11, 3, -10 }, // 0x6a 'j' U+006A
|
||||
{ 696, 9, 11, 11, 1, -10 }, // 0x6b 'k' U+006B
|
||||
{ 709, 7, 11, 11, 2, -10 }, // 0x6c 'l' U+006C
|
||||
{ 719, 11, 8, 11, 0, -7 }, // 0x6d 'm' U+006D
|
||||
{ 730, 9, 8, 11, 1, -7 }, // 0x6e 'n' U+006E
|
||||
{ 739, 9, 8, 11, 1, -7 }, // 0x6f 'o' U+006F
|
||||
{ 748, 10, 11, 11, 0, -7 }, // 0x70 'p' U+0070
|
||||
{ 762, 10, 11, 11, 1, -7 }, // 0x71 'q' U+0071
|
||||
{ 776, 8, 8, 11, 2, -7 }, // 0x72 'r' U+0072
|
||||
{ 784, 7, 8, 11, 2, -7 }, // 0x73 's' U+0073
|
||||
{ 791, 8, 10, 11, 1, -9 }, // 0x74 't' U+0074
|
||||
{ 801, 9, 8, 11, 1, -7 }, // 0x75 'u' U+0075
|
||||
{ 810, 9, 8, 11, 1, -7 }, // 0x76 'v' U+0076
|
||||
{ 819, 9, 8, 11, 1, -7 }, // 0x77 'w' U+0077
|
||||
{ 828, 9, 8, 11, 1, -7 }, // 0x78 'x' U+0078
|
||||
{ 837, 9, 11, 11, 1, -7 }, // 0x79 'y' U+0079
|
||||
{ 850, 7, 8, 11, 2, -7 }, // 0x7a 'z' U+007A
|
||||
{ 857, 4, 13, 11, 3, -10 }, // 0x7b '{' U+007B
|
||||
{ 864, 1, 13, 11, 5, -10 }, // 0x7c '|' U+007C
|
||||
{ 866, 5, 13, 11, 3, -10 }, // 0x7d '}' U+007D
|
||||
{ 875, 7, 2, 11, 2, -5 }, // 0x7e '~' U+007E
|
||||
{ 877, 11, 14, 11, 0, -11 }, // 0x7f 'REPLACEMENT CHARACTER *' U+2370
|
||||
{ 897, 1, 1, 11, 0, 0 }, // 0x80 'NO-BREAK SPACE' U+00A0
|
||||
{ 898, 2, 11, 11, 4, -7 }, // 0x81 'INVERTED EXCLAMATION MARK' U+00A1
|
||||
{ 901, 6, 11, 11, 2, -10 }, // 0x82 'CENT SIGN' U+00A2
|
||||
{ 910, 8, 10, 11, 1, -9 }, // 0x83 'POUND SIGN' U+00A3
|
||||
{ 920, 9, 10, 11, 1, -9 }, // 0x84 'EURO SIGN *' U+20AC
|
||||
{ 932, 9, 10, 11, 1, -9 }, // 0x85 'YEN SIGN' U+00A5
|
||||
{ 944, 7, 13, 11, 2, -12 }, // 0x86 'LATIN CAPITAL LETTER S WITH CARON *' U+0160
|
||||
{ 956, 9, 12, 11, 1, -10 }, // 0x87 'SECTION SIGN' U+00A7
|
||||
{ 970, 7, 12, 11, 2, -11 }, // 0x88 'LATIN SMALL LETTER S WITH CARON *' U+0161
|
||||
{ 981, 11, 10, 11, 0, -9 }, // 0x89 'COPYRIGHT SIGN' U+00A9
|
||||
{ 995, 5, 5, 11, 3, -9 }, // 0x8a 'FEMININE ORDINAL INDICATOR' U+00AA
|
||||
{ 999, 9, 8, 11, 1, -7 }, // 0x8b 'LEFT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00AB
|
||||
{ 1008, 9, 5, 11, 1, -7 }, // 0x8c 'NOT SIGN' U+00AC
|
||||
{ 1014, 9, 1, 11, 1, -5 }, // 0x8d 'SOFT HYPHEN' U+00AD
|
||||
{ 1016, 11, 10, 11, 0, -9 }, // 0x8e 'REGISTERED SIGN' U+00AE
|
||||
{ 1030, 5, 1, 11, 3, -10 }, // 0x8f 'MACRON' U+00AF
|
||||
{ 1031, 5, 5, 11, 3, -10 }, // 0x90 'DEGREE SIGN' U+00B0
|
||||
{ 1035, 9, 10, 11, 1, -9 }, // 0x91 'PLUS-MINUS SIGN' U+00B1
|
||||
{ 1047, 4, 6, 11, 3, -10 }, // 0x92 'SUPERSCRIPT TWO' U+00B2
|
||||
{ 1050, 4, 6, 11, 3, -10 }, // 0x93 'SUPERSCRIPT THREE' U+00B3
|
||||
{ 1053, 7, 14, 11, 2, -13 }, // 0x94 'LATIN CAPITAL LETTER Z WITH CARON *' U+017D
|
||||
{ 1066, 9, 12, 11, 1, -7 }, // 0x95 'MICRO SIGN' U+00B5
|
||||
{ 1080, 8, 12, 11, 1, -10 }, // 0x96 'PILCROW SIGN' U+00B6
|
||||
{ 1092, 2, 2, 11, 4, -4 }, // 0x97 'MIDDLE DOT' U+00B7
|
||||
{ 1093, 7, 12, 11, 2, -11 }, // 0x98 'LATIN SMALL LETTER Z WITH CARON *' U+017E
|
||||
{ 1104, 4, 6, 11, 3, -10 }, // 0x99 'SUPERSCRIPT ONE' U+00B9
|
||||
{ 1107, 5, 5, 11, 3, -9 }, // 0x9a 'MASCULINE ORDINAL INDICATOR' U+00BA
|
||||
{ 1111, 9, 8, 11, 1, -7 }, // 0x9b 'RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00BB
|
||||
{ 1120, 11, 10, 11, 0, -9 }, // 0x9c 'LATIN CAPITAL LIGATURE OE *' U+0152
|
||||
{ 1134, 10, 8, 11, 0, -7 }, // 0x9d 'LATIN SMALL LIGATURE OE *' U+0153
|
||||
{ 1144, 9, 13, 11, 1, -12 }, // 0x9e 'LATIN CAPITAL LETTER Y WITH DIAERESIS *' U+0178
|
||||
{ 1159, 6, 11, 11, 2, -7 }, // 0x9f 'INVERTED QUESTION MARK' U+00BF
|
||||
{ 1168, 11, 14, 11, 0, -13 }, // 0xa0 'LATIN CAPITAL LETTER A WITH GRAVE' U+00C0
|
||||
{ 1188, 11, 14, 11, 0, -13 }, // 0xa1 'LATIN CAPITAL LETTER A WITH ACUTE' U+00C1
|
||||
{ 1208, 11, 14, 11, 0, -13 }, // 0xa2 'LATIN CAPITAL LETTER A WITH CIRCUMFLEX' U+00C2
|
||||
{ 1228, 11, 13, 11, 0, -12 }, // 0xa3 'LATIN CAPITAL LETTER A WITH TILDE' U+00C3
|
||||
{ 1246, 11, 13, 11, 0, -12 }, // 0xa4 'LATIN CAPITAL LETTER A WITH DIAERESIS' U+00C4
|
||||
{ 1264, 11, 14, 11, 0, -13 }, // 0xa5 'LATIN CAPITAL LETTER A WITH RING ABOVE' U+00C5
|
||||
{ 1284, 11, 10, 11, 0, -9 }, // 0xa6 'LATIN CAPITAL LETTER AE' U+00C6
|
||||
{ 1298, 9, 13, 11, 1, -9 }, // 0xa7 'LATIN CAPITAL LETTER C WITH CEDILLA' U+00C7
|
||||
{ 1313, 8, 14, 11, 1, -13 }, // 0xa8 'LATIN CAPITAL LETTER E WITH GRAVE' U+00C8
|
||||
{ 1327, 8, 14, 11, 1, -13 }, // 0xa9 'LATIN CAPITAL LETTER E WITH ACUTE' U+00C9
|
||||
{ 1341, 8, 14, 11, 1, -13 }, // 0xaa 'LATIN CAPITAL LETTER E WITH CIRCUMFLEX' U+00CA
|
||||
{ 1355, 8, 13, 11, 1, -12 }, // 0xab 'LATIN CAPITAL LETTER E WITH DIAERESIS' U+00CB
|
||||
{ 1368, 7, 14, 11, 2, -13 }, // 0xac 'LATIN CAPITAL LETTER I WITH GRAVE' U+00CC
|
||||
{ 1381, 7, 14, 11, 2, -13 }, // 0xad 'LATIN CAPITAL LETTER I WITH ACUTE' U+00CD
|
||||
{ 1394, 7, 14, 11, 2, -13 }, // 0xae 'LATIN CAPITAL LETTER I WITH CIRCUMFLEX' U+00CE
|
||||
{ 1407, 7, 13, 11, 2, -12 }, // 0xaf 'LATIN CAPITAL LETTER I WITH DIAERESIS' U+00CF
|
||||
{ 1419, 9, 10, 11, 0, -9 }, // 0xb0 'LATIN CAPITAL LETTER ETH' U+00D0
|
||||
{ 1431, 10, 13, 11, 0, -12 }, // 0xb1 'LATIN CAPITAL LETTER N WITH TILDE' U+00D1
|
||||
{ 1448, 9, 14, 11, 1, -13 }, // 0xb2 'LATIN CAPITAL LETTER O WITH GRAVE' U+00D2
|
||||
{ 1464, 9, 14, 11, 1, -13 }, // 0xb3 'LATIN CAPITAL LETTER O WITH ACUTE' U+00D3
|
||||
{ 1480, 9, 14, 11, 1, -13 }, // 0xb4 'LATIN CAPITAL LETTER O WITH CIRCUMFLEX' U+00D4
|
||||
{ 1496, 9, 13, 11, 1, -12 }, // 0xb5 'LATIN CAPITAL LETTER O WITH TILDE' U+00D5
|
||||
{ 1511, 9, 13, 11, 1, -12 }, // 0xb6 'LATIN CAPITAL LETTER O WITH DIAERESIS' U+00D6
|
||||
{ 1526, 7, 6, 11, 2, -7 }, // 0xb7 'MULTIPLICATION SIGN' U+00D7
|
||||
{ 1532, 9, 12, 11, 1, -10 }, // 0xb8 'LATIN CAPITAL LETTER O WITH STROKE' U+00D8
|
||||
{ 1546, 9, 14, 11, 1, -13 }, // 0xb9 'LATIN CAPITAL LETTER U WITH GRAVE' U+00D9
|
||||
{ 1562, 9, 14, 11, 1, -13 }, // 0xba 'LATIN CAPITAL LETTER U WITH ACUTE' U+00DA
|
||||
{ 1578, 9, 14, 11, 1, -13 }, // 0xbb 'LATIN CAPITAL LETTER U WITH CIRCUMFLEX' U+00DB
|
||||
{ 1594, 9, 13, 11, 1, -12 }, // 0xbc 'LATIN CAPITAL LETTER U WITH DIAERESIS' U+00DC
|
||||
{ 1609, 9, 14, 11, 1, -13 }, // 0xbd 'LATIN CAPITAL LETTER Y WITH ACUTE' U+00DD
|
||||
{ 1625, 8, 10, 11, 1, -9 }, // 0xbe 'LATIN CAPITAL LETTER THORN' U+00DE
|
||||
{ 1635, 9, 11, 11, 0, -10 }, // 0xbf 'LATIN SMALL LETTER SHARP S' U+00DF
|
||||
{ 1648, 9, 12, 11, 1, -11 }, // 0xc0 'LATIN SMALL LETTER A WITH GRAVE' U+00E0
|
||||
{ 1662, 9, 12, 11, 1, -11 }, // 0xc1 'LATIN SMALL LETTER A WITH ACUTE' U+00E1
|
||||
{ 1676, 9, 11, 11, 1, -10 }, // 0xc2 'LATIN SMALL LETTER A WITH CIRCUMFLEX' U+00E2
|
||||
{ 1689, 9, 10, 11, 1, -9 }, // 0xc3 'LATIN SMALL LETTER A WITH TILDE' U+00E3
|
||||
{ 1701, 9, 11, 11, 1, -10 }, // 0xc4 'LATIN SMALL LETTER A WITH DIAERESIS' U+00E4
|
||||
{ 1714, 9, 12, 11, 1, -11 }, // 0xc5 'LATIN SMALL LETTER A WITH RING ABOVE' U+00E5
|
||||
{ 1728, 10, 8, 11, 0, -7 }, // 0xc6 'LATIN SMALL LETTER AE' U+00E6
|
||||
{ 1738, 8, 11, 11, 2, -7 }, // 0xc7 'LATIN SMALL LETTER C WITH CEDILLA' U+00E7
|
||||
{ 1749, 8, 12, 11, 1, -11 }, // 0xc8 'LATIN SMALL LETTER E WITH GRAVE' U+00E8
|
||||
{ 1761, 8, 12, 11, 1, -11 }, // 0xc9 'LATIN SMALL LETTER E WITH ACUTE' U+00E9
|
||||
{ 1773, 8, 11, 11, 1, -10 }, // 0xca 'LATIN SMALL LETTER E WITH CIRCUMFLEX' U+00EA
|
||||
{ 1784, 8, 11, 11, 1, -10 }, // 0xcb 'LATIN SMALL LETTER E WITH DIAERESIS' U+00EB
|
||||
{ 1795, 7, 12, 11, 2, -11 }, // 0xcc 'LATIN SMALL LETTER I WITH GRAVE' U+00EC
|
||||
{ 1806, 7, 12, 11, 2, -11 }, // 0xcd 'LATIN SMALL LETTER I WITH ACUTE' U+00ED
|
||||
{ 1817, 7, 11, 11, 2, -10 }, // 0xce 'LATIN SMALL LETTER I WITH CIRCUMFLEX' U+00EE
|
||||
{ 1827, 7, 11, 11, 2, -10 }, // 0xcf 'LATIN SMALL LETTER I WITH DIAERESIS' U+00EF
|
||||
{ 1837, 9, 11, 11, 1, -10 }, // 0xd0 'LATIN SMALL LETTER ETH' U+00F0
|
||||
{ 1850, 9, 10, 11, 1, -9 }, // 0xd1 'LATIN SMALL LETTER N WITH TILDE' U+00F1
|
||||
{ 1862, 9, 12, 11, 1, -11 }, // 0xd2 'LATIN SMALL LETTER O WITH GRAVE' U+00F2
|
||||
{ 1876, 9, 12, 11, 1, -11 }, // 0xd3 'LATIN SMALL LETTER O WITH ACUTE' U+00F3
|
||||
{ 1890, 9, 11, 11, 1, -10 }, // 0xd4 'LATIN SMALL LETTER O WITH CIRCUMFLEX' U+00F4
|
||||
{ 1903, 9, 10, 11, 1, -9 }, // 0xd5 'LATIN SMALL LETTER O WITH TILDE' U+00F5
|
||||
{ 1915, 9, 11, 11, 1, -10 }, // 0xd6 'LATIN SMALL LETTER O WITH DIAERESIS' U+00F6
|
||||
{ 1928, 9, 10, 11, 1, -9 }, // 0xd7 'DIVISION SIGN' U+00F7
|
||||
{ 1940, 9, 9, 11, 1, -7 }, // 0xd8 'LATIN SMALL LETTER O WITH STROKE' U+00F8
|
||||
{ 1951, 9, 12, 11, 1, -11 }, // 0xd9 'LATIN SMALL LETTER U WITH GRAVE' U+00F9
|
||||
{ 1965, 9, 12, 11, 1, -11 }, // 0xda 'LATIN SMALL LETTER U WITH ACUTE' U+00FA
|
||||
{ 1979, 9, 11, 11, 1, -10 }, // 0xdb 'LATIN SMALL LETTER U WITH CIRCUMFLEX' U+00FB
|
||||
{ 1992, 9, 11, 11, 1, -10 }, // 0xdc 'LATIN SMALL LETTER U WITH DIAERESIS' U+00FC
|
||||
{ 2005, 9, 15, 11, 1, -11 }, // 0xdd 'LATIN SMALL LETTER Y WITH ACUTE' U+00FD
|
||||
{ 2022, 10, 14, 11, 0, -10 }, // 0xde 'LATIN SMALL LETTER THORN' U+00FE
|
||||
{ 2040, 9, 14, 11, 1, -10 } }; // 0xdf 'LATIN SMALL LETTER Y WITH DIAERESIS' U+000FF
|
||||
|
||||
const GFXfont FreeMono9pt8b PROGMEM = {
|
||||
(uint8_t *)FreeMono9pt8bBitmaps,
|
||||
(GFXglyph *)FreeMono9pt8bGlyphs,
|
||||
0x20, 0xDF, 19 };
|
||||
|
||||
// Approx. 3407 bytes
|
0
libraries/fonts/FreeSans12pt7b.h → RX_FSK/src/fonts/FreeSans12pt7b.h
Executable file → Normal file
0
libraries/fonts/FreeSans12pt7b.h → RX_FSK/src/fonts/FreeSans12pt7b.h
Executable file → Normal file
596
RX_FSK/src/fonts/FreeSans12pt8b.h
Normal file
596
RX_FSK/src/fonts/FreeSans12pt8b.h
Normal file
|
@ -0,0 +1,596 @@
|
|||
const uint8_t FreeSans12pt8bBitmaps[] PROGMEM = {
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xF3, 0xF0, 0xCF, 0x3C, 0xF3, 0x4D, 0x10, 0x06,
|
||||
0x30, 0x31, 0x01, 0x18, 0x18, 0xC0, 0xC6, 0x3F, 0xFD, 0xFF, 0xE1, 0x98,
|
||||
0x18, 0xC0, 0xC6, 0x06, 0x31, 0xFF, 0xE1, 0x88, 0x08, 0xC0, 0xC6, 0x06,
|
||||
0x30, 0x31, 0x80, 0x04, 0x03, 0xF1, 0xFF, 0x32, 0x7C, 0x47, 0x88, 0xF1,
|
||||
0x07, 0x20, 0x7C, 0x07, 0xF0, 0x1F, 0x02, 0x70, 0x47, 0x88, 0xF1, 0x1E,
|
||||
0x23, 0x64, 0xE7, 0xF8, 0x10, 0x02, 0x00, 0x40, 0x00, 0x06, 0x07, 0xC0,
|
||||
0x40, 0xE6, 0x0C, 0x0C, 0x30, 0x80, 0x83, 0x18, 0x0C, 0x31, 0x00, 0xC6,
|
||||
0x30, 0x07, 0xE2, 0x00, 0x38, 0x60, 0x00, 0x0C, 0x38, 0x00, 0xC7, 0xC0,
|
||||
0x18, 0xC6, 0x01, 0x18, 0x30, 0x31, 0x83, 0x02, 0x08, 0x20, 0x60, 0xC6,
|
||||
0x04, 0x07, 0xC0, 0x0F, 0x00, 0x7E, 0x03, 0x8C, 0x0C, 0x30, 0x30, 0xC0,
|
||||
0x67, 0x01, 0xF8, 0x03, 0xC0, 0x1E, 0x00, 0xCC, 0x66, 0x39, 0xB0, 0x7C,
|
||||
0xC0, 0xF3, 0x01, 0x8E, 0x0F, 0x1C, 0xFE, 0x3F, 0x9C, 0x10, 0x00, 0xFF,
|
||||
0x50, 0x08, 0x8C, 0x46, 0x31, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC2,
|
||||
0x18, 0x43, 0x08, 0x60, 0x86, 0x18, 0xC3, 0x18, 0x43, 0x18, 0xC6, 0x31,
|
||||
0x8C, 0x63, 0x11, 0x8C, 0x46, 0x23, 0x00, 0x10, 0x22, 0x4F, 0xF3, 0x85,
|
||||
0x1B, 0x00, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x0F, 0xFF, 0x06,
|
||||
0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xFF, 0x97, 0xA0, 0xFC, 0xFF,
|
||||
0x80, 0x06, 0x0C, 0x10, 0x20, 0xC1, 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x02,
|
||||
0x0C, 0x10, 0x20, 0xC1, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x6E, 0x0F,
|
||||
0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3E, 0x06, 0xC1,
|
||||
0xD8, 0x31, 0xCE, 0x3F, 0x80, 0x80, 0x04, 0x30, 0xFF, 0xFC, 0x30, 0xC3,
|
||||
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x1F, 0x07, 0xF9, 0xC3, 0xB0,
|
||||
0x3C, 0x07, 0x80, 0xC0, 0x18, 0x07, 0x01, 0xC0, 0xF0, 0x78, 0x1C, 0x07,
|
||||
0x01, 0xC0, 0x30, 0x07, 0xFF, 0xFF, 0xE0, 0x1F, 0x0F, 0xF9, 0x83, 0x70,
|
||||
0x7C, 0x0E, 0x01, 0xC0, 0x30, 0x7C, 0x0F, 0x80, 0x38, 0x01, 0x80, 0x3C,
|
||||
0x07, 0x80, 0xF8, 0x3B, 0x8E, 0x3F, 0x80, 0x80, 0x01, 0x80, 0x70, 0x0E,
|
||||
0x03, 0xC0, 0xD8, 0x33, 0x06, 0x61, 0x8C, 0x61, 0x8C, 0x33, 0x06, 0x7F,
|
||||
0xFF, 0xFE, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x3F, 0xCF, 0xF9, 0x80,
|
||||
0x30, 0x06, 0x00, 0xC0, 0x1F, 0xE3, 0xFE, 0xE0, 0xE0, 0x0C, 0x01, 0x80,
|
||||
0x30, 0x07, 0x80, 0xF8, 0x3B, 0x8E, 0x3F, 0x80, 0x80, 0x0F, 0x07, 0xF9,
|
||||
0xC3, 0x30, 0x36, 0x01, 0x80, 0x30, 0x86, 0xFC, 0xF9, 0xDC, 0x1F, 0x81,
|
||||
0xE0, 0x3C, 0x06, 0xC0, 0xD8, 0x3B, 0xCE, 0x3F, 0x80, 0x80, 0xFF, 0xFF,
|
||||
0xFC, 0x01, 0x80, 0x60, 0x0C, 0x03, 0x00, 0xC0, 0x18, 0x06, 0x00, 0xC0,
|
||||
0x30, 0x06, 0x00, 0xC0, 0x30, 0x06, 0x00, 0xC0, 0x38, 0x00, 0x1F, 0x07,
|
||||
0xF9, 0xC3, 0x30, 0x7E, 0x06, 0xC1, 0xD8, 0x31, 0xFC, 0x3F, 0x8E, 0x1B,
|
||||
0x81, 0xE0, 0x3C, 0x07, 0x80, 0xF8, 0x3B, 0x8E, 0x3F, 0x80, 0x80, 0x1F,
|
||||
0x07, 0xF1, 0x87, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x07, 0x60, 0xEF,
|
||||
0xFC, 0x7D, 0x80, 0x30, 0x07, 0x81, 0x98, 0x33, 0x9C, 0x3F, 0x00, 0x80,
|
||||
0xFC, 0x00, 0x0F, 0xC0, 0xFC, 0x00, 0x0F, 0xD7, 0x00, 0x00, 0x30, 0x1F,
|
||||
0x07, 0x81, 0xE0, 0xF8, 0x0E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0xC0, 0x0F,
|
||||
0x00, 0x30, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0xC0, 0x0F,
|
||||
0x80, 0x1E, 0x00, 0x78, 0x01, 0xF0, 0x03, 0x01, 0xE0, 0x78, 0x3E, 0x0F,
|
||||
0x00, 0xC0, 0x00, 0x1E, 0x1F, 0xE6, 0x1F, 0x03, 0xC0, 0xF0, 0x30, 0x0C,
|
||||
0x06, 0x03, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x0C,
|
||||
0x03, 0x00, 0x00, 0x7C, 0x00, 0x0F, 0xFE, 0x00, 0x70, 0x3C, 0x07, 0x00,
|
||||
0x38, 0x38, 0x00, 0x70, 0xC0, 0x40, 0xE6, 0x0F, 0xD9, 0x98, 0x71, 0xC7,
|
||||
0xC3, 0x87, 0x0F, 0x0C, 0x0C, 0x3C, 0x30, 0x70, 0xF1, 0xC1, 0x86, 0xC7,
|
||||
0x06, 0x1B, 0x1C, 0x38, 0xEC, 0x39, 0xE7, 0x18, 0x7D, 0xF8, 0x70, 0x01,
|
||||
0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0xF3, 0xC0, 0x03, 0xFF, 0x00,
|
||||
0x01, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x06, 0x60, 0x06, 0x60,
|
||||
0x0E, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18, 0x1F, 0xF8,
|
||||
0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06, 0x60, 0x07,
|
||||
0xFE, 0x07, 0xFF, 0x30, 0x79, 0x80, 0xEC, 0x03, 0x60, 0x1B, 0x00, 0xD8,
|
||||
0x0C, 0xFF, 0xC7, 0xFF, 0x30, 0x1D, 0x80, 0x7C, 0x01, 0xE0, 0x0F, 0x00,
|
||||
0xF8, 0x0E, 0xFF, 0xF7, 0xFE, 0x00, 0x03, 0xC0, 0x1F, 0xF0, 0xF0, 0xE1,
|
||||
0x80, 0xE7, 0x00, 0xEC, 0x01, 0xF8, 0x00, 0x70, 0x00, 0xC0, 0x01, 0x80,
|
||||
0x03, 0x00, 0x07, 0x00, 0x06, 0x00, 0x6C, 0x01, 0xDC, 0x03, 0x9C, 0x0E,
|
||||
0x1F, 0x78, 0x1F, 0xE0, 0x04, 0x00, 0xFE, 0x03, 0xFF, 0x8C, 0x1F, 0x30,
|
||||
0x0E, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C,
|
||||
0x00, 0xF0, 0x03, 0xC0, 0x1F, 0x00, 0x6C, 0x03, 0xB0, 0x1C, 0xFF, 0xE3,
|
||||
0xFF, 0x00, 0xFF, 0xF7, 0xFF, 0xB0, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03,
|
||||
0x00, 0x18, 0x00, 0xFF, 0xF7, 0xFF, 0xB0, 0x01, 0x80, 0x0C, 0x00, 0x60,
|
||||
0x03, 0x00, 0x18, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xFF, 0xEF, 0xFE, 0xC0,
|
||||
0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0x03,
|
||||
0xE0, 0x0F, 0xF8, 0x1E, 0x3C, 0x38, 0x0E, 0x70, 0x06, 0x60, 0x07, 0xE0,
|
||||
0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x7F, 0xC0, 0x7F, 0xE0, 0x03, 0xE0,
|
||||
0x03, 0x60, 0x03, 0x70, 0x07, 0x38, 0x0F, 0x1F, 0x7B, 0x0F, 0xF3, 0x00,
|
||||
0x80, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00,
|
||||
0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F,
|
||||
0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFC, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03,
|
||||
0x00, 0xC0, 0x30, 0x0C, 0x03, 0xE0, 0xF8, 0x3E, 0x0D, 0x87, 0x73, 0x8F,
|
||||
0xE0, 0x40, 0xC0, 0x1F, 0x00, 0xEC, 0x07, 0x30, 0x38, 0xC1, 0xC3, 0x0E,
|
||||
0x0C, 0x70, 0x33, 0x80, 0xDE, 0x03, 0xFC, 0x0F, 0x38, 0x38, 0x60, 0xC1,
|
||||
0xC3, 0x03, 0x8C, 0x06, 0x30, 0x1C, 0xC0, 0x3B, 0x00, 0x60, 0xC0, 0x18,
|
||||
0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03,
|
||||
0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xFF, 0xFF, 0xFC, 0xE0,
|
||||
0x07, 0xE0, 0x07, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xD8, 0x1B, 0xD8,
|
||||
0x1B, 0xD8, 0x1B, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xC6, 0x63, 0xC6,
|
||||
0x63, 0xC6, 0x63, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC1, 0x83, 0xC0,
|
||||
0x1F, 0x80, 0x7F, 0x01, 0xFC, 0x07, 0xF8, 0x1F, 0x60, 0x7C, 0xC1, 0xF3,
|
||||
0x87, 0xC6, 0x1F, 0x0C, 0x7C, 0x39, 0xF0, 0x67, 0xC1, 0xDF, 0x03, 0xFC,
|
||||
0x07, 0xF0, 0x1F, 0xC0, 0x3F, 0x00, 0x70, 0x03, 0xE0, 0x07, 0xFC, 0x0F,
|
||||
0x8F, 0x07, 0x01, 0xC7, 0x00, 0x73, 0x00, 0x1B, 0x80, 0x0D, 0x80, 0x07,
|
||||
0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x7E, 0x00, 0x33, 0x00,
|
||||
0x19, 0xC0, 0x1C, 0x70, 0x1C, 0x1F, 0x7C, 0x07, 0xFC, 0x00, 0x20, 0x00,
|
||||
0xFE, 0x07, 0xFF, 0x30, 0x7D, 0x80, 0x6C, 0x03, 0xE0, 0x1F, 0x00, 0xF8,
|
||||
0x07, 0xC0, 0xF7, 0xFF, 0x3F, 0xC1, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00,
|
||||
0x18, 0x00, 0xC0, 0x06, 0x00, 0x00, 0x03, 0xE0, 0x07, 0xFC, 0x0F, 0x8F,
|
||||
0x07, 0x01, 0xC7, 0x00, 0x73, 0x00, 0x1B, 0x80, 0x0D, 0x80, 0x07, 0xC0,
|
||||
0x01, 0xE0, 0x00, 0xF0, 0x00, 0xF8, 0x00, 0x7E, 0x00, 0x33, 0x01, 0x19,
|
||||
0xC0, 0xDC, 0x70, 0x3C, 0x1F, 0x7E, 0x07, 0xFF, 0x80, 0x20, 0xC0, 0xFF,
|
||||
0x03, 0xFF, 0xCC, 0x0F, 0xB0, 0x06, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xB0,
|
||||
0x06, 0xC0, 0xF3, 0xFF, 0x8C, 0x0F, 0x30, 0x06, 0xC0, 0x1B, 0x00, 0x6C,
|
||||
0x01, 0xB0, 0x06, 0xC0, 0x1F, 0x00, 0x70, 0x07, 0x80, 0xFF, 0x87, 0x87,
|
||||
0x18, 0x0E, 0x60, 0x19, 0x80, 0x66, 0x00, 0x1E, 0x00, 0x3F, 0x80, 0x3F,
|
||||
0xC0, 0x0F, 0x80, 0x07, 0xC0, 0x1F, 0x00, 0x3E, 0x01, 0xDC, 0x06, 0x7E,
|
||||
0xF8, 0x7F, 0x80, 0x20, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x38, 0x00, 0xE0,
|
||||
0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38,
|
||||
0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E,
|
||||
0x00, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00,
|
||||
0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F,
|
||||
0x80, 0x6C, 0x07, 0x7D, 0xF1, 0xFF, 0x00, 0x80, 0xC0, 0x0F, 0x00, 0x3E,
|
||||
0x01, 0xD8, 0x06, 0x70, 0x18, 0xC0, 0xE3, 0x03, 0x0E, 0x0C, 0x18, 0x70,
|
||||
0x61, 0x81, 0xC6, 0x03, 0x38, 0x0C, 0xC0, 0x3B, 0x00, 0x6C, 0x01, 0xE0,
|
||||
0x07, 0x80, 0x0E, 0x00, 0xC0, 0x70, 0x1E, 0x03, 0x80, 0xF0, 0x1C, 0x0F,
|
||||
0xC1, 0xE0, 0x76, 0x0D, 0x83, 0x30, 0x6C, 0x19, 0x83, 0x61, 0xCE, 0x33,
|
||||
0x8E, 0x31, 0x8C, 0x61, 0x8C, 0x63, 0x0C, 0xE3, 0x18, 0x76, 0x0D, 0xC1,
|
||||
0xB0, 0x6C, 0x0D, 0x83, 0x60, 0x78, 0x1F, 0x03, 0xC0, 0x78, 0x0E, 0x03,
|
||||
0x80, 0x70, 0x1C, 0x00, 0xE0, 0x0C, 0xC0, 0x39, 0xC0, 0xE1, 0xC1, 0x81,
|
||||
0x87, 0x03, 0x9C, 0x03, 0xB0, 0x03, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x1E,
|
||||
0x00, 0x76, 0x01, 0xCE, 0x03, 0x0C, 0x0E, 0x0C, 0x38, 0x1C, 0x60, 0x1D,
|
||||
0xC0, 0x38, 0xE0, 0x07, 0x70, 0x06, 0x30, 0x0E, 0x38, 0x1C, 0x18, 0x18,
|
||||
0x1C, 0x38, 0x0E, 0x30, 0x06, 0x70, 0x07, 0x60, 0x03, 0xC0, 0x01, 0xC0,
|
||||
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
|
||||
0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xC0, 0x0E, 0x00, 0xE0, 0x06, 0x00, 0x70,
|
||||
0x07, 0x00, 0x70, 0x07, 0x00, 0x38, 0x03, 0x80, 0x38, 0x03, 0x80, 0x18,
|
||||
0x01, 0xC0, 0x1C, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xCC, 0xCC, 0xCC,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCF, 0xF0, 0x81, 0x03, 0x02, 0x04,
|
||||
0x0C, 0x08, 0x10, 0x30, 0x20, 0x40, 0xC0, 0x81, 0x03, 0x02, 0x04, 0x0C,
|
||||
0xFF, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0xF0,
|
||||
0x0C, 0x0E, 0x05, 0x86, 0xC3, 0x21, 0x19, 0x8C, 0x83, 0xC1, 0x80, 0xFF,
|
||||
0xFE, 0xC3, 0x0C, 0x20, 0x1F, 0x07, 0xFC, 0x60, 0xC6, 0x0C, 0x00, 0xC0,
|
||||
0x1C, 0x3F, 0xC7, 0x8C, 0xE0, 0xCC, 0x0C, 0xC0, 0xCE, 0x3E, 0x7E, 0x70,
|
||||
0x02, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0xF0, 0xDF, 0xCF,
|
||||
0x0E, 0xE0, 0x6E, 0x06, 0xC0, 0x6C, 0x07, 0xC0, 0x7C, 0x06, 0xE0, 0x6E,
|
||||
0x0E, 0xF9, 0xCD, 0xF8, 0x00, 0x00, 0x1F, 0x0F, 0xE6, 0x1F, 0x83, 0xC0,
|
||||
0xF0, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x3E, 0x0D, 0xC7, 0x3F, 0x81, 0x00,
|
||||
0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x3C, 0xDF, 0xDB, 0x8F, 0xE0,
|
||||
0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x3F, 0x07, 0x7B, 0xE7,
|
||||
0xEC, 0x10, 0x00, 0x0F, 0x07, 0xF9, 0xC3, 0x30, 0x3C, 0x07, 0x80, 0xFF,
|
||||
0xFE, 0x00, 0xC0, 0x18, 0x0D, 0x83, 0xBC, 0xE3, 0xF8, 0x08, 0x00, 0x04,
|
||||
0x73, 0x0C, 0x33, 0xFF, 0xCC, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30,
|
||||
0xC0, 0x1E, 0x67, 0xED, 0x87, 0xF0, 0x7C, 0x0F, 0x80, 0xF0, 0x1E, 0x03,
|
||||
0xC0, 0x78, 0x1F, 0x83, 0xB9, 0xF3, 0xF6, 0x00, 0xF0, 0x37, 0x06, 0x7F,
|
||||
0xC7, 0xE0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x33, 0xCF, 0xFB, 0x87,
|
||||
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0,
|
||||
0x30, 0xFC, 0x3F, 0xFF, 0xFF, 0xF0, 0x33, 0x30, 0x03, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x33, 0x3F, 0xE0, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C,
|
||||
0x01, 0x81, 0xB0, 0x66, 0x18, 0xC6, 0x19, 0x83, 0x70, 0x7B, 0x0E, 0x71,
|
||||
0x86, 0x30, 0xE6, 0x0C, 0xC0, 0xD8, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
|
||||
0xDE, 0x1E, 0xFF, 0x7F, 0xE3, 0xC3, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83,
|
||||
0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83,
|
||||
0xC1, 0x83, 0xCF, 0x3F, 0xEE, 0x1F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
||||
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xC0, 0x1F, 0x07, 0xF1, 0xC7, 0x70,
|
||||
0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0D, 0x83, 0xBD, 0xE3,
|
||||
0xF8, 0x08, 0x00, 0xCF, 0x0D, 0xFC, 0xF0, 0xCE, 0x06, 0xE0, 0x6C, 0x06,
|
||||
0xC0, 0x7C, 0x07, 0xC0, 0x6E, 0x06, 0xE0, 0xEF, 0x9C, 0xDF, 0x8C, 0x00,
|
||||
0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0x1E, 0x6F, 0xFD, 0xC7, 0xF0, 0x7C,
|
||||
0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x1F, 0x83, 0xBD, 0xF3, 0xF6,
|
||||
0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0xDF, 0xFF, 0x30, 0xC3, 0x0C,
|
||||
0x30, 0xC3, 0x0C, 0x30, 0xC0, 0x1E, 0x1F, 0xEE, 0x1B, 0x06, 0xC0, 0x3C,
|
||||
0x07, 0xF0, 0x3E, 0x01, 0xF0, 0x3C, 0x0F, 0xCE, 0x7F, 0x82, 0x00, 0x30,
|
||||
0xC3, 0x3F, 0xFC, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0F, 0x08,
|
||||
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC1, 0xF0,
|
||||
0x7C, 0x1F, 0x8F, 0x7E, 0xC4, 0x00, 0xE0, 0x76, 0x06, 0x60, 0x67, 0x0C,
|
||||
0x30, 0xC3, 0x0C, 0x39, 0x81, 0x98, 0x19, 0x81, 0xB0, 0x0F, 0x00, 0xE0,
|
||||
0x0E, 0x00, 0xC1, 0xC1, 0xF0, 0xE1, 0xD8, 0x70, 0xCC, 0x2C, 0x66, 0x36,
|
||||
0x31, 0x9B, 0x38, 0xCD, 0x98, 0x64, 0x6C, 0x36, 0x36, 0x0F, 0x1E, 0x07,
|
||||
0x8F, 0x03, 0x83, 0x80, 0xC1, 0x80, 0x60, 0x6E, 0x1C, 0xC3, 0x0C, 0xC1,
|
||||
0xF0, 0x1E, 0x01, 0x80, 0x78, 0x0F, 0x03, 0x30, 0xC7, 0x38, 0x66, 0x06,
|
||||
0x60, 0x6C, 0x0D, 0x81, 0x98, 0x63, 0x0C, 0x63, 0x86, 0x60, 0xCC, 0x1B,
|
||||
0x81, 0xE0, 0x3C, 0x07, 0x00, 0x60, 0x0C, 0x03, 0x00, 0x60, 0x78, 0x0F,
|
||||
0x00, 0xFF, 0xFF, 0xF0, 0x18, 0x0E, 0x07, 0x03, 0x80, 0xC0, 0x60, 0x30,
|
||||
0x1C, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0x04, 0xF3, 0x0C, 0x30, 0xC3, 0x0C,
|
||||
0x30, 0xC6, 0x30, 0xE1, 0x83, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xE1, 0xC0,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x87, 0x18, 0x42, 0x10, 0x84, 0x21,
|
||||
0x8C, 0x31, 0x98, 0xC4, 0x21, 0x08, 0x42, 0x73, 0x80, 0x00, 0x3E, 0x1D,
|
||||
0xC6, 0x1F, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x01,
|
||||
0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C,
|
||||
0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFC,
|
||||
0xFF, 0xFF, 0xFF, 0xF0, 0x04, 0x00, 0x80, 0x3C, 0x1F, 0xE7, 0x4E, 0xC8,
|
||||
0xD9, 0x1E, 0x20, 0xC4, 0x18, 0x83, 0x10, 0x32, 0x36, 0x46, 0x7B, 0x87,
|
||||
0xE0, 0x30, 0x04, 0x00, 0x80, 0x00, 0x01, 0xF8, 0x79, 0xC6, 0x0E, 0xE0,
|
||||
0x6E, 0x06, 0xE0, 0x06, 0x00, 0x70, 0x0F, 0xF0, 0x38, 0x01, 0x80, 0x18,
|
||||
0x01, 0x00, 0x30, 0x06, 0x00, 0xFF, 0xEE, 0xFF, 0x00, 0x80, 0x01, 0xF0,
|
||||
0x1F, 0xF0, 0xE0, 0x87, 0x00, 0x18, 0x00, 0xC0, 0x0F, 0xFF, 0x3F, 0xFC,
|
||||
0x30, 0x03, 0xFF, 0x8F, 0xFC, 0x0C, 0x00, 0x38, 0x00, 0x60, 0x01, 0xC0,
|
||||
0x03, 0xC6, 0x07, 0xF8, 0x00, 0x00, 0x60, 0x1B, 0x01, 0x8C, 0x0C, 0x60,
|
||||
0xC1, 0x86, 0x0C, 0x60, 0x36, 0x00, 0xF0, 0x07, 0xF1, 0xFF, 0x80, 0xC0,
|
||||
0x06, 0x03, 0xFF, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x0C, 0xC0,
|
||||
0x16, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0xFF, 0x87, 0x87, 0x18, 0x0E,
|
||||
0x60, 0x19, 0x80, 0x66, 0x00, 0x1E, 0x00, 0x3F, 0x80, 0x3F, 0xC0, 0x0F,
|
||||
0x80, 0x07, 0xC0, 0x1F, 0x00, 0x3E, 0x01, 0xDC, 0x06, 0x7E, 0xF8, 0x7F,
|
||||
0x80, 0x20, 0x00, 0x00, 0x03, 0xF0, 0xE7, 0x18, 0x63, 0x0C, 0x60, 0x0E,
|
||||
0x01, 0xF0, 0x67, 0x98, 0x7B, 0x03, 0xE0, 0x37, 0x06, 0xF0, 0xC7, 0x18,
|
||||
0x7E, 0x07, 0x80, 0x31, 0x87, 0x30, 0x67, 0x1C, 0x7F, 0x07, 0xC0, 0x21,
|
||||
0x0C, 0xC1, 0xE0, 0x70, 0x00, 0x07, 0x87, 0xFB, 0x86, 0xC1, 0xB0, 0x0F,
|
||||
0x01, 0xFC, 0x0F, 0x80, 0x7C, 0x0F, 0x03, 0xF3, 0x9F, 0xE0, 0x80, 0x03,
|
||||
0xE0, 0x03, 0xFF, 0x01, 0x80, 0xE0, 0xC0, 0x0C, 0x61, 0xE1, 0xB0, 0xCC,
|
||||
0x6C, 0x61, 0x8F, 0x10, 0x63, 0x8C, 0x00, 0xE3, 0x00, 0x38, 0xC0, 0x0F,
|
||||
0x10, 0x63, 0xC6, 0x18, 0x90, 0xFC, 0x66, 0x1E, 0x30, 0xC0, 0x1C, 0x1C,
|
||||
0x0E, 0x01, 0xFE, 0x00, 0x08, 0x00, 0x39, 0xDB, 0x10, 0x67, 0x50, 0xA3,
|
||||
0x7F, 0x01, 0xFF, 0xF8, 0x00, 0x18, 0xDC, 0xF8, 0xC8, 0x47, 0x31, 0xCE,
|
||||
0x23, 0xFF, 0xFF, 0xFF, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30,
|
||||
0xFC, 0x03, 0xE0, 0x03, 0xFF, 0x01, 0x80, 0xE0, 0xC0, 0x0C, 0x67, 0xF1,
|
||||
0xB1, 0x8E, 0x6C, 0x61, 0x8F, 0x18, 0x63, 0x86, 0x38, 0xE1, 0xFC, 0x38,
|
||||
0x61, 0x8F, 0x18, 0x63, 0xC6, 0x18, 0x91, 0x86, 0x66, 0x60, 0xF0, 0xC0,
|
||||
0x1C, 0x1C, 0x0E, 0x01, 0xFE, 0x00, 0x08, 0x00, 0xFF, 0xF0, 0x7D, 0x8A,
|
||||
0x1C, 0x38, 0x7F, 0x8E, 0x00, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06,
|
||||
0x0F, 0xFF, 0xFF, 0xF0, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x00,
|
||||
0x00, 0x00, 0xFF, 0xF0, 0x3C, 0x66, 0x43, 0x43, 0x02, 0x0E, 0x38, 0x60,
|
||||
0x40, 0xFF, 0x3C, 0x66, 0x42, 0x02, 0x1E, 0x1E, 0x03, 0xC3, 0x43, 0x7E,
|
||||
0x00, 0x08, 0xC0, 0x6C, 0x01, 0xC0, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00,
|
||||
0xE0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x03, 0x80,
|
||||
0x38, 0x03, 0x80, 0x38, 0x01, 0x80, 0x1C, 0x01, 0xC0, 0x0F, 0xFF, 0xFF,
|
||||
0xFC, 0xC0, 0xD8, 0x1B, 0x03, 0x60, 0x6C, 0x0D, 0x81, 0xB0, 0x36, 0x06,
|
||||
0xC1, 0xD8, 0x3B, 0x07, 0x71, 0xEF, 0xEF, 0xA0, 0x30, 0x06, 0x00, 0xC0,
|
||||
0x18, 0x00, 0x03, 0xF3, 0xFF, 0x7E, 0x47, 0xE4, 0xFE, 0x4F, 0xE4, 0xFE,
|
||||
0x4F, 0xE4, 0x7E, 0x47, 0xE4, 0x3E, 0x40, 0xE4, 0x06, 0x40, 0x64, 0x06,
|
||||
0x40, 0x64, 0x06, 0x40, 0x64, 0x06, 0x40, 0x64, 0x06, 0x40, 0x64, 0xFF,
|
||||
0x80, 0x21, 0x0C, 0xC1, 0xE0, 0x30, 0x00, 0x3F, 0xFF, 0xFC, 0x06, 0x03,
|
||||
0x81, 0xC0, 0xE0, 0x30, 0x18, 0x0C, 0x07, 0x03, 0x80, 0xFF, 0xFF, 0xF0,
|
||||
0x33, 0xF3, 0x33, 0x33, 0x33, 0x38, 0xDB, 0x1C, 0x38, 0x70, 0xF1, 0x3E,
|
||||
0x01, 0xFF, 0xF8, 0xC4, 0x73, 0x8C, 0xE2, 0x13, 0x1F, 0x3B, 0x18, 0x00,
|
||||
0x07, 0x8F, 0xFC, 0x7F, 0xBF, 0xF3, 0x87, 0xC0, 0x1C, 0x0F, 0x00, 0x60,
|
||||
0x1C, 0x01, 0x80, 0x30, 0x0E, 0x00, 0xC0, 0x30, 0x03, 0x00, 0xC0, 0x0F,
|
||||
0xFF, 0x00, 0x3F, 0xFC, 0x00, 0xC0, 0x30, 0x03, 0x00, 0xE0, 0x0C, 0x01,
|
||||
0x80, 0x30, 0x06, 0x01, 0xC0, 0x1C, 0x0F, 0x00, 0x3F, 0xEF, 0xFC, 0x3F,
|
||||
0x3F, 0xF0, 0x1F, 0x07, 0x83, 0xF9, 0xFE, 0x71, 0xF8, 0x7E, 0x0F, 0x03,
|
||||
0xC0, 0x60, 0x3C, 0x06, 0x03, 0xC0, 0x7F, 0xFC, 0x06, 0x00, 0xC0, 0x60,
|
||||
0x0C, 0x07, 0x03, 0x60, 0xF0, 0x77, 0xBF, 0xCE, 0x3F, 0x9F, 0xC0, 0x40,
|
||||
0x20, 0x06, 0x60, 0x06, 0x60, 0x00, 0x00, 0xE0, 0x07, 0x70, 0x06, 0x30,
|
||||
0x0E, 0x38, 0x1C, 0x18, 0x18, 0x1C, 0x38, 0x0E, 0x30, 0x06, 0x70, 0x07,
|
||||
0x60, 0x03, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
|
||||
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0C, 0x03, 0x00, 0xC0, 0x00,
|
||||
0x00, 0x03, 0x00, 0xC0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x00, 0xC0, 0xF0,
|
||||
0x3C, 0x0F, 0x86, 0x7F, 0x87, 0x80, 0x07, 0x00, 0x03, 0x00, 0x01, 0x80,
|
||||
0x00, 0x00, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x06, 0x60,
|
||||
0x06, 0x60, 0x0E, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18,
|
||||
0x1F, 0xF8, 0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06,
|
||||
0x60, 0x07, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x01, 0xC0,
|
||||
0x03, 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70,
|
||||
0x0C, 0x30, 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18, 0x1F, 0xF8, 0x3F, 0xFC,
|
||||
0x30, 0x0C, 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06, 0x60, 0x07, 0x03, 0xC0,
|
||||
0x03, 0xC0, 0x06, 0x60, 0x00, 0x00, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
|
||||
0x03, 0xE0, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x0C, 0x30, 0x0C, 0x30,
|
||||
0x1C, 0x38, 0x18, 0x18, 0x1F, 0xF8, 0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C,
|
||||
0x70, 0x0E, 0x60, 0x06, 0x60, 0x07, 0x07, 0xB0, 0x0D, 0xE0, 0x00, 0x00,
|
||||
0x01, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x06, 0x60, 0x06, 0x60,
|
||||
0x0E, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18, 0x1F, 0xF8,
|
||||
0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06, 0x60, 0x07,
|
||||
0x06, 0x60, 0x06, 0x60, 0x00, 0x00, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
|
||||
0x03, 0xE0, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x0C, 0x30, 0x0C, 0x30,
|
||||
0x1C, 0x38, 0x18, 0x18, 0x1F, 0xF8, 0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C,
|
||||
0x70, 0x0E, 0x60, 0x06, 0x60, 0x07, 0x03, 0xC0, 0x03, 0x40, 0x06, 0x60,
|
||||
0x03, 0xC0, 0x01, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xE0,
|
||||
0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x1C, 0x38,
|
||||
0x18, 0x18, 0x1F, 0xF8, 0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x70, 0x0E,
|
||||
0x60, 0x06, 0x60, 0x07, 0x01, 0xFF, 0xFC, 0x03, 0xFF, 0xF8, 0x06, 0x60,
|
||||
0x00, 0x18, 0xC0, 0x00, 0x31, 0x80, 0x00, 0xE3, 0x00, 0x01, 0x86, 0x00,
|
||||
0x03, 0x0C, 0x00, 0x0C, 0x1F, 0xFC, 0x18, 0x3F, 0xF8, 0x70, 0x60, 0x00,
|
||||
0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x07, 0x03, 0x00, 0x0C, 0x06, 0x00, 0x38,
|
||||
0x0C, 0x00, 0x60, 0x1F, 0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xC0, 0x1F, 0xF0,
|
||||
0xF0, 0xE1, 0x80, 0xE7, 0x00, 0xEC, 0x01, 0xF8, 0x00, 0x70, 0x00, 0xC0,
|
||||
0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x06, 0x00, 0x6C, 0x01, 0xDC, 0x03,
|
||||
0x9C, 0x0E, 0x1F, 0x78, 0x1F, 0xE0, 0x04, 0x00, 0x0C, 0x00, 0x0C, 0x00,
|
||||
0x18, 0x01, 0xF0, 0x00, 0x1C, 0x00, 0x30, 0x00, 0x80, 0x00, 0x0F, 0xFF,
|
||||
0x7F, 0xFB, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0F,
|
||||
0xFF, 0x7F, 0xFB, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80,
|
||||
0x0F, 0xFF, 0xFF, 0xFC, 0x03, 0x80, 0x18, 0x01, 0x80, 0x00, 0x0F, 0xFF,
|
||||
0x7F, 0xFB, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0F,
|
||||
0xFF, 0x7F, 0xFB, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80,
|
||||
0x0F, 0xFF, 0xFF, 0xFC, 0x07, 0x00, 0x6C, 0x06, 0x60, 0x00, 0x0F, 0xFF,
|
||||
0x7F, 0xFB, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0F,
|
||||
0xFF, 0x7F, 0xFB, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80,
|
||||
0x0F, 0xFF, 0xFF, 0xFC, 0x1D, 0xC0, 0xEE, 0x00, 0x01, 0xFF, 0xEF, 0xFF,
|
||||
0x60, 0x03, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0xFF, 0xEF,
|
||||
0xFF, 0x60, 0x03, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0xFF,
|
||||
0xFF, 0xFF, 0x80, 0xE1, 0x84, 0x13, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C,
|
||||
0xE7, 0x39, 0xCE, 0x73, 0x9C, 0x33, 0x30, 0x0E, 0x73, 0x9C, 0xE7, 0x39,
|
||||
0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x70, 0x38, 0xD9, 0x14, 0x03, 0x87,
|
||||
0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1,
|
||||
0xC3, 0x87, 0x00, 0xEF, 0xDC, 0x01, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70,
|
||||
0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x80, 0x3F, 0x80,
|
||||
0x3F, 0xF8, 0x30, 0x7C, 0x30, 0x0E, 0x30, 0x06, 0x30, 0x06, 0x30, 0x07,
|
||||
0x30, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x07,
|
||||
0x30, 0x06, 0x30, 0x0E, 0x30, 0x1C, 0x3F, 0xF8, 0x3F, 0xF0, 0x0C, 0x40,
|
||||
0x7F, 0x01, 0x08, 0x30, 0x07, 0xE0, 0x1F, 0xC0, 0x7F, 0x01, 0xFE, 0x07,
|
||||
0xD8, 0x1F, 0x30, 0x7C, 0xE1, 0xF1, 0x87, 0xC3, 0x1F, 0x0E, 0x7C, 0x19,
|
||||
0xF0, 0x77, 0xC0, 0xFF, 0x01, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x1C, 0x07,
|
||||
0x00, 0x00, 0xC0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x7F, 0xC0,
|
||||
0xF8, 0xF0, 0x70, 0x1C, 0x70, 0x07, 0x30, 0x01, 0xB8, 0x00, 0xD8, 0x00,
|
||||
0x7C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x07, 0xE0, 0x03, 0x30,
|
||||
0x01, 0x9C, 0x01, 0xC7, 0x01, 0xC1, 0xF7, 0xC0, 0x7F, 0xC0, 0x02, 0x00,
|
||||
0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x7F,
|
||||
0xC0, 0xF8, 0xF0, 0x70, 0x1C, 0x70, 0x07, 0x30, 0x01, 0xB8, 0x00, 0xD8,
|
||||
0x00, 0x7C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x07, 0xE0, 0x03,
|
||||
0x30, 0x01, 0x9C, 0x01, 0xC7, 0x01, 0xC1, 0xF7, 0xC0, 0x7F, 0xC0, 0x02,
|
||||
0x00, 0x01, 0xC0, 0x01, 0xB0, 0x01, 0x88, 0x00, 0x00, 0x00, 0x3E, 0x00,
|
||||
0x7F, 0xC0, 0xF8, 0xF0, 0x70, 0x1C, 0x70, 0x07, 0x30, 0x01, 0xB8, 0x00,
|
||||
0xD8, 0x00, 0x7C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x07, 0xE0,
|
||||
0x03, 0x30, 0x01, 0x9C, 0x01, 0xC7, 0x01, 0xC1, 0xF7, 0xC0, 0x7F, 0xC0,
|
||||
0x02, 0x00, 0x07, 0xB0, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x7C, 0x00, 0xFF,
|
||||
0x81, 0xF1, 0xE0, 0xE0, 0x38, 0xE0, 0x0E, 0x60, 0x03, 0x70, 0x01, 0xB0,
|
||||
0x00, 0xF8, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x0F, 0xC0, 0x06,
|
||||
0x60, 0x03, 0x38, 0x03, 0x8E, 0x03, 0x83, 0xEF, 0x80, 0xFF, 0x80, 0x04,
|
||||
0x00, 0x07, 0x70, 0x03, 0xB8, 0x00, 0x00, 0x00, 0x7C, 0x00, 0xFF, 0x81,
|
||||
0xF1, 0xE0, 0xE0, 0x38, 0xE0, 0x0E, 0x60, 0x03, 0x70, 0x01, 0xB0, 0x00,
|
||||
0xF8, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x0F, 0xC0, 0x06, 0x60,
|
||||
0x03, 0x38, 0x03, 0x8E, 0x03, 0x83, 0xEF, 0x80, 0xFF, 0x80, 0x04, 0x00,
|
||||
0x40, 0x98, 0x63, 0x30, 0x78, 0x0C, 0x07, 0x83, 0x31, 0x86, 0x40, 0x80,
|
||||
0x03, 0xC1, 0x87, 0xFD, 0x8F, 0x8F, 0x86, 0x01, 0xC7, 0x00, 0xF7, 0x00,
|
||||
0xDB, 0x00, 0xCD, 0x80, 0xC7, 0xC0, 0xC3, 0xE0, 0xC1, 0xF0, 0xC0, 0xF8,
|
||||
0xC0, 0x7E, 0xC0, 0x33, 0xC0, 0x19, 0xC0, 0x18, 0x70, 0x1C, 0x5F, 0x7C,
|
||||
0x67, 0xFC, 0x00, 0x20, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x0C,
|
||||
0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80,
|
||||
0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF8, 0x06,
|
||||
0xC0, 0x77, 0xDF, 0x1F, 0xF0, 0x08, 0x00, 0x01, 0xC0, 0x18, 0x00, 0x80,
|
||||
0x08, 0x0C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0,
|
||||
0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00,
|
||||
0xF8, 0x06, 0xC0, 0x77, 0xDF, 0x1F, 0xF0, 0x08, 0x00, 0x07, 0x00, 0x2C,
|
||||
0x03, 0x30, 0x00, 0x0C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E,
|
||||
0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0,
|
||||
0x1E, 0x00, 0xF8, 0x06, 0xC0, 0x77, 0xDF, 0x1F, 0xF0, 0x08, 0x00, 0x0C,
|
||||
0xC0, 0x66, 0x00, 0x01, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03,
|
||||
0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78,
|
||||
0x03, 0xC0, 0x1F, 0x00, 0xD8, 0x0E, 0xFB, 0xE3, 0xFE, 0x01, 0x00, 0x00,
|
||||
0xE0, 0x00, 0xC0, 0x01, 0x80, 0x00, 0x00, 0xE0, 0x07, 0x70, 0x06, 0x30,
|
||||
0x0E, 0x38, 0x1C, 0x18, 0x18, 0x1C, 0x38, 0x0E, 0x30, 0x06, 0x70, 0x07,
|
||||
0x60, 0x03, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
|
||||
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0xC0, 0x06, 0x00, 0x30, 0x01,
|
||||
0xFE, 0x0F, 0xFE, 0x60, 0x7B, 0x00, 0xD8, 0x07, 0xC0, 0x3E, 0x01, 0xF0,
|
||||
0x0D, 0x83, 0xEF, 0xFE, 0x60, 0x03, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00,
|
||||
0x00, 0x7F, 0x8F, 0x3C, 0xC0, 0xEC, 0x06, 0xC0, 0x6C, 0x0E, 0xC1, 0xCC,
|
||||
0x78, 0xC7, 0xEC, 0x06, 0xC0, 0x7C, 0x07, 0xC0, 0x7C, 0x06, 0xC0, 0x6C,
|
||||
0xFC, 0xCF, 0x80, 0x1C, 0x00, 0xC0, 0x06, 0x00, 0x00, 0x1F, 0x07, 0xFC,
|
||||
0x60, 0xC6, 0x0C, 0x00, 0xC0, 0x1C, 0x3F, 0xC7, 0x8C, 0xE0, 0xCC, 0x0C,
|
||||
0xC0, 0xCE, 0x3E, 0x7E, 0x70, 0x02, 0x03, 0x00, 0x60, 0x0C, 0x00, 0x00,
|
||||
0x1F, 0x07, 0xFC, 0x60, 0xC6, 0x0C, 0x00, 0xC0, 0x1C, 0x3F, 0xC7, 0x8C,
|
||||
0xE0, 0xCC, 0x0C, 0xC0, 0xCE, 0x3E, 0x7E, 0x70, 0x02, 0x0E, 0x01, 0xB0,
|
||||
0x11, 0x80, 0x00, 0x1F, 0x07, 0xFC, 0x60, 0xC6, 0x0C, 0x00, 0xC0, 0x1C,
|
||||
0x3F, 0xC7, 0x8C, 0xE0, 0xCC, 0x0C, 0xC0, 0xCE, 0x3E, 0x7E, 0x70, 0x02,
|
||||
0x1C, 0x83, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0x07, 0xFC, 0x60, 0xC6, 0x0C,
|
||||
0x00, 0xC0, 0x1C, 0x3F, 0xC7, 0x8C, 0xE0, 0xCC, 0x0C, 0xC0, 0xCE, 0x3E,
|
||||
0x7E, 0x70, 0x02, 0x3B, 0x83, 0xB8, 0x00, 0x00, 0x00, 0x1F, 0x07, 0xFC,
|
||||
0x60, 0xC6, 0x0C, 0x00, 0xC0, 0x1C, 0x3F, 0xC7, 0x8C, 0xE0, 0xCC, 0x0C,
|
||||
0xC0, 0xCE, 0x3E, 0x7E, 0x70, 0x02, 0x04, 0x00, 0xF0, 0x19, 0x01, 0xB0,
|
||||
0x0F, 0x00, 0x00, 0x1F, 0x07, 0xFC, 0x60, 0xC6, 0x0C, 0x00, 0xC0, 0x1C,
|
||||
0x3F, 0xC7, 0x8C, 0xE0, 0xCC, 0x0C, 0xC0, 0xCE, 0x3E, 0x7E, 0x70, 0x02,
|
||||
0x1F, 0x0F, 0x0F, 0xF7, 0xF9, 0x83, 0xC3, 0xB0, 0x70, 0x30, 0x0C, 0x06,
|
||||
0x03, 0x80, 0xCF, 0xFF, 0xFB, 0xC6, 0x00, 0xE0, 0xC0, 0x18, 0x1C, 0x0F,
|
||||
0x03, 0x83, 0xF1, 0xDC, 0xE7, 0xE3, 0xF8, 0x00, 0x08, 0x00, 0x1F, 0x0F,
|
||||
0xE6, 0x1F, 0x83, 0xC0, 0xF0, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x3E, 0x0D,
|
||||
0xC7, 0x3F, 0x83, 0x00, 0xC0, 0x0C, 0x03, 0x0F, 0x80, 0x38, 0x03, 0x80,
|
||||
0x30, 0x03, 0x00, 0x00, 0x1E, 0x0F, 0xF3, 0x86, 0x60, 0x78, 0x0F, 0x01,
|
||||
0xFF, 0xFC, 0x01, 0x80, 0x30, 0x1B, 0x07, 0x79, 0xC7, 0xF0, 0x10, 0x00,
|
||||
0x03, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00, 0x1E, 0x0F, 0xF3, 0x86, 0x60,
|
||||
0x78, 0x0F, 0x01, 0xFF, 0xFC, 0x01, 0x80, 0x30, 0x1B, 0x07, 0x79, 0xC7,
|
||||
0xF0, 0x10, 0x00, 0x0F, 0x03, 0x60, 0x66, 0x00, 0x00, 0xF0, 0x7F, 0x9C,
|
||||
0x33, 0x03, 0xC0, 0x78, 0x0F, 0xFF, 0xE0, 0x0C, 0x01, 0x80, 0xD8, 0x3B,
|
||||
0xCE, 0x3F, 0x80, 0x80, 0x19, 0x83, 0x30, 0x00, 0x00, 0x00, 0xF0, 0x7F,
|
||||
0x9C, 0x33, 0x03, 0xC0, 0x78, 0x0F, 0xFF, 0xE0, 0x0C, 0x01, 0x80, 0xD8,
|
||||
0x3B, 0xCE, 0x3F, 0x80, 0x80, 0xE3, 0x0C, 0x30, 0x18, 0xC6, 0x31, 0x8C,
|
||||
0x63, 0x18, 0xC6, 0x31, 0x80, 0x39, 0x99, 0x80, 0x31, 0x8C, 0x63, 0x18,
|
||||
0xC6, 0x31, 0x8C, 0x63, 0x00, 0x30, 0xF1, 0xB6, 0x20, 0x06, 0x0C, 0x18,
|
||||
0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xCF, 0x30, 0x00,
|
||||
0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0x20, 0x07,
|
||||
0xE0, 0x70, 0x3F, 0x00, 0x30, 0x3F, 0x0F, 0xF3, 0x8E, 0xE0, 0xF8, 0x0F,
|
||||
0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1B, 0x07, 0x7B, 0xC7, 0xF0, 0x10,
|
||||
0x00, 0x39, 0x1F, 0xC4, 0x20, 0x00, 0xCF, 0x3F, 0xEE, 0x1F, 0x03, 0xC0,
|
||||
0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xC0, 0x38,
|
||||
0x03, 0x00, 0x30, 0x03, 0x00, 0x00, 0x3E, 0x0F, 0xE3, 0x8E, 0xE0, 0xF8,
|
||||
0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1B, 0x07, 0x7B, 0xC7, 0xF0,
|
||||
0x10, 0x00, 0x03, 0x80, 0xE0, 0x18, 0x06, 0x00, 0x00, 0x3E, 0x0F, 0xE3,
|
||||
0x8E, 0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1B, 0x07,
|
||||
0x7B, 0xC7, 0xF0, 0x10, 0x00, 0x0E, 0x01, 0xC0, 0x6C, 0x18, 0xC0, 0x00,
|
||||
0x3E, 0x0F, 0xE3, 0x8E, 0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80,
|
||||
0xF0, 0x1B, 0x07, 0x7B, 0xC7, 0xF0, 0x10, 0x00, 0x1C, 0x87, 0xF0, 0x00,
|
||||
0x00, 0x01, 0xF0, 0x7F, 0x1C, 0x77, 0x07, 0xC0, 0x78, 0x0F, 0x01, 0xE0,
|
||||
0x3C, 0x07, 0x80, 0xD8, 0x3B, 0xDE, 0x3F, 0x80, 0x80, 0x3B, 0x87, 0x70,
|
||||
0xEE, 0x00, 0x00, 0x00, 0x3E, 0x0F, 0xE3, 0x8E, 0xE0, 0xF8, 0x0F, 0x01,
|
||||
0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1B, 0x07, 0x7B, 0xC7, 0xF0, 0x10, 0x00,
|
||||
0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x60, 0x06, 0x00, 0x0F, 0x80, 0xFE, 0x8E, 0x38, 0xE0, 0xE6,
|
||||
0x0B, 0x30, 0x99, 0x8C, 0xCC, 0xC6, 0x6C, 0x33, 0x41, 0x8C, 0x1C, 0x79,
|
||||
0xC5, 0xFC, 0x01, 0x00, 0x70, 0x0C, 0x01, 0x80, 0x30, 0x00, 0x30, 0x3C,
|
||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x7C, 0x1F, 0x07,
|
||||
0xE3, 0xDF, 0xB1, 0x00, 0x07, 0x03, 0x80, 0xC0, 0x60, 0x00, 0x30, 0x3C,
|
||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x7C, 0x1F, 0x07,
|
||||
0xE3, 0xDF, 0xB1, 0x00, 0x1C, 0x07, 0x03, 0x60, 0x8C, 0x00, 0x30, 0x3C,
|
||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x7C, 0x1F, 0x07,
|
||||
0xE3, 0xDF, 0xB1, 0x00, 0x77, 0x1D, 0xC7, 0x70, 0x00, 0x00, 0x30, 0x3C,
|
||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x7C, 0x1F, 0x07,
|
||||
0xE3, 0xDF, 0xB1, 0x00, 0x03, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00, 0xC0,
|
||||
0xD8, 0x1B, 0x03, 0x30, 0xC6, 0x18, 0xC7, 0x0C, 0xC1, 0x98, 0x37, 0x03,
|
||||
0xC0, 0x78, 0x0E, 0x00, 0xC0, 0x18, 0x06, 0x00, 0xC0, 0xF0, 0x1E, 0x00,
|
||||
0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xCF, 0x0D, 0xFC, 0xF0, 0xCE, 0x06,
|
||||
0xE0, 0x6C, 0x06, 0xC0, 0x7C, 0x07, 0xC0, 0x6E, 0x06, 0xE0, 0xEF, 0x9C,
|
||||
0xDF, 0x8C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0x19, 0x83, 0x30,
|
||||
0x66, 0x00, 0x00, 0x00, 0xC0, 0xD8, 0x1B, 0x03, 0x30, 0xC6, 0x18, 0xC7,
|
||||
0x0C, 0xC1, 0x98, 0x37, 0x03, 0xC0, 0x78, 0x0E, 0x00, 0xC0, 0x18, 0x06,
|
||||
0x00, 0xC0, 0xF0, 0x1E, 0x00 };
|
||||
|
||||
const GFXglyph FreeSans12pt8bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 7, 0, 0 }, // 0x20 ' ' U+0020
|
||||
{ 1, 2, 18, 7, 3, -17 }, // 0x21 '!' U+0021
|
||||
{ 6, 6, 6, 9, 1, -16 }, // 0x22 '"' U+0022
|
||||
{ 11, 13, 17, 13, 0, -16 }, // 0x23 '#' U+0023
|
||||
{ 39, 11, 21, 13, 1, -17 }, // 0x24 '$' U+0024
|
||||
{ 68, 20, 17, 21, 1, -16 }, // 0x25 '%' U+0025
|
||||
{ 111, 14, 18, 16, 1, -16 }, // 0x26 '&' U+0026
|
||||
{ 143, 2, 6, 5, 1, -16 }, // 0x27 ''' U+0027
|
||||
{ 145, 5, 23, 8, 2, -17 }, // 0x28 '(' U+0028
|
||||
{ 160, 5, 23, 8, 1, -17 }, // 0x29 ')' U+0029
|
||||
{ 175, 7, 7, 9, 1, -17 }, // 0x2a '*' U+002A
|
||||
{ 182, 12, 11, 14, 1, -10 }, // 0x2b '+' U+002B
|
||||
{ 199, 3, 7, 7, 2, -2 }, // 0x2c ',' U+002C
|
||||
{ 202, 6, 1, 8, 1, -6 }, // 0x2d '-' U+002D
|
||||
{ 203, 3, 3, 7, 2, -2 }, // 0x2e '.' U+002E
|
||||
{ 205, 7, 18, 7, 0, -17 }, // 0x2f '/' U+002F
|
||||
{ 221, 11, 18, 13, 1, -16 }, // 0x30 '0' U+0030
|
||||
{ 246, 6, 17, 13, 2, -16 }, // 0x31 '1' U+0031
|
||||
{ 259, 11, 17, 13, 1, -16 }, // 0x32 '2' U+0032
|
||||
{ 283, 11, 18, 13, 1, -16 }, // 0x33 '3' U+0033
|
||||
{ 308, 11, 17, 13, 1, -16 }, // 0x34 '4' U+0034
|
||||
{ 332, 11, 18, 13, 1, -16 }, // 0x35 '5' U+0035
|
||||
{ 357, 11, 18, 13, 1, -16 }, // 0x36 '6' U+0036
|
||||
{ 382, 11, 17, 13, 1, -16 }, // 0x37 '7' U+0037
|
||||
{ 406, 11, 18, 13, 1, -16 }, // 0x38 '8' U+0038
|
||||
{ 431, 11, 18, 13, 1, -16 }, // 0x39 '9' U+0039
|
||||
{ 456, 2, 13, 7, 3, -12 }, // 0x3a ':' U+003A
|
||||
{ 460, 2, 17, 7, 3, -12 }, // 0x3b ';' U+003B
|
||||
{ 465, 12, 11, 14, 1, -10 }, // 0x3c '<' U+003C
|
||||
{ 482, 12, 5, 14, 1, -7 }, // 0x3d '=' U+003D
|
||||
{ 490, 12, 11, 14, 1, -10 }, // 0x3e '>' U+003E
|
||||
{ 507, 10, 18, 13, 2, -17 }, // 0x3f '?' U+003F
|
||||
{ 530, 22, 21, 24, 1, -17 }, // 0x40 '@' U+0040
|
||||
{ 588, 16, 18, 16, 0, -17 }, // 0x41 'A' U+0041
|
||||
{ 624, 13, 18, 16, 2, -17 }, // 0x42 'B' U+0042
|
||||
{ 654, 15, 19, 17, 1, -17 }, // 0x43 'C' U+0043
|
||||
{ 690, 14, 18, 17, 2, -17 }, // 0x44 'D' U+0044
|
||||
{ 722, 13, 18, 16, 2, -17 }, // 0x45 'E' U+0045
|
||||
{ 752, 12, 18, 15, 2, -17 }, // 0x46 'F' U+0046
|
||||
{ 779, 16, 19, 19, 1, -17 }, // 0x47 'G' U+0047
|
||||
{ 817, 13, 18, 17, 2, -17 }, // 0x48 'H' U+0048
|
||||
{ 847, 3, 18, 7, 2, -17 }, // 0x49 'I' U+0049
|
||||
{ 854, 10, 19, 12, 0, -17 }, // 0x4a 'J' U+004A
|
||||
{ 878, 14, 18, 16, 2, -17 }, // 0x4b 'K' U+004B
|
||||
{ 910, 11, 18, 13, 2, -17 }, // 0x4c 'L' U+004C
|
||||
{ 935, 16, 18, 20, 2, -17 }, // 0x4d 'M' U+004D
|
||||
{ 971, 14, 18, 17, 2, -17 }, // 0x4e 'N' U+004E
|
||||
{ 1003, 17, 19, 19, 1, -17 }, // 0x4f 'O' U+004F
|
||||
{ 1044, 13, 18, 16, 2, -17 }, // 0x50 'P' U+0050
|
||||
{ 1074, 17, 19, 19, 1, -17 }, // 0x51 'Q' U+0051
|
||||
{ 1115, 14, 18, 17, 2, -17 }, // 0x52 'R' U+0052
|
||||
{ 1147, 14, 19, 16, 1, -17 }, // 0x53 'S' U+0053
|
||||
{ 1181, 14, 18, 15, 0, -17 }, // 0x54 'T' U+0054
|
||||
{ 1213, 13, 19, 17, 2, -17 }, // 0x55 'U' U+0055
|
||||
{ 1244, 14, 18, 16, 1, -17 }, // 0x56 'V' U+0056
|
||||
{ 1276, 21, 18, 23, 1, -17 }, // 0x57 'W' U+0057
|
||||
{ 1324, 15, 18, 16, 1, -17 }, // 0x58 'X' U+0058
|
||||
{ 1358, 16, 18, 16, 0, -17 }, // 0x59 'Y' U+0059
|
||||
{ 1394, 13, 18, 15, 1, -17 }, // 0x5a 'Z' U+005A
|
||||
{ 1424, 4, 23, 7, 2, -17 }, // 0x5b '[' U+005B
|
||||
{ 1436, 7, 18, 7, 0, -17 }, // 0x5c '\' U+005C
|
||||
{ 1452, 4, 23, 7, 1, -17 }, // 0x5d ']' U+005D
|
||||
{ 1464, 9, 9, 11, 1, -16 }, // 0x5e '^' U+005E
|
||||
{ 1475, 15, 1, 13, -1, 4 }, // 0x5f '_' U+005F
|
||||
{ 1477, 5, 4, 8, 1, -17 }, // 0x60 '`' U+0060
|
||||
{ 1480, 12, 14, 13, 1, -12 }, // 0x61 'a' U+0061
|
||||
{ 1501, 12, 19, 13, 1, -17 }, // 0x62 'b' U+0062
|
||||
{ 1530, 10, 14, 12, 1, -12 }, // 0x63 'c' U+0063
|
||||
{ 1548, 11, 19, 13, 1, -17 }, // 0x64 'd' U+0064
|
||||
{ 1575, 11, 14, 13, 1, -12 }, // 0x65 'e' U+0065
|
||||
{ 1595, 6, 18, 7, 0, -17 }, // 0x66 'f' U+0066
|
||||
{ 1609, 11, 18, 13, 1, -12 }, // 0x67 'g' U+0067
|
||||
{ 1634, 10, 18, 13, 2, -17 }, // 0x68 'h' U+0068
|
||||
{ 1657, 2, 18, 5, 2, -17 }, // 0x69 'i' U+0069
|
||||
{ 1662, 4, 23, 5, 0, -17 }, // 0x6a 'j' U+006A
|
||||
{ 1674, 11, 18, 12, 1, -17 }, // 0x6b 'k' U+006B
|
||||
{ 1699, 2, 18, 5, 2, -17 }, // 0x6c 'l' U+006C
|
||||
{ 1704, 16, 13, 20, 2, -12 }, // 0x6d 'm' U+006D
|
||||
{ 1730, 10, 13, 13, 2, -12 }, // 0x6e 'n' U+006E
|
||||
{ 1747, 11, 14, 13, 1, -12 }, // 0x6f 'o' U+006F
|
||||
{ 1767, 12, 18, 13, 1, -12 }, // 0x70 'p' U+0070
|
||||
{ 1794, 11, 18, 13, 1, -12 }, // 0x71 'q' U+0071
|
||||
{ 1819, 6, 13, 8, 2, -12 }, // 0x72 'r' U+0072
|
||||
{ 1829, 10, 14, 12, 1, -12 }, // 0x73 's' U+0073
|
||||
{ 1847, 6, 17, 7, 0, -15 }, // 0x74 't' U+0074
|
||||
{ 1860, 10, 14, 13, 2, -12 }, // 0x75 'u' U+0075
|
||||
{ 1878, 12, 13, 12, 0, -12 }, // 0x76 'v' U+0076
|
||||
{ 1898, 17, 13, 17, 0, -12 }, // 0x77 'w' U+0077
|
||||
{ 1926, 11, 13, 12, 0, -12 }, // 0x78 'x' U+0078
|
||||
{ 1944, 11, 18, 12, 0, -12 }, // 0x79 'y' U+0079
|
||||
{ 1969, 10, 13, 12, 1, -12 }, // 0x7a 'z' U+007A
|
||||
{ 1986, 6, 23, 8, 1, -17 }, // 0x7b '{' U+007B
|
||||
{ 2004, 2, 23, 6, 2, -17 }, // 0x7c '|' U+007C
|
||||
{ 2010, 5, 23, 8, 1, -17 }, // 0x7d '}' U+007D
|
||||
{ 2025, 10, 5, 14, 2, -10 }, // 0x7e '~' U+007E
|
||||
{ 2032, 13, 18, 17, 2, -17 }, // 0x7f 'REPLACEMENT CHARACTER *' U+2370
|
||||
{ 2062, 1, 1, 7, 0, 0 }, // 0x80 'NO-BREAK SPACE' U+00A0
|
||||
{ 2063, 2, 18, 7, 3, -12 }, // 0x81 'INVERTED EXCLAMATION MARK' U+00A1
|
||||
{ 2068, 11, 18, 13, 1, -14 }, // 0x82 'CENT SIGN' U+00A2
|
||||
{ 2093, 12, 19, 13, 1, -17 }, // 0x83 'POUND SIGN' U+00A3
|
||||
{ 2122, 14, 18, 16, 1, -16 }, // 0x84 'EURO SIGN *' U+20AC
|
||||
{ 2154, 13, 17, 13, 0, -16 }, // 0x85 'YEN SIGN' U+00A5
|
||||
{ 2182, 14, 23, 16, 1, -21 }, // 0x86 'LATIN CAPITAL LETTER S WITH CARON *' U+0160
|
||||
{ 2223, 11, 23, 13, 1, -17 }, // 0x87 'SECTION SIGN' U+00A7
|
||||
{ 2255, 10, 19, 12, 1, -17 }, // 0x88 'LATIN SMALL LETTER S WITH CARON *' U+0161
|
||||
{ 2279, 18, 19, 18, 0, -17 }, // 0x89 'COPYRIGHT SIGN' U+00A9
|
||||
{ 2322, 7, 11, 9, 1, -17 }, // 0x8a 'FEMININE ORDINAL INDICATOR' U+00AA
|
||||
{ 2332, 9, 8, 11, 1, -10 }, // 0x8b 'LEFT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00AB
|
||||
{ 2341, 12, 7, 14, 1, -8 }, // 0x8c 'NOT SIGN' U+00AC
|
||||
{ 2352, 6, 1, 8, 1, -6 }, // 0x8d 'SOFT HYPHEN' U+00AD
|
||||
{ 2353, 18, 19, 18, 0, -17 }, // 0x8e 'REGISTERED SIGN' U+00AE
|
||||
{ 2396, 6, 2, 8, 1, -16 }, // 0x8f 'MACRON' U+00AF
|
||||
{ 2398, 7, 7, 15, 4, -15 }, // 0x90 'DEGREE SIGN' U+00B0
|
||||
{ 2405, 12, 15, 14, 1, -14 }, // 0x91 'PLUS-MINUS SIGN' U+00B1
|
||||
{ 2428, 8, 10, 8, 0, -16 }, // 0x92 'SUPERSCRIPT TWO' U+00B2
|
||||
{ 2438, 8, 11, 8, 0, -16 }, // 0x93 'SUPERSCRIPT THREE' U+00B3
|
||||
{ 2449, 13, 22, 15, 1, -21 }, // 0x94 'LATIN CAPITAL LETTER Z WITH CARON *' U+017D
|
||||
{ 2485, 11, 18, 13, 2, -12 }, // 0x95 'MICRO SIGN' U+00B5
|
||||
{ 2510, 12, 22, 13, 1, -17 }, // 0x96 'PILCROW SIGN' U+00B6
|
||||
{ 2543, 3, 3, 7, 2, -7 }, // 0x97 'MIDDLE DOT' U+00B7
|
||||
{ 2545, 10, 18, 12, 1, -17 }, // 0x98 'LATIN SMALL LETTER Z WITH CARON *' U+017E
|
||||
{ 2568, 4, 10, 8, 2, -16 }, // 0x99 'SUPERSCRIPT ONE' U+00B9
|
||||
{ 2573, 7, 11, 9, 1, -17 }, // 0x9a 'MASCULINE ORDINAL INDICATOR' U+00BA
|
||||
{ 2583, 9, 8, 11, 1, -9 }, // 0x9b 'RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00BB
|
||||
{ 2592, 22, 18, 24, 1, -17 }, // 0x9c 'LATIN CAPITAL LIGATURE OE *' U+0152
|
||||
{ 2642, 20, 14, 23, 1, -12 }, // 0x9d 'LATIN SMALL LIGATURE OE *' U+0153
|
||||
{ 2677, 16, 21, 16, 0, -20 }, // 0x9e 'LATIN CAPITAL LETTER Y WITH DIAERESIS *' U+0178
|
||||
{ 2719, 10, 18, 13, 3, -12 }, // 0x9f 'INVERTED QUESTION MARK' U+00BF
|
||||
{ 2742, 16, 22, 16, 0, -21 }, // 0xa0 'LATIN CAPITAL LETTER A WITH GRAVE' U+00C0
|
||||
{ 2786, 16, 22, 16, 0, -21 }, // 0xa1 'LATIN CAPITAL LETTER A WITH ACUTE' U+00C1
|
||||
{ 2830, 16, 22, 16, 0, -21 }, // 0xa2 'LATIN CAPITAL LETTER A WITH CIRCUMFLEX' U+00C2
|
||||
{ 2874, 16, 21, 16, 0, -20 }, // 0xa3 'LATIN CAPITAL LETTER A WITH TILDE' U+00C3
|
||||
{ 2916, 16, 21, 16, 0, -20 }, // 0xa4 'LATIN CAPITAL LETTER A WITH DIAERESIS' U+00C4
|
||||
{ 2958, 16, 23, 16, 0, -22 }, // 0xa5 'LATIN CAPITAL LETTER A WITH RING ABOVE' U+00C5
|
||||
{ 3004, 23, 18, 24, 0, -17 }, // 0xa6 'LATIN CAPITAL LETTER AE' U+00C6
|
||||
{ 3056, 15, 23, 17, 1, -17 }, // 0xa7 'LATIN CAPITAL LETTER C WITH CEDILLA' U+00C7
|
||||
{ 3100, 13, 22, 16, 2, -21 }, // 0xa8 'LATIN CAPITAL LETTER E WITH GRAVE' U+00C8
|
||||
{ 3136, 13, 22, 16, 2, -21 }, // 0xa9 'LATIN CAPITAL LETTER E WITH ACUTE' U+00C9
|
||||
{ 3172, 13, 22, 16, 2, -21 }, // 0xaa 'LATIN CAPITAL LETTER E WITH CIRCUMFLEX' U+00CA
|
||||
{ 3208, 13, 21, 16, 2, -20 }, // 0xab 'LATIN CAPITAL LETTER E WITH DIAERESIS' U+00CB
|
||||
{ 3243, 5, 22, 7, 0, -21 }, // 0xac 'LATIN CAPITAL LETTER I WITH GRAVE' U+00CC
|
||||
{ 3257, 5, 22, 7, 2, -21 }, // 0xad 'LATIN CAPITAL LETTER I WITH ACUTE' U+00CD
|
||||
{ 3271, 7, 22, 7, 0, -21 }, // 0xae 'LATIN CAPITAL LETTER I WITH CIRCUMFLEX' U+00CE
|
||||
{ 3291, 7, 21, 7, 0, -20 }, // 0xaf 'LATIN CAPITAL LETTER I WITH DIAERESIS' U+00CF
|
||||
{ 3310, 16, 18, 17, 0, -17 }, // 0xb0 'LATIN CAPITAL LETTER ETH' U+00D0
|
||||
{ 3346, 14, 21, 17, 2, -20 }, // 0xb1 'LATIN CAPITAL LETTER N WITH TILDE' U+00D1
|
||||
{ 3383, 17, 23, 19, 1, -21 }, // 0xb2 'LATIN CAPITAL LETTER O WITH GRAVE' U+00D2
|
||||
{ 3432, 17, 23, 19, 1, -21 }, // 0xb3 'LATIN CAPITAL LETTER O WITH ACUTE' U+00D3
|
||||
{ 3481, 17, 23, 19, 1, -21 }, // 0xb4 'LATIN CAPITAL LETTER O WITH CIRCUMFLEX' U+00D4
|
||||
{ 3530, 17, 22, 19, 1, -20 }, // 0xb5 'LATIN CAPITAL LETTER O WITH TILDE' U+00D5
|
||||
{ 3577, 17, 22, 19, 1, -20 }, // 0xb6 'LATIN CAPITAL LETTER O WITH DIAERESIS' U+00D6
|
||||
{ 3624, 10, 9, 14, 2, -9 }, // 0xb7 'MULTIPLICATION SIGN' U+00D7
|
||||
{ 3636, 17, 19, 19, 1, -17 }, // 0xb8 'LATIN CAPITAL LETTER O WITH STROKE' U+00D8
|
||||
{ 3677, 13, 23, 17, 2, -21 }, // 0xb9 'LATIN CAPITAL LETTER U WITH GRAVE' U+00D9
|
||||
{ 3715, 13, 23, 17, 2, -21 }, // 0xba 'LATIN CAPITAL LETTER U WITH ACUTE' U+00DA
|
||||
{ 3753, 13, 23, 17, 2, -21 }, // 0xbb 'LATIN CAPITAL LETTER U WITH CIRCUMFLEX' U+00DB
|
||||
{ 3791, 13, 22, 17, 2, -20 }, // 0xbc 'LATIN CAPITAL LETTER U WITH DIAERESIS' U+00DC
|
||||
{ 3827, 16, 22, 16, 0, -21 }, // 0xbd 'LATIN CAPITAL LETTER Y WITH ACUTE' U+00DD
|
||||
{ 3871, 13, 18, 16, 2, -17 }, // 0xbe 'LATIN CAPITAL LETTER THORN' U+00DE
|
||||
{ 3901, 12, 17, 15, 2, -16 }, // 0xbf 'LATIN SMALL LETTER SHARP S' U+00DF
|
||||
{ 3927, 12, 18, 13, 1, -16 }, // 0xc0 'LATIN SMALL LETTER A WITH GRAVE' U+00E0
|
||||
{ 3954, 12, 18, 13, 1, -16 }, // 0xc1 'LATIN SMALL LETTER A WITH ACUTE' U+00E1
|
||||
{ 3981, 12, 18, 13, 1, -16 }, // 0xc2 'LATIN SMALL LETTER A WITH CIRCUMFLEX' U+00E2
|
||||
{ 4008, 12, 18, 13, 1, -16 }, // 0xc3 'LATIN SMALL LETTER A WITH TILDE' U+00E3
|
||||
{ 4035, 12, 18, 13, 1, -16 }, // 0xc4 'LATIN SMALL LETTER A WITH DIAERESIS' U+00E4
|
||||
{ 4062, 12, 20, 13, 1, -18 }, // 0xc5 'LATIN SMALL LETTER A WITH RING ABOVE' U+00E5
|
||||
{ 4092, 19, 14, 22, 1, -12 }, // 0xc6 'LATIN SMALL LETTER AE' U+00E6
|
||||
{ 4126, 10, 18, 12, 1, -12 }, // 0xc7 'LATIN SMALL LETTER C WITH CEDILLA' U+00E7
|
||||
{ 4149, 11, 19, 13, 1, -17 }, // 0xc8 'LATIN SMALL LETTER E WITH GRAVE' U+00E8
|
||||
{ 4176, 11, 19, 13, 1, -17 }, // 0xc9 'LATIN SMALL LETTER E WITH ACUTE' U+00E9
|
||||
{ 4203, 11, 18, 13, 1, -16 }, // 0xca 'LATIN SMALL LETTER E WITH CIRCUMFLEX' U+00EA
|
||||
{ 4228, 11, 18, 13, 1, -16 }, // 0xcb 'LATIN SMALL LETTER E WITH DIAERESIS' U+00EB
|
||||
{ 4253, 5, 18, 6, 0, -17 }, // 0xcc 'LATIN SMALL LETTER I WITH GRAVE' U+00EC
|
||||
{ 4265, 5, 18, 6, 1, -17 }, // 0xcd 'LATIN SMALL LETTER I WITH ACUTE' U+00ED
|
||||
{ 4277, 7, 18, 6, 0, -17 }, // 0xce 'LATIN SMALL LETTER I WITH CIRCUMFLEX' U+00EE
|
||||
{ 4293, 6, 17, 6, 0, -16 }, // 0xcf 'LATIN SMALL LETTER I WITH DIAERESIS' U+00EF
|
||||
{ 4306, 11, 19, 13, 1, -17 }, // 0xd0 'LATIN SMALL LETTER ETH' U+00F0
|
||||
{ 4333, 10, 17, 13, 2, -16 }, // 0xd1 'LATIN SMALL LETTER N WITH TILDE' U+00F1
|
||||
{ 4355, 11, 19, 13, 1, -17 }, // 0xd2 'LATIN SMALL LETTER O WITH GRAVE' U+00F2
|
||||
{ 4382, 11, 19, 13, 1, -17 }, // 0xd3 'LATIN SMALL LETTER O WITH ACUTE' U+00F3
|
||||
{ 4409, 11, 19, 13, 1, -17 }, // 0xd4 'LATIN SMALL LETTER O WITH CIRCUMFLEX' U+00F4
|
||||
{ 4436, 11, 18, 13, 1, -16 }, // 0xd5 'LATIN SMALL LETTER O WITH TILDE' U+00F5
|
||||
{ 4461, 11, 19, 13, 1, -17 }, // 0xd6 'LATIN SMALL LETTER O WITH DIAERESIS' U+00F6
|
||||
{ 4488, 12, 11, 14, 1, -10 }, // 0xd7 'DIVISION SIGN' U+00F7
|
||||
{ 4505, 13, 14, 15, 0, -12 }, // 0xd8 'LATIN SMALL LETTER O WITH STROKE' U+00F8
|
||||
{ 4528, 10, 19, 13, 2, -17 }, // 0xd9 'LATIN SMALL LETTER U WITH GRAVE' U+00F9
|
||||
{ 4552, 10, 19, 13, 2, -17 }, // 0xda 'LATIN SMALL LETTER U WITH ACUTE' U+00FA
|
||||
{ 4576, 10, 19, 13, 2, -17 }, // 0xdb 'LATIN SMALL LETTER U WITH CIRCUMFLEX' U+00FB
|
||||
{ 4600, 10, 19, 13, 2, -17 }, // 0xdc 'LATIN SMALL LETTER U WITH DIAERESIS' U+00FC
|
||||
{ 4624, 11, 23, 12, 0, -17 }, // 0xdd 'LATIN SMALL LETTER Y WITH ACUTE' U+00FD
|
||||
{ 4656, 12, 22, 13, 1, -16 }, // 0xde 'LATIN SMALL LETTER THORN' U+00FE
|
||||
{ 4689, 11, 23, 12, 0, -17 } }; // 0xdf 'LATIN SMALL LETTER Y WITH DIAERESIS' U+000FF
|
||||
|
||||
const GFXfont FreeSans12pt8b PROGMEM = {
|
||||
(uint8_t *)FreeSans12pt8bBitmaps,
|
||||
(GFXglyph *)FreeSans12pt8bGlyphs,
|
||||
0x20, 0xDF, 33 };
|
||||
|
||||
// Approx. 6072 bytes
|
451
RX_FSK/src/fonts/FreeSans18pt7b.h
Normal file
451
RX_FSK/src/fonts/FreeSans18pt7b.h
Normal file
|
@ -0,0 +1,451 @@
|
|||
const uint8_t FreeSans18pt7bBitmaps[] PROGMEM = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x20, 0x3F, 0xFC, 0xE3, 0xF1,
|
||||
0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8E, 0x82, 0x41, 0x00, 0x01, 0xC3, 0x80,
|
||||
0x38, 0x70, 0x06, 0x0E, 0x00, 0xC1, 0x80, 0x38, 0x70, 0x07, 0x0E, 0x0F,
|
||||
0xFF, 0xF9, 0xFF, 0xFF, 0x3F, 0xFF, 0xE0, 0xE1, 0xC0, 0x1C, 0x38, 0x03,
|
||||
0x87, 0x00, 0x70, 0xE0, 0x0C, 0x18, 0x3F, 0xFF, 0xF7, 0xFF, 0xFE, 0xFF,
|
||||
0xFF, 0xC1, 0xC3, 0x80, 0x30, 0x60, 0x06, 0x0C, 0x01, 0xC3, 0x80, 0x38,
|
||||
0x70, 0x07, 0x0E, 0x00, 0xC1, 0x80, 0x03, 0x00, 0x0F, 0xC0, 0x3F, 0xF0,
|
||||
0x3F, 0xF8, 0x7B, 0x3C, 0xF3, 0x1C, 0xE3, 0x0E, 0xE3, 0x0E, 0xE3, 0x0E,
|
||||
0xE3, 0x00, 0xE3, 0x00, 0xF3, 0x00, 0x7B, 0x00, 0x7F, 0x80, 0x1F, 0xF0,
|
||||
0x07, 0xFC, 0x03, 0x7E, 0x03, 0x0F, 0x03, 0x07, 0xE3, 0x07, 0xE3, 0x07,
|
||||
0xE3, 0x07, 0xE3, 0x0F, 0x73, 0x3E, 0x7F, 0xFC, 0x3F, 0xF8, 0x0F, 0xE0,
|
||||
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x78, 0x00,
|
||||
0xE0, 0x0F, 0xF0, 0x06, 0x00, 0xFF, 0xC0, 0x70, 0x07, 0x0E, 0x07, 0x00,
|
||||
0x70, 0x38, 0x38, 0x03, 0x00, 0xC3, 0x80, 0x18, 0x06, 0x1C, 0x00, 0xE0,
|
||||
0x71, 0xC0, 0x03, 0x87, 0x8C, 0x00, 0x1F, 0xF8, 0xE0, 0x00, 0x7F, 0x86,
|
||||
0x00, 0x01, 0xF8, 0x70, 0x00, 0x00, 0x03, 0x03, 0xC0, 0x00, 0x38, 0x7F,
|
||||
0x80, 0x01, 0x87, 0xFE, 0x00, 0x1C, 0x38, 0x70, 0x00, 0xC3, 0x81, 0xC0,
|
||||
0x0E, 0x18, 0x06, 0x00, 0xE0, 0xC0, 0x30, 0x07, 0x07, 0x03, 0x80, 0x70,
|
||||
0x1C, 0x38, 0x03, 0x80, 0xFF, 0xC0, 0x38, 0x03, 0xFC, 0x01, 0x80, 0x07,
|
||||
0x80, 0x01, 0xF0, 0x00, 0x7F, 0x80, 0x0F, 0xFC, 0x01, 0xE1, 0xE0, 0x1C,
|
||||
0x0E, 0x01, 0xC0, 0xE0, 0x1C, 0x0E, 0x01, 0xE1, 0xE0, 0x0E, 0x3C, 0x00,
|
||||
0x77, 0x80, 0x07, 0xF0, 0x00, 0x7C, 0x00, 0x0F, 0xE0, 0x03, 0xCF, 0x1C,
|
||||
0x78, 0x79, 0xC7, 0x03, 0xDC, 0xE0, 0x1F, 0x8E, 0x00, 0xF8, 0xE0, 0x0F,
|
||||
0x0E, 0x00, 0x70, 0xF0, 0x0F, 0x87, 0xC3, 0xFC, 0x7F, 0xFD, 0xC3, 0xFF,
|
||||
0x0E, 0x0F, 0xC0, 0xF0, 0xFF, 0xFF, 0xFA, 0x40, 0x06, 0x06, 0x0C, 0x0C,
|
||||
0x18, 0x18, 0x38, 0x30, 0x70, 0x70, 0x70, 0x60, 0xE0, 0xE0, 0xE0, 0xE0,
|
||||
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x60, 0x70, 0x70, 0x70, 0x30, 0x38, 0x18,
|
||||
0x18, 0x0C, 0x0C, 0x06, 0x03, 0xC0, 0x60, 0x30, 0x30, 0x38, 0x18, 0x1C,
|
||||
0x0C, 0x0E, 0x0E, 0x0E, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x06, 0x0E, 0x0E, 0x0E, 0x0C, 0x1C, 0x18, 0x38, 0x30, 0x30,
|
||||
0x60, 0xC0, 0x0C, 0x03, 0x00, 0xC3, 0xB7, 0xFF, 0xC7, 0x81, 0xE0, 0xEC,
|
||||
0x73, 0x88, 0x40, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
|
||||
0x80, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0x01,
|
||||
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0xFF,
|
||||
0xF6, 0xDA, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xC0, 0x30, 0x18,
|
||||
0x06, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x06, 0x01, 0x80, 0x60, 0x30, 0x0C,
|
||||
0x03, 0x00, 0xC0, 0x60, 0x18, 0x06, 0x03, 0x00, 0xC0, 0x30, 0x18, 0x06,
|
||||
0x01, 0x80, 0xC0, 0x30, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1F, 0xFC, 0x3C,
|
||||
0x3C, 0x78, 0x1E, 0x70, 0x0E, 0x70, 0x0E, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
|
||||
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
|
||||
0x07, 0xE0, 0x07, 0xE0, 0x0F, 0x70, 0x0E, 0x70, 0x0E, 0x78, 0x1E, 0x3C,
|
||||
0x3C, 0x1F, 0xF8, 0x1F, 0xF0, 0x07, 0xE0, 0x03, 0x03, 0x07, 0x0F, 0x3F,
|
||||
0xFF, 0xFF, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xE0, 0x1F, 0xF8,
|
||||
0x3F, 0xFC, 0x7C, 0x3E, 0x70, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x07,
|
||||
0x00, 0x07, 0x00, 0x07, 0x00, 0x0F, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0xF8,
|
||||
0x03, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x3C, 0x00, 0x38, 0x00, 0x70, 0x00,
|
||||
0x60, 0x00, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xF0,
|
||||
0x07, 0xFE, 0x07, 0xFF, 0x87, 0x83, 0xC3, 0x80, 0xF3, 0x80, 0x39, 0xC0,
|
||||
0x1C, 0xE0, 0x0E, 0x00, 0x07, 0x00, 0x0F, 0x00, 0x7F, 0x00, 0x3F, 0x00,
|
||||
0x1F, 0xE0, 0x00, 0x78, 0x00, 0x1E, 0x00, 0x07, 0x00, 0x03, 0xF0, 0x01,
|
||||
0xF8, 0x00, 0xFE, 0x00, 0x77, 0x00, 0x73, 0xE0, 0xF8, 0xFF, 0xF8, 0x3F,
|
||||
0xF8, 0x07, 0xF0, 0x00, 0x00, 0x38, 0x00, 0x38, 0x00, 0x78, 0x00, 0xF8,
|
||||
0x00, 0xF8, 0x01, 0xF8, 0x03, 0xB8, 0x03, 0x38, 0x07, 0x38, 0x0E, 0x38,
|
||||
0x1C, 0x38, 0x18, 0x38, 0x38, 0x38, 0x70, 0x38, 0x60, 0x38, 0xE0, 0x38,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x1F, 0xFF, 0x0F, 0xFF, 0x8F, 0xFF,
|
||||
0xC7, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x39,
|
||||
0xF0, 0x3F, 0xFE, 0x1F, 0xFF, 0x8F, 0x83, 0xE7, 0x00, 0xF0, 0x00, 0x3C,
|
||||
0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xFC, 0x00,
|
||||
0xEF, 0x00, 0x73, 0xC0, 0xF0, 0xFF, 0xF8, 0x3F, 0xF8, 0x07, 0xE0, 0x00,
|
||||
0x03, 0xE0, 0x0F, 0xF8, 0x1F, 0xFC, 0x3C, 0x1E, 0x38, 0x0E, 0x70, 0x0E,
|
||||
0x70, 0x00, 0x60, 0x00, 0xE0, 0x00, 0xE3, 0xE0, 0xEF, 0xF8, 0xFF, 0xFC,
|
||||
0xFC, 0x3E, 0xF0, 0x0E, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07,
|
||||
0x60, 0x07, 0x70, 0x0F, 0x70, 0x0E, 0x3C, 0x3E, 0x3F, 0xFC, 0x1F, 0xF8,
|
||||
0x07, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x06, 0x00, 0x0E,
|
||||
0x00, 0x1C, 0x00, 0x18, 0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x00, 0xE0,
|
||||
0x00, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0x00,
|
||||
0x07, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0C, 0x00,
|
||||
0x1C, 0x00, 0x1C, 0x00, 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0xFF, 0x87, 0x83,
|
||||
0xC7, 0x80, 0xF3, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x78, 0x0F, 0x1E,
|
||||
0x0F, 0x07, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0xE3, 0xE0, 0xF9, 0xC0, 0x1D,
|
||||
0xC0, 0x0F, 0xE0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0xF7, 0x00,
|
||||
0x73, 0xE0, 0xF8, 0xFF, 0xF8, 0x3F, 0xF8, 0x07, 0xF0, 0x00, 0x07, 0xE0,
|
||||
0x1F, 0xF8, 0x3F, 0xFC, 0x7C, 0x3C, 0x70, 0x0E, 0xF0, 0x0E, 0xE0, 0x06,
|
||||
0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0F, 0x70, 0x0F, 0x78, 0x3F,
|
||||
0x3F, 0xFF, 0x1F, 0xF7, 0x07, 0xC7, 0x00, 0x07, 0x00, 0x06, 0x00, 0x0E,
|
||||
0x70, 0x0E, 0x70, 0x1C, 0x78, 0x3C, 0x3F, 0xF8, 0x1F, 0xF0, 0x07, 0xC0,
|
||||
0xFF, 0xF0, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x00, 0x00,
|
||||
0x00, 0x07, 0xFF, 0xB6, 0xD6, 0x00, 0x00, 0x80, 0x03, 0xC0, 0x07, 0xE0,
|
||||
0x0F, 0xC0, 0x3F, 0x80, 0x7E, 0x00, 0xFC, 0x01, 0xF0, 0x00, 0xE0, 0x00,
|
||||
0x7C, 0x00, 0x1F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00,
|
||||
0x7E, 0x00, 0x0F, 0x00, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x80, 0x80, 0x00, 0x70, 0x00, 0x3E, 0x00, 0x0F, 0xE0, 0x00, 0xFC,
|
||||
0x00, 0x1F, 0xC0, 0x03, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0x80, 0x0F, 0xC0,
|
||||
0x1F, 0x80, 0x7F, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x01, 0xC0, 0x00,
|
||||
0x80, 0x00, 0x00, 0x0F, 0xC0, 0x7F, 0xE1, 0xFF, 0xE3, 0xC3, 0xEF, 0x01,
|
||||
0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0x00, 0x0E, 0x00, 0x38, 0x00, 0xF0,
|
||||
0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x0E,
|
||||
0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x03, 0x80,
|
||||
0x07, 0x00, 0x0E, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x3F, 0xFF, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0xC0, 0x01, 0xF8, 0x0F, 0xE0, 0x03, 0xE0, 0x01, 0xF0,
|
||||
0x07, 0x80, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x3C, 0x1E, 0x00, 0x00, 0x1E,
|
||||
0x3C, 0x03, 0xE0, 0x1E, 0x38, 0x0F, 0xF3, 0x8E, 0x78, 0x1E, 0x3F, 0x0F,
|
||||
0x70, 0x38, 0x1F, 0x07, 0x70, 0x78, 0x0F, 0x07, 0xE0, 0x70, 0x0E, 0x07,
|
||||
0xE0, 0x70, 0x0E, 0x07, 0xE0, 0xE0, 0x0E, 0x07, 0xE0, 0xE0, 0x1C, 0x07,
|
||||
0xE0, 0xE0, 0x1C, 0x0E, 0xE0, 0xE0, 0x1C, 0x0E, 0xE0, 0xE0, 0x38, 0x1C,
|
||||
0xF0, 0x70, 0x78, 0x3C, 0x70, 0x78, 0xFC, 0x78, 0x78, 0x3F, 0xDF, 0xF0,
|
||||
0x38, 0x1F, 0x0F, 0xC0, 0x3C, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x80, 0x00, 0x00, 0x07, 0xF0, 0x0E, 0x00, 0x01, 0xFF, 0xFE, 0x00,
|
||||
0x00, 0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x03,
|
||||
0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x7F, 0x00, 0x01, 0xDC, 0x00, 0x07, 0x78,
|
||||
0x00, 0x3C, 0xE0, 0x00, 0xE3, 0x80, 0x03, 0x8F, 0x00, 0x1E, 0x1C, 0x00,
|
||||
0x70, 0x70, 0x01, 0xC1, 0xE0, 0x0E, 0x03, 0x80, 0x38, 0x0E, 0x00, 0xE0,
|
||||
0x3C, 0x07, 0xFF, 0xF0, 0x1F, 0xFF, 0xE0, 0xFF, 0xFF, 0x83, 0xC0, 0x0E,
|
||||
0x0E, 0x00, 0x3C, 0x78, 0x00, 0xF1, 0xE0, 0x01, 0xC7, 0x00, 0x07, 0xBC,
|
||||
0x00, 0x1E, 0xF0, 0x00, 0x3B, 0x80, 0x00, 0xF0, 0xFF, 0xFC, 0x1F, 0xFF,
|
||||
0xE3, 0xFF, 0xFE, 0x70, 0x03, 0xCE, 0x00, 0x3D, 0xC0, 0x03, 0xB8, 0x00,
|
||||
0x77, 0x00, 0x0E, 0xE0, 0x01, 0xDC, 0x00, 0x73, 0x80, 0x1E, 0x7F, 0xFF,
|
||||
0x8F, 0xFF, 0xF1, 0xFF, 0xFF, 0x38, 0x00, 0xF7, 0x00, 0x0E, 0xE0, 0x00,
|
||||
0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x03,
|
||||
0xF8, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0xFF, 0x1F, 0xFF, 0x80, 0x00, 0xFF,
|
||||
0x00, 0x0F, 0xFF, 0x00, 0xFF, 0xFE, 0x07, 0xE0, 0x7C, 0x3E, 0x00, 0x78,
|
||||
0xF0, 0x00, 0xE7, 0x80, 0x03, 0xDC, 0x00, 0x07, 0x70, 0x00, 0x03, 0x80,
|
||||
0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00, 0x03, 0x80, 0x00,
|
||||
0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00, 0x1D, 0xC0, 0x00, 0x77,
|
||||
0x00, 0x03, 0xDE, 0x00, 0x0E, 0x3C, 0x00, 0x78, 0xF8, 0x03, 0xC1, 0xF8,
|
||||
0x1F, 0x03, 0xFF, 0xF8, 0x03, 0xFF, 0xC0, 0x03, 0xF8, 0x00, 0xFF, 0xF8,
|
||||
0x0F, 0xFF, 0xE0, 0xFF, 0xFF, 0x0E, 0x00, 0xF8, 0xE0, 0x03, 0xCE, 0x00,
|
||||
0x1C, 0xE0, 0x00, 0xEE, 0x00, 0x0E, 0xE0, 0x00, 0xFE, 0x00, 0x07, 0xE0,
|
||||
0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x7E,
|
||||
0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00, 0x0F, 0xE0, 0x00, 0xEE, 0x00, 0x0E,
|
||||
0xE0, 0x01, 0xEE, 0x00, 0x3C, 0xE0, 0x0F, 0x8F, 0xFF, 0xF0, 0xFF, 0xFE,
|
||||
0x0F, 0xFF, 0x80, 0xFF, 0xFF, 0xBF, 0xFF, 0xEF, 0xFF, 0xFB, 0x80, 0x00,
|
||||
0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00, 0xE0, 0x00, 0x38,
|
||||
0x00, 0x0E, 0x00, 0x03, 0xFF, 0xFE, 0xFF, 0xFF, 0xBF, 0xFF, 0xEE, 0x00,
|
||||
0x03, 0x80, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00,
|
||||
0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x0E, 0x00,
|
||||
0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38,
|
||||
0x00, 0x1F, 0xFF, 0xCF, 0xFF, 0xE7, 0xFF, 0xF3, 0x80, 0x01, 0xC0, 0x00,
|
||||
0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00,
|
||||
0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x7F,
|
||||
0x80, 0x03, 0xFF, 0xE0, 0x07, 0xFF, 0xF8, 0x0F, 0x80, 0xFC, 0x1E, 0x00,
|
||||
0x3E, 0x3C, 0x00, 0x0E, 0x78, 0x00, 0x0F, 0x70, 0x00, 0x07, 0x70, 0x00,
|
||||
0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x03,
|
||||
0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x07, 0xF0, 0x00,
|
||||
0x07, 0x70, 0x00, 0x07, 0x70, 0x00, 0x0F, 0x78, 0x00, 0x0F, 0x3C, 0x00,
|
||||
0x1F, 0x1E, 0x00, 0x3F, 0x0F, 0xC0, 0xF7, 0x07, 0xFF, 0xE7, 0x03, 0xFF,
|
||||
0xC3, 0x00, 0xFF, 0x03, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0,
|
||||
0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0,
|
||||
0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80,
|
||||
0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00,
|
||||
0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00,
|
||||
0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0,
|
||||
0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x80, 0x7E,
|
||||
0x01, 0xF8, 0x07, 0xE0, 0x1F, 0xC0, 0xF7, 0x87, 0x9F, 0xFE, 0x3F, 0xF0,
|
||||
0x3F, 0x00, 0xE0, 0x01, 0xEE, 0x00, 0x3C, 0xE0, 0x07, 0x8E, 0x00, 0xF0,
|
||||
0xE0, 0x1E, 0x0E, 0x03, 0xE0, 0xE0, 0x7C, 0x0E, 0x0F, 0x80, 0xE1, 0xF0,
|
||||
0x0E, 0x1E, 0x00, 0xE3, 0xC0, 0x0E, 0x7C, 0x00, 0xEF, 0xE0, 0x0F, 0xCE,
|
||||
0x00, 0xF8, 0xF0, 0x0F, 0x07, 0x80, 0xE0, 0x3C, 0x0E, 0x03, 0xC0, 0xE0,
|
||||
0x1E, 0x0E, 0x00, 0xF0, 0xE0, 0x0F, 0x0E, 0x00, 0x78, 0xE0, 0x03, 0xCE,
|
||||
0x00, 0x3C, 0xE0, 0x01, 0xEE, 0x00, 0x0F, 0xE0, 0x01, 0xC0, 0x03, 0x80,
|
||||
0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01,
|
||||
0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70,
|
||||
0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00,
|
||||
0x38, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0x00, 0x1F, 0xF8,
|
||||
0x00, 0x1F, 0xF8, 0x00, 0x1F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC,
|
||||
0x00, 0x3F, 0xEE, 0x00, 0x77, 0xEE, 0x00, 0x77, 0xEE, 0x00, 0x77, 0xE7,
|
||||
0x00, 0xE7, 0xE7, 0x00, 0xE7, 0xE7, 0x00, 0xE7, 0xE3, 0x81, 0xC7, 0xE3,
|
||||
0x81, 0xC7, 0xE3, 0x81, 0xC7, 0xE1, 0xC3, 0x87, 0xE1, 0xC3, 0x87, 0xE1,
|
||||
0xC3, 0x87, 0xE0, 0xE7, 0x07, 0xE0, 0xE7, 0x07, 0xE0, 0xE7, 0x07, 0xE0,
|
||||
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x3C, 0x07, 0xE0,
|
||||
0x3C, 0x07, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xF8, 0x00, 0x7F, 0xC0, 0x07,
|
||||
0xFC, 0x00, 0x7F, 0xE0, 0x07, 0xEF, 0x00, 0x7E, 0x70, 0x07, 0xE7, 0x80,
|
||||
0x7E, 0x3C, 0x07, 0xE1, 0xC0, 0x7E, 0x1E, 0x07, 0xE0, 0xE0, 0x7E, 0x0F,
|
||||
0x07, 0xE0, 0x78, 0x7E, 0x03, 0x87, 0xE0, 0x3C, 0x7E, 0x01, 0xE7, 0xE0,
|
||||
0x0E, 0x7E, 0x00, 0xF7, 0xE0, 0x07, 0xFE, 0x00, 0x3F, 0xE0, 0x03, 0xFE,
|
||||
0x00, 0x1F, 0xE0, 0x01, 0xFE, 0x00, 0x0F, 0x00, 0x7F, 0x00, 0x01, 0xFF,
|
||||
0xF0, 0x01, 0xFF, 0xFC, 0x01, 0xF0, 0x1F, 0x01, 0xE0, 0x03, 0xC1, 0xE0,
|
||||
0x00, 0xF1, 0xE0, 0x00, 0x3C, 0xE0, 0x00, 0x0E, 0x70, 0x00, 0x07, 0x70,
|
||||
0x00, 0x03, 0xF8, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x3F,
|
||||
0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0xC0, 0x00, 0x07, 0xE0, 0x00, 0x03,
|
||||
0xB8, 0x00, 0x03, 0x9C, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xE3, 0xC0, 0x01,
|
||||
0xE0, 0xF0, 0x01, 0xE0, 0x3E, 0x03, 0xE0, 0x0F, 0xFF, 0xE0, 0x03, 0xFF,
|
||||
0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFF, 0xFC, 0x3F, 0xFF, 0x8F, 0xFF, 0xF3,
|
||||
0x80, 0x3E, 0xE0, 0x03, 0xF8, 0x00, 0x7E, 0x00, 0x1F, 0x80, 0x07, 0xE0,
|
||||
0x01, 0xF8, 0x00, 0x7E, 0x00, 0x3F, 0x80, 0x1E, 0xFF, 0xFF, 0x3F, 0xFF,
|
||||
0x8F, 0xFF, 0xC3, 0x80, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03,
|
||||
0x80, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00, 0xE0,
|
||||
0x00, 0x38, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xFF, 0xF0, 0x01, 0xFF,
|
||||
0xFC, 0x01, 0xF0, 0x1F, 0x01, 0xE0, 0x03, 0xC1, 0xE0, 0x00, 0xF1, 0xE0,
|
||||
0x00, 0x3C, 0xE0, 0x00, 0x0E, 0x70, 0x00, 0x07, 0x70, 0x00, 0x01, 0xF8,
|
||||
0x00, 0x00, 0xFC, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x1F,
|
||||
0x80, 0x00, 0x0F, 0xC0, 0x00, 0x07, 0xE0, 0x00, 0x07, 0xB8, 0x00, 0x03,
|
||||
0x9C, 0x00, 0x01, 0xCF, 0x00, 0x39, 0xE3, 0xC0, 0x1F, 0xE0, 0xF0, 0x07,
|
||||
0xE0, 0x3E, 0x03, 0xF0, 0x0F, 0xFF, 0xFC, 0x03, 0xFF, 0xEE, 0x00, 0x3F,
|
||||
0x83, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x20, 0xFF, 0xFE, 0x0F, 0xFF,
|
||||
0xF8, 0xFF, 0xFF, 0xCE, 0x00, 0x3C, 0xE0, 0x01, 0xEE, 0x00, 0x0E, 0xE0,
|
||||
0x00, 0xEE, 0x00, 0x0E, 0xE0, 0x00, 0xEE, 0x00, 0x0E, 0xE0, 0x01, 0xCE,
|
||||
0x00, 0x3C, 0xFF, 0xFF, 0x8F, 0xFF, 0xF0, 0xFF, 0xFF, 0x8E, 0x00, 0x3C,
|
||||
0xE0, 0x01, 0xEE, 0x00, 0x0E, 0xE0, 0x00, 0xEE, 0x00, 0x0E, 0xE0, 0x00,
|
||||
0xEE, 0x00, 0x0E, 0xE0, 0x00, 0xEE, 0x00, 0x0E, 0xE0, 0x00, 0xFE, 0x00,
|
||||
0x0F, 0x03, 0xFC, 0x00, 0xFF, 0xF0, 0x1F, 0xFF, 0x83, 0xE0, 0x7C, 0x38,
|
||||
0x01, 0xE7, 0x00, 0x0E, 0x70, 0x00, 0xE7, 0x00, 0x00, 0x70, 0x00, 0x07,
|
||||
0x80, 0x00, 0x3E, 0x00, 0x01, 0xFE, 0x00, 0x0F, 0xFE, 0x00, 0x3F, 0xF8,
|
||||
0x00, 0x3F, 0xE0, 0x00, 0x3E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0xE0, 0x00,
|
||||
0x7E, 0x00, 0x07, 0xF0, 0x00, 0x77, 0x80, 0x0E, 0x7C, 0x03, 0xE3, 0xFF,
|
||||
0xFC, 0x1F, 0xFF, 0x80, 0x3F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x80, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07,
|
||||
0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E,
|
||||
0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C,
|
||||
0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38,
|
||||
0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0xE0, 0x00, 0xFC, 0x00,
|
||||
0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00,
|
||||
0x3F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00,
|
||||
0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00,
|
||||
0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7F, 0x00, 0x1E, 0xF0, 0x07,
|
||||
0x9F, 0x01, 0xF1, 0xFF, 0xFC, 0x1F, 0xFE, 0x00, 0x7F, 0x00, 0xE0, 0x00,
|
||||
0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1C, 0xE0, 0x01, 0xE7, 0x80, 0x0F, 0x3C,
|
||||
0x00, 0x70, 0xE0, 0x07, 0x87, 0x80, 0x3C, 0x1C, 0x01, 0xC0, 0xE0, 0x0E,
|
||||
0x07, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0xE0, 0x38, 0x07, 0x83, 0x80, 0x1C,
|
||||
0x1C, 0x00, 0xE0, 0xE0, 0x07, 0x8E, 0x00, 0x1C, 0x70, 0x00, 0xE3, 0x80,
|
||||
0x07, 0xB8, 0x00, 0x1D, 0xC0, 0x00, 0xEE, 0x00, 0x07, 0xE0, 0x00, 0x1F,
|
||||
0x00, 0x00, 0xF8, 0x00, 0x03, 0x80, 0x00, 0x70, 0x03, 0xC0, 0x0F, 0x70,
|
||||
0x03, 0xC0, 0x0F, 0x78, 0x03, 0xE0, 0x0F, 0x78, 0x03, 0xE0, 0x0E, 0x38,
|
||||
0x07, 0xE0, 0x0E, 0x38, 0x07, 0xF0, 0x1E, 0x3C, 0x07, 0x70, 0x1E, 0x3C,
|
||||
0x07, 0x70, 0x1C, 0x1C, 0x0E, 0x70, 0x1C, 0x1C, 0x0E, 0x38, 0x3C, 0x1C,
|
||||
0x0E, 0x38, 0x3C, 0x1E, 0x1E, 0x38, 0x38, 0x0E, 0x1C, 0x38, 0x38, 0x0E,
|
||||
0x1C, 0x1C, 0x38, 0x0E, 0x1C, 0x1C, 0x78, 0x0F, 0x3C, 0x1C, 0x70, 0x07,
|
||||
0x38, 0x0E, 0x70, 0x07, 0x38, 0x0E, 0x70, 0x07, 0x38, 0x0E, 0x70, 0x07,
|
||||
0x70, 0x0E, 0xE0, 0x03, 0xF0, 0x07, 0xE0, 0x03, 0xF0, 0x07, 0xE0, 0x03,
|
||||
0xF0, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xC0, 0x01, 0xE0, 0x03, 0xC0, 0x01,
|
||||
0xE0, 0x03, 0xC0, 0xF0, 0x00, 0x7B, 0xC0, 0x07, 0x8F, 0x00, 0x38, 0x78,
|
||||
0x03, 0xC1, 0xE0, 0x3C, 0x07, 0x81, 0xC0, 0x3C, 0x1E, 0x00, 0xF1, 0xE0,
|
||||
0x03, 0x8E, 0x00, 0x1E, 0xF0, 0x00, 0x7F, 0x00, 0x01, 0xF0, 0x00, 0x0F,
|
||||
0x80, 0x00, 0x7C, 0x00, 0x07, 0xF0, 0x00, 0x3B, 0x80, 0x03, 0xDE, 0x00,
|
||||
0x3C, 0x78, 0x01, 0xC1, 0xC0, 0x1E, 0x0F, 0x01, 0xE0, 0x3C, 0x0E, 0x00,
|
||||
0xE0, 0xF0, 0x07, 0x8F, 0x00, 0x1E, 0x70, 0x00, 0xF7, 0x80, 0x03, 0xC0,
|
||||
0xF0, 0x00, 0x3C, 0xF0, 0x00, 0x78, 0xF0, 0x01, 0xE1, 0xE0, 0x03, 0x81,
|
||||
0xE0, 0x0F, 0x01, 0xC0, 0x1C, 0x03, 0xC0, 0x78, 0x03, 0xC1, 0xE0, 0x07,
|
||||
0x83, 0x80, 0x07, 0x8F, 0x00, 0x07, 0x1C, 0x00, 0x0F, 0x78, 0x00, 0x0E,
|
||||
0xE0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38,
|
||||
0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80,
|
||||
0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00,
|
||||
0x00, 0x70, 0x00, 0x7F, 0xFF, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0x80, 0x00,
|
||||
0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x1E,
|
||||
0x00, 0x07, 0x80, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0,
|
||||
0x00, 0x78, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x7C, 0x00,
|
||||
0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xF8, 0xE3, 0x8E, 0x38, 0xE3,
|
||||
0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3,
|
||||
0x8E, 0x38, 0xE3, 0x8F, 0xFF, 0xFC, 0xC0, 0x30, 0x06, 0x01, 0x80, 0x60,
|
||||
0x0C, 0x03, 0x00, 0xC0, 0x18, 0x06, 0x01, 0x80, 0x20, 0x0C, 0x03, 0x00,
|
||||
0x40, 0x18, 0x06, 0x01, 0x80, 0x30, 0x0C, 0x03, 0x00, 0x60, 0x18, 0x06,
|
||||
0x00, 0xC0, 0x30, 0xFF, 0xFF, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7,
|
||||
0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7,
|
||||
0x1C, 0x7F, 0xFF, 0xFC, 0x07, 0x00, 0x78, 0x03, 0xC0, 0x3F, 0x01, 0xD8,
|
||||
0x0C, 0xE0, 0xE3, 0x06, 0x1C, 0x70, 0xE3, 0x83, 0x18, 0x1D, 0xC0, 0x6C,
|
||||
0x03, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0xF0, 0xE0, 0xE0,
|
||||
0xE0, 0x07, 0xF0, 0x0F, 0xFC, 0x0F, 0xFF, 0x0F, 0x03, 0xC7, 0x00, 0xE0,
|
||||
0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0xFE, 0x0F, 0xFF, 0x1F, 0xF3,
|
||||
0x9F, 0x01, 0xCF, 0x00, 0xE7, 0x00, 0x73, 0x80, 0x79, 0xE0, 0xFC, 0x7F,
|
||||
0xEF, 0x9F, 0xE3, 0xC7, 0xE1, 0xE0, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
|
||||
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE3, 0xE0, 0xEF, 0xF8,
|
||||
0xFF, 0xFC, 0xFC, 0x3E, 0xF8, 0x1E, 0xF0, 0x0E, 0xE0, 0x0F, 0xE0, 0x07,
|
||||
0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xF0, 0x0E,
|
||||
0xF8, 0x1E, 0xFC, 0x3C, 0xEF, 0xFC, 0xEF, 0xF8, 0xE3, 0xE0, 0x07, 0xF0,
|
||||
0x1F, 0xF8, 0x3F, 0xFC, 0x3C, 0x1E, 0x78, 0x0E, 0x70, 0x07, 0xE0, 0x00,
|
||||
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x07,
|
||||
0x70, 0x07, 0x78, 0x0E, 0x7C, 0x1E, 0x3F, 0xFC, 0x1F, 0xF8, 0x07, 0xE0,
|
||||
0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00,
|
||||
0x1C, 0x00, 0x0E, 0x0F, 0xC7, 0x1F, 0xFB, 0x9F, 0xFF, 0xDF, 0x07, 0xEF,
|
||||
0x01, 0xF7, 0x00, 0x7F, 0x80, 0x3F, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x03,
|
||||
0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0x77, 0x00, 0x7B, 0xC0, 0x7D, 0xF0,
|
||||
0x7E, 0x7F, 0xFB, 0x1F, 0xF9, 0x83, 0xF0, 0xC0, 0x07, 0xE0, 0x1F, 0xF8,
|
||||
0x3F, 0xFC, 0x7C, 0x1E, 0x70, 0x0E, 0x60, 0x06, 0xE0, 0x07, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x70, 0x07,
|
||||
0x78, 0x0E, 0x3C, 0x1E, 0x3F, 0xFC, 0x1F, 0xF8, 0x07, 0xE0, 0x0E, 0x3C,
|
||||
0xF9, 0xC3, 0x87, 0x0E, 0x7F, 0xFF, 0xFC, 0xE1, 0xC3, 0x87, 0x0E, 0x1C,
|
||||
0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0x07, 0xC7, 0x1F,
|
||||
0xF7, 0x3F, 0xFF, 0x3C, 0x3F, 0x78, 0x0F, 0x70, 0x0F, 0xE0, 0x07, 0xE0,
|
||||
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0x70,
|
||||
0x0F, 0x78, 0x0F, 0x7C, 0x3F, 0x3F, 0xF7, 0x1F, 0xE7, 0x07, 0xC7, 0x00,
|
||||
0x07, 0x00, 0x07, 0x00, 0x0E, 0x70, 0x0E, 0x78, 0x1E, 0x3F, 0xFC, 0x1F,
|
||||
0xF8, 0x07, 0xE0, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00,
|
||||
0x1C, 0x00, 0x38, 0x00, 0x71, 0xF8, 0xE7, 0xFD, 0xDF, 0xFB, 0xF0, 0xFF,
|
||||
0xC0, 0xFF, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0,
|
||||
0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07,
|
||||
0xE0, 0x0F, 0xC0, 0x1C, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFC, 0x1C, 0x71, 0xC7, 0x00, 0x00, 0x07, 0x1C, 0x71, 0xC7, 0x1C,
|
||||
0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C,
|
||||
0x73, 0xFF, 0xFB, 0xC0, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
|
||||
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x3C, 0xE0, 0x78, 0xE0, 0xF0,
|
||||
0xE1, 0xE0, 0xE3, 0xC0, 0xE7, 0x80, 0xEF, 0x00, 0xEF, 0x80, 0xFF, 0x80,
|
||||
0xFB, 0xC0, 0xF1, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xE0, 0x70, 0xE0, 0x78,
|
||||
0xE0, 0x3C, 0xE0, 0x1C, 0xE0, 0x1E, 0xE0, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xE3, 0xE0, 0xF8, 0xE7, 0xF1, 0xFE,
|
||||
0xEF, 0xFB, 0xFE, 0xF8, 0x7F, 0x0F, 0xF0, 0x3E, 0x07, 0xF0, 0x1C, 0x07,
|
||||
0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07,
|
||||
0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07,
|
||||
0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07, 0xE0, 0x1C, 0x07,
|
||||
0xE0, 0x1C, 0x07, 0xE3, 0xF1, 0xCF, 0xFB, 0xBF, 0xF7, 0xE1, 0xFF, 0x81,
|
||||
0xFE, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F,
|
||||
0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0,
|
||||
0x1F, 0x80, 0x38, 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0xFF, 0x87, 0x83, 0xC7,
|
||||
0x80, 0xF3, 0x80, 0x3B, 0x80, 0x1F, 0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01,
|
||||
0xF8, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0x3B, 0x80, 0x39, 0xE0, 0x3C, 0x78,
|
||||
0x3C, 0x3F, 0xFE, 0x0F, 0xFE, 0x01, 0xFC, 0x00, 0xE3, 0xE0, 0xE7, 0xF8,
|
||||
0xEF, 0xFC, 0xFC, 0x3E, 0xF8, 0x1E, 0xF0, 0x0E, 0xE0, 0x0F, 0xE0, 0x07,
|
||||
0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xF0, 0x0E,
|
||||
0xF8, 0x1E, 0xFC, 0x3E, 0xFF, 0xFC, 0xEF, 0xF8, 0xE3, 0xE0, 0xE0, 0x00,
|
||||
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x07, 0xE1,
|
||||
0x8F, 0xFC, 0xCF, 0xFF, 0x67, 0x83, 0xF7, 0x80, 0xFB, 0x80, 0x3F, 0xC0,
|
||||
0x1F, 0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0x7E,
|
||||
0x00, 0x3B, 0x80, 0x3D, 0xE0, 0x3E, 0xF8, 0x3F, 0x3F, 0xFF, 0x8F, 0xFD,
|
||||
0xC1, 0xF8, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00,
|
||||
0x07, 0x00, 0x03, 0x80, 0xE3, 0xF7, 0xFB, 0xFF, 0x8F, 0x07, 0x83, 0x81,
|
||||
0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||
0x38, 0x00, 0x0F, 0xC0, 0xFF, 0x87, 0xFF, 0x3C, 0x1E, 0xE0, 0x3B, 0x80,
|
||||
0x0E, 0x00, 0x3C, 0x00, 0x7F, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x7F, 0x00,
|
||||
0x3F, 0x80, 0x7E, 0x01, 0xFC, 0x1F, 0x7F, 0xF8, 0xFF, 0xC1, 0xFC, 0x00,
|
||||
0x38, 0x70, 0xE1, 0xCF, 0xFF, 0xFF, 0x9C, 0x38, 0x70, 0xE1, 0xC3, 0x87,
|
||||
0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0xE7, 0xC7, 0x80, 0xE0, 0x0F, 0xC0,
|
||||
0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07,
|
||||
0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x03, 0xFC,
|
||||
0x0F, 0xFC, 0x3F, 0x7F, 0xEE, 0xFF, 0x9C, 0x7E, 0x38, 0x70, 0x03, 0xB8,
|
||||
0x03, 0x9C, 0x01, 0xC7, 0x00, 0xE3, 0x80, 0xE1, 0xC0, 0x70, 0x70, 0x38,
|
||||
0x38, 0x38, 0x1C, 0x1C, 0x07, 0x0E, 0x03, 0x8E, 0x01, 0xC7, 0x00, 0x77,
|
||||
0x00, 0x3B, 0x80, 0x1D, 0xC0, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0, 0x00,
|
||||
0x70, 0x00, 0xF0, 0x1C, 0x03, 0xB8, 0x1F, 0x03, 0xDC, 0x0F, 0x81, 0xCE,
|
||||
0x07, 0xC0, 0xE7, 0x83, 0xE0, 0x71, 0xC3, 0xB8, 0x70, 0xE1, 0xDC, 0x38,
|
||||
0x70, 0xEE, 0x1C, 0x1C, 0x63, 0x0E, 0x0E, 0x71, 0xCE, 0x07, 0x38, 0xE7,
|
||||
0x03, 0x9C, 0x73, 0x80, 0xEC, 0x19, 0x80, 0x7E, 0x0F, 0xC0, 0x3F, 0x07,
|
||||
0xE0, 0x0F, 0x83, 0xF0, 0x07, 0x80, 0xF0, 0x03, 0xC0, 0x78, 0x01, 0xE0,
|
||||
0x3C, 0x00, 0x70, 0x07, 0x38, 0x0E, 0x3C, 0x1C, 0x1C, 0x1C, 0x0E, 0x38,
|
||||
0x0F, 0x70, 0x07, 0x70, 0x03, 0xE0, 0x03, 0xC0, 0x01, 0xC0, 0x03, 0xE0,
|
||||
0x07, 0xE0, 0x07, 0x70, 0x0E, 0x78, 0x1E, 0x38, 0x1C, 0x1C, 0x38, 0x1E,
|
||||
0x78, 0x0E, 0x70, 0x07, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xC7, 0x01,
|
||||
0xC3, 0x80, 0xE1, 0xC0, 0x70, 0x70, 0x70, 0x38, 0x38, 0x1C, 0x3C, 0x07,
|
||||
0x1C, 0x03, 0x8E, 0x01, 0xCE, 0x00, 0x77, 0x00, 0x3B, 0x80, 0x1F, 0x80,
|
||||
0x07, 0xC0, 0x03, 0xE0, 0x01, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x1C, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x3F, 0x00, 0x1F, 0x00, 0x0F,
|
||||
0x00, 0x00, 0x7F, 0xFC, 0xFF, 0xF9, 0xFF, 0xF0, 0x00, 0xE0, 0x03, 0x80,
|
||||
0x0E, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x1C, 0x00, 0x70,
|
||||
0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xF8, 0x07, 0x0F, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x38, 0xF8, 0xE0, 0xF8, 0x38, 0x1C, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x0F, 0x07, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xE0, 0xF0, 0xF8, 0x38,
|
||||
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x1C, 0x1F,
|
||||
0x07, 0x1F, 0x1C, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
|
||||
0x38, 0x38, 0xF8, 0xF0, 0xE0, 0x38, 0x00, 0xFC, 0x03, 0xFC, 0x1F, 0x3E,
|
||||
0x3C, 0x1F, 0xE0, 0x1F, 0x80, 0x1E, 0x00};
|
||||
|
||||
const GFXglyph FreeSans18pt7bGlyphs[] PROGMEM = {
|
||||
{0, 0, 0, 9, 0, 1}, // 0x20 ' '
|
||||
{0, 3, 26, 12, 4, -25}, // 0x21 '!'
|
||||
{10, 9, 9, 12, 1, -24}, // 0x22 '"'
|
||||
{21, 19, 24, 19, 0, -23}, // 0x23 '#'
|
||||
{78, 16, 30, 19, 2, -26}, // 0x24 '$'
|
||||
{138, 29, 25, 31, 1, -24}, // 0x25 '%'
|
||||
{229, 20, 25, 23, 2, -24}, // 0x26 '&'
|
||||
{292, 3, 9, 7, 2, -24}, // 0x27 '''
|
||||
{296, 8, 33, 12, 3, -25}, // 0x28 '('
|
||||
{329, 8, 33, 12, 1, -25}, // 0x29 ')'
|
||||
{362, 10, 10, 14, 2, -25}, // 0x2A '*'
|
||||
{375, 16, 16, 20, 2, -15}, // 0x2B '+'
|
||||
{407, 3, 9, 10, 3, -3}, // 0x2C ','
|
||||
{411, 8, 3, 12, 2, -10}, // 0x2D '-'
|
||||
{414, 3, 4, 9, 3, -3}, // 0x2E '.'
|
||||
{416, 10, 26, 10, 0, -25}, // 0x2F '/'
|
||||
{449, 16, 25, 19, 2, -24}, // 0x30 '0'
|
||||
{499, 8, 25, 19, 4, -24}, // 0x31 '1'
|
||||
{524, 16, 25, 19, 2, -24}, // 0x32 '2'
|
||||
{574, 17, 25, 19, 1, -24}, // 0x33 '3'
|
||||
{628, 16, 25, 19, 1, -24}, // 0x34 '4'
|
||||
{678, 17, 25, 19, 1, -24}, // 0x35 '5'
|
||||
{732, 16, 25, 19, 2, -24}, // 0x36 '6'
|
||||
{782, 16, 25, 19, 2, -24}, // 0x37 '7'
|
||||
{832, 17, 25, 19, 1, -24}, // 0x38 '8'
|
||||
{886, 16, 25, 19, 1, -24}, // 0x39 '9'
|
||||
{936, 3, 19, 9, 3, -18}, // 0x3A ':'
|
||||
{944, 3, 24, 9, 3, -18}, // 0x3B ';'
|
||||
{953, 17, 17, 20, 2, -16}, // 0x3C '<'
|
||||
{990, 17, 9, 20, 2, -12}, // 0x3D '='
|
||||
{1010, 17, 17, 20, 2, -16}, // 0x3E '>'
|
||||
{1047, 15, 26, 19, 3, -25}, // 0x3F '?'
|
||||
{1096, 32, 31, 36, 1, -25}, // 0x40 '@'
|
||||
{1220, 22, 26, 23, 1, -25}, // 0x41 'A'
|
||||
{1292, 19, 26, 23, 3, -25}, // 0x42 'B'
|
||||
{1354, 22, 26, 25, 1, -25}, // 0x43 'C'
|
||||
{1426, 20, 26, 24, 3, -25}, // 0x44 'D'
|
||||
{1491, 18, 26, 22, 3, -25}, // 0x45 'E'
|
||||
{1550, 17, 26, 21, 3, -25}, // 0x46 'F'
|
||||
{1606, 24, 26, 27, 1, -25}, // 0x47 'G'
|
||||
{1684, 19, 26, 25, 3, -25}, // 0x48 'H'
|
||||
{1746, 3, 26, 10, 4, -25}, // 0x49 'I'
|
||||
{1756, 14, 26, 18, 1, -25}, // 0x4A 'J'
|
||||
{1802, 20, 26, 24, 3, -25}, // 0x4B 'K'
|
||||
{1867, 15, 26, 20, 3, -25}, // 0x4C 'L'
|
||||
{1916, 24, 26, 30, 3, -25}, // 0x4D 'M'
|
||||
{1994, 20, 26, 26, 3, -25}, // 0x4E 'N'
|
||||
{2059, 25, 26, 27, 1, -25}, // 0x4F 'O'
|
||||
{2141, 18, 26, 23, 3, -25}, // 0x50 'P'
|
||||
{2200, 25, 28, 27, 1, -25}, // 0x51 'Q'
|
||||
{2288, 20, 26, 25, 3, -25}, // 0x52 'R'
|
||||
{2353, 20, 26, 23, 1, -25}, // 0x53 'S'
|
||||
{2418, 19, 26, 22, 1, -25}, // 0x54 'T'
|
||||
{2480, 19, 26, 25, 3, -25}, // 0x55 'U'
|
||||
{2542, 21, 26, 23, 1, -25}, // 0x56 'V'
|
||||
{2611, 32, 26, 33, 0, -25}, // 0x57 'W'
|
||||
{2715, 21, 26, 23, 1, -25}, // 0x58 'X'
|
||||
{2784, 23, 26, 24, 0, -25}, // 0x59 'Y'
|
||||
{2859, 19, 26, 22, 1, -25}, // 0x5A 'Z'
|
||||
{2921, 6, 33, 10, 2, -25}, // 0x5B '['
|
||||
{2946, 10, 26, 10, 0, -25}, // 0x5C '\'
|
||||
{2979, 6, 33, 10, 1, -25}, // 0x5D ']'
|
||||
{3004, 13, 13, 16, 2, -24}, // 0x5E '^'
|
||||
{3026, 21, 2, 19, -1, 5}, // 0x5F '_'
|
||||
{3032, 7, 5, 9, 1, -25}, // 0x60 '`'
|
||||
{3037, 17, 19, 19, 1, -18}, // 0x61 'a'
|
||||
{3078, 16, 26, 20, 2, -25}, // 0x62 'b'
|
||||
{3130, 16, 19, 18, 1, -18}, // 0x63 'c'
|
||||
{3168, 17, 26, 20, 1, -25}, // 0x64 'd'
|
||||
{3224, 16, 19, 19, 1, -18}, // 0x65 'e'
|
||||
{3262, 7, 26, 10, 1, -25}, // 0x66 'f'
|
||||
{3285, 16, 27, 19, 1, -18}, // 0x67 'g'
|
||||
{3339, 15, 26, 19, 2, -25}, // 0x68 'h'
|
||||
{3388, 3, 26, 8, 2, -25}, // 0x69 'i'
|
||||
{3398, 6, 34, 9, 0, -25}, // 0x6A 'j'
|
||||
{3424, 16, 26, 18, 2, -25}, // 0x6B 'k'
|
||||
{3476, 3, 26, 7, 2, -25}, // 0x6C 'l'
|
||||
{3486, 24, 19, 28, 2, -18}, // 0x6D 'm'
|
||||
{3543, 15, 19, 19, 2, -18}, // 0x6E 'n'
|
||||
{3579, 17, 19, 19, 1, -18}, // 0x6F 'o'
|
||||
{3620, 16, 25, 20, 2, -18}, // 0x70 'p'
|
||||
{3670, 17, 25, 20, 1, -18}, // 0x71 'q'
|
||||
{3724, 9, 19, 12, 2, -18}, // 0x72 'r'
|
||||
{3746, 14, 19, 17, 2, -18}, // 0x73 's'
|
||||
{3780, 7, 23, 10, 1, -22}, // 0x74 't'
|
||||
{3801, 15, 19, 19, 2, -18}, // 0x75 'u'
|
||||
{3837, 17, 19, 17, 0, -18}, // 0x76 'v'
|
||||
{3878, 25, 19, 25, 0, -18}, // 0x77 'w'
|
||||
{3938, 16, 19, 17, 0, -18}, // 0x78 'x'
|
||||
{3976, 17, 27, 17, 0, -18}, // 0x79 'y'
|
||||
{4034, 15, 19, 17, 1, -18}, // 0x7A 'z'
|
||||
{4070, 8, 33, 12, 1, -25}, // 0x7B '{'
|
||||
{4103, 2, 33, 9, 3, -25}, // 0x7C '|'
|
||||
{4112, 8, 33, 12, 3, -25}, // 0x7D '}'
|
||||
{4145, 15, 7, 18, 1, -15}}; // 0x7E '~'
|
||||
|
||||
const GFXfont FreeSans18pt7b PROGMEM = {(uint8_t *)FreeSans18pt7bBitmaps,
|
||||
(GFXglyph *)FreeSans18pt7bGlyphs, 0x20,
|
||||
0x7E, 42};
|
||||
|
||||
// Approx. 4831 bytes
|
1030
RX_FSK/src/fonts/FreeSans18pt8b.h
Normal file
1030
RX_FSK/src/fonts/FreeSans18pt8b.h
Normal file
File diff suppressed because it is too large
Load Diff
0
libraries/fonts/FreeSans9pt7b.h → RX_FSK/src/fonts/FreeSans9pt7b.h
Executable file → Normal file
0
libraries/fonts/FreeSans9pt7b.h → RX_FSK/src/fonts/FreeSans9pt7b.h
Executable file → Normal file
421
RX_FSK/src/fonts/FreeSans9pt8b.h
Normal file
421
RX_FSK/src/fonts/FreeSans9pt8b.h
Normal file
|
@ -0,0 +1,421 @@
|
|||
const uint8_t FreeSans9pt8bBitmaps[] PROGMEM = {
|
||||
0x00, 0xFF, 0xFF, 0x83, 0xC0, 0xDD, 0xD9, 0x90, 0x09, 0x82, 0x61, 0x90,
|
||||
0x64, 0x7F, 0xC4, 0xC1, 0x30, 0xC8, 0xFF, 0xBF, 0xE2, 0x20, 0x98, 0x26,
|
||||
0x00, 0x10, 0x3C, 0x76, 0xD3, 0x93, 0xD0, 0xF0, 0x7C, 0x17, 0x13, 0x91,
|
||||
0x91, 0xD3, 0x7E, 0x10, 0x10, 0x00, 0x21, 0xE1, 0x08, 0x84, 0x23, 0x20,
|
||||
0x8C, 0x83, 0x64, 0x07, 0x10, 0x00, 0x8E, 0x06, 0x6C, 0x13, 0x10, 0xCC,
|
||||
0x42, 0x11, 0x18, 0x78, 0x1C, 0x0F, 0x86, 0x21, 0x88, 0x36, 0x0F, 0x03,
|
||||
0x81, 0xB2, 0xC6, 0xA0, 0xEC, 0x13, 0x1E, 0x7C, 0xC0, 0xFE, 0x80, 0x12,
|
||||
0x26, 0x44, 0xCC, 0xCC, 0x44, 0x46, 0x22, 0x10, 0x84, 0x46, 0x22, 0x23,
|
||||
0x33, 0x22, 0x26, 0x4C, 0x80, 0x25, 0x5C, 0xA5, 0x00, 0x08, 0x04, 0x02,
|
||||
0x01, 0x0F, 0xF8, 0x40, 0x20, 0x10, 0x08, 0x00, 0xF0, 0xFF, 0xC0, 0x08,
|
||||
0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00, 0x18, 0x7E, 0x42, 0xC3,
|
||||
0xC3, 0x83, 0x83, 0x83, 0x83, 0xC3, 0xC3, 0x46, 0x7C, 0x11, 0x7F, 0x11,
|
||||
0x11, 0x11, 0x11, 0x10, 0x3C, 0x7E, 0xC3, 0xC1, 0x81, 0x03, 0x06, 0x1C,
|
||||
0x30, 0x60, 0xC0, 0xFF, 0xFF, 0x3C, 0x7E, 0xC3, 0xC3, 0x03, 0x06, 0x1C,
|
||||
0x03, 0x03, 0x83, 0x83, 0xC3, 0x7E, 0x02, 0x03, 0x01, 0x81, 0x41, 0xA1,
|
||||
0x90, 0x88, 0xC4, 0xC2, 0x7F, 0xC0, 0x80, 0x40, 0x20, 0x7F, 0x7F, 0x40,
|
||||
0x40, 0xC0, 0xFE, 0xC3, 0x03, 0x01, 0x01, 0x83, 0xC3, 0x7E, 0x1C, 0x7E,
|
||||
0x43, 0xC3, 0xC0, 0xBC, 0xFE, 0xC3, 0xC1, 0xC1, 0xC3, 0x63, 0x7E, 0xFF,
|
||||
0xFF, 0x03, 0x02, 0x04, 0x0C, 0x08, 0x18, 0x10, 0x30, 0x30, 0x20, 0x20,
|
||||
0x3C, 0x7E, 0xC3, 0xC3, 0xC3, 0x66, 0x7C, 0xC3, 0x83, 0x81, 0x83, 0xC3,
|
||||
0x7E, 0x38, 0x7E, 0xC2, 0x83, 0x83, 0x83, 0xC3, 0x7D, 0x13, 0x03, 0xC3,
|
||||
0xC6, 0x7C, 0xC0, 0x03, 0xC0, 0xC0, 0x03, 0xD6, 0x00, 0x01, 0xC3, 0x8F,
|
||||
0x0C, 0x07, 0x00, 0xF0, 0x0E, 0x01, 0x80, 0xFF, 0x80, 0x00, 0x1F, 0xF0,
|
||||
0x00, 0x60, 0x1E, 0x01, 0xC0, 0x38, 0x3C, 0x71, 0xE0, 0x80, 0x00, 0x3E,
|
||||
0x63, 0x43, 0xC1, 0x03, 0x06, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18,
|
||||
0x07, 0xF0, 0x1C, 0x1C, 0x30, 0x0E, 0x60, 0x06, 0x43, 0xD3, 0xC6, 0x33,
|
||||
0x8C, 0x31, 0x8C, 0x23, 0x88, 0x23, 0x8C, 0x62, 0xCC, 0xEC, 0xC7, 0x38,
|
||||
0x60, 0x00, 0x38, 0x00, 0x0F, 0xF0, 0x01, 0x80, 0x06, 0x00, 0xF0, 0x0F,
|
||||
0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x06, 0x60,
|
||||
0x66, 0x06, 0xC0, 0x30, 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xB0, 0xEF,
|
||||
0xFB, 0x03, 0xC0, 0xF0, 0x1C, 0x0F, 0x07, 0xFF, 0x00, 0x1F, 0x86, 0x19,
|
||||
0x81, 0xE0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x78, 0x0D, 0x81,
|
||||
0xB8, 0x63, 0xF8, 0xFE, 0x20, 0xC8, 0x1A, 0x03, 0x80, 0xE0, 0x38, 0x0E,
|
||||
0x03, 0x80, 0xE0, 0x38, 0x1A, 0x1C, 0xFE, 0x00, 0xFF, 0xC0, 0x20, 0x10,
|
||||
0x08, 0x04, 0x03, 0xFD, 0x00, 0x80, 0x40, 0x20, 0x10, 0x0F, 0xF8, 0xFF,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x1F, 0x83, 0x0E, 0x60, 0x6C, 0x03, 0xC0, 0x0C, 0x00, 0x83, 0xFC, 0x3F,
|
||||
0xC0, 0x3C, 0x03, 0x60, 0x77, 0x0F, 0x1F, 0x90, 0xC0, 0x78, 0x0F, 0x01,
|
||||
0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0,
|
||||
0x3C, 0x06, 0xFF, 0xF8, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0xC3, 0xC3, 0x66, 0x7E, 0xC0, 0xD8, 0x33, 0x0C, 0x63, 0x0C, 0xC1,
|
||||
0xB8, 0x3F, 0x07, 0x30, 0xC3, 0x18, 0x63, 0x06, 0x60, 0x6C, 0x04, 0xC0,
|
||||
0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18,
|
||||
0x0F, 0xF8, 0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F,
|
||||
0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, 0x80,
|
||||
0xE0, 0x7C, 0x0F, 0xC1, 0xEC, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3,
|
||||
0x78, 0x2F, 0x07, 0xE0, 0x7C, 0x0E, 0x1F, 0x87, 0x0E, 0x60, 0x6C, 0x03,
|
||||
0xC0, 0x38, 0x01, 0x80, 0x18, 0x01, 0xC0, 0x3C, 0x03, 0x60, 0x67, 0x0E,
|
||||
0x1F, 0x80, 0xFF, 0x41, 0xE0, 0x70, 0x38, 0x1C, 0x0F, 0xFD, 0x00, 0x80,
|
||||
0x40, 0x20, 0x10, 0x08, 0x00, 0x1F, 0x87, 0x0E, 0x60, 0x6C, 0x03, 0xC0,
|
||||
0x38, 0x01, 0x80, 0x18, 0x01, 0xC0, 0x3C, 0x03, 0x61, 0xE7, 0x0E, 0x1F,
|
||||
0xF0, 0x01, 0xFF, 0x20, 0x68, 0x0E, 0x03, 0x80, 0xE0, 0x6F, 0xF2, 0x06,
|
||||
0x80, 0xA0, 0x28, 0x0A, 0x03, 0x80, 0xC0, 0x3F, 0x18, 0x6C, 0x0F, 0x03,
|
||||
0xC0, 0x1E, 0x01, 0xF0, 0x0F, 0x00, 0xF0, 0x3C, 0x0D, 0x87, 0x3F, 0x80,
|
||||
0xFF, 0xE0, 0x80, 0x10, 0x02, 0x00, 0x40, 0x08, 0x01, 0x00, 0x20, 0x04,
|
||||
0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80,
|
||||
0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3C, 0x0B, 0x86, 0x7F, 0x00, 0xC0,
|
||||
0x58, 0x1B, 0x03, 0x30, 0x46, 0x18, 0x43, 0x0C, 0x41, 0x98, 0x13, 0x03,
|
||||
0x40, 0x78, 0x07, 0x00, 0xC0, 0x41, 0xC1, 0xB0, 0xE1, 0x98, 0x50, 0xCC,
|
||||
0x28, 0x62, 0x36, 0x31, 0x9B, 0x10, 0xC8, 0x98, 0x64, 0x6C, 0x16, 0x36,
|
||||
0x0B, 0x0A, 0x07, 0x07, 0x03, 0x83, 0x80, 0xC1, 0xC0, 0x60, 0x63, 0x0C,
|
||||
0x30, 0xC1, 0x98, 0x0F, 0x00, 0x70, 0x06, 0x00, 0xF0, 0x09, 0x81, 0x98,
|
||||
0x30, 0xC6, 0x06, 0x60, 0x60, 0x60, 0x36, 0x06, 0x30, 0xC1, 0x0C, 0x19,
|
||||
0x80, 0xD0, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06,
|
||||
0x00, 0x7F, 0xC0, 0x18, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x80, 0x60,
|
||||
0x18, 0x06, 0x01, 0x80, 0x30, 0x0F, 0xFE, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
0xCC, 0xCC, 0xCC, 0xF0, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10,
|
||||
0x80, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xF0, 0x30, 0x60,
|
||||
0xA2, 0x44, 0xD8, 0xA1, 0x00, 0xFF, 0xC0, 0x63, 0x3C, 0x3F, 0x30, 0x80,
|
||||
0x60, 0x73, 0xFB, 0x0D, 0x06, 0xC7, 0x7D, 0xC0, 0x80, 0x80, 0x80, 0x9C,
|
||||
0xBE, 0xC3, 0xC1, 0xC1, 0x81, 0xC1, 0xC3, 0xE3, 0xBE, 0x38, 0x7E, 0xC2,
|
||||
0x82, 0x80, 0x80, 0x80, 0x82, 0xC6, 0x7C, 0x01, 0x80, 0xC0, 0x63, 0xB3,
|
||||
0xFB, 0x0D, 0x06, 0x83, 0xC1, 0xA0, 0xD0, 0x6C, 0x73, 0xE8, 0x18, 0x7E,
|
||||
0xC3, 0xC3, 0x81, 0xFF, 0x80, 0xC3, 0xC3, 0x7E, 0x39, 0x08, 0x4F, 0x90,
|
||||
0x84, 0x21, 0x08, 0x42, 0x00, 0x38, 0x7F, 0xC7, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0xC7, 0x7F, 0x03, 0x82, 0xE6, 0x7C, 0xC0, 0xC0, 0xC0, 0xDC, 0xFE,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xF0, 0xFF, 0xFF, 0xC0,
|
||||
0x6C, 0x06, 0xDB, 0x6D, 0xB6, 0xDB, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC6,
|
||||
0xCC, 0xD8, 0xF8, 0xD8, 0xCC, 0xC4, 0xC6, 0xC3, 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
0x1C, 0x67, 0xFF, 0xB0, 0xC7, 0x84, 0x3C, 0x21, 0xE1, 0x0F, 0x08, 0x78,
|
||||
0x43, 0xC2, 0x1E, 0x10, 0xC0, 0x1C, 0xFE, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0x38, 0x7E, 0xC3, 0x83, 0x81, 0x81, 0x81, 0xC3, 0xC6,
|
||||
0x7E, 0x1C, 0xBE, 0xC3, 0xC1, 0xC1, 0x81, 0xC1, 0xC3, 0xE3, 0xBE, 0x80,
|
||||
0x80, 0x80, 0x80, 0x1C, 0x1F, 0x58, 0x68, 0x34, 0x1E, 0x0D, 0x06, 0x83,
|
||||
0x63, 0x9F, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x1F, 0xF9, 0x8C, 0x63, 0x18,
|
||||
0xC6, 0x00, 0x39, 0xFB, 0x1C, 0x0E, 0x07, 0x81, 0xC1, 0xC7, 0xF8, 0x21,
|
||||
0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, 0x70, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC7, 0x7F, 0x41, 0x31, 0x98, 0xC4, 0x42, 0x61, 0xA0, 0x50,
|
||||
0x38, 0x18, 0x00, 0xC7, 0x12, 0x38, 0x99, 0x4C, 0xCA, 0x62, 0xDA, 0x14,
|
||||
0xD0, 0xE3, 0x87, 0x18, 0x18, 0xC0, 0x63, 0x13, 0x0D, 0x03, 0x81, 0xC0,
|
||||
0xE0, 0xD8, 0xC6, 0x43, 0x00, 0x41, 0x31, 0x98, 0xC4, 0x43, 0x61, 0xA0,
|
||||
0x50, 0x38, 0x18, 0x0C, 0x06, 0x0E, 0x06, 0x00, 0xFE, 0x08, 0x30, 0xC3,
|
||||
0x0C, 0x10, 0x60, 0xFE, 0x36, 0x66, 0x66, 0x4C, 0x84, 0x66, 0x66, 0x66,
|
||||
0x30, 0xFF, 0xFF, 0x80, 0xC4, 0x44, 0x44, 0x46, 0x36, 0x44, 0x44, 0x44,
|
||||
0x80, 0x60, 0x59, 0x8F, 0xFF, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03,
|
||||
0x01, 0x80, 0xC0, 0x60, 0x30, 0x1F, 0xF8, 0x00, 0xF0, 0x7F, 0xFF, 0xC0,
|
||||
0x08, 0x1C, 0x7E, 0x4B, 0xC9, 0xC8, 0xC8, 0xC8, 0xCB, 0x6B, 0x3E, 0x08,
|
||||
0x08, 0x1F, 0x0C, 0xE6, 0x19, 0x82, 0x60, 0x08, 0x0F, 0xE0, 0x40, 0x10,
|
||||
0x04, 0x03, 0x01, 0xF2, 0x7F, 0xC0, 0x07, 0x07, 0xF3, 0x04, 0x80, 0x60,
|
||||
0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x18, 0x03, 0x00, 0x61, 0x0F, 0xC0, 0xC0,
|
||||
0xD0, 0x22, 0x18, 0xCC, 0x12, 0x07, 0x80, 0xC1, 0xFE, 0x0C, 0x1F, 0xE0,
|
||||
0xC0, 0x30, 0x0C, 0x00, 0x12, 0x07, 0x80, 0xC0, 0x00, 0x3F, 0x18, 0x6C,
|
||||
0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0F, 0x00, 0xF0, 0x3C, 0x0D, 0x87,
|
||||
0x3F, 0x80, 0x3C, 0x66, 0x62, 0x62, 0x30, 0x5C, 0x8E, 0x83, 0xC1, 0x61,
|
||||
0x3B, 0x1E, 0x06, 0xC6, 0x46, 0x7E, 0x38, 0x6C, 0x70, 0x41, 0xCF, 0xD8,
|
||||
0xE0, 0x70, 0x3C, 0x0E, 0x0E, 0x3F, 0xC0, 0x1F, 0xC0, 0xC1, 0x86, 0x31,
|
||||
0x33, 0x66, 0x88, 0xCA, 0x60, 0x29, 0x80, 0xE6, 0x12, 0x88, 0xCB, 0x36,
|
||||
0x66, 0x71, 0x0C, 0x18, 0x1F, 0xC0, 0xF4, 0x9D, 0x29, 0x74, 0x1F, 0x21,
|
||||
0x99, 0xA6, 0x4C, 0x90, 0xFF, 0xFF, 0xC0, 0x20, 0x10, 0x08, 0xFF, 0x1F,
|
||||
0xC0, 0xC1, 0x86, 0xF1, 0x33, 0xF6, 0x88, 0x4A, 0x23, 0x28, 0xF8, 0xE2,
|
||||
0x32, 0x88, 0xCB, 0x23, 0x66, 0x01, 0x0C, 0x18, 0x1F, 0xC0, 0xFF, 0xC0,
|
||||
0xF4, 0x63, 0x17, 0x00, 0x08, 0x04, 0x02, 0x01, 0x0F, 0xF8, 0x40, 0x20,
|
||||
0x10, 0x08, 0x00, 0x3F, 0xE0, 0x39, 0x34, 0x43, 0x19, 0x84, 0x3F, 0x31,
|
||||
0x2C, 0xC6, 0x08, 0x1C, 0xDE, 0x11, 0x01, 0x60, 0x18, 0x00, 0x07, 0xFC,
|
||||
0x01, 0x80, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x38, 0x06, 0x01, 0x80, 0x60,
|
||||
0x18, 0x03, 0x00, 0xFF, 0xE0, 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B,
|
||||
0x0D, 0x8E, 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x00, 0x3F, 0x7A, 0xFA, 0xFA,
|
||||
0xFA, 0xFA, 0xFA, 0x7A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
|
||||
0xC0, 0x6C, 0x50, 0x40, 0x0F, 0xE0, 0x83, 0x0C, 0x30, 0xC1, 0x06, 0x0F,
|
||||
0xE0, 0x27, 0x92, 0x49, 0xF4, 0x63, 0x19, 0x38, 0x1F, 0x93, 0x26, 0x59,
|
||||
0x98, 0x40, 0x3F, 0xFF, 0x71, 0xC0, 0x40, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
0x80, 0xC0, 0x80, 0xFF, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x40, 0xC0,
|
||||
0x61, 0xC0, 0x3F, 0xFF, 0x38, 0x30, 0xFD, 0xFB, 0x0E, 0x1C, 0x18, 0x38,
|
||||
0x10, 0x70, 0x3F, 0xE0, 0x40, 0x61, 0x83, 0xC7, 0x84, 0xFD, 0xF8, 0x19,
|
||||
0x81, 0x98, 0x00, 0x06, 0x03, 0x60, 0x63, 0x0C, 0x10, 0xC1, 0x98, 0x0D,
|
||||
0x00, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x18,
|
||||
0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x60, 0xC0, 0x83, 0xC2, 0xC6, 0x7C,
|
||||
0x0C, 0x00, 0x40, 0x02, 0x00, 0x00, 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90,
|
||||
0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x06, 0x60, 0x66, 0x06,
|
||||
0xC0, 0x30, 0x01, 0x80, 0x30, 0x06, 0x00, 0x00, 0x06, 0x00, 0xF0, 0x0F,
|
||||
0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x06, 0x60,
|
||||
0x66, 0x06, 0xC0, 0x30, 0x06, 0x00, 0xF0, 0x09, 0x00, 0x00, 0x06, 0x00,
|
||||
0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2,
|
||||
0x06, 0x60, 0x66, 0x06, 0xC0, 0x30, 0x0C, 0x81, 0x30, 0x00, 0x00, 0x60,
|
||||
0x0F, 0x00, 0xF0, 0x09, 0x01, 0x98, 0x19, 0x81, 0x08, 0x30, 0xC3, 0xFC,
|
||||
0x20, 0x66, 0x06, 0x60, 0x6C, 0x03, 0x19, 0x81, 0x98, 0x00, 0x00, 0x60,
|
||||
0x0F, 0x00, 0xF0, 0x09, 0x01, 0x98, 0x19, 0x81, 0x08, 0x30, 0xC3, 0xFC,
|
||||
0x20, 0x66, 0x06, 0x60, 0x6C, 0x03, 0x0F, 0x00, 0x90, 0x0F, 0x00, 0x00,
|
||||
0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C,
|
||||
0x3F, 0xC2, 0x06, 0x60, 0x66, 0x06, 0xC0, 0x30, 0x07, 0xFF, 0x83, 0x60,
|
||||
0x01, 0x30, 0x01, 0x98, 0x00, 0x8C, 0x00, 0xC6, 0x00, 0x63, 0xFC, 0x61,
|
||||
0x80, 0x3F, 0xC0, 0x10, 0x60, 0x18, 0x30, 0x0C, 0x18, 0x0C, 0x0F, 0xF8,
|
||||
0x1F, 0x86, 0x19, 0x81, 0xE0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0,
|
||||
0x78, 0x0D, 0x81, 0xB8, 0x63, 0xF8, 0x08, 0x01, 0x80, 0x10, 0x0E, 0x00,
|
||||
0x30, 0x08, 0x02, 0x00, 0x0F, 0xFC, 0x02, 0x01, 0x00, 0x80, 0x40, 0x3F,
|
||||
0xD0, 0x08, 0x04, 0x02, 0x01, 0x00, 0xFF, 0x80, 0x04, 0x04, 0x04, 0x00,
|
||||
0x0F, 0xFC, 0x02, 0x01, 0x00, 0x80, 0x40, 0x3F, 0xD0, 0x08, 0x04, 0x02,
|
||||
0x01, 0x00, 0xFF, 0x80, 0x18, 0x0E, 0x09, 0x00, 0x0F, 0xFC, 0x02, 0x01,
|
||||
0x00, 0x80, 0x40, 0x3F, 0xD0, 0x08, 0x04, 0x02, 0x01, 0x00, 0xFF, 0x80,
|
||||
0x66, 0x33, 0x00, 0x1F, 0xF8, 0x04, 0x02, 0x01, 0x00, 0x80, 0x7F, 0xA0,
|
||||
0x10, 0x08, 0x04, 0x02, 0x01, 0xFF, 0xC6, 0x20, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x20, 0x36, 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40,
|
||||
0x32, 0xB2, 0x02, 0x10, 0x84, 0x21, 0x08, 0x42, 0x10, 0x84, 0x20, 0xCF,
|
||||
0x30, 0x08, 0x20, 0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x82, 0x08, 0x3F,
|
||||
0x82, 0x0C, 0x20, 0x62, 0x03, 0x20, 0x32, 0x03, 0xFC, 0x32, 0x03, 0x20,
|
||||
0x32, 0x03, 0x20, 0x62, 0x1C, 0x3F, 0x80, 0x09, 0x03, 0xE0, 0x00, 0x70,
|
||||
0x3E, 0x07, 0xE0, 0xF6, 0x1E, 0xC3, 0xCC, 0x78, 0x8F, 0x19, 0xE1, 0xBC,
|
||||
0x17, 0x83, 0xF0, 0x3E, 0x07, 0x0C, 0x00, 0x40, 0x02, 0x00, 0x00, 0x1F,
|
||||
0x87, 0x0E, 0x60, 0x6C, 0x03, 0xC0, 0x38, 0x01, 0x80, 0x18, 0x01, 0xC0,
|
||||
0x3C, 0x03, 0x60, 0x67, 0x0E, 0x1F, 0x80, 0x03, 0x00, 0x20, 0x04, 0x00,
|
||||
0x00, 0x1F, 0x87, 0x0E, 0x60, 0x6C, 0x03, 0xC0, 0x38, 0x01, 0x80, 0x18,
|
||||
0x01, 0xC0, 0x3C, 0x03, 0x60, 0x67, 0x0E, 0x1F, 0x80, 0x06, 0x00, 0xF0,
|
||||
0x09, 0x00, 0x00, 0x1F, 0x87, 0x0E, 0x60, 0x6C, 0x03, 0xC0, 0x38, 0x01,
|
||||
0x80, 0x18, 0x01, 0xC0, 0x3C, 0x03, 0x60, 0x67, 0x0E, 0x1F, 0x80, 0x0C,
|
||||
0x81, 0x30, 0x00, 0x01, 0xF8, 0x70, 0xE6, 0x06, 0xC0, 0x3C, 0x03, 0x80,
|
||||
0x18, 0x01, 0x80, 0x1C, 0x03, 0xC0, 0x36, 0x06, 0x70, 0xE1, 0xF8, 0x19,
|
||||
0x81, 0x98, 0x00, 0x01, 0xF8, 0x70, 0xE6, 0x06, 0xC0, 0x3C, 0x03, 0x80,
|
||||
0x18, 0x01, 0x80, 0x1C, 0x03, 0xC0, 0x36, 0x06, 0x70, 0xE1, 0xF8, 0x81,
|
||||
0x89, 0xA1, 0x83, 0x89, 0xA1, 0x80, 0x00, 0x01, 0xF9, 0x70, 0xE6, 0x06,
|
||||
0xC0, 0xBC, 0x13, 0x82, 0x18, 0x41, 0x8C, 0x1D, 0x83, 0xF0, 0x36, 0x06,
|
||||
0x70, 0xE9, 0xF8, 0x30, 0x06, 0x00, 0x80, 0x00, 0x80, 0xE0, 0x38, 0x0E,
|
||||
0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3C, 0x0B, 0x86, 0x7F,
|
||||
0x00, 0x06, 0x03, 0x00, 0x80, 0x00, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80,
|
||||
0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3C, 0x0B, 0x86, 0x7F, 0x00, 0x0C,
|
||||
0x05, 0x03, 0x20, 0x00, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38,
|
||||
0x0E, 0x03, 0x80, 0xE0, 0x3C, 0x0B, 0x86, 0x7F, 0x00, 0x33, 0x0C, 0xC0,
|
||||
0x02, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03,
|
||||
0x80, 0xF0, 0x2E, 0x19, 0xFC, 0x01, 0x00, 0x20, 0x04, 0x00, 0x00, 0x60,
|
||||
0x36, 0x06, 0x30, 0xC1, 0x0C, 0x19, 0x80, 0xD0, 0x0F, 0x00, 0x60, 0x06,
|
||||
0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x80, 0x40, 0x3F, 0x9F, 0xE8,
|
||||
0x1C, 0x0E, 0x07, 0x03, 0xFF, 0x7E, 0x20, 0x10, 0x08, 0x00, 0x3E, 0x31,
|
||||
0xB0, 0x78, 0x3C, 0x16, 0x7B, 0x3D, 0x83, 0xC0, 0xE0, 0x70, 0x78, 0x7C,
|
||||
0xF0, 0x30, 0x0C, 0x02, 0x07, 0x87, 0xE6, 0x10, 0x0C, 0x0E, 0x7F, 0x61,
|
||||
0xA0, 0xD8, 0xEF, 0xB8, 0x0C, 0x0C, 0x04, 0x07, 0x87, 0xE6, 0x10, 0x0C,
|
||||
0x0E, 0x7F, 0x61, 0xA0, 0xD8, 0xEF, 0xB8, 0x18, 0x16, 0x19, 0x07, 0x87,
|
||||
0xE6, 0x10, 0x0C, 0x0E, 0x7F, 0x61, 0xA0, 0xD8, 0xEF, 0xB8, 0x32, 0x3E,
|
||||
0x00, 0x07, 0x87, 0xE6, 0x10, 0x0C, 0x0E, 0x7F, 0x61, 0xA0, 0xD8, 0xEF,
|
||||
0xB8, 0x66, 0x33, 0x00, 0x07, 0x87, 0xE6, 0x10, 0x0C, 0x0E, 0x7F, 0x61,
|
||||
0xA0, 0xD8, 0xEF, 0xB8, 0x18, 0x12, 0x09, 0x03, 0x03, 0xC3, 0xF3, 0x08,
|
||||
0x06, 0x07, 0x3F, 0xB0, 0xD0, 0x6C, 0x77, 0xDC, 0x38, 0x71, 0xFF, 0xEC,
|
||||
0x30, 0xC0, 0xC1, 0x06, 0x05, 0xFF, 0xFC, 0x20, 0x20, 0xC1, 0xC7, 0x8F,
|
||||
0xE7, 0xE0, 0x38, 0x7E, 0xC2, 0x82, 0x80, 0x80, 0x80, 0x83, 0xC6, 0x7C,
|
||||
0x10, 0x18, 0x08, 0x78, 0x30, 0x18, 0x08, 0x18, 0x7E, 0xC3, 0xC3, 0x81,
|
||||
0xFF, 0x80, 0xC3, 0xC3, 0x7E, 0x0C, 0x18, 0x10, 0x18, 0x7E, 0xC3, 0xC3,
|
||||
0x81, 0xFF, 0x80, 0xC3, 0xC3, 0x7E, 0x18, 0x34, 0x22, 0x18, 0x7E, 0xC3,
|
||||
0xC3, 0x81, 0xFF, 0x80, 0xC3, 0xC3, 0x7E, 0x66, 0x66, 0x00, 0x18, 0x7E,
|
||||
0xC3, 0xC3, 0x81, 0xFF, 0x80, 0xC3, 0xC3, 0x7E, 0x42, 0x10, 0x22, 0x22,
|
||||
0x22, 0x22, 0x20, 0x6C, 0x80, 0x44, 0x44, 0x44, 0x44, 0x40, 0x72, 0xA2,
|
||||
0x02, 0x10, 0x84, 0x21, 0x08, 0x42, 0x00, 0xCF, 0x30, 0x00, 0x10, 0x41,
|
||||
0x04, 0x10, 0x41, 0x04, 0x10, 0x6C, 0x30, 0x4C, 0x3E, 0x7E, 0xC3, 0x83,
|
||||
0x81, 0x81, 0x81, 0xC3, 0xC6, 0x7E, 0x32, 0x7C, 0x00, 0x1C, 0xFE, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x30, 0x10, 0x08, 0x38, 0x7E,
|
||||
0xC3, 0x83, 0x81, 0x81, 0x81, 0xC3, 0xC6, 0x7E, 0x0C, 0x18, 0x10, 0x38,
|
||||
0x7E, 0xC3, 0x83, 0x81, 0x81, 0x81, 0xC3, 0xC6, 0x7E, 0x18, 0x2C, 0x64,
|
||||
0x38, 0x7E, 0xC3, 0x83, 0x81, 0x81, 0x81, 0xC3, 0xC6, 0x7E, 0x32, 0x5C,
|
||||
0x00, 0x38, 0x7E, 0xC3, 0x83, 0x81, 0x81, 0x81, 0xC3, 0xC6, 0x7E, 0x66,
|
||||
0x66, 0x00, 0x38, 0x7E, 0xC3, 0x83, 0x81, 0x81, 0x81, 0xC3, 0xC6, 0x7E,
|
||||
0x18, 0x0C, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x30, 0x18, 0x00, 0x1C,
|
||||
0x0F, 0xE6, 0x19, 0x8E, 0x44, 0x92, 0x25, 0x09, 0xC6, 0x63, 0x1F, 0xC0,
|
||||
0x00, 0x30, 0x10, 0x08, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC7, 0x7F, 0x0C, 0x18, 0x10, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC7, 0x7F, 0x18, 0x2C, 0x64, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC7, 0x7F, 0x66, 0x66, 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0xC7, 0x7F, 0x0C, 0x04, 0x04, 0x00, 0x04, 0x13, 0x19,
|
||||
0x8C, 0x44, 0x36, 0x1A, 0x05, 0x03, 0x81, 0x80, 0xC0, 0x60, 0xE0, 0x60,
|
||||
0x00, 0x80, 0x80, 0x80, 0x9C, 0xBE, 0xC3, 0xC1, 0xC1, 0x81, 0xC1, 0xC3,
|
||||
0xE3, 0xBE, 0x80, 0x80, 0x80, 0x80, 0x22, 0x11, 0x00, 0x00, 0x04, 0x13,
|
||||
0x19, 0x8C, 0x44, 0x36, 0x1A, 0x05, 0x03, 0x81, 0x80, 0xC0, 0x60, 0xE0,
|
||||
0x60, 0x00 };
|
||||
|
||||
const GFXglyph FreeSans9pt8bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' ' U+0020
|
||||
{ 1, 2, 13, 5, 2, -12 }, // 0x21 '!' U+0021
|
||||
{ 5, 4, 5, 6, 1, -12 }, // 0x22 '"' U+0022
|
||||
{ 8, 10, 13, 10, 0, -12 }, // 0x23 '#' U+0023
|
||||
{ 25, 8, 16, 10, 1, -13 }, // 0x24 '$' U+0024
|
||||
{ 41, 14, 13, 16, 1, -12 }, // 0x25 '%' U+0025
|
||||
{ 64, 10, 13, 12, 1, -12 }, // 0x26 '&' U+0026
|
||||
{ 81, 2, 5, 3, 1, -12 }, // 0x27 ''' U+0027
|
||||
{ 83, 4, 17, 6, 1, -12 }, // 0x28 '(' U+0028
|
||||
{ 92, 4, 17, 6, 1, -12 }, // 0x29 ')' U+0029
|
||||
{ 101, 5, 5, 7, 1, -12 }, // 0x2a '*' U+002A
|
||||
{ 105, 9, 9, 11, 1, -8 }, // 0x2b '+' U+002B
|
||||
{ 116, 1, 5, 5, 2, -1 }, // 0x2c ',' U+002C
|
||||
{ 117, 4, 2, 6, 1, -5 }, // 0x2d '-' U+002D
|
||||
{ 118, 1, 2, 5, 2, -1 }, // 0x2e '.' U+002E
|
||||
{ 119, 5, 13, 5, 0, -12 }, // 0x2f '/' U+002F
|
||||
{ 128, 8, 13, 10, 1, -12 }, // 0x30 '0' U+0030
|
||||
{ 141, 4, 13, 10, 2, -12 }, // 0x31 '1' U+0031
|
||||
{ 148, 8, 13, 10, 1, -12 }, // 0x32 '2' U+0032
|
||||
{ 161, 8, 13, 10, 1, -12 }, // 0x33 '3' U+0033
|
||||
{ 174, 9, 13, 10, 0, -12 }, // 0x34 '4' U+0034
|
||||
{ 189, 8, 13, 10, 1, -12 }, // 0x35 '5' U+0035
|
||||
{ 202, 8, 13, 10, 1, -12 }, // 0x36 '6' U+0036
|
||||
{ 215, 8, 13, 10, 1, -12 }, // 0x37 '7' U+0037
|
||||
{ 228, 8, 13, 10, 1, -12 }, // 0x38 '8' U+0038
|
||||
{ 241, 8, 13, 10, 1, -12 }, // 0x39 '9' U+0039
|
||||
{ 254, 2, 9, 5, 2, -8 }, // 0x3a ':' U+003A
|
||||
{ 257, 2, 12, 5, 2, -8 }, // 0x3b ';' U+003B
|
||||
{ 260, 9, 9, 11, 1, -8 }, // 0x3c '<' U+003C
|
||||
{ 271, 9, 4, 11, 1, -5 }, // 0x3d '=' U+003D
|
||||
{ 276, 9, 9, 11, 1, -8 }, // 0x3e '>' U+003E
|
||||
{ 287, 8, 13, 10, 1, -12 }, // 0x3f '?' U+003F
|
||||
{ 300, 16, 16, 18, 1, -12 }, // 0x40 '@' U+0040
|
||||
{ 332, 12, 13, 12, 0, -12 }, // 0x41 'A' U+0041
|
||||
{ 352, 10, 13, 12, 1, -12 }, // 0x42 'B' U+0042
|
||||
{ 369, 11, 13, 13, 1, -12 }, // 0x43 'C' U+0043
|
||||
{ 387, 10, 13, 13, 2, -12 }, // 0x44 'D' U+0044
|
||||
{ 404, 9, 13, 12, 2, -12 }, // 0x45 'E' U+0045
|
||||
{ 419, 8, 13, 11, 2, -12 }, // 0x46 'F' U+0046
|
||||
{ 432, 12, 13, 14, 1, -12 }, // 0x47 'G' U+0047
|
||||
{ 452, 11, 13, 13, 1, -12 }, // 0x48 'H' U+0048
|
||||
{ 470, 1, 13, 5, 2, -12 }, // 0x49 'I' U+0049
|
||||
{ 472, 8, 13, 9, 0, -12 }, // 0x4a 'J' U+004A
|
||||
{ 485, 11, 13, 12, 1, -12 }, // 0x4b 'K' U+004B
|
||||
{ 503, 9, 13, 10, 1, -12 }, // 0x4c 'L' U+004C
|
||||
{ 518, 13, 13, 15, 1, -12 }, // 0x4d 'M' U+004D
|
||||
{ 540, 11, 13, 13, 1, -12 }, // 0x4e 'N' U+004E
|
||||
{ 558, 12, 13, 14, 1, -12 }, // 0x4f 'O' U+004F
|
||||
{ 578, 9, 13, 12, 2, -12 }, // 0x50 'P' U+0050
|
||||
{ 593, 12, 14, 14, 1, -12 }, // 0x51 'Q' U+0051
|
||||
{ 614, 10, 13, 13, 2, -12 }, // 0x52 'R' U+0052
|
||||
{ 631, 10, 13, 12, 1, -12 }, // 0x53 'S' U+0053
|
||||
{ 648, 11, 13, 11, 0, -12 }, // 0x54 'T' U+0054
|
||||
{ 666, 10, 13, 13, 2, -12 }, // 0x55 'U' U+0055
|
||||
{ 683, 11, 13, 12, 1, -12 }, // 0x56 'V' U+0056
|
||||
{ 701, 17, 13, 17, 0, -12 }, // 0x57 'W' U+0057
|
||||
{ 729, 12, 13, 12, 0, -12 }, // 0x58 'X' U+0058
|
||||
{ 749, 12, 13, 12, 0, -12 }, // 0x59 'Y' U+0059
|
||||
{ 769, 11, 13, 11, 0, -12 }, // 0x5a 'Z' U+005A
|
||||
{ 787, 4, 17, 5, 1, -12 }, // 0x5b '[' U+005B
|
||||
{ 796, 5, 13, 5, 0, -12 }, // 0x5c '\' U+005C
|
||||
{ 805, 4, 17, 5, 0, -12 }, // 0x5d ']' U+005D
|
||||
{ 814, 7, 7, 8, 1, -12 }, // 0x5e '^' U+005E
|
||||
{ 821, 10, 1, 10, 0, 3 }, // 0x5f '_' U+005F
|
||||
{ 823, 4, 2, 6, 0, -12 }, // 0x60 '`' U+0060
|
||||
{ 824, 9, 10, 10, 1, -9 }, // 0x61 'a' U+0061
|
||||
{ 836, 8, 13, 10, 1, -12 }, // 0x62 'b' U+0062
|
||||
{ 849, 8, 10, 9, 1, -9 }, // 0x63 'c' U+0063
|
||||
{ 859, 9, 13, 10, 0, -12 }, // 0x64 'd' U+0064
|
||||
{ 874, 8, 10, 10, 1, -9 }, // 0x65 'e' U+0065
|
||||
{ 884, 5, 13, 5, 0, -12 }, // 0x66 'f' U+0066
|
||||
{ 893, 8, 14, 10, 1, -9 }, // 0x67 'g' U+0067
|
||||
{ 907, 8, 13, 10, 1, -12 }, // 0x68 'h' U+0068
|
||||
{ 920, 2, 13, 4, 1, -12 }, // 0x69 'i' U+0069
|
||||
{ 924, 3, 17, 4, 0, -12 }, // 0x6a 'j' U+006A
|
||||
{ 931, 8, 13, 9, 1, -12 }, // 0x6b 'k' U+006B
|
||||
{ 944, 2, 13, 4, 1, -12 }, // 0x6c 'l' U+006C
|
||||
{ 948, 13, 10, 15, 1, -9 }, // 0x6d 'm' U+006D
|
||||
{ 965, 8, 10, 10, 1, -9 }, // 0x6e 'n' U+006E
|
||||
{ 975, 8, 10, 10, 1, -9 }, // 0x6f 'o' U+006F
|
||||
{ 985, 8, 14, 10, 1, -9 }, // 0x70 'p' U+0070
|
||||
{ 999, 9, 14, 10, 0, -9 }, // 0x71 'q' U+0071
|
||||
{ 1015, 5, 10, 6, 1, -9 }, // 0x72 'r' U+0072
|
||||
{ 1022, 7, 10, 9, 1, -9 }, // 0x73 's' U+0073
|
||||
{ 1031, 5, 12, 5, 0, -11 }, // 0x74 't' U+0074
|
||||
{ 1039, 8, 9, 10, 1, -8 }, // 0x75 'u' U+0075
|
||||
{ 1048, 9, 9, 9, 0, -8 }, // 0x76 'v' U+0076
|
||||
{ 1059, 13, 9, 13, 0, -8 }, // 0x77 'w' U+0077
|
||||
{ 1074, 9, 9, 9, 0, -8 }, // 0x78 'x' U+0078
|
||||
{ 1085, 9, 13, 9, 0, -8 }, // 0x79 'y' U+0079
|
||||
{ 1100, 7, 9, 9, 1, -8 }, // 0x7a 'z' U+007A
|
||||
{ 1108, 4, 17, 6, 1, -12 }, // 0x7b '{' U+007B
|
||||
{ 1117, 1, 17, 5, 2, -12 }, // 0x7c '|' U+007C
|
||||
{ 1120, 4, 17, 6, 1, -12 }, // 0x7d '}' U+007D
|
||||
{ 1129, 8, 3, 11, 1, -7 }, // 0x7e '~' U+007E
|
||||
{ 1132, 9, 13, 13, 2, -12 }, // 0x7f 'REPLACEMENT CHARACTER *' U+2370
|
||||
{ 1147, 1, 1, 5, 0, 0 }, // 0x80 'NO-BREAK SPACE' U+00A0
|
||||
{ 1148, 2, 13, 5, 2, -8 }, // 0x81 'INVERTED EXCLAMATION MARK' U+00A1
|
||||
{ 1152, 8, 13, 10, 1, -10 }, // 0x82 'CENT SIGN' U+00A2
|
||||
{ 1165, 10, 13, 10, 0, -12 }, // 0x83 'POUND SIGN' U+00A3
|
||||
{ 1182, 10, 13, 12, 1, -12 }, // 0x84 'EURO SIGN *' U+20AC
|
||||
{ 1199, 10, 13, 10, 0, -12 }, // 0x85 'YEN SIGN' U+00A5
|
||||
{ 1216, 10, 17, 12, 1, -16 }, // 0x86 'LATIN CAPITAL LETTER S WITH CARON *' U+0160
|
||||
{ 1238, 8, 17, 10, 1, -12 }, // 0x87 'SECTION SIGN' U+00A7
|
||||
{ 1255, 7, 13, 9, 1, -12 }, // 0x88 'LATIN SMALL LETTER S WITH CARON *' U+0161
|
||||
{ 1267, 14, 13, 13, 0, -12 }, // 0x89 'COPYRIGHT SIGN' U+00A9
|
||||
{ 1290, 5, 8, 7, 1, -12 }, // 0x8a 'FEMININE ORDINAL INDICATOR' U+00AA
|
||||
{ 1295, 6, 6, 8, 1, -7 }, // 0x8b 'LEFT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00AB
|
||||
{ 1300, 9, 5, 11, 1, -6 }, // 0x8c 'NOT SIGN' U+00AC
|
||||
{ 1306, 4, 2, 6, 1, -5 }, // 0x8d 'SOFT HYPHEN' U+00AD
|
||||
{ 1307, 14, 13, 13, 0, -12 }, // 0x8e 'REGISTERED SIGN' U+00AE
|
||||
{ 1330, 5, 2, 6, 0, -12 }, // 0x8f 'MACRON' U+00AF
|
||||
{ 1332, 5, 5, 11, 3, -11 }, // 0x90 'DEGREE SIGN' U+00B0
|
||||
{ 1336, 9, 11, 11, 1, -10 }, // 0x91 'PLUS-MINUS SIGN' U+00B1
|
||||
{ 1349, 6, 8, 6, 0, -12 }, // 0x92 'SUPERSCRIPT TWO' U+00B2
|
||||
{ 1355, 6, 8, 6, 0, -12 }, // 0x93 'SUPERSCRIPT THREE' U+00B3
|
||||
{ 1361, 11, 17, 11, 0, -16 }, // 0x94 'LATIN CAPITAL LETTER Z WITH CARON *' U+017D
|
||||
{ 1385, 9, 13, 10, 1, -8 }, // 0x95 'MICRO SIGN' U+00B5
|
||||
{ 1400, 8, 16, 10, 1, -12 }, // 0x96 'PILCROW SIGN' U+00B6
|
||||
{ 1416, 1, 2, 5, 2, -5 }, // 0x97 'MIDDLE DOT' U+00B7
|
||||
{ 1417, 7, 13, 9, 1, -12 }, // 0x98 'LATIN SMALL LETTER Z WITH CARON *' U+017E
|
||||
{ 1429, 3, 8, 6, 1, -12 }, // 0x99 'SUPERSCRIPT ONE' U+00B9
|
||||
{ 1432, 5, 8, 7, 1, -12 }, // 0x9a 'MASCULINE ORDINAL INDICATOR' U+00BA
|
||||
{ 1437, 6, 6, 8, 1, -7 }, // 0x9b 'RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00BB
|
||||
{ 1442, 16, 13, 18, 1, -12 }, // 0x9c 'LATIN CAPITAL LIGATURE OE *' U+0152
|
||||
{ 1468, 15, 10, 17, 1, -9 }, // 0x9d 'LATIN SMALL LIGATURE OE *' U+0153
|
||||
{ 1487, 12, 16, 12, 0, -15 }, // 0x9e 'LATIN CAPITAL LETTER Y WITH DIAERESIS *' U+0178
|
||||
{ 1511, 8, 13, 10, 2, -8 }, // 0x9f 'INVERTED QUESTION MARK' U+00BF
|
||||
{ 1524, 12, 17, 12, 0, -16 }, // 0xa0 'LATIN CAPITAL LETTER A WITH GRAVE' U+00C0
|
||||
{ 1550, 12, 17, 12, 0, -16 }, // 0xa1 'LATIN CAPITAL LETTER A WITH ACUTE' U+00C1
|
||||
{ 1576, 12, 17, 12, 0, -16 }, // 0xa2 'LATIN CAPITAL LETTER A WITH CIRCUMFLEX' U+00C2
|
||||
{ 1602, 12, 16, 12, 0, -15 }, // 0xa3 'LATIN CAPITAL LETTER A WITH TILDE' U+00C3
|
||||
{ 1626, 12, 16, 12, 0, -15 }, // 0xa4 'LATIN CAPITAL LETTER A WITH DIAERESIS' U+00C4
|
||||
{ 1650, 12, 17, 12, 0, -16 }, // 0xa5 'LATIN CAPITAL LETTER A WITH RING ABOVE' U+00C5
|
||||
{ 1676, 17, 13, 18, 0, -12 }, // 0xa6 'LATIN CAPITAL LETTER AE' U+00C6
|
||||
{ 1704, 11, 17, 13, 1, -12 }, // 0xa7 'LATIN CAPITAL LETTER C WITH CEDILLA' U+00C7
|
||||
{ 1728, 9, 17, 12, 2, -16 }, // 0xa8 'LATIN CAPITAL LETTER E WITH GRAVE' U+00C8
|
||||
{ 1748, 9, 17, 12, 2, -16 }, // 0xa9 'LATIN CAPITAL LETTER E WITH ACUTE' U+00C9
|
||||
{ 1768, 9, 17, 12, 2, -16 }, // 0xaa 'LATIN CAPITAL LETTER E WITH CIRCUMFLEX' U+00CA
|
||||
{ 1788, 9, 16, 12, 2, -15 }, // 0xab 'LATIN CAPITAL LETTER E WITH DIAERESIS' U+00CB
|
||||
{ 1806, 4, 17, 5, 0, -16 }, // 0xac 'LATIN CAPITAL LETTER I WITH GRAVE' U+00CC
|
||||
{ 1815, 4, 17, 5, 1, -16 }, // 0xad 'LATIN CAPITAL LETTER I WITH ACUTE' U+00CD
|
||||
{ 1824, 5, 17, 5, 0, -16 }, // 0xae 'LATIN CAPITAL LETTER I WITH CIRCUMFLEX' U+00CE
|
||||
{ 1835, 6, 16, 5, 0, -15 }, // 0xaf 'LATIN CAPITAL LETTER I WITH DIAERESIS' U+00CF
|
||||
{ 1847, 12, 13, 13, 0, -12 }, // 0xb0 'LATIN CAPITAL LETTER ETH' U+00D0
|
||||
{ 1867, 11, 16, 13, 1, -15 }, // 0xb1 'LATIN CAPITAL LETTER N WITH TILDE' U+00D1
|
||||
{ 1889, 12, 17, 14, 1, -16 }, // 0xb2 'LATIN CAPITAL LETTER O WITH GRAVE' U+00D2
|
||||
{ 1915, 12, 17, 14, 1, -16 }, // 0xb3 'LATIN CAPITAL LETTER O WITH ACUTE' U+00D3
|
||||
{ 1941, 12, 17, 14, 1, -16 }, // 0xb4 'LATIN CAPITAL LETTER O WITH CIRCUMFLEX' U+00D4
|
||||
{ 1967, 12, 16, 14, 1, -15 }, // 0xb5 'LATIN CAPITAL LETTER O WITH TILDE' U+00D5
|
||||
{ 1991, 12, 16, 14, 1, -15 }, // 0xb6 'LATIN CAPITAL LETTER O WITH DIAERESIS' U+00D6
|
||||
{ 2015, 7, 7, 11, 2, -7 }, // 0xb7 'MULTIPLICATION SIGN' U+00D7
|
||||
{ 2022, 12, 14, 14, 1, -13 }, // 0xb8 'LATIN CAPITAL LETTER O WITH STROKE' U+00D8
|
||||
{ 2043, 10, 17, 13, 2, -16 }, // 0xb9 'LATIN CAPITAL LETTER U WITH GRAVE' U+00D9
|
||||
{ 2065, 10, 17, 13, 2, -16 }, // 0xba 'LATIN CAPITAL LETTER U WITH ACUTE' U+00DA
|
||||
{ 2087, 10, 17, 13, 2, -16 }, // 0xbb 'LATIN CAPITAL LETTER U WITH CIRCUMFLEX' U+00DB
|
||||
{ 2109, 10, 16, 13, 2, -15 }, // 0xbc 'LATIN CAPITAL LETTER U WITH DIAERESIS' U+00DC
|
||||
{ 2129, 12, 17, 12, 0, -16 }, // 0xbd 'LATIN CAPITAL LETTER Y WITH ACUTE' U+00DD
|
||||
{ 2155, 9, 13, 12, 2, -12 }, // 0xbe 'LATIN CAPITAL LETTER THORN' U+00DE
|
||||
{ 2170, 9, 13, 11, 1, -12 }, // 0xbf 'LATIN SMALL LETTER SHARP S' U+00DF
|
||||
{ 2185, 9, 13, 10, 1, -12 }, // 0xc0 'LATIN SMALL LETTER A WITH GRAVE' U+00E0
|
||||
{ 2200, 9, 13, 10, 1, -12 }, // 0xc1 'LATIN SMALL LETTER A WITH ACUTE' U+00E1
|
||||
{ 2215, 9, 13, 10, 1, -12 }, // 0xc2 'LATIN SMALL LETTER A WITH CIRCUMFLEX' U+00E2
|
||||
{ 2230, 9, 13, 10, 1, -12 }, // 0xc3 'LATIN SMALL LETTER A WITH TILDE' U+00E3
|
||||
{ 2245, 9, 13, 10, 1, -12 }, // 0xc4 'LATIN SMALL LETTER A WITH DIAERESIS' U+00E4
|
||||
{ 2260, 9, 14, 10, 1, -13 }, // 0xc5 'LATIN SMALL LETTER A WITH RING ABOVE' U+00E5
|
||||
{ 2276, 14, 10, 16, 1, -9 }, // 0xc6 'LATIN SMALL LETTER AE' U+00E6
|
||||
{ 2294, 8, 14, 9, 1, -9 }, // 0xc7 'LATIN SMALL LETTER C WITH CEDILLA' U+00E7
|
||||
{ 2308, 8, 13, 10, 1, -12 }, // 0xc8 'LATIN SMALL LETTER E WITH GRAVE' U+00E8
|
||||
{ 2321, 8, 13, 10, 1, -12 }, // 0xc9 'LATIN SMALL LETTER E WITH ACUTE' U+00E9
|
||||
{ 2334, 8, 13, 10, 1, -12 }, // 0xca 'LATIN SMALL LETTER E WITH CIRCUMFLEX' U+00EA
|
||||
{ 2347, 8, 13, 10, 1, -12 }, // 0xcb 'LATIN SMALL LETTER E WITH DIAERESIS' U+00EB
|
||||
{ 2360, 4, 13, 5, 0, -12 }, // 0xcc 'LATIN SMALL LETTER I WITH GRAVE' U+00EC
|
||||
{ 2367, 4, 13, 5, 1, -12 }, // 0xcd 'LATIN SMALL LETTER I WITH ACUTE' U+00ED
|
||||
{ 2374, 5, 13, 5, 0, -12 }, // 0xce 'LATIN SMALL LETTER I WITH CIRCUMFLEX' U+00EE
|
||||
{ 2383, 6, 13, 5, -1, -12 }, // 0xcf 'LATIN SMALL LETTER I WITH DIAERESIS' U+00EF
|
||||
{ 2393, 8, 13, 10, 1, -12 }, // 0xd0 'LATIN SMALL LETTER ETH' U+00F0
|
||||
{ 2406, 8, 13, 10, 1, -12 }, // 0xd1 'LATIN SMALL LETTER N WITH TILDE' U+00F1
|
||||
{ 2419, 8, 13, 10, 1, -12 }, // 0xd2 'LATIN SMALL LETTER O WITH GRAVE' U+00F2
|
||||
{ 2432, 8, 13, 10, 1, -12 }, // 0xd3 'LATIN SMALL LETTER O WITH ACUTE' U+00F3
|
||||
{ 2445, 8, 13, 10, 1, -12 }, // 0xd4 'LATIN SMALL LETTER O WITH CIRCUMFLEX' U+00F4
|
||||
{ 2458, 8, 13, 10, 1, -12 }, // 0xd5 'LATIN SMALL LETTER O WITH TILDE' U+00F5
|
||||
{ 2471, 8, 13, 10, 1, -12 }, // 0xd6 'LATIN SMALL LETTER O WITH DIAERESIS' U+00F6
|
||||
{ 2484, 9, 9, 11, 1, -8 }, // 0xd7 'DIVISION SIGN' U+00F7
|
||||
{ 2495, 10, 11, 11, 0, -9 }, // 0xd8 'LATIN SMALL LETTER O WITH STROKE' U+00F8
|
||||
{ 2509, 8, 13, 10, 1, -12 }, // 0xd9 'LATIN SMALL LETTER U WITH GRAVE' U+00F9
|
||||
{ 2522, 8, 13, 10, 1, -12 }, // 0xda 'LATIN SMALL LETTER U WITH ACUTE' U+00FA
|
||||
{ 2535, 8, 13, 10, 1, -12 }, // 0xdb 'LATIN SMALL LETTER U WITH CIRCUMFLEX' U+00FB
|
||||
{ 2548, 8, 13, 10, 1, -12 }, // 0xdc 'LATIN SMALL LETTER U WITH DIAERESIS' U+00FC
|
||||
{ 2561, 9, 17, 9, 0, -12 }, // 0xdd 'LATIN SMALL LETTER Y WITH ACUTE' U+00FD
|
||||
{ 2581, 8, 17, 10, 1, -12 }, // 0xde 'LATIN SMALL LETTER THORN' U+00FE
|
||||
{ 2598, 9, 17, 9, 0, -12 } }; // 0xdf 'LATIN SMALL LETTER Y WITH DIAERESIS' U+000FF
|
||||
|
||||
const GFXfont FreeSans9pt8b PROGMEM = {
|
||||
(uint8_t *)FreeSans9pt8bBitmaps,
|
||||
(GFXglyph *)FreeSans9pt8bGlyphs,
|
||||
0x20, 0xDF, 25 };
|
||||
|
||||
// Approx. 3969 bytes
|
0
libraries/fonts/Picopixel.h → RX_FSK/src/fonts/Picopixel.h
Executable file → Normal file
0
libraries/fonts/Picopixel.h → RX_FSK/src/fonts/Picopixel.h
Executable file → Normal file
221
RX_FSK/src/fonts/Terminal11x16.h
Normal file
221
RX_FSK/src/fonts/Terminal11x16.h
Normal file
|
@ -0,0 +1,221 @@
|
|||
const uint8_t Terminal11x16Bitmap[] = {
|
||||
0x0C, 0x18, 0x78, 0xF1, 0xE3, 0xC7, 0x86, 0x0C, 0x18, 0x00, 0x00, 0xC1,
|
||||
0x80, 0x33, 0x33, 0x33, 0x33, 0x0C, 0xC1, 0x98, 0x33, 0x3F, 0xF1, 0x98,
|
||||
0x33, 0x0C, 0xC1, 0x98, 0xFF, 0x8C, 0xC1, 0x98, 0x33, 0x00, 0x0C, 0x06,
|
||||
0x0F, 0xCF, 0xF6, 0xC3, 0x61, 0xFC, 0x7F, 0x0D, 0x86, 0xDF, 0xE7, 0xE0,
|
||||
0xC0, 0x60, 0x00, 0x2E, 0x0D, 0xC3, 0xB8, 0xE0, 0x38, 0x0E, 0x03, 0x80,
|
||||
0xE0, 0x38, 0x0E, 0x3B, 0x87, 0x60, 0xE0, 0x0E, 0x06, 0xC3, 0x30, 0xCC,
|
||||
0x36, 0x07, 0x03, 0xC1, 0xF0, 0x66, 0xD9, 0xE6, 0x31, 0xDE, 0x3C, 0xC0,
|
||||
0x1C, 0x71, 0xC3, 0x0C, 0x60, 0x07, 0x0C, 0x1C, 0x18, 0x38, 0x38, 0x38,
|
||||
0x38, 0x38, 0x38, 0x18, 0x1C, 0x0C, 0x07, 0x38, 0x0C, 0x0E, 0x06, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0E, 0x0C, 0x38, 0x6D, 0xB6, 0xCF,
|
||||
0xC3, 0xC7, 0xF8, 0xF0, 0xFC, 0xDB, 0x6D, 0x80, 0x0C, 0x06, 0x03, 0x0F,
|
||||
0xF7, 0xF8, 0x60, 0x30, 0x18, 0x1C, 0x71, 0xC3, 0x18, 0x7F, 0xBF, 0xC0,
|
||||
0x1C, 0x71, 0xC0, 0x00, 0x20, 0x0C, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03,
|
||||
0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0x60, 0x00, 0x1F, 0x0F, 0xF9, 0x83,
|
||||
0x60, 0x7C, 0x1F, 0x86, 0xF1, 0x9E, 0x63, 0xD8, 0x7E, 0x0F, 0x81, 0xB0,
|
||||
0x67, 0xFC, 0x3E, 0x00, 0x06, 0x03, 0x83, 0xE0, 0xF8, 0x06, 0x01, 0x80,
|
||||
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x3F, 0xCF, 0xF0, 0x3F, 0x8F,
|
||||
0xFB, 0x83, 0xE0, 0x3C, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80,
|
||||
0xE0, 0x38, 0x0F, 0xFF, 0xFF, 0xC0, 0x3F, 0x8F, 0xFB, 0x83, 0xE0, 0x30,
|
||||
0x06, 0x01, 0xC7, 0xF0, 0xFC, 0x00, 0xC0, 0x0F, 0x01, 0xF0, 0x77, 0xFC,
|
||||
0x7F, 0x00, 0x03, 0x80, 0xF0, 0x3E, 0x0E, 0xC3, 0x98, 0xE3, 0x38, 0x66,
|
||||
0x0C, 0xFF, 0xFF, 0xFC, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x00, 0x60, 0x0C, 0x01, 0xFF, 0x1F, 0xF0, 0x07, 0x00, 0x60, 0x0F,
|
||||
0x01, 0xF0, 0x77, 0xFC, 0x7F, 0x00, 0x07, 0x81, 0xF0, 0x70, 0x1C, 0x07,
|
||||
0x00, 0xC0, 0x3F, 0xE7, 0xFE, 0xE0, 0xF8, 0x0F, 0x01, 0xF0, 0x77, 0xFC,
|
||||
0x7F, 0x00, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0x60, 0x18, 0x03, 0x00, 0xC0,
|
||||
0x18, 0x06, 0x00, 0xC0, 0x30, 0x06, 0x01, 0x80, 0x30, 0x00, 0x1F, 0x07,
|
||||
0xF1, 0xC7, 0x30, 0x66, 0x0C, 0xE3, 0x8F, 0xE3, 0xFE, 0xE0, 0xF8, 0x0F,
|
||||
0x01, 0xF0, 0x77, 0xFC, 0x7F, 0x00, 0x3F, 0x8F, 0xFB, 0x83, 0xE0, 0x3C,
|
||||
0x07, 0xC1, 0xDF, 0xF9, 0xFF, 0x00, 0xC0, 0x38, 0x0E, 0x03, 0x83, 0xE0,
|
||||
0x78, 0x00, 0x1C, 0x71, 0xC0, 0x00, 0x01, 0xC7, 0x1C, 0x1C, 0x71, 0xC0,
|
||||
0x00, 0x01, 0xC7, 0x1C, 0x30, 0xC6, 0x01, 0x81, 0xC1, 0xC1, 0xC1, 0xC1,
|
||||
0xC1, 0xC0, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0C, 0x7F, 0xDF,
|
||||
0xF0, 0x00, 0x00, 0x7F, 0xDF, 0xF0, 0x60, 0x38, 0x0E, 0x03, 0x80, 0xE0,
|
||||
0x38, 0x0E, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x00, 0x3F, 0x1F,
|
||||
0xEE, 0x1F, 0x03, 0xC1, 0xC0, 0xE0, 0x70, 0x38, 0x0C, 0x03, 0x00, 0xC0,
|
||||
0x00, 0x0C, 0x03, 0x00, 0x3F, 0x8F, 0xF9, 0x83, 0x67, 0xBD, 0xF7, 0xB6,
|
||||
0xF6, 0xDE, 0xDB, 0xDB, 0x7B, 0xFB, 0x3E, 0x70, 0x07, 0xF8, 0x3F, 0x00,
|
||||
0x0C, 0x03, 0x01, 0xE0, 0x78, 0x1E, 0x0C, 0xC3, 0x30, 0xCC, 0x61, 0x9F,
|
||||
0xE7, 0xFB, 0x03, 0xC0, 0xF0, 0x30, 0xFE, 0x3F, 0xCC, 0x3B, 0x06, 0xC1,
|
||||
0xB0, 0xEF, 0xF3, 0xFE, 0xC1, 0xF0, 0x3C, 0x0F, 0x07, 0xFF, 0xBF, 0xC0,
|
||||
0x1F, 0x0F, 0xE7, 0x1D, 0x83, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
|
||||
0x06, 0x0D, 0xC7, 0x3F, 0x87, 0xC0, 0xFE, 0x3F, 0xCC, 0x3B, 0x06, 0xC0,
|
||||
0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x1B, 0x0E, 0xFF, 0x3F, 0x80,
|
||||
0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x30, 0x0F, 0xF3, 0xFC, 0xC0, 0x30,
|
||||
0x0C, 0x03, 0x00, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0,
|
||||
0x30, 0x0F, 0xF3, 0xFC, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x00,
|
||||
0x1F, 0x8F, 0xF7, 0x0D, 0x80, 0xC0, 0x30, 0x0C, 0x7F, 0x1F, 0xC0, 0xF0,
|
||||
0x36, 0x0D, 0xC3, 0x3F, 0xC7, 0xF0, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
|
||||
0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x30,
|
||||
0x3F, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x3F, 0x3F, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03,
|
||||
0x00, 0xF0, 0x3C, 0x0F, 0x86, 0x7F, 0x8F, 0xC0, 0xC0, 0xF0, 0x7C, 0x3B,
|
||||
0x1C, 0xCE, 0x37, 0x0F, 0x83, 0xE0, 0xDC, 0x33, 0x8C, 0x73, 0x0E, 0xC1,
|
||||
0xF0, 0x30, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00,
|
||||
0xC0, 0x30, 0x0C, 0x03, 0x00, 0xFF, 0xFF, 0xF0, 0xC0, 0xF8, 0x7E, 0x1F,
|
||||
0xCF, 0xF3, 0xF7, 0xBD, 0xEF, 0x33, 0xCC, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
|
||||
0xF0, 0x30, 0xC0, 0xF8, 0x3E, 0x0F, 0xC3, 0xD8, 0xF6, 0x3C, 0xCF, 0x33,
|
||||
0xC6, 0xF1, 0xBC, 0x3F, 0x07, 0xC1, 0xF0, 0x30, 0x1E, 0x0F, 0xC7, 0x39,
|
||||
0x86, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x36, 0x19, 0xCE, 0x3F,
|
||||
0x07, 0x80, 0xFF, 0x3F, 0xEC, 0x1F, 0x03, 0xC0, 0xF0, 0x3C, 0x1F, 0xFE,
|
||||
0xFF, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x00, 0x1E, 0x0F, 0xC7, 0x39,
|
||||
0x86, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF1, 0xB6, 0x79, 0xCE, 0x3F,
|
||||
0xC7, 0xB0, 0xFF, 0x3F, 0xEC, 0x1F, 0x03, 0xC0, 0xF0, 0x3C, 0x1F, 0xFE,
|
||||
0xFF, 0x33, 0x8C, 0x73, 0x0E, 0xC1, 0xF0, 0x30, 0x3F, 0x1F, 0xEE, 0x1F,
|
||||
0x03, 0xC0, 0x38, 0x07, 0xF0, 0xFE, 0x01, 0xC0, 0x3C, 0x0F, 0x87, 0x7F,
|
||||
0x8F, 0xC0, 0x7F, 0xBF, 0xC3, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C,
|
||||
0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
|
||||
0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0D, 0x86, 0x7F, 0x8F, 0xC0,
|
||||
0xC0, 0xF0, 0x3C, 0x0D, 0x86, 0x61, 0x98, 0x63, 0x30, 0xCC, 0x33, 0x07,
|
||||
0x81, 0xE0, 0x78, 0x0C, 0x03, 0x00, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
|
||||
0xF0, 0x3C, 0x0F, 0x33, 0xCC, 0xF7, 0xBF, 0x3F, 0x87, 0xE1, 0xF0, 0x30,
|
||||
0xC0, 0xF0, 0x36, 0x19, 0x86, 0x33, 0x07, 0x80, 0xC0, 0x30, 0x1E, 0x0C,
|
||||
0xC6, 0x19, 0x86, 0xC0, 0xF0, 0x30, 0xC0, 0xF0, 0x36, 0x19, 0x86, 0x33,
|
||||
0x0C, 0xC1, 0xE0, 0x78, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00,
|
||||
0xFF, 0xFF, 0xF0, 0x18, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x30, 0x18, 0x0C,
|
||||
0x06, 0x01, 0x80, 0xFF, 0xFF, 0xF0, 0x3F, 0x3F, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3F, 0x3F, 0x80, 0x18, 0x03, 0x80,
|
||||
0x38, 0x03, 0x80, 0x38, 0x03, 0x80, 0x38, 0x03, 0x80, 0x38, 0x03, 0x80,
|
||||
0x30, 0x3F, 0x3F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x3F, 0x3F, 0x04, 0x01, 0xC0, 0x7C, 0x1D, 0xC7, 0x1D, 0xC1, 0xF0,
|
||||
0x18, 0xFF, 0xFF, 0xFC, 0x0E, 0x1C, 0x38, 0x60, 0xC0, 0xC0, 0x3F, 0x9F,
|
||||
0xF0, 0x0C, 0xFF, 0x7F, 0xF0, 0x3C, 0x0F, 0xFF, 0x7F, 0xC0, 0xC0, 0x30,
|
||||
0x0C, 0x03, 0x00, 0xC0, 0x37, 0xCF, 0xFB, 0x87, 0xC0, 0xF0, 0x3C, 0x0F,
|
||||
0x07, 0xFF, 0xBF, 0xC0, 0x3F, 0x1F, 0xEE, 0x0F, 0x00, 0xC0, 0x30, 0x0E,
|
||||
0x0D, 0xFE, 0x3F, 0x00, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xCF, 0xB7,
|
||||
0xFF, 0x8F, 0xC0, 0xF0, 0x3C, 0x0F, 0x83, 0x7F, 0xCF, 0xF0, 0x3F, 0x1F,
|
||||
0xEE, 0x0F, 0xFF, 0xFF, 0xB0, 0x0E, 0x01, 0xFE, 0x3F, 0x00, 0x0F, 0x1F,
|
||||
0x38, 0x30, 0x30, 0x30, 0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x3F, 0xDF, 0xFE, 0x0F, 0x03, 0xE1, 0xDF, 0xF3, 0xEC, 0x03, 0x01, 0xDF,
|
||||
0xE7, 0xF0, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0xF3, 0xFD, 0xC7, 0xC1,
|
||||
0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0C, 0x0C, 0x0C, 0x00, 0x1C, 0x1C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x3F, 0x03, 0x03, 0x00, 0x07, 0x07, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x33, 0x3F, 0x1E, 0x60, 0x30, 0x18, 0x0C,
|
||||
0x06, 0x03, 0x19, 0x9C, 0xDC, 0x7C, 0x3E, 0x1B, 0x8C, 0xE6, 0x3B, 0x0C,
|
||||
0x1C, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x3F, 0x3F, 0xB3, 0x3F, 0xEF, 0xFF, 0x33, 0xCC, 0xF3, 0x3C, 0xCF, 0x33,
|
||||
0xCC, 0xC0, 0x7F, 0x1F, 0xE6, 0x1D, 0x83, 0x60, 0xD8, 0x36, 0x0D, 0x83,
|
||||
0x60, 0xC0, 0x3F, 0x1F, 0xEE, 0x1F, 0x03, 0xC0, 0xF0, 0x3E, 0x1D, 0xFE,
|
||||
0x3F, 0x00, 0xFF, 0x3F, 0xEC, 0x1F, 0x03, 0xC0, 0xF8, 0x7F, 0xFB, 0x7C,
|
||||
0xC0, 0x30, 0x0C, 0x00, 0x3F, 0xDF, 0xFE, 0x0F, 0x03, 0xC0, 0xF8, 0x77,
|
||||
0xFC, 0xFB, 0x00, 0xC0, 0x30, 0x0C, 0x6F, 0x9F, 0xF7, 0x0D, 0x80, 0x60,
|
||||
0x18, 0x06, 0x01, 0x80, 0x60, 0x00, 0x7E, 0xFF, 0xC0, 0xFE, 0x7F, 0x03,
|
||||
0x03, 0xFF, 0x7E, 0x30, 0x30, 0x30, 0x30, 0xFE, 0xFE, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x3F, 0x1F, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3E,
|
||||
0x1D, 0xFF, 0x3E, 0xC0, 0xC0, 0xF0, 0x36, 0x19, 0x86, 0x33, 0x0C, 0xC1,
|
||||
0xE0, 0x78, 0x0C, 0x00, 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xCC, 0xF7, 0xB7,
|
||||
0xF9, 0xCE, 0x21, 0x00, 0xC1, 0xF1, 0xDD, 0xC7, 0xC1, 0xC1, 0xF1, 0xDD,
|
||||
0xC7, 0xC1, 0x80, 0x61, 0xB0, 0xCC, 0xC6, 0x61, 0xE0, 0xF0, 0x30, 0x18,
|
||||
0x18, 0x0C, 0x0C, 0x00, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0xFF, 0xFF, 0x80, 0x07, 0x87, 0xC7, 0x03, 0x01, 0x80, 0xC0, 0xE0, 0xE0,
|
||||
0x38, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x7C, 0x1E, 0x0C, 0x30, 0xC3, 0x0C,
|
||||
0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0x78, 0x3E, 0x03, 0x80, 0xC0,
|
||||
0x60, 0x30, 0x1C, 0x07, 0x07, 0x03, 0x01, 0x80, 0xC0, 0xE3, 0xE1, 0xE0,
|
||||
0x38, 0xDB, 0x6C, 0x70, 0x0C, 0x07, 0x83, 0x31, 0x86, 0xC0, 0xF0, 0x3F,
|
||||
0xFF, 0xFF,
|
||||
};
|
||||
|
||||
const GFXglyph Terminal11x16Glyphs[] = {
|
||||
{ 0, 6, 0, 7, 0, 4 }, // 0x20 ' '
|
||||
{ 0, 7, 14, 8, 0, -12 }, // 0x21 '!'
|
||||
{ 13, 8, 4, 9, 0, -10 }, // 0x22 '"'
|
||||
{ 17, 11, 12, 12, 0, -11 }, // 0x23 '#'
|
||||
{ 34, 9, 14, 10, 0, -12 }, // 0x24 '$'
|
||||
{ 50, 11, 12, 12, 0, -10 }, // 0x25 '%'
|
||||
{ 67, 10, 13, 11, 0, -11 }, // 0x26 '&'
|
||||
{ 84, 6, 6, 7, 0, -12 }, // 0x27 '''
|
||||
{ 89, 8, 14, 9, 0, -12 }, // 0x28 '('
|
||||
{ 103, 8, 14, 9, 0, -12 }, // 0x29 ')'
|
||||
{ 117, 9, 9, 10, 0, -9 }, // 0x2a '*'
|
||||
{ 128, 9, 8, 10, 0, -8 }, // 0x2b '+'
|
||||
{ 137, 6, 5, 7, 0, -1 }, // 0x2c ','
|
||||
{ 141, 9, 2, 10, 0, -5 }, // 0x2d '-'
|
||||
{ 144, 6, 3, 7, 0, -1 }, // 0x2e '.'
|
||||
{ 147, 11, 12, 12, 0, -11 }, // 0x2f '/'
|
||||
{ 164, 11, 14, 12, 0, -12 }, // 0x30 '0'
|
||||
{ 184, 10, 14, 11, 0, -12 }, // 0x31 '1'
|
||||
{ 202, 11, 14, 12, 0, -12 }, // 0x32 '2'
|
||||
{ 222, 11, 14, 12, 0, -12 }, // 0x33 '3'
|
||||
{ 242, 11, 14, 12, 0, -12 }, // 0x34 '4'
|
||||
{ 262, 11, 14, 12, 0, -12 }, // 0x35 '5'
|
||||
{ 282, 11, 14, 12, 0, -12 }, // 0x36 '6'
|
||||
{ 302, 11, 14, 12, 0, -12 }, // 0x37 '7'
|
||||
{ 322, 11, 14, 12, 0, -12 }, // 0x38 '8'
|
||||
{ 342, 11, 14, 12, 0, -12 }, // 0x39 '9'
|
||||
{ 362, 6, 9, 7, 0, -8 }, // 0x3a ':'
|
||||
{ 369, 6, 12, 7, 0, -8 }, // 0x3b ';'
|
||||
{ 378, 9, 14, 10, 0, -12 }, // 0x3c '<'
|
||||
{ 394, 10, 6, 11, 0, -7 }, // 0x3d '='
|
||||
{ 402, 9, 14, 10, 0, -12 }, // 0x3e '>'
|
||||
{ 418, 10, 14, 11, 0, -12 }, // 0x3f '?'
|
||||
{ 436, 11, 14, 12, 0, -12 }, // 0x40 '@'
|
||||
{ 456, 10, 14, 11, 0, -12 }, // 0x41 'A'
|
||||
{ 474, 10, 14, 11, 0, -12 }, // 0x42 'B'
|
||||
{ 492, 10, 14, 11, 0, -12 }, // 0x43 'C'
|
||||
{ 510, 10, 14, 11, 0, -12 }, // 0x44 'D'
|
||||
{ 528, 10, 14, 11, 0, -12 }, // 0x45 'E'
|
||||
{ 546, 10, 14, 11, 0, -12 }, // 0x46 'F'
|
||||
{ 564, 10, 14, 11, 0, -12 }, // 0x47 'G'
|
||||
{ 582, 10, 14, 11, 0, -12 }, // 0x48 'H'
|
||||
{ 600, 8, 14, 9, 0, -12 }, // 0x49 'I'
|
||||
{ 614, 10, 14, 11, 0, -12 }, // 0x4a 'J'
|
||||
{ 632, 10, 14, 11, 0, -12 }, // 0x4b 'K'
|
||||
{ 650, 10, 14, 11, 0, -12 }, // 0x4c 'L'
|
||||
{ 668, 10, 14, 11, 0, -12 }, // 0x4d 'M'
|
||||
{ 686, 10, 14, 11, 0, -12 }, // 0x4e 'N'
|
||||
{ 704, 10, 14, 11, 0, -12 }, // 0x4f 'O'
|
||||
{ 722, 10, 14, 11, 0, -12 }, // 0x50 'P'
|
||||
{ 740, 10, 14, 11, 0, -12 }, // 0x51 'Q'
|
||||
{ 758, 10, 14, 11, 0, -12 }, // 0x52 'R'
|
||||
{ 776, 10, 14, 11, 0, -12 }, // 0x53 'S'
|
||||
{ 794, 9, 14, 10, 0, -12 }, // 0x54 'T'
|
||||
{ 810, 10, 14, 11, 0, -12 }, // 0x55 'U'
|
||||
{ 828, 10, 14, 11, 0, -12 }, // 0x56 'V'
|
||||
{ 846, 10, 14, 11, 0, -12 }, // 0x57 'W'
|
||||
{ 864, 10, 14, 11, 0, -12 }, // 0x58 'X'
|
||||
{ 882, 10, 14, 11, 0, -12 }, // 0x59 'Y'
|
||||
{ 900, 10, 14, 11, 0, -12 }, // 0x5a 'Z'
|
||||
{ 918, 8, 14, 9, 0, -12 }, // 0x5b '['
|
||||
{ 932, 11, 12, 12, 0, -11 }, // 0x5c '\'
|
||||
{ 949, 8, 14, 9, 0, -12 }, // 0x5d ']'
|
||||
{ 963, 11, 7, 12, 0, -12 }, // 0x5e '^'
|
||||
{ 973, 11, 2, 12, 0, 2 }, // 0x5f '_'
|
||||
{ 976, 7, 6, 8, 0, -11 }, // 0x60 '`'
|
||||
{ 982, 10, 9, 11, 0, -7 }, // 0x61 'a'
|
||||
{ 994, 10, 14, 11, 0, -12 }, // 0x62 'b'
|
||||
{ 1012, 10, 9, 11, 0, -7 }, // 0x63 'c'
|
||||
{ 1024, 10, 14, 11, 0, -12 }, // 0x64 'd'
|
||||
{ 1042, 10, 9, 11, 0, -7 }, // 0x65 'e'
|
||||
{ 1054, 8, 14, 9, 0, -12 }, // 0x66 'f'
|
||||
{ 1068, 10, 11, 11, 0, -7 }, // 0x67 'g'
|
||||
{ 1082, 9, 14, 10, 0, -12 }, // 0x68 'h'
|
||||
{ 1098, 8, 12, 9, 0, -10 }, // 0x69 'i'
|
||||
{ 1110, 8, 14, 9, 0, -10 }, // 0x6a 'j'
|
||||
{ 1124, 9, 14, 10, 0, -12 }, // 0x6b 'k'
|
||||
{ 1140, 8, 14, 9, 0, -12 }, // 0x6c 'l'
|
||||
{ 1154, 10, 9, 11, 0, -7 }, // 0x6d 'm'
|
||||
{ 1166, 10, 9, 11, 0, -7 }, // 0x6e 'n'
|
||||
{ 1178, 10, 9, 11, 0, -7 }, // 0x6f 'o'
|
||||
{ 1190, 10, 11, 11, 0, -7 }, // 0x70 'p'
|
||||
{ 1204, 10, 11, 11, 0, -7 }, // 0x71 'q'
|
||||
{ 1218, 10, 9, 11, 0, -7 }, // 0x72 'r'
|
||||
{ 1230, 8, 9, 9, 0, -7 }, // 0x73 's'
|
||||
{ 1239, 8, 13, 9, 0, -11 }, // 0x74 't'
|
||||
{ 1252, 10, 9, 11, 0, -7 }, // 0x75 'u'
|
||||
{ 1264, 10, 9, 11, 0, -7 }, // 0x76 'v'
|
||||
{ 1276, 10, 9, 11, 0, -7 }, // 0x77 'w'
|
||||
{ 1288, 9, 9, 10, 0, -7 }, // 0x78 'x'
|
||||
{ 1299, 9, 11, 10, 0, -7 }, // 0x79 'y'
|
||||
{ 1312, 9, 9, 10, 0, -7 }, // 0x7a 'z'
|
||||
{ 1323, 9, 15, 10, 0, -12 }, // 0x7b '{'
|
||||
{ 1340, 6, 14, 7, 0, -12 }, // 0x7c '|'
|
||||
{ 1351, 9, 15, 10, 0, -12 }, // 0x7d '}'
|
||||
{ 1368, 10, 3, 11, 0, -10 }, // 0x7e '~'
|
||||
{ 1372, 10, 8, 11, 0, -8 }, // 0x7f ''
|
||||
};
|
||||
const GFXfont Terminal11x16Font = {
|
||||
(uint8_t *)Terminal11x16Bitmap,
|
||||
(GFXglyph *)Terminal11x16Glyphs,
|
||||
0x20, 0x7F, 18 };
|
25
RX_FSK/src/fonts/fonts.cpp
Normal file
25
RX_FSK/src/fonts/fonts.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <inttypes.h>
|
||||
#include "gfxfont.h"
|
||||
|
||||
#define PROGMEM
|
||||
|
||||
#include "FreeMono12pt8b.h"
|
||||
#include "FreeMono9pt8b.h"
|
||||
#include "FreeSans12pt8b.h"
|
||||
#include "FreeSans18pt8b.h"
|
||||
#include "FreeSans9pt8b.h"
|
||||
#include "Picopixel.h"
|
||||
#include "Terminal11x16.h"
|
||||
|
||||
__attribute__((used)) const GFXfont * const allfonts[]={
|
||||
(const GFXfont *)0x544E4F46,
|
||||
&Terminal11x16Font,
|
||||
&Terminal11x16Font,
|
||||
&FreeSans9pt8b,
|
||||
&FreeSans12pt8b,
|
||||
&Picopixel,
|
||||
&FreeSans18pt8b,
|
||||
&FreeMono9pt8b,
|
||||
&FreeMono12pt8b,
|
||||
0,
|
||||
};
|
31
RX_FSK/src/fonts/gfxfont.h
Normal file
31
RX_FSK/src/fonts/gfxfont.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Font structures for newer Adafruit_GFX (1.1 and later).
|
||||
// Example fonts are included in 'Fonts' directory.
|
||||
// To use a font in your Arduino sketch, #include the corresponding .h
|
||||
// file and pass address of GFXfont struct to setFont(). Pass NULL to
|
||||
// revert to 'classic' fixed-space bitmap font.
|
||||
|
||||
#ifndef _GFXFONT_H_
|
||||
#define _GFXFONT_H_
|
||||
|
||||
/// Font data stored PER GLYPH
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
|
||||
uint8_t width; ///< Bitmap dimensions in pixels
|
||||
uint8_t height; ///< Bitmap dimensions in pixels
|
||||
uint8_t xAdvance; ///< Distance to advance cursor (x axis)
|
||||
int8_t xOffset; ///< X dist from cursor pos to UL corner
|
||||
int8_t yOffset; ///< Y dist from cursor pos to UL corner
|
||||
} GFXglyph;
|
||||
|
||||
/// Data stored for FONT AS A WHOLE
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *bitmap; ///< Glyph bitmaps, concatenated
|
||||
GFXglyph *glyph; ///< Glyph array
|
||||
uint8_t first; ///< ASCII extents (first char)
|
||||
uint8_t last; ///< ASCII extents (last char)
|
||||
uint8_t yAdvance; ///< Newline distance (y axis)
|
||||
} GFXfont;
|
||||
|
||||
#endif // _GFXFONT_H_
|
64
libraries/SondeLib/geteph.cpp → RX_FSK/src/geteph.cpp
Executable file → Normal file
64
libraries/SondeLib/geteph.cpp → RX_FSK/src/geteph.cpp
Executable file → Normal file
|
@ -6,12 +6,15 @@
|
|||
#include <inttypes.h>
|
||||
#include <WiFi.h>
|
||||
#include "Display.h"
|
||||
|
||||
#include "Sonde.h"
|
||||
|
||||
extern WiFiClient client;
|
||||
|
||||
static const char *ftpserver = "www.ngs.noaa.gov";
|
||||
//static const char *ftpserver = "www.ngs.noaa.gov";
|
||||
char outbuf[128];
|
||||
uint8_t ephstate = EPH_NOTUSED;
|
||||
//enum EPHSTATE { EPH_NOTUSED, EPH_PENDING, EPH_TIMEERR, EPH_ERROR, EPH_EPHERROR, EPH_GOOD };
|
||||
const char *ephtxt[] = { "Disabled", "Pending", "Time error", "Fetch error", "Read error", "Good" };
|
||||
|
||||
uint8_t getreply() {
|
||||
String s = client.readStringUntil('\n');
|
||||
|
@ -45,10 +48,12 @@ void writeFully(File &file, uint8_t *buf, size_t len)
|
|||
|
||||
void geteph() {
|
||||
// Set current time via network...
|
||||
ephstate = EPH_PENDING;
|
||||
struct tm tinfo;
|
||||
configTime(0, 0, "pool.ntp.org");
|
||||
bool ok = getLocalTime(&tinfo, 2000); // wait max 2 seconds to get current time via ntp
|
||||
if(!ok) {
|
||||
ephstate = EPH_TIMEERR;
|
||||
Serial.println("Failed to get current date/time");
|
||||
return;
|
||||
}
|
||||
|
@ -66,37 +71,39 @@ void geteph() {
|
|||
if(tsstr && strlen(tsstr)>=9) {
|
||||
if(strcmp(nowstr, ts.c_str())<=0) {
|
||||
Serial.println("local brdc is up to date\n");
|
||||
ephstate = EPH_GOOD;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Serial.printf("now: %s, existing: %s => updating\n", nowstr, tsstr);
|
||||
}
|
||||
status.close();
|
||||
disp.rdis->clear();
|
||||
disp.rdis->setFont(FONT_SMALL);
|
||||
disp.rdis->drawString(0, 0, "FTP ngs.noaa.gov");
|
||||
// fetch rinex from server
|
||||
File fh = SPIFFS.open("/brdc.gz","w");
|
||||
if(!fh) {
|
||||
Serial.println("cannot open file\n");
|
||||
return;
|
||||
}
|
||||
char buf[252];
|
||||
snprintf(buf, 128, "/cors/rinex/%04d/%03d/brdc%03d0.%02dn.gz", year, day, day, year-2000);
|
||||
char host[252];
|
||||
strcpy(host, sonde.config.ephftp);
|
||||
char *buf = strchr(host, '/');
|
||||
if(!buf) { Serial.println("Invalid FTP host config"); return; }
|
||||
*buf = 0;
|
||||
buf++;
|
||||
uint8_t dispw, disph, dispxs, dispys;
|
||||
disp.rdis->getDispSize(&disph, &dispw, &dispxs, &dispys);
|
||||
disp.rdis->clear();
|
||||
disp.rdis->setFont(FONT_SMALL);
|
||||
disp.rdis->drawString(0, 0, host);
|
||||
// fetch rinex from server
|
||||
char *ptr = buf + strlen(buf);
|
||||
snprintf(ptr, 128, "%04d/%03d/brdc%03d0.%02dn.gz", year, day, day, year-2000);
|
||||
Serial.println("running geteph\n");
|
||||
disp.rdis->drawString(0, 1, buf+21);
|
||||
disp.rdis->drawString(0, 1*dispys, ptr+9);
|
||||
|
||||
if(!client.connect(ftpserver, 21)) {
|
||||
Serial.println("FTP connection to www.ngs.noaa.gov failed");
|
||||
if(!client.connect(host, 21)) {
|
||||
Serial.printf("FTP connection to %s failed\n", host);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
while(!client.available()) delay(1);
|
||||
while(client.available()) {
|
||||
String s = client.readStringUntil('\n');
|
||||
Serial.println(s);
|
||||
}
|
||||
#endif
|
||||
if(getreply()>='4') { Serial.println("connected failed"); return; }
|
||||
client.print("USER anonymous\r\n");
|
||||
if(getreply()>='4') { Serial.println("USER failed"); return; }
|
||||
|
@ -121,8 +128,8 @@ void geteph() {
|
|||
}
|
||||
uint16_t port = (array_pasv[4]<<8) | (array_pasv[5]&0xff);
|
||||
WiFiClient dclient;
|
||||
Serial.printf("connecting to %s:%d\n", ftpserver,port);
|
||||
dclient.connect(ftpserver, port);
|
||||
Serial.printf("connecting to %s:%d\n", host, port);
|
||||
dclient.connect(host, port);
|
||||
if(!dclient) {
|
||||
Serial.println("data connection failed");
|
||||
return;
|
||||
|
@ -136,18 +143,22 @@ void geteph() {
|
|||
int len=0;
|
||||
while(dclient.connected()) {
|
||||
while(dclient.available()) {
|
||||
char c = dclient.read();
|
||||
fh.write(c);
|
||||
len++;
|
||||
int c = dclient.read();
|
||||
if(c==-1) {
|
||||
Serial.println("dclient.read() returned -1 inspite of available() being true?!");
|
||||
} else {
|
||||
fh.write(c);
|
||||
len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Serial.printf("fetched %d bytes\n", len);
|
||||
fh.close();
|
||||
snprintf(buf, 16, "Fetched %d B ",len);
|
||||
buf[16]=0;
|
||||
disp.rdis->drawString(0,2,buf);
|
||||
disp.rdis->drawString(0,2*dispys,buf);
|
||||
|
||||
disp.rdis->drawString(0,4,"Decompressing...");
|
||||
disp.rdis->drawString(0,4*dispys,"Decompressing...");
|
||||
// decompression
|
||||
tinfl_decompressor *decomp = (tinfl_decompressor *)malloc(sizeof(tinfl_decompressor));
|
||||
tinfl_init(decomp);
|
||||
|
@ -215,7 +226,8 @@ void geteph() {
|
|||
status.close();
|
||||
snprintf(buf, 16, "Done: %d B ",total);
|
||||
buf[16]=0;
|
||||
disp.rdis->drawString(0,5,buf);
|
||||
disp.rdis->drawString(0,5*dispys,buf);
|
||||
ephstate = EPH_GOOD;
|
||||
delay(1000);
|
||||
|
||||
free(obuf);
|
11
RX_FSK/src/geteph.h
Normal file
11
RX_FSK/src/geteph.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <inttypes.h>
|
||||
|
||||
#ifndef GETEPH_H
|
||||
#define GETEPH_H
|
||||
void geteph();
|
||||
|
||||
enum EPHSTATE { EPH_NOTUSED, EPH_PENDING, EPH_TIMEERR, EPH_ERROR, EPH_EPHERROR, EPH_GOOD };
|
||||
|
||||
extern uint8_t ephstate;
|
||||
extern const char *ephtxt[];
|
||||
#endif
|
0
libraries/SondeLib/gfxfont.h → RX_FSK/src/gfxfont.h
Executable file → Normal file
0
libraries/SondeLib/gfxfont.h → RX_FSK/src/gfxfont.h
Executable file → Normal file
106
RX_FSK/src/json.cpp
Normal file
106
RX_FSK/src/json.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include "json.h"
|
||||
#include "RS41.h"
|
||||
|
||||
extern const char *sondeTypeStrSH[];
|
||||
extern const char *dfmSubtypeStrSH[];
|
||||
|
||||
static char typestr[11];
|
||||
|
||||
const char *getType(SondeInfo *si) {
|
||||
if( si->type == STYPE_RS41 ) {
|
||||
if ( RS41::getSubtype(typestr, 11, si) == 0 ) return typestr;
|
||||
} else if ( TYPE_IS_DFM(si->type) && si->d.subtype > 0 && si->d.subtype < 16 ) {
|
||||
const char *t = dfmSubtypeStrSH[si->d.subtype];
|
||||
if(t) return t;
|
||||
sprintf(typestr, "DFMx%X", si->d.subtype);
|
||||
return typestr;
|
||||
}
|
||||
return sondeTypeStrSH[sonde.realType(si)];
|
||||
}
|
||||
|
||||
int float2json(char **buf, int *maxlen, const char *fmt, float value) {
|
||||
if(isnan(value)) return 0;
|
||||
int n = snprintf(*buf, *maxlen, fmt, value);
|
||||
if(n>*maxlen) return -1;
|
||||
*buf += n; *maxlen -= n;
|
||||
return n;
|
||||
}
|
||||
|
||||
// To be used by
|
||||
// - MQTT
|
||||
// - rdzJSON (for Android app)
|
||||
// - Web map
|
||||
int sonde2json(char *buf, int maxlen, SondeInfo *si)
|
||||
{
|
||||
SondeData *s = &(si->d);
|
||||
int n;
|
||||
|
||||
n = float2json(&buf, &maxlen, "\"lat\": %.5f,", s->lat);
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"lon\": %.5f,", s->lon);
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"alt\": %.1f,", s->alt);
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"vs\": %.1f,", s->vs);
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"hs\": %.1f,", s->hs);
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"climb\": %.1f,", s->vs); // used by HTML map, to be removed (-> vs)
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"speed\": %.1f,", s->hs); // used by HTML map, to be removed (-> hs)
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"dir\": %.1f,", s->dir);
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"temp\": %.1f,", s->temperature );
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"humidity\": %.1f,", s->relativeHumidity);
|
||||
if(n<0) return -1;
|
||||
n = float2json(&buf, &maxlen, "\"pressure\": %.1f,", s->pressure);
|
||||
if(n<0) return -1;
|
||||
n = snprintf(buf, maxlen,
|
||||
"\"type\":\"%s\","
|
||||
"\"id\": \"%s\"," // TODO: maybe remove in the future, ser is enough, client can calculate APRS id if needed
|
||||
"\"ser\": \"%s\","
|
||||
"\"frame\": %u," // raw frame, from sonde, can be 0. (TODO: add virtual frame # as in sondehub?)
|
||||
"\"vframe\": %d,"
|
||||
"\"time\": %u,"
|
||||
"\"sats\": %d,"
|
||||
"\"freq\": %.2f,"
|
||||
"\"rssi\": %d,"
|
||||
"\"afc\": %d,"
|
||||
"\"launchKT\": %d,"
|
||||
"\"burstKT\": %d,"
|
||||
"\"countKT\": %d,"
|
||||
"\"crefKT\": %d,"
|
||||
"\"launchsite\": \"%s\","
|
||||
"\"res\": %d",
|
||||
getType(si),
|
||||
s->id,
|
||||
s->ser,
|
||||
s->frame,
|
||||
s->vframe,
|
||||
s->time,
|
||||
s->sats,
|
||||
si->freq,
|
||||
si->rssi,
|
||||
si->afc,
|
||||
s->launchKT,
|
||||
s->burstKT,
|
||||
s->countKT,
|
||||
s->crefKT,
|
||||
si->launchsite,
|
||||
(int)si->rxStat[0]
|
||||
);
|
||||
if(n>=maxlen) return -1;
|
||||
buf += n; maxlen -= n;
|
||||
|
||||
// add only if available
|
||||
if(s->batteryVoltage > 0) {
|
||||
n = snprintf(buf, maxlen, ",\"batt\": %.1f", s->batteryVoltage);
|
||||
if(n>=maxlen) return -1;
|
||||
buf += n; maxlen -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
8
RX_FSK/src/json.h
Normal file
8
RX_FSK/src/json.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef _JSON_H
|
||||
#define _JSON_H
|
||||
|
||||
#include "Sonde.h"
|
||||
|
||||
int sonde2json(char *buf, int maxlen, SondeInfo *si);
|
||||
|
||||
#endif
|
11
RX_FSK/src/library.json
Normal file
11
RX_FSK/src/library.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
|
||||
"dependencies":
|
||||
[
|
||||
{
|
||||
"owner": "olikraus",
|
||||
"name": "U8g2",
|
||||
"version": "^2.28.8"
|
||||
}
|
||||
]
|
||||
}
|
165
RX_FSK/src/mqtt.cpp
Normal file
165
RX_FSK/src/mqtt.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
#include <Arduino.h>
|
||||
#include "mqtt.h"
|
||||
#include <WiFi.h>
|
||||
//#include <AsyncMqttClient.h>
|
||||
#include <AsyncMqtt_Generic.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include "RS41.h"
|
||||
#include "json.h"
|
||||
|
||||
extern const char *version_name;
|
||||
extern const char *version_id;
|
||||
|
||||
TimerHandle_t mqttReconnectTimer;
|
||||
|
||||
void mqttCallback(char* topic, byte* payload, unsigned int length) {
|
||||
Serial.print("Message arrived [");
|
||||
Serial.print(topic);
|
||||
Serial.print("] ");
|
||||
for (int i=0;i<length;i++) {
|
||||
Serial.print((char)payload[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
static char buffer[21];
|
||||
void MQTT::init(const char* host, uint16_t port, const char* id, const char *username, const char *password, const char *prefix)
|
||||
{
|
||||
WiFi.hostByName(host, this->ip);
|
||||
this->port = port;
|
||||
this->username = username;
|
||||
this->password = password;
|
||||
this->prefix = prefix;
|
||||
|
||||
Serial.println("[MQTT] pubsub client");
|
||||
mqttClient.setServer(ip, port);
|
||||
snprintf(buffer, 20, "%s%04d", id, (int)random(0, 1000));
|
||||
buffer[20] = 0;
|
||||
Serial.print(buffer);
|
||||
mqttClient.setClientId(buffer);
|
||||
if (strlen(password) > 0) {
|
||||
mqttClient.setCredentials(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTT::connectToMqtt() {
|
||||
Serial.println("Connecting to MQTT...");
|
||||
mqttClient.connect();
|
||||
}
|
||||
|
||||
void MQTT::publishUptime()
|
||||
{
|
||||
mqttClient.connect(); // ensure we've got connection
|
||||
|
||||
Serial.println("[MQTT] writing");
|
||||
char payload[256];
|
||||
// maybe TODO: Use dynamic position if GPS is available?
|
||||
// rxlat, rxlon only if not empty
|
||||
snprintf(payload, 256, "{\"uptime\": %lu, \"user\": \"%s\", ", millis(), username);
|
||||
if( !isnan(sonde.config.rxlat) && !isnan(sonde.config.rxlon) ) {
|
||||
snprintf(payload, 256, "%s\"rxlat\": %.5f, \"rxlon\": %.5f, ", payload, sonde.config.rxlat, sonde.config.rxlon);
|
||||
}
|
||||
snprintf(payload, 256, "%s\"SW\": \"%s\", \"VER\": \"%s\"}", payload, version_name, version_id);
|
||||
Serial.println(payload);
|
||||
char topic[128];
|
||||
snprintf(topic, 128, "%s%s", this->prefix, "uptime");
|
||||
mqttClient.publish(topic, 1, 1, payload);
|
||||
}
|
||||
|
||||
void MQTT::publishPacket(SondeInfo *si)
|
||||
{
|
||||
SondeData *s = &(si->d);
|
||||
mqttClient.connect(); // ensure we've got connection
|
||||
|
||||
char payload[1024];
|
||||
payload[0] = '{';
|
||||
int n = sonde2json(payload+1, 1023, si);
|
||||
if(n<0) {
|
||||
// ERROR
|
||||
Serial.println("publishPacket: sonde2json failed, string too long");
|
||||
}
|
||||
|
||||
#if 0
|
||||
snprintf(payload, 1024, "{"
|
||||
"\"active\": %d,"
|
||||
"\"freq\": %.2f,"
|
||||
"\"id\": \"%s\","
|
||||
"\"ser\": \"%s\","
|
||||
"\"validId\": %d,"
|
||||
"\"launchsite\": \"%s\","
|
||||
"\"lat\": %.5f,"
|
||||
"\"lon\": %.5f,"
|
||||
"\"alt\": %.1f,"
|
||||
"\"vs\": %.1f,"
|
||||
"\"hs\": %.1f,"
|
||||
"\"dir\": %.1f,"
|
||||
"\"sats\": %d,"
|
||||
"\"validPos\": %d,"
|
||||
"\"time\": %u,"
|
||||
"\"frame\": %u,"
|
||||
"\"validTime\": %d,"
|
||||
"\"rssi\": %d,"
|
||||
"\"afc\": %d,"
|
||||
"\"rxStat\": \"%s\","
|
||||
"\"rxStart\": %u,"
|
||||
"\"norxStart\": %u,"
|
||||
"\"viewStart\": %u,"
|
||||
"\"lastState\": %d,"
|
||||
"\"launchKT\": %d,"
|
||||
"\"burstKT\": %d,"
|
||||
"\"countKT\": %d,"
|
||||
"\"crefKT\": %d",
|
||||
(int)si->active,
|
||||
si->freq,
|
||||
s->id,
|
||||
s->ser,
|
||||
(int)s->validID,
|
||||
si->launchsite,
|
||||
s->lat,
|
||||
s->lon,
|
||||
s->alt,
|
||||
s->vs,
|
||||
s->hs,
|
||||
s->dir,
|
||||
s->sats,
|
||||
s->validPos,
|
||||
s->time,
|
||||
s->frame,
|
||||
(int)s->validTime,
|
||||
si->rssi,
|
||||
si->afc,
|
||||
si->rxStat,
|
||||
si->rxStart,
|
||||
si->norxStart,
|
||||
si->viewStart,
|
||||
si->lastState,
|
||||
s->launchKT,
|
||||
s->burstKT,
|
||||
s->countKT,
|
||||
s->crefKT
|
||||
);
|
||||
if ( !isnan( s->temperature ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"temp\": ", s->temperature );
|
||||
}
|
||||
if ( !isnan( s->relativeHumidity ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"humidity\": ", s->relativeHumidity );
|
||||
}
|
||||
if ( !isnan( s->pressure ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"pressure\": ", s->pressure );
|
||||
}
|
||||
if ( !isnan( s->batteryVoltage && s->batteryVoltage > 0 ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"batt\": ", s->batteryVoltage );
|
||||
}
|
||||
char subtype[11];
|
||||
if ( RS41::getSubtype( subtype, 11, si) == 0 ) {
|
||||
snprintf(payload, 1024, "%s%s%s%s", payload, ",\"subtype\": \"", subtype, "\"" );
|
||||
}
|
||||
snprintf(payload, 1024, "%s%s", payload, "}" ); // terminate payload string
|
||||
#endif
|
||||
strcat(payload, "}"); // terminate payload string
|
||||
|
||||
char topic[128];
|
||||
snprintf(topic, 128, "%s%s", this->prefix, "packet");
|
||||
Serial.print(payload);
|
||||
mqttClient.publish(topic, 1, 1, payload);
|
||||
}
|
29
RX_FSK/src/mqtt.h
Normal file
29
RX_FSK/src/mqtt.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef MQTT_h
|
||||
#define MQTT_h
|
||||
|
||||
#include <WiFi.h>
|
||||
//#include <AsyncMqttClient.h>
|
||||
#include <AsyncMqtt_Generic.h>
|
||||
#include "Sonde.h"
|
||||
#include "RS41.h"
|
||||
|
||||
class MQTT
|
||||
{
|
||||
public:
|
||||
WiFiClient mqttWifiClient;
|
||||
AsyncMqttClient mqttClient;
|
||||
TimerHandle_t mqttReconnectTimer;
|
||||
IPAddress ip;
|
||||
uint16_t port;
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *prefix;
|
||||
|
||||
void init(const char *host, uint16_t port, const char *id, const char *username, const char *password, const char *prefix);
|
||||
void publishPacket(SondeInfo *s);
|
||||
void publishUptime();
|
||||
private:
|
||||
void connectToMqtt();
|
||||
};
|
||||
|
||||
#endif
|
283
libraries/SondeLib/nav_gps_vel.cpp → RX_FSK/src/nav_gps_vel.cpp
Executable file → Normal file
283
libraries/SondeLib/nav_gps_vel.cpp → RX_FSK/src/nav_gps_vel.cpp
Executable file → Normal file
|
@ -78,174 +78,6 @@ void rotZ(double x1, double y1, double z1, double angle, double *x2, double *y2,
|
|||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if 0
|
||||
int read_SEMalmanac(FILE *fp, EPHEM_t *alm) {
|
||||
int l, j;
|
||||
char buf[64];
|
||||
unsigned n, week, toa, ui;
|
||||
double dbl;
|
||||
|
||||
l = fscanf(fp, "%u", &n); if (l != 1) return -1;
|
||||
l = fscanf(fp, "%s", buf); if (l != 1) return -1;
|
||||
l = fscanf(fp, "%u", &week); if (l != 1) return -1;
|
||||
l = fscanf(fp, "%u", &toa); if (l != 1) return -1;
|
||||
|
||||
for (j = 1; j <= n; j++) {
|
||||
//memset(&ephem, 0, sizeof(ephem));
|
||||
|
||||
alm[j].week = (uint16_t)week;
|
||||
alm[j].toa = (uint32_t)toa;
|
||||
alm[j].toe = (double)toa;
|
||||
alm[j].toc = alm[j].toe;
|
||||
|
||||
l = fscanf(fp, "%u", &ui); if (l != 1) return -1; alm[j].prn = (uint16_t)ui;
|
||||
l = fscanf(fp, "%u", &ui); if (l != 1) return -2; alm[j].svn = (uint16_t)ui;
|
||||
l = fscanf(fp, "%u", &ui); if (l != 1) return -3; alm[j].ura = (uint8_t)ui;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -4; alm[j].e = dbl;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -5; alm[j].delta_i = dbl;
|
||||
alm[j].i0 = (0.30 + alm[j].delta_i) * PI;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -6; alm[j].OmegaDot = dbl * PI;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -7; alm[j].sqrta = dbl;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -6; alm[j].Omega0 = dbl * PI;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -8; alm[j].w = dbl * PI;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -9; alm[j].M0 = dbl * PI;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -10; alm[j].af0 = dbl;
|
||||
l = fscanf(fp, "%lf", &dbl); if (l != 1) return -11; alm[j].af1 = dbl;
|
||||
alm[j].af2 = 0;
|
||||
alm[j].crc = 0;
|
||||
alm[j].crs = 0;
|
||||
alm[j].cuc = 0;
|
||||
alm[j].cus = 0;
|
||||
alm[j].cic = 0;
|
||||
alm[j].cis = 0;
|
||||
alm[j].tgd = 0;
|
||||
alm[j].idot = 0;
|
||||
alm[j].delta_n = 0;
|
||||
l = fscanf(fp, "%u", &ui); if (l != 1) return -12; alm[j].health = (uint8_t)ui;
|
||||
l = fscanf(fp, "%u", &ui); if (l != 1) return -13; alm[j].conf = (uint8_t)ui;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_RNXephemeris(FILE *fp, EPHEM_t eph[][24]) {
|
||||
int l, i;
|
||||
char buf[64], str[20];
|
||||
char buf_header[83];
|
||||
//buf_data[80]; // 3 + 4*19 = 79
|
||||
char *pbuf;
|
||||
unsigned ui;
|
||||
double dbl;
|
||||
int c;
|
||||
EPHEM_t ephem = {};
|
||||
int hr = 0;
|
||||
|
||||
do {
|
||||
//l = fread(buf_header, 81, 1, fp); // Zeilen in Header sind nicht immer mit Leerzeichen aufgefuellt
|
||||
pbuf = fgets(buf_header, 82, fp); // max 82-1 Zeichen + '\0'
|
||||
buf_header[82] = '\0'; // doppelt haelt besser
|
||||
//l = strlen(buf_header);
|
||||
} while ( pbuf && !strstr(buf_header, "END OF HEADER") );
|
||||
|
||||
//l = fread(buf_data, 80, 1, fp);
|
||||
//buf_data[79] = '\0';
|
||||
|
||||
|
||||
while (hr < 24) { // brdc/hour-rinex sollte nur Daten von einem Tag enthalten
|
||||
|
||||
//memset(&ephem, 0, sizeof(ephem));
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0; sscanf(buf, "%d", &ui);
|
||||
ephem.prn = ui;
|
||||
|
||||
|
||||
for (i = 0; i < 16; i++) ephem.epoch[i] = '0';
|
||||
ephem.epoch[16] = '\0';
|
||||
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; buf[19] = 0;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
c = buf[3*i ]; if (c == ' ') c = '0'; str[2*i ] = c;
|
||||
c = buf[3*i+1]; if (c == ' ') c = '0'; str[2*i+1] = c;
|
||||
}
|
||||
str[12] = buf[17];
|
||||
str[13] = buf[18];
|
||||
str[14] = '\0';
|
||||
|
||||
strncpy(ephem.epoch , "20", 2); // vorausgesetzt 21.Jhd; Datum steht auch im Header
|
||||
strncpy(ephem.epoch+2, str, 15);
|
||||
ephem.epoch[16] = '\0';
|
||||
|
||||
strncpy(str, buf+9, 2); str[2] = '\0';
|
||||
hr = atoi(str);
|
||||
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af0 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af1 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af2 = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break;
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iode = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crs = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.delta_n = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.M0 = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break;
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cuc = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.e = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cus = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.sqrta = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break;
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.toe = dbl;
|
||||
ephem.toc = ephem.toe;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cic = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.Omega0 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cis = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break;
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.i0 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crc = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.w = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.OmegaDot = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break;
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.idot = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.codeL2 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.gpsweek = (int)dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break;
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.sva = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.health = (uint8_t)(dbl+0.1);
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.tgd = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break;
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.ttom = dbl;
|
||||
pbuf = fgets(buf_header, 82, fp);
|
||||
/* // die letzten beiden Felder (spare) sind manchmal leer (statt 0.00); manchmal fehlt sogar das drittletzte Feld
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.fit = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.spare1 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.spare2 = dbl;
|
||||
if ((c=fgetc(fp)) == EOF) break; */
|
||||
|
||||
|
||||
ephem.week = 1; // ephem.gpsweek
|
||||
eph[ephem.prn][hr] = ephem;
|
||||
|
||||
if (pbuf == NULL) break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static EPHEM_t *te;
|
||||
|
||||
|
@ -253,18 +85,23 @@ static EPHEM_t *te;
|
|||
#define fread(buffer, siz, els, file) (file.read((uint8_t *)buffer, (siz)*(els))/siz)
|
||||
#define fgetc(file) (char)file.read()
|
||||
|
||||
int readDbl(File *fp, double *dbl) {
|
||||
uint8_t buf[20];
|
||||
int l = fp->read(buf, 19);
|
||||
if(l!=19) return -1;
|
||||
if (buf[15] == 'D') buf[15] = 'E';
|
||||
buf[19] = 0;
|
||||
sscanf((char *)buf, "%lf", dbl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//EPHEM_t *read_RNXpephs(FILE *fp) {
|
||||
EPHEM_t *read_RNXpephs(const char *file) {
|
||||
int l, i;
|
||||
//char buffer[86];
|
||||
char buf[64], str[20];
|
||||
unsigned ui;
|
||||
double dbl;
|
||||
int c;
|
||||
EPHEM_t ephem = {};
|
||||
// int count = 0;
|
||||
//long fpos;
|
||||
|
||||
File fp = SPIFFS.open(file, "r");
|
||||
if(!fp) { Serial.printf("Error opening %s\n", file); }
|
||||
|
@ -277,23 +114,7 @@ EPHEM_t *read_RNXpephs(const char *file) {
|
|||
Serial.printf("Skipping header: %s\n", line.c_str());
|
||||
} while ( fp.available() && !strstr((const char *)line.c_str(), "END OF HEADER") );
|
||||
if (!fp.available()) return NULL;
|
||||
/*
|
||||
fpos = ftell(fp);
|
||||
count = 0;
|
||||
while (count >= 0) { // data-Zeilen: 79 Zeichen
|
||||
pbuf = fgets(buffer, 84, fp); if (pbuf == 0) break;
|
||||
strncpy(str, buffer, 3);
|
||||
str[3] = '\0';
|
||||
sscanf(str, "%d", &ui);
|
||||
if (ui < 33) count++;
|
||||
for (i = 1; i < 8; i++) {
|
||||
pbuf = fgets(buffer, 84, fp); if (pbuf == 0) break;
|
||||
}
|
||||
}
|
||||
printf("Ephemerides: %d total=%d\n", count, count*sizeof(ephem));
|
||||
|
||||
fseek(fp, fpos, SEEK_SET);
|
||||
*/
|
||||
if(te) free(te);
|
||||
te = (EPHEM_t *)calloc( 34, sizeof(ephem) ); // calloc( 1, sizeof(ephem) );
|
||||
if (te == NULL) return NULL;
|
||||
|
@ -325,56 +146,84 @@ EPHEM_t *read_RNXpephs(const char *file) {
|
|||
strncpy(ephem.epoch+2, str, 15);
|
||||
ephem.epoch[16] = '\0';
|
||||
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af0 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af1 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af2 = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.af0 = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.af1 = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.af2 = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af0 = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af1 = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.af2 = dbl;
|
||||
while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; }
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iode = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crs = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.delta_n = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.M0 = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; //ephem.iode = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.crs = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.delta_n = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.M0 = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iode = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crs = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.delta_n = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.M0 = dbl;
|
||||
while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; }
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cuc = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.e = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cus = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.sqrta = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.cuc = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.e = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.cus = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.sqrta = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cuc = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.e = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cus = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.sqrta = dbl;
|
||||
while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; }
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.toe = dbl;
|
||||
ephem.toc = ephem.toe;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cic = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.Omega0 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cis = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.toe = dbl; ephem.toc = ephem.toe;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.cic = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.Omega0 = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.cis = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.toe = dbl;
|
||||
// ephem.toc = ephem.toe;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cic = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.Omega0 = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.cis = dbl;
|
||||
while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; }
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.i0 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crc = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.w = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.OmegaDot = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.i0 = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.crc = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.w = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.OmegaDot = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.i0 = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.crc = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.w = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.OmegaDot = dbl;
|
||||
while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; }
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.idot = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.codeL2 = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.gpsweek = (int)dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.idot = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; //ephem.codeL2 = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.gpsweek = (int)dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; //ephem.iodc = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.idot = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.codeL2 = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.gpsweek = (int)dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl;
|
||||
while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; }
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.sva = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.health = (uint8_t)(dbl+0.1);
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.tgd = dbl;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; //ephem.sva = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.health = (uint8_t)(dbl+0.1);
|
||||
if(readDbl(&fp, &dbl)<0) break; ephem.tgd = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; //ephem.iodc = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.sva = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.health = (uint8_t)(dbl+0.1);
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); ephem.tgd = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.iodc = dbl;
|
||||
while ((c=fgetc(fp)) != '\n') { if (c == EOF) break; }
|
||||
|
||||
l = fread(buf, 3, 1, fp); if (l != 1) break; buf[ 3] = 0;
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.ttom = dbl;
|
||||
if(readDbl(&fp, &dbl)<0) break; //ephem.ttom = dbl;
|
||||
//l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.ttom = dbl;
|
||||
String l = fp.readStringUntil('\n');
|
||||
/* // die letzten beiden Felder (spare) sind manchmal leer (statt 0.00); manchmal fehlt sogar das drittletzte Feld
|
||||
l = fread(buf, 19, 1, fp); if (l != 1) break; if (buf[15] == 'D') buf[15] = 'E'; buf[19] = 0; sscanf(buf, "%lf", &dbl); //ephem.fit = dbl;
|
0
libraries/SondeLib/nav_gps_vel.h → RX_FSK/src/nav_gps_vel.h
Executable file → Normal file
0
libraries/SondeLib/nav_gps_vel.h → RX_FSK/src/nav_gps_vel.h
Executable file → Normal file
571
libraries/SondeLib/rs92gps.cpp → RX_FSK/src/rs92gps.cpp
Executable file → Normal file
571
libraries/SondeLib/rs92gps.cpp → RX_FSK/src/rs92gps.cpp
Executable file → Normal file
|
@ -41,24 +41,23 @@
|
|||
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <SPIFFS.h>
|
||||
#include "nav_gps_vel.h"
|
||||
#include "rs92gps.h"
|
||||
#include "geteph.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
|
||||
|
||||
gpx_t gpx;
|
||||
|
||||
int option_verbose = 0, // ausfuehrliche Anzeige
|
||||
const int option_verbose = 0, // ausfuehrliche Anzeige
|
||||
option_raw = 1, // rohe Frames
|
||||
option_inv = 0, // invertiert Signal
|
||||
option_res = 0, // genauere Bitmessung
|
||||
|
@ -83,25 +82,6 @@ int almanac = 0,
|
|||
|
||||
int exSat = -1;
|
||||
|
||||
#if 0
|
||||
/* --- RS92-SGP: 8N1 manchester --- */
|
||||
#define BITS (2*(1+8+1)) // 20
|
||||
#define HEADOFS 40 // HEADOFS+HEADLEN = 120 (bis 0x10)
|
||||
#define HEADLEN 80 // (HEADOFS+HEADLEN) mod BITS = 0
|
||||
/*
|
||||
#define HEADOFS 0 // HEADOFS muss 0 wegen Wiederholung
|
||||
#define HEADLEN 60 // HEADLEN < 100, (HEADOFS+HEADLEN) mod BITS = 0
|
||||
*/
|
||||
#define FRAMESTART ((HEADOFS+HEADLEN)/BITS)
|
||||
|
||||
/* 2A 10*/
|
||||
char header[] = "10100110011001101001"
|
||||
"10100110011001101001"
|
||||
"10100110011001101001"
|
||||
"10100110011001101001"
|
||||
"1010011001100110100110101010100110101001";
|
||||
char buf[HEADLEN+1] = "x";
|
||||
#endif
|
||||
|
||||
int bufpos = -1;
|
||||
|
||||
|
@ -143,225 +123,7 @@ int findstr(char *buff, char *str, int pos) {
|
|||
return i;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int read_wav_header(FILE *fp) {
|
||||
char txt[4+1] = "\0\0\0\0";
|
||||
unsigned char dat[4];
|
||||
int byte, p=0;
|
||||
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "RIFF", 4)) return -1;
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
// pos_WAVE = 8L
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "WAVE", 4)) return -1;
|
||||
// pos_fmt = 12L
|
||||
for ( ; ; ) {
|
||||
if ( (byte=fgetc(fp)) == EOF ) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++; if (p==4) p=0;
|
||||
if (findstr(txt, "fmt ", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
channels = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
memcpy(&sample_rate, dat, 4); //sample_rate = dat[0]|(dat[1]<<8)|(dat[2]<<16)|(dat[3]<<24);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
//byte = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
bits_sample = dat[0] + (dat[1] << 8);
|
||||
|
||||
// pos_dat = 36L + info
|
||||
for ( ; ; ) {
|
||||
if ( (byte=fgetc(fp)) == EOF ) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++; if (p==4) p=0;
|
||||
if (findstr(txt, "data", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
|
||||
|
||||
Serial.printf("sample_rate: %d\n", sample_rate);
|
||||
Serial.printf("bits : %d\n", bits_sample);
|
||||
Serial.printf("channels : %d\n", channels);
|
||||
|
||||
if ((bits_sample != 8) && (bits_sample != 16)) return -1;
|
||||
|
||||
samples_per_bit = sample_rate/(float)BAUD_RATE;
|
||||
|
||||
Serial.printf("samples/bit: %.2f\n", samples_per_bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define EOF_INT 0x1000000
|
||||
|
||||
#define LEN_movAvg 3
|
||||
int movAvg[LEN_movAvg];
|
||||
unsigned long sample_count = 0;
|
||||
double bitgrenze = 0;
|
||||
|
||||
int read_signed_sample(FILE *fp) { // int = i32_t
|
||||
int byte, i, sample, s=0; // EOF -> 0x1000000
|
||||
|
||||
for (i = 0; i < channels; i++) {
|
||||
// i = 0: links bzw. mono
|
||||
byte = fgetc(fp);
|
||||
if (byte == EOF) return EOF_INT;
|
||||
if (i == 0) sample = byte;
|
||||
|
||||
if (bits_sample == 16) {
|
||||
byte = fgetc(fp);
|
||||
if (byte == EOF) return EOF_INT;
|
||||
if (i == 0) sample += byte << 8;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (bits_sample == 8) s = sample-128; // 8bit: 00..FF, centerpoint 0x80=128
|
||||
if (bits_sample == 16) s = (short)sample;
|
||||
|
||||
if (option_avg) {
|
||||
movAvg[sample_count % LEN_movAvg] = s;
|
||||
s = 0;
|
||||
for (i = 0; i < LEN_movAvg; i++) s += movAvg[i];
|
||||
s = (s+0.5) / LEN_movAvg;
|
||||
}
|
||||
|
||||
sample_count++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int par=1, par_alt=1;
|
||||
|
||||
int read_bits_fsk(FILE *fp, int *bit, int *len) {
|
||||
static int sample;
|
||||
int n, y0;
|
||||
float l, x1;
|
||||
static float x0;
|
||||
|
||||
n = 0;
|
||||
do{
|
||||
y0 = sample;
|
||||
sample = read_signed_sample(fp);
|
||||
if (sample == EOF_INT) return EOF;
|
||||
//sample_count++; // in read_signed_sample()
|
||||
par_alt = par;
|
||||
par = (sample >= 0) ? 1 : -1; // 8bit: 0..127,128..255 (-128..-1,0..127)
|
||||
n++;
|
||||
} while (par*par_alt > 0);
|
||||
|
||||
if (!option_res) l = (float)n / samples_per_bit;
|
||||
else { // genauere Bitlaengen-Messung
|
||||
x1 = sample/(float)(sample-y0); // hilft bei niedriger sample rate
|
||||
l = (n+x0-x1) / samples_per_bit; // meist mehr frames (nicht immer)
|
||||
x0 = x1;
|
||||
}
|
||||
|
||||
*len = (int)(l+0.5);
|
||||
|
||||
if (!option_inv) *bit = (1+par_alt)/2; // oben 1, unten -1
|
||||
else *bit = (1-par_alt)/2; // sdr#<rev1381?, invers: unten 1, oben -1
|
||||
|
||||
/* Y-offset ? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bitstart = 0;
|
||||
int read_rawbit(FILE *fp, int *bit) {
|
||||
int sample;
|
||||
int n, sum;
|
||||
|
||||
sum = 0;
|
||||
n = 0;
|
||||
|
||||
if (bitstart) {
|
||||
n = 1; // d.h. bitgrenze = sample_count-1 (?)
|
||||
bitgrenze = sample_count-1;
|
||||
bitstart = 0;
|
||||
}
|
||||
bitgrenze += samples_per_bit;
|
||||
|
||||
do {
|
||||
sample = read_signed_sample(fp);
|
||||
if (sample == EOF_INT) return EOF;
|
||||
//sample_count++; // in read_signed_sample()
|
||||
//par = (sample >= 0) ? 1 : -1; // 8bit: 0..127,128..255 (-128..-1,0..127)
|
||||
sum += sample;
|
||||
n++;
|
||||
} while (sample_count < bitgrenze); // n < samples_per_bit
|
||||
|
||||
if (sum >= 0) *bit = 1;
|
||||
else *bit = 0;
|
||||
|
||||
if (option_inv) *bit ^= 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
|
||||
// manchester1 1->10,0->01: 1.bit
|
||||
// manchester2 0->10,1->01: 2.bit
|
||||
// RS92-SGP: 8N1 manchester2
|
||||
char manch(char *mbits) {
|
||||
if ((mbits[0] == 1) && (mbits[1] == 0)) return 0;
|
||||
else if ((mbits[0] == 0) && (mbits[1] == 1)) return 1;
|
||||
else return -1;
|
||||
}
|
||||
int bits2byte(char bits[]) {
|
||||
int i, byteval=0, d=1;
|
||||
int bit8[8];
|
||||
|
||||
if (manch(bits+0) != 0) return 0x100;
|
||||
for (i = 0; i < 8; i++) {
|
||||
bit8[i] = manch(bits+2*(i+1));
|
||||
}
|
||||
if (manch(bits+(2*(8+1))) != 1) return 0x100;
|
||||
|
||||
for (i = 0; i < 8; i++) { // little endian
|
||||
if (bit8[i] == 1) byteval += d;
|
||||
else if (bit8[i] == 0) byteval += 0;
|
||||
else return 0x100;
|
||||
d <<= 1;
|
||||
}
|
||||
return byteval;
|
||||
}
|
||||
|
||||
|
||||
void inc_bufpos() {
|
||||
bufpos = (bufpos+1) % HEADLEN;
|
||||
}
|
||||
|
||||
int compare() {
|
||||
int i=0, j = bufpos;
|
||||
|
||||
while (i < HEADLEN) {
|
||||
if (j < 0) j = HEADLEN-1;
|
||||
if (buf[j] != header[HEADOFS+HEADLEN-1-i]) break;
|
||||
j--;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
uint8_t xorbyte(int pos) {
|
||||
return xframe[pos] ^ mask[pos % MASK_LEN];
|
||||
}
|
||||
*/
|
||||
uint8_t framebyte(int pos) {
|
||||
return frame[pos];
|
||||
}
|
||||
|
@ -698,53 +460,6 @@ void prn12(uint8_t *prn_le, uint8_t prns[12]) {
|
|||
}
|
||||
|
||||
|
||||
int calc_satpos_alm(EPHEM_t alm[], double t, SAT_t *satp) {
|
||||
return -1;
|
||||
#if 0
|
||||
double X, Y, Z, vX, vY, vZ;
|
||||
int j;
|
||||
int week;
|
||||
double cl_corr, cl_drift;
|
||||
|
||||
for (j = 1; j < 33; j++) {
|
||||
if (alm[j].prn > 0) { // prn==j
|
||||
|
||||
// Woche hat 604800 sec
|
||||
if (t-alm[j].toa > WEEKSEC/2) rollover = +1;
|
||||
else if (t-alm[j].toa < -WEEKSEC/2) rollover = -1;
|
||||
else rollover = 0;
|
||||
week = alm[j].week - rollover;
|
||||
/*if (j == 1)*/ gpx.week = week + GPS_WEEK1024*1024;
|
||||
|
||||
if (option_vel >= 2) {
|
||||
GPS_SatellitePositionVelocity_Ephem(
|
||||
week, t, alm[j],
|
||||
&cl_corr, &cl_drift, &X, &Y, &Z, &vX, &vY, &vZ
|
||||
);
|
||||
satp[alm[j].prn].clock_drift = cl_drift;
|
||||
satp[alm[j].prn].vX = vX;
|
||||
satp[alm[j].prn].vY = vY;
|
||||
satp[alm[j].prn].vZ = vZ;
|
||||
}
|
||||
else {
|
||||
GPS_SatellitePosition_Ephem(
|
||||
week, t, alm[j],
|
||||
&cl_corr, &X, &Y, &Z
|
||||
);
|
||||
}
|
||||
|
||||
satp[alm[j].prn].X = X;
|
||||
satp[alm[j].prn].Y = Y;
|
||||
satp[alm[j].prn].Z = Z;
|
||||
satp[alm[j].prn].clock_corr = cl_corr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int calc_satpos_rnx(EPHEM_t eph[][24], double t, SAT_t *satp) {
|
||||
double X, Y, Z, vX, vY, vZ;
|
||||
int j, i, ti;
|
||||
|
@ -924,12 +639,10 @@ int get_pseudorange() {
|
|||
|
||||
|
||||
// GPS Sat Pos (& Vel)
|
||||
//if (almanac) calc_satpos_alm( alm, gpstime/1000.0, sat);
|
||||
if (ephem) calc_satpos_rnx2(ephs, gpstime/1000.0, sat);
|
||||
|
||||
// GPS Sat Pos t -= 1s
|
||||
if (option_vel == 1) {
|
||||
//if (almanac) calc_satpos_alm( alm, gpstime/1000.0-1, sat1s);
|
||||
if (ephem) calc_satpos_rnx2(ephs, gpstime/1000.0-1, sat1s);
|
||||
}
|
||||
|
||||
|
@ -1115,27 +828,33 @@ int naiv_2Dfix(int N, SAT_t sats[], double alt) {
|
|||
int get_GPSkoord(int N) {
|
||||
double lat, lon, alt, rx_cl_bias;
|
||||
double vH, vD, vU;
|
||||
double lat1s, lon1s, alt1s,
|
||||
lat0 , lon0 , alt0 , pos0_ecef[3];
|
||||
double pos_ecef[3], pos1s_ecef[3], dpos_ecef[3],
|
||||
double pos_ecef[3], dpos_ecef[3],
|
||||
vel_ecef[3], dvel_ecef[3];
|
||||
double gdop, gdop0 = 1000.0;
|
||||
//double hdop, vdop, pdop;
|
||||
int i0, i1, i2, i3, j, k, n;
|
||||
int i0, i1, i2, i3, j;
|
||||
int nav_ret = 0;
|
||||
int num = 0;
|
||||
SAT_t Sat_A[4];
|
||||
#if 0
|
||||
int k, n;
|
||||
double lat1s, lon1s, alt1s,
|
||||
lat0 , lon0 , alt0 , pos0_ecef[3];
|
||||
double pos1s_ecef[3];
|
||||
SAT_t Sat_B[12]; // N <= 12
|
||||
SAT_t Sat_B1s[12];
|
||||
SAT_t Sat_C[12]; // 11
|
||||
double diter = 0;
|
||||
int exN = -1;
|
||||
#endif
|
||||
double diter = 0;
|
||||
|
||||
#if 0
|
||||
if (option_vergps == 8) {
|
||||
fprintf(stdout, " sats: ");
|
||||
for (j = 0; j < N; j++) fprintf(stdout, "%02d ", prn[j]);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
gpx.lat = gpx.lon = gpx.alt = 0;
|
||||
|
||||
|
@ -1166,6 +885,7 @@ int get_GPSkoord(int N) {
|
|||
for (j=0; j<3; j++) vel_ecef[j] += dvel_ecef[j];
|
||||
get_GPSvel(lat, lon, vel_ecef, &vH, &vD, &vU);
|
||||
}
|
||||
#if 0
|
||||
if (option_vergps == 8) {
|
||||
// gdop = sqrt(DOP[0]+DOP[1]+DOP[2]+DOP[3]); // s.o.
|
||||
//hdop = sqrt(DOP[0]+DOP[1]);
|
||||
|
@ -1186,6 +906,7 @@ int get_GPSkoord(int N) {
|
|||
fprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else gdop = -1;
|
||||
|
||||
|
@ -1209,6 +930,7 @@ int get_GPSkoord(int N) {
|
|||
}}}}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (option_vergps == 8 || option_vergps == 2) {
|
||||
|
||||
for (j = 0; j < N; j++) Sat_B[j] = sat[prn[j]];
|
||||
|
@ -1335,6 +1057,7 @@ int get_GPSkoord(int N) {
|
|||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return num;
|
||||
}
|
||||
|
@ -1472,264 +1195,10 @@ void get_eph(const char *file) {
|
|||
if (ephs) {
|
||||
ephem = 1;
|
||||
almanac = 0;
|
||||
}
|
||||
} else {
|
||||
ephstate = EPH_EPHERROR;
|
||||
}
|
||||
Serial.printf("reading RNX done, result is %d, ephs=%p\n", ephem, ephs);
|
||||
if (!option_der) d_err = 1000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
FILE *fp, *fp_alm = NULL, *fp_eph = NULL;
|
||||
char *fpname;
|
||||
char bitbuf[BITS];
|
||||
int bit_count = 0,
|
||||
byte_count = FRAMESTART,
|
||||
header_found = 0,
|
||||
byte, i;
|
||||
int bit, len;
|
||||
char *pbuf = NULL;
|
||||
|
||||
#ifdef CYGWIN
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
#endif
|
||||
setbuf(stdout, NULL);
|
||||
|
||||
fpname = argv[0];
|
||||
++argv;
|
||||
while ((*argv) && (!fileloaded)) {
|
||||
if ( (strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--help") == 0) ) {
|
||||
Serial.printf("%s [options] <file>\n", fpname);
|
||||
Serial.printf(" file: audio.wav or raw_data\n");
|
||||
Serial.printf(" options:\n");
|
||||
Serial.printf(" --vel; --vel1, --vel2 (-g2)\n");
|
||||
Serial.printf(" -v, -vx, -vv\n");
|
||||
Serial.printf(" -r, --raw\n");
|
||||
Serial.printf(" -i, --invert\n");
|
||||
Serial.printf(" -a, --almanac <almanacSEM>\n");
|
||||
Serial.printf(" -e, --ephem <ephemperisRinex>\n");
|
||||
Serial.printf(" -g1 (verbose GPS: 4 sats)\n");
|
||||
Serial.printf(" -g2 (verbose GPS: all sats)\n");
|
||||
Serial.printf(" -gg (vverbose GPS)\n");
|
||||
Serial.printf(" --crc (CRC check GPS)\n");
|
||||
Serial.printf(" --rawin1,2 (raw_data file)\n");
|
||||
return 0;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--vel") == 0) ) {
|
||||
option_vel = 4;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--vel1") == 0) ) {
|
||||
option_vel = 1;
|
||||
if (option_vergps < 1) option_vergps = 2;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--vel2") == 0) ) {
|
||||
option_vel = 2;
|
||||
if (option_vergps < 1) option_vergps = 2;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--iter") == 0) ) {
|
||||
option_iter = 1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "-v") == 0) ) {
|
||||
option_verbose = 1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "-vv") == 0) ) {
|
||||
option_verbose = 4;
|
||||
}
|
||||
else if ( (strcmp(*argv, "-vx") == 0) ) {
|
||||
option_aux = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--crc") == 0) { option_crc = 1; }
|
||||
else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) {
|
||||
option_raw = 1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) {
|
||||
option_inv = 1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "-a") == 0) || (strcmp(*argv, "--almanac") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) fp_alm = fopen(*argv, "r"); // txt-mode
|
||||
else return -1;
|
||||
if (fp_alm == NULL) Serial.printf("[almanac] %s konnte nicht geoeffnet werden\n", *argv);
|
||||
}
|
||||
else if ( (strcmp(*argv, "-e") == 0) || (strncmp(*argv, "--ephem", 7) == 0) ) {
|
||||
++argv;
|
||||
if (*argv) fp_eph = fopen(*argv, "rb"); // bin-mode
|
||||
else return -1;
|
||||
if (fp_eph == NULL) Serial.printf("[rinex] %s konnte nicht geoeffnet werden\n", *argv);
|
||||
}
|
||||
else if ( (strcmp(*argv, "--dop") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
dop_limit = atof(*argv);
|
||||
if (dop_limit <= 0 || dop_limit >= 100) dop_limit = 9.9;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--der") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
d_err = atof(*argv);
|
||||
if (d_err <= 0 || d_err >= 100000) d_err = 10000;
|
||||
else option_der = 1;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--exsat") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
exSat = atoi(*argv);
|
||||
if (exSat < 1 || exSat > 32) exSat = -1;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
else if (strcmp(*argv, "-g1") == 0) { option_vergps = 1; } // verbose1 GPS
|
||||
else if (strcmp(*argv, "-g2") == 0) { option_vergps = 2; } // verbose2 GPS (bancroft)
|
||||
else if (strcmp(*argv, "-gg") == 0) { option_vergps = 8; } // vverbose GPS
|
||||
else if (strcmp(*argv, "--rawin1") == 0) { rawin = 2; } // raw_txt input1
|
||||
else if (strcmp(*argv, "--rawin2") == 0) { rawin = 3; } // raw_txt input2 (SM)
|
||||
else if ( (strcmp(*argv, "--avg") == 0) ) {
|
||||
option_avg = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "-b") == 0) { option_b = 1; }
|
||||
else {
|
||||
if (!rawin) fp = fopen(*argv, "rb");
|
||||
else fp = fopen(*argv, "r");
|
||||
if (fp == NULL) {
|
||||
Serial.printf("%s konnte nicht geoeffnet werden\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
fileloaded = 1;
|
||||
}
|
||||
++argv;
|
||||
}
|
||||
if (!fileloaded) fp = stdin;
|
||||
|
||||
if (fp_alm) {
|
||||
i = read_SEMalmanac(fp_alm, alm);
|
||||
if (i == 0) {
|
||||
almanac = 1;
|
||||
}
|
||||
fclose(fp_alm);
|
||||
if (!option_der) d_err = 4000;
|
||||
}
|
||||
if (fp_eph) {
|
||||
/* i = read_RNXephemeris(fp_eph, eph);
|
||||
if (i == 0) {
|
||||
ephem = 1;
|
||||
almanac = 0;
|
||||
}
|
||||
fclose(fp_eph); */
|
||||
ephs = read_RNXpephs(fp_eph);
|
||||
if (ephs) {
|
||||
ephem = 1;
|
||||
almanac = 0;
|
||||
}
|
||||
fclose(fp_eph);
|
||||
if (!option_der) d_err = 1000;
|
||||
}
|
||||
|
||||
|
||||
if (!rawin) {
|
||||
|
||||
i = read_wav_header(fp);
|
||||
if (i) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (!read_bits_fsk(fp, &bit, &len)) {
|
||||
|
||||
if (len == 0) { // reset_frame();
|
||||
if (byte_count > pos_SondeID+8) {
|
||||
if (byte_count < FRAME_LEN-20) err_gps = 1;
|
||||
print_frame(byte_count);
|
||||
err_gps = 0;
|
||||
}
|
||||
bit_count = 0;
|
||||
byte_count = FRAMESTART;
|
||||
header_found = 0;
|
||||
inc_bufpos();
|
||||
buf[bufpos] = 'x';
|
||||
continue; // ...
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
inc_bufpos();
|
||||
buf[bufpos] = 0x30 + bit; // Ascii
|
||||
|
||||
if (!header_found) {
|
||||
if (compare() >= HEADLEN) header_found = 1;
|
||||
}
|
||||
else {
|
||||
bitbuf[bit_count] = bit;
|
||||
bit_count++;
|
||||
|
||||
if (bit_count == BITS) {
|
||||
bit_count = 0;
|
||||
byte = bits2byte(bitbuf);
|
||||
frame[byte_count] = byte;
|
||||
byte_count++;
|
||||
if (byte_count == FRAME_LEN) {
|
||||
byte_count = FRAMESTART;
|
||||
header_found = 0;
|
||||
//inc_bufpos();
|
||||
//buf[bufpos] = 'x';
|
||||
print_frame(FRAME_LEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (header_found && option_b) {
|
||||
bitstart = 1;
|
||||
|
||||
while ( byte_count < FRAME_LEN ) {
|
||||
if (read_rawbit(fp, &bit) == EOF) break;
|
||||
bitbuf[bit_count] = bit;
|
||||
bit_count++;
|
||||
if (bit_count == BITS) {
|
||||
bit_count = 0;
|
||||
byte = bits2byte(bitbuf);
|
||||
frame[byte_count] = byte;
|
||||
byte_count++;
|
||||
}
|
||||
}
|
||||
header_found = 0;
|
||||
print_frame(byte_count);
|
||||
byte_count = FRAMESTART;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else //if (rawin)
|
||||
{
|
||||
if (rawin == 3) frameofs = 5;
|
||||
|
||||
while (1 > 0) {
|
||||
|
||||
pbuf = fgets(buffer_rawin, rawin*FRAME_LEN+4, fp);
|
||||
if (pbuf == NULL) break;
|
||||
buffer_rawin[rawin*FRAME_LEN+1] = '\0';
|
||||
len = strlen(buffer_rawin) / rawin;
|
||||
if (len > pos_SondeID+8) {
|
||||
for (i = 0; i < len-frameofs; i++) { //%2x SCNx8=%hhx(inttypes.h)
|
||||
sscanf(buffer_rawin+rawin*i, "%2hhx", frame+frameofs+i);
|
||||
// wenn ohne %hhx: sscanf(buffer_rawin+rawin*i, "%2x", &byte); frame[frameofs+i] = (uint8_t)byte;
|
||||
}
|
||||
if (len < FRAME_LEN-20) err_gps = 1;
|
||||
print_frame(len);
|
||||
err_gps = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(ephs);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
0
libraries/SondeLib/rs92gps.h → RX_FSK/src/rs92gps.h
Executable file → Normal file
0
libraries/SondeLib/rs92gps.h → RX_FSK/src/rs92gps.h
Executable file → Normal file
0
libraries/SondeLib/rsc.cpp → RX_FSK/src/rsc.cpp
Executable file → Normal file
0
libraries/SondeLib/rsc.cpp → RX_FSK/src/rsc.cpp
Executable file → Normal file
0
libraries/SondeLib/rsc.h → RX_FSK/src/rsc.h
Executable file → Normal file
0
libraries/SondeLib/rsc.h → RX_FSK/src/rsc.h
Executable file → Normal file
0
libraries/SondeLib/rsc_decode.cpp → RX_FSK/src/rsc_decode.cpp
Executable file → Normal file
0
libraries/SondeLib/rsc_decode.cpp → RX_FSK/src/rsc_decode.cpp
Executable file → Normal file
BIN
RX_FSK/update.ino.bin
Normal file
BIN
RX_FSK/update.ino.bin
Normal file
Binary file not shown.
4
RX_FSK/version.h
Normal file
4
RX_FSK/version.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
const char *version_name = "RadioSonde";
|
||||
const char *version_id = "1.0.0";
|
||||
const int SPIFFS_MAJOR=1;
|
||||
const int SPIFFS_MINOR=0;
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +0,0 @@
|
|||
Radiosonde
|
||||
Radiosonde
|
||||
Terreandro
|
||||
terrexavier
|
||||
TERREWIFI
|
||||
terrexavier
|
|
@ -1,24 +0,0 @@
|
|||
# Frequency in Mhz (format nnn.nnn)
|
||||
# Type (4=RS41, R=RS92, 6=DFM normal, DFM-06, 9=DFM inverted, DFM-09, M=M10)
|
||||
#
|
||||
400.000 9 + Test(FR)
|
||||
401.500 4 - Santander(ES)
|
||||
402.000 M + Nimes(FR)
|
||||
402.800 4 + Cuneo(IT)
|
||||
403.000 6 + Ajactio(FR)
|
||||
403.010 6 + Canjuers(FR)
|
||||
404.200 4 + Rome(IT)
|
||||
404.500 4 - Payern(CH)
|
||||
404.500 M - Bourges(FR)
|
||||
404.789 9 + Frejus1(FR)
|
||||
404.800 4 + Milan(IT)
|
||||
405.000 R + Frejus2(FR)
|
||||
401.199 M - Trappes(FR)
|
||||
405.789 9 + Pegomas(FR)
|
||||
405.100 4 - Lindenberg
|
||||
405.700 4 - Bergen
|
||||
405.900 4 - Bergen_2
|
||||
405.100 4 - Meppen_2
|
||||
405.300 4 - Essen
|
||||
405.500 4 - Essen_2
|
||||
# end
|
|
@ -1,10 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">
|
||||
</head>
|
||||
<body>
|
||||
<button class="tablinks" onclick="javascript:window.open('http://wx.dl2mf.de/','_blank')"> Sonde Map</button><br><br>
|
||||
<button class="tablinks" onclick="javascript:window.open('http://radiosondy.info/','_self')"> RadioSondy</button><br><br>
|
||||
<button class="tablinks" onclick="javascript:window.open('http://tracker.sondehub.org/','_blank')"> SondeHub</button><br><br>
|
||||
</body>
|
||||
</html>
|
|
@ -1,4 +0,0 @@
|
|||
const char *version_name = "RadioSonde";
|
||||
const char *version_id = "0.8.8";
|
||||
//const int SPIFFS_MAJOR=3;
|
||||
//const int SPIFFS_MINOR=5;
|
9
Setup.md
9
Setup.md
|
@ -38,10 +38,8 @@ Installer "U8g2"
|
|||
|
||||
Installer "MicroNMEA"
|
||||
|
||||
Installer "TFT_22_ILI9225" nécessaire pas pour l'écran car j'ai tout supprimé
|
||||
mais pour les fonts, car le TTGO fonctionne avec OLED SSD1306 par défaut!
|
||||
|
||||
|
||||
## Ajouter les bibliothèques, parties 2
|
||||
|
||||
Depuis https://github.com/me-no-dev/ESPAsyncWebServer télécharger le ZIP , l'extraire dans "libraries"
|
||||
|
@ -52,6 +50,7 @@ Depuis https://github.com/me-no-dev/AsyncTCP télécharger le ZIP, l'extraire da
|
|||
de même pour https://github.com/lewisxhe/AXP202X_Library télécharger le ZIP, l'extraire dans "libraries", et renommer le répertoire en AXP202X_Library
|
||||
|
||||
|
||||
aussi https://www.arduino.cc/reference/en/libraries/gfx-library-for-arduino/
|
||||
## Ajouter les bibliothèques, parties 3
|
||||
|
||||
Copier libraries/SX1278FSK
|
||||
|
@ -69,12 +68,6 @@ ln -s <whereyouclonedthegit>/radiosonde/libraries/SX1278FSK/ .
|
|||
```
|
||||
Redémarrer Arduino IDE
|
||||
|
||||
## Ajout carte esp32
|
||||
|
||||
Allez dans Outils-> type de cartes -> gestionnaire de cartes
|
||||
|
||||
puis dans la case taper esp32 et Installer.
|
||||
|
||||
## Dernière parties
|
||||
|
||||
Dans Outils -> Esp32 arduino: ->
|
||||
|
|
|
@ -1,347 +0,0 @@
|
|||
|
||||
/* DFM decoder functions */
|
||||
#include "DFM.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
#define DFM_DEBUG 1
|
||||
|
||||
#if DFM_DEBUG
|
||||
#define DFM_DBG(x) x
|
||||
#else
|
||||
#define DFM_DBG(x)
|
||||
#endif
|
||||
|
||||
int DFM::setup(float frequency, int inv)
|
||||
{
|
||||
inverse = inv;
|
||||
#if DFM_DEBUG
|
||||
Serial.printf("Setup sx1278 for DFM sonde (inv=%d)\n",inv);
|
||||
#endif
|
||||
if(sx1278.ON()!=0) {
|
||||
DFM_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setFSK()!=0) {
|
||||
DFM_DBG(Serial.println("Setting FSM mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setBitrate(2500)!=0) {
|
||||
DFM_DBG(Serial.println("Setting bitrate 2500bit/s FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#if DFM_DEBUG
|
||||
float br = sx1278.getBitrate();
|
||||
Serial.print("Exact bitrate is ");
|
||||
Serial.println(br);
|
||||
#endif
|
||||
|
||||
if(sx1278.setAFCBandwidth(sonde.config.dfm.agcbw)!=0) {
|
||||
DFM_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.dfm.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.dfm.rxbw)!=0) {
|
||||
DFM_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.dfm.rxbw));
|
||||
return 1;
|
||||
}
|
||||
// Enable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
if(sx1278.setRxConf(0x1E)!=0) {
|
||||
DFM_DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// Set autostart_RX to 01, preamble 0, SYNC detect==on, syncsize=3 (==4 byte
|
||||
//char header[] = "0110.0101 0110.0110 1010.0101 1010.1010";
|
||||
|
||||
const char *SYNC=inverse?"\x9A\x99\x5A\x55":"\x65\x66\xA5\xAA";
|
||||
if(sx1278.setSyncConf(0x53, 4, (const uint8_t *)SYNC)!=0) {
|
||||
DFM_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setPreambleDetect(0xA8)!=0) {
|
||||
DFM_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Packet config 1: fixed len, mancecer, no crc, no address filter
|
||||
// Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0)
|
||||
if(sx1278.setPacketConfig(0x28, 0x40)!=0) {
|
||||
DFM_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
Serial.print("DFM: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
|
||||
int retval = sx1278.setFrequency(frequency);
|
||||
sx1278.clearIRQFlags();
|
||||
DFM_DBG(Serial.println("Setting SX1278 config for DFM finished\n"); Serial.println());
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
#define bitpick(value,bitpos) (((value)>>(7-(bitpos)))&0x01)
|
||||
// Input: str: packed data, MSB first
|
||||
void DFM::deinterleave(uint8_t *str, int L, uint8_t *block) {
|
||||
int i, j;
|
||||
for (j = 0; j < B; j++) { // L = 7 (CFG), 13 (DAT1, DAT2)
|
||||
for (i = 0; i < L; i++) {
|
||||
block[B*i+j] = bitpick( str[(L*j+i)/8], (L*j+i)&7 )?0:1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DFM::bits2val(const uint8_t *bits, int len) {
|
||||
uint32_t val = 0;
|
||||
for (int j = 0; j < len; j++) {
|
||||
val |= (bits[j] << (len-1-j));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// Error correction for hamming code
|
||||
// returns 0: ok >0: 1 error was corrected -1: uncorrectable error
|
||||
int DFM::check(uint8_t code[8]) {
|
||||
int i, j;
|
||||
uint32_t synval = 0;
|
||||
uint8_t syndrom[4];
|
||||
int ret=0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
syndrom[i] = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
syndrom[i] ^= H[i][j] & code[j];
|
||||
}
|
||||
}
|
||||
synval = bits2val(syndrom, 4);
|
||||
if (synval) {
|
||||
ret = -1;
|
||||
for (j = 0; j < 8; j++) { // 1-bit-error
|
||||
if (synval == He[j]) { // reicht auf databits zu pruefen, d.h.
|
||||
ret = j+1; // (systematischer Code) He[0..3]
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else ret = 0;
|
||||
if (ret > 0) code[ret-1] ^= 0x1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Extended (8,4) Hamming code
|
||||
// Return number of corrected bits, -1 if uncorrectable error
|
||||
int DFM::hamming(uint8_t *ham, int L, uint8_t *sym) {
|
||||
int i, j;
|
||||
int ret = 0; // DFM: length L = 7 or 13
|
||||
for (i = 0; i < L; i++) { // L bytes (4bit data, 4bit parity)
|
||||
if (use_ecc) {
|
||||
int res = check(ham+8*i);
|
||||
if(ret>=0 && res>=0) ret += res; else ret=-1;
|
||||
}
|
||||
// systematic Hamming code: copy bits 0..3
|
||||
for (j = 0; j < 4; j++) {
|
||||
sym[4*i+j] = ham[8*i+j];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DFM::DFM() {
|
||||
}
|
||||
|
||||
void DFM::printRaw(const char *label, int len, int ret, const uint8_t *data)
|
||||
{
|
||||
Serial.print(label); Serial.print("(");
|
||||
Serial.print(ret);
|
||||
Serial.print("):");
|
||||
int i;
|
||||
for(i=0; i<len/2; i++) {
|
||||
char str[10];
|
||||
snprintf(str, 10, "%02X", data[i]);
|
||||
Serial.print(str);
|
||||
}
|
||||
Serial.print(data[i]&0x0F, HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
|
||||
void DFM::decodeCFG(uint8_t *cfg)
|
||||
{
|
||||
static int lowid, highid, idgood=0, type=0;
|
||||
if((cfg[0]>>4)==0x06 && type==0) { // DFM-6 ID
|
||||
lowid = ((cfg[0]&0x0F)<<20) | (cfg[1]<<12) | (cfg[2]<<4) | (cfg[3]&0x0f);
|
||||
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
|
||||
type=9;
|
||||
if(cfg[3]==1) {
|
||||
lowid = (cfg[1]<<8) | cfg[2];
|
||||
idgood |= 1;
|
||||
} else {
|
||||
highid = (cfg[1]<<8) | cfg[2];
|
||||
idgood |= 2;
|
||||
}
|
||||
if(idgood==3) {
|
||||
uint32_t dfmid = (highid<<16) | lowid;
|
||||
Serial.print("DFM-09 ID: "); Serial.print(dfmid);
|
||||
snprintf(sonde.si()->ser, 10, "%d", dfmid);
|
||||
// dxlAPRS sonde number (DF6 (why??) and 5 last digits of serial number as hex number
|
||||
snprintf(sonde.si()->id, 9, "DF6%05X", dfmid&0xfffff);
|
||||
sonde.si()->validID = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int bitCount(int x) {
|
||||
int m4 = 0x1 | (0x1<<8) | (0x1<<16) | (0x1<<24);
|
||||
int m1 = 0xFF;
|
||||
int s4 = (x&m4) + ((x>>1)&m4) + ((x>>2)&m4) + ((x>>3)&m4) + ((x>>4)&m4) + ((x>>5)&m4) + ((x>>6)&m4) + ((x>>7)&m4);
|
||||
int s1 = (s4&m1) + ((s4>>8)&m1) + ((s4>>16)&m1) + ((s4>>24)&m1);
|
||||
return s1;
|
||||
}
|
||||
|
||||
static uint16_t MON[]={0,0,31,59,90,120,151,181,212,243,273,304,334};
|
||||
|
||||
void DFM::decodeDAT(uint8_t *dat)
|
||||
{
|
||||
Serial.print(" DAT["); Serial.print(dat[6]); Serial.print("]: ");
|
||||
switch(dat[6]) {
|
||||
case 0:
|
||||
Serial.print("Packet counter: "); Serial.print(dat[3]);
|
||||
sonde.si()->frame = dat[3];
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
int val = (((uint16_t)dat[4])<<8) + (uint16_t)dat[5];
|
||||
Serial.print("UTC-msec: "); Serial.print(val);
|
||||
sonde.si()->sec = val/1000;
|
||||
uint32_t tmp = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + ((uint32_t)dat[3]);
|
||||
sonde.si()->sats = bitCount(tmp); // maybe!?!?!?
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
float lat, vh;
|
||||
lat = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + ((uint32_t)dat[3]);
|
||||
vh = ((uint16_t)dat[4]<<8) + dat[5];
|
||||
Serial.print("GPS-lat: "); Serial.print(lat*0.0000001);
|
||||
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;
|
||||
case 3:
|
||||
{
|
||||
float lon, dir;
|
||||
lon = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + (uint32_t)dat[3];
|
||||
dir = ((uint16_t)dat[4]<<8) + dat[5];
|
||||
Serial.print("GPS-lon: "); Serial.print(lon*0.0000001);
|
||||
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;
|
||||
case 4:
|
||||
{
|
||||
float alt, vv;
|
||||
alt = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + dat[3];
|
||||
vv = (int16_t)( ((int16_t)dat[4]<<8) | dat[5] );
|
||||
Serial.print("GPS-height: "); Serial.print(alt*0.01);
|
||||
Serial.print(", vv: "); Serial.print(vv*0.01);
|
||||
sonde.si()->alt = alt*0.01;
|
||||
sonde.si()->vs = vv*0.01;
|
||||
sonde.si()->validPos |= 0x0C;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
{
|
||||
int y = (dat[0]<<4) + (dat[1]>>4);
|
||||
int m = dat[1]&0x0F;
|
||||
int d = dat[2]>>3;
|
||||
int h = ((dat[2]&0x07)<<2) + (dat[3]>>6);
|
||||
int mi = (dat[3]&0x3F);
|
||||
char buf[100];
|
||||
snprintf(buf, 100, "%04d-%02d-%02d %02d:%02dz", y, m, d, h, mi);
|
||||
Serial.print("Date: "); Serial.print(buf);
|
||||
// convert to unix time
|
||||
int tt = (y-1970)*365 + (y-1969)/4; // days since 1970
|
||||
if(m<=12) { tt += MON[m]; if((y%4)==0 && m>2) tt++; }
|
||||
tt = (tt+d-1)*(60*60*24) + h*3600 + mi*60;
|
||||
sonde.si()->time = tt;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Serial.print("(?)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DFM::bitsToBytes(uint8_t *bits, uint8_t *bytes, int len)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<len*4; i++) {
|
||||
//Serial.print(bits[i]?"1":"0");
|
||||
bytes[i/8] = (bytes[i/8]<<1) | (bits[i]?1:0);
|
||||
}
|
||||
bytes[(i-1)/8] &= 0x0F;
|
||||
}
|
||||
|
||||
int DFM::receive() {
|
||||
byte data[1000]; // pending data from previous mode may write more than 33 bytes. TODO.
|
||||
for(int i=0; i<2; i++) {
|
||||
sx1278.setPayloadLength(33); // Expect 33 bytes (7+13+13 bytes)
|
||||
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
int e = sx1278.receivePacketTimeout(1000, data);
|
||||
if(e) { return RX_TIMEOUT; } //if timeout... return 1
|
||||
|
||||
Serial.printf("inverse is %d\b", inverse);
|
||||
if(!inverse) { for(int i=0; i<33; i++) { data[i]^=0xFF; } }
|
||||
deinterleave(data, 7, hamming_conf);
|
||||
deinterleave(data+7, 13, hamming_dat1);
|
||||
deinterleave(data+20, 13, hamming_dat2);
|
||||
|
||||
int ret0 = hamming(hamming_conf, 7, block_conf);
|
||||
int ret1 = hamming(hamming_dat1, 13, block_dat1);
|
||||
int ret2 = hamming(hamming_dat2, 13, block_dat2);
|
||||
|
||||
byte byte_conf[4], byte_dat1[7], byte_dat2[7];
|
||||
bitsToBytes(block_conf, byte_conf, 7);
|
||||
bitsToBytes(block_dat1, byte_dat1, 13);
|
||||
bitsToBytes(block_dat2, byte_dat2, 13);
|
||||
|
||||
printRaw("CFG", 7, ret0, byte_conf);
|
||||
printRaw("DAT", 13, ret1, byte_dat1);
|
||||
printRaw("DAT", 13, ret2, byte_dat2);
|
||||
decodeCFG(byte_conf);
|
||||
decodeDAT(byte_dat1);
|
||||
decodeDAT(byte_dat2);
|
||||
}
|
||||
return RX_OK;
|
||||
}
|
||||
|
||||
// moved to a single function in Sonde(). This function can be used for additional
|
||||
// processing here, that takes too long for doing in the RX task loop
|
||||
int DFM::waitRXcomplete() {
|
||||
#if 0
|
||||
int res=0;
|
||||
uint32_t t0 = millis();
|
||||
while( rxtask.receiveResult < 0 && millis()-t0 < 2000) { delay(50); }
|
||||
|
||||
if( rxtask.receiveResult<0 || rxtask.receiveResult==RX_TIMEOUT) {
|
||||
res = RX_TIMEOUT;
|
||||
} else if ( rxtask.receiveResult ==0) {
|
||||
res = RX_OK;
|
||||
} else {
|
||||
res = RX_ERROR;
|
||||
}
|
||||
rxtask.receiveResult = -1;
|
||||
Serial.printf("waitRXcomplete returning %d\n", res);
|
||||
return res;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
DFM dfm = DFM();
|
|
@ -1,529 +0,0 @@
|
|||
|
||||
/* M10 decoder functions */
|
||||
#include "M10.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "rsc.h"
|
||||
#include "Sonde.h"
|
||||
#include <SPIFFS.h>
|
||||
|
||||
// well...
|
||||
//#include "rs92gps.h"
|
||||
|
||||
#define M10_DEBUG 1
|
||||
|
||||
#if M10_DEBUG
|
||||
#define M10_DBG(x) x
|
||||
#else
|
||||
#define M10_DBG(x)
|
||||
#endif
|
||||
|
||||
|
||||
static byte data1[512];
|
||||
static byte *dataptr=data1;
|
||||
|
||||
static uint8_t rxbitc;
|
||||
static uint16_t rxbyte;
|
||||
static int rxp=0;
|
||||
static int haveNewFrame = 0;
|
||||
static int lastFrame = 0;
|
||||
static int headerDetected = 0;
|
||||
|
||||
int M10::setup(float frequency)
|
||||
{
|
||||
#if M10_DEBUG
|
||||
Serial.println("Setup sx1278 for M10 sonde");
|
||||
#endif
|
||||
//if(!initialized) {
|
||||
//Gencrctab();
|
||||
//initrsc();
|
||||
// not here for now.... get_eph("/brdc.19n");
|
||||
// initialized = true;
|
||||
//}
|
||||
|
||||
if(sx1278.ON()!=0) {
|
||||
M10_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setFSK()!=0) {
|
||||
M10_DBG(Serial.println("Setting FSJ mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setBitrate(9600)!=0) {
|
||||
M10_DBG(Serial.println("Setting bitrate 9600bit/s FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#if M10_DEBUG
|
||||
float br = sx1278.getBitrate();
|
||||
Serial.print("Exact bitrate is ");
|
||||
Serial.println(br);
|
||||
#endif
|
||||
if(sx1278.setAFCBandwidth(sonde.config.rs92.rxbw)!=0) {
|
||||
M10_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.rs92.rxbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.rs92.rxbw)!=0) {
|
||||
M10_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.rs92.rxbw));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Enable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
if(sx1278.setRxConf(0x1E)!=0) {
|
||||
M10_DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// Set autostart_RX to 01, preamble 0, SYNC detect==on, syncsize=3 (==4 byte
|
||||
//char header[] = "0110.0101 0110.0110 1010.0101 1010.1010";
|
||||
|
||||
//const char *SYNC="\x10\xB6\xCA\x11\x22\x96\x12\xF8";
|
||||
//const char *SYNC="\x08\x6D\x53\x88\x44\x69\x48\x1F";
|
||||
// was 0x57
|
||||
//const char *SYNC="\x99\x9A";
|
||||
#if 1
|
||||
// version 1, working with continuous RX
|
||||
const char *SYNC="\x66\x65";
|
||||
if(sx1278.setSyncConf(0x70, 2, (const uint8_t *)SYNC)!=0) {
|
||||
M10_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
//if(sx1278.setPreambleDetect(0xA8)!=0) {
|
||||
if((sx1278.setPreambleDetect(0x9F)!=0)&&((sx1278.setPreambleDetect(0xAF)!=0))) {
|
||||
M10_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
// version 2, with per-packet rx start, untested
|
||||
// header is 2a 10 65, i.e. with lsb first
|
||||
// 0 0101 0100 1 0 0000 1000 1 0 1010 0110 1
|
||||
// 10 10011001 10011010 01 10 10101010 01101010 01 10 01100110 10010110 01
|
||||
// preamble 0x6A 0x66 0x6A
|
||||
// i.e. preamble detector on (0x80), preamble detector size 1 (0x00), preample chip errors??? (0x0A)
|
||||
// after 2a2a2a2a2a1065
|
||||
if(sx1278.setPreambleDetect(0xA8)!=0) {
|
||||
M10_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// sync config: ato restart (01), preamble polarity AA (0), sync on (1), resevered (0), syncsize 2+1 (010) => 0x52
|
||||
const char *SYNC="\x6A\x66\x69";
|
||||
if(sx1278.setSyncConf(0x52, 3, (const uint8_t *)SYNC)!=0) {
|
||||
M10_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// payload length is ((240 - 7)*10 +6)/8 = 292
|
||||
#endif
|
||||
|
||||
// Packet config 1: fixed len, no mancecer, no crc, no address filter
|
||||
// Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0)
|
||||
if(sx1278.setPacketConfig(0x08, 0x40)!=0) {
|
||||
M10_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
Serial.print("M10: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
int res = sx1278.setFrequency(frequency);
|
||||
// enable RX
|
||||
sx1278.setPayloadLength(0); // infinite for now...
|
||||
//sx1278.setPayloadLength(292);
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
|
||||
#if M10_DEBUG
|
||||
M10_DBG(Serial.println("Setting SX1278 config for M10 finished\n"); Serial.println());
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int M10::setFrequency(float frequency) {
|
||||
Serial.print("M10: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
int res = sx1278.setFrequency(frequency);
|
||||
// enable RX
|
||||
sx1278.setPayloadLength(0); // infinite for now...
|
||||
|
||||
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
uint32_t M10::bits2val(const uint8_t *bits, int len) {
|
||||
uint32_t val = 0;
|
||||
for (int j = 0; j < len; j++) {
|
||||
val |= (bits[j] << (len-1-j));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
M10::M10() {
|
||||
}
|
||||
|
||||
#define M10_FRAMELEN 101
|
||||
#define M10_CRCPOS 99
|
||||
|
||||
void M10::printRaw(uint8_t *data, int len)
|
||||
{
|
||||
char buf[3];
|
||||
int i;
|
||||
for(i=0; i<len; i++) {
|
||||
snprintf(buf, 3, "%02X ", data[i]);
|
||||
Serial.print(buf);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
static int update_checkM10(int c, uint8_t b) {
|
||||
int c0, c1, t, t6, t7, s;
|
||||
c1 = c & 0xFF;
|
||||
// B
|
||||
b = (b >> 1) | ((b & 1) << 7);
|
||||
b ^= (b >> 2) & 0xFF;
|
||||
// A1
|
||||
t6 = ( c & 1) ^ ((c >> 2) & 1) ^ ((c >> 4) & 1);
|
||||
t7 = ((c >> 1) & 1) ^ ((c >> 3) & 1) ^ ((c >> 5) & 1);
|
||||
t = (c & 0x3F) | (t6 << 6) | (t7 << 7);
|
||||
// A2
|
||||
s = (c >> 7) & 0xFF;
|
||||
s ^= (s >> 2) & 0xFF;
|
||||
c0 = b ^ t ^ s;
|
||||
return ((c1 << 8) | c0) & 0xFFFF;
|
||||
}
|
||||
static bool checkM10crc(uint8_t *msg) {
|
||||
int i, cs, cs1;
|
||||
cs = 0;
|
||||
for (i = 0; i < M10_CRCPOS; i++) {
|
||||
cs = update_checkM10(cs, msg[i]);
|
||||
}
|
||||
cs = cs & 0xFFFF;
|
||||
cs1 = (msg[M10_CRCPOS] << 8) | msg[M10_CRCPOS+1];
|
||||
return (cs1 == cs);
|
||||
}
|
||||
|
||||
typedef uint32_t SET256[8];
|
||||
static SET256 sondeudp_VARSET = {0x03BBBBF0UL,0x80600000UL,0x06A001A0UL,
|
||||
0x0000001CUL,0x00000000UL,0x00000000UL,0x00000000UL,
|
||||
0x00000000UL};
|
||||
// VARSET=SET256{4..9,11..13,15..17,19..21,23..25,53..54,63,69,71,72,85,87,89,90,98..100};
|
||||
|
||||
static uint8_t fixcnt[M10_FRAMELEN];
|
||||
static uint8_t fixbytes[M10_FRAMELEN];
|
||||
|
||||
static int32_t getint32(uint8_t *data) {
|
||||
return (int32_t)( data[3]|(data[2]<<8)|(data[1]<<16)|(data[0]<<24) );
|
||||
}
|
||||
static int16_t getint16(uint8_t *data) {
|
||||
return (int16_t)(data[1]|((uint16_t)data[0]<<8));
|
||||
}
|
||||
|
||||
static char dez(uint8_t nr) {
|
||||
nr = nr%10;
|
||||
return '0'+nr;
|
||||
}
|
||||
static char hex(uint8_t nr) {
|
||||
nr = nr&0x0f;
|
||||
if(nr<10) return '0'+nr;
|
||||
else return 'A'+nr-10;
|
||||
}
|
||||
const static float DEGMUL = 1.0/0xB60B60;
|
||||
#define VMUL 0.005
|
||||
#ifndef PI
|
||||
#define PI (3.1415926535897932384626433832795)
|
||||
#endif
|
||||
#define RAD (PI/180)
|
||||
|
||||
|
||||
// ret: 1=frame ok; 2=frame with errors; 0=ignored frame (m10dop-alternativ)
|
||||
int M10::decodeframeM10(uint8_t *data) {
|
||||
int repairstep = 16;
|
||||
int repl = 0;
|
||||
bool crcok;
|
||||
// error correction, inspired by oe5dxl's sondeudp
|
||||
do {
|
||||
crcok = checkM10crc(data);
|
||||
if(crcok) break;
|
||||
repl = 0;
|
||||
for(int i=0; i<M10_CRCPOS; i++) {
|
||||
if( ((sondeudp_VARSET[i/32]&(1<<(i%32))) != 1) && (fixcnt[i]>=repairstep) ) {
|
||||
repl++;
|
||||
data[i] = fixbytes[i];
|
||||
}
|
||||
}
|
||||
repairstep >>= 1;
|
||||
} while(repairstep>0);
|
||||
if(crcok) {
|
||||
for(int i=0; i<M10_CRCPOS; i++) {
|
||||
if(fixbytes[i]==data[i] &&fixcnt[i]<255) fixcnt[i]++;
|
||||
else { fixcnt[i]=0; fixbytes[i]=data[i]; }
|
||||
}
|
||||
}
|
||||
Serial.println(crcok?"CRC OK":"CRC NOT OK");
|
||||
//M10 0x9F M10Plus 0xAF M20 0x20
|
||||
if((data[1]==0x9F && data[2]==0x20) || (data[1]==0xAF && data[2]==0x20)) {
|
||||
Serial.println("Decoding...");
|
||||
// Its a M10
|
||||
// getid...
|
||||
char ids[11];
|
||||
ids[0] = 'M';
|
||||
ids[1] = 'E';
|
||||
ids[2] = hex(data[95]/16);
|
||||
ids[3] = hex(data[95]);
|
||||
ids[4] = hex(data[93]);
|
||||
uint32_t id = data[96] + data[97]*256;
|
||||
ids[5] = hex(id/4096);
|
||||
ids[6] = hex(id/256);
|
||||
ids[7] = hex(id/16);
|
||||
ids[8] = hex(id);
|
||||
ids[9] = 0;
|
||||
strncpy(sonde.si()->id, ids, 10);
|
||||
ids[0] = hex(data[95]/16);
|
||||
ids[1] = dez((data[95]&0x0f)/10);
|
||||
ids[2] = dez((data[95]&0x0f));
|
||||
ids[3] = dez(data[93]);
|
||||
ids[4] = dez(id>>13);
|
||||
id &= 0x1fff;
|
||||
ids[5] = dez(id/1000);
|
||||
ids[6] = dez((id/100)%10);
|
||||
ids[7] = dez((id/10)%10);
|
||||
ids[8] = dez(id%10);
|
||||
strncpy(sonde.si()->ser, ids, 10);
|
||||
sonde.si()->validID = true;
|
||||
Serial.printf("ID is %s [%02x %02x %d]\n", ids, data[95], data[93], id);
|
||||
// ID printed on sonde is ...-.-abbbb, with a=id>>13, bbbb=id&0x1fff in decimal
|
||||
// position data
|
||||
sonde.si()->lat = getint32(data+14) * DEGMUL;
|
||||
sonde.si()->lon = getint32(data+18) * DEGMUL;
|
||||
sonde.si()->alt = getint32(data+22) * 0.001;
|
||||
float ve = getint16(data+4)*VMUL;
|
||||
float vn = getint16(data+6)*VMUL;
|
||||
sonde.si()->vs = getint16(data+8) * VMUL;
|
||||
sonde.si()->hs = sqrt(ve*ve+vn*vn);
|
||||
float dir = atan2(vn, ve)*(1.0/RAD);
|
||||
if(dir<0) dir+=360;
|
||||
sonde.si()->dir = dir;
|
||||
sonde.si()->validPos = 0x3f;
|
||||
|
||||
uint32_t gpstime = getint32(data+10);
|
||||
uint16_t gpsweek = getint16(data+32);
|
||||
// UTC is GPSTIME - 18s (24*60*60-18 = 86382)
|
||||
// one week = 7*24*60*60 = 604800 seconds
|
||||
// unix epoch starts jan 1st 1970 0:00
|
||||
// gps time starts jan 6, 1980 0:00. thats 315964800 epoch seconds.
|
||||
// subtracting 86400 yields 315878400UL
|
||||
sonde.si()->time = (gpstime/1000) + 86382 + gpsweek*604800 + 315878400UL;
|
||||
sonde.si()->validTime = true;
|
||||
} else {
|
||||
Serial.printf("data is %02x %02x %02x\n", data[0], data[1], data[2]);
|
||||
return 0;
|
||||
}
|
||||
return crcok?1:2;
|
||||
}
|
||||
|
||||
static uint32_t rxdata;
|
||||
static bool rxsearching=true;
|
||||
|
||||
// search for
|
||||
// //101001100110011010011010011001100110100110101010100110101001
|
||||
// //1010011001100110100110100110 0110.0110 1001.1010 1010.1001 1010.1001 => 0x669AA9A9
|
||||
void M10::processM10data(uint8_t dt)
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
uint8_t d = (dt&0x80)?1:0;
|
||||
dt <<= 1;
|
||||
rxdata = (rxdata<<1) | d;
|
||||
//uint8_t value = ((rxdata>>1)^rxdata)&0x01;
|
||||
//if((rxbitc&1)==1) { rxbyte = (rxbyte>>1) + ((value)<<8); } // mancester decoded data
|
||||
//rxbyte = (rxbyte>>1) | (d<<8);
|
||||
if( (rxbitc&1)==0 ) {
|
||||
// "bit1"
|
||||
rxbyte = (rxbyte<<1) | d;
|
||||
} else {
|
||||
// "bit2" ==> 01 or 10 => 1, otherweise => 0
|
||||
rxbyte = rxbyte ^ d;
|
||||
}
|
||||
//
|
||||
if(rxsearching) {
|
||||
if( rxdata == 0xcccca64c || rxdata == 0x333359b3 ) {
|
||||
rxsearching = false;
|
||||
rxbitc = 0;
|
||||
rxp = 0;
|
||||
#if 1
|
||||
int rssi=sx1278.getRSSI();
|
||||
int fei=sx1278.getFEI();
|
||||
int afc=sx1278.getAFC();
|
||||
Serial.print("Test: RSSI="); Serial.print(rssi);
|
||||
Serial.print(" FEI="); Serial.print(fei);
|
||||
Serial.print(" AFC="); Serial.println(afc);
|
||||
sonde.si()->rssi = rssi;
|
||||
sonde.si()->afc = afc;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
rxbitc = (rxbitc+1)%16; // 16;
|
||||
if(rxbitc == 0) { // got 8 data bit
|
||||
//Serial.printf("%03x ",rxbyte);
|
||||
dataptr[rxp++] = rxbyte&0xff; // (rxbyte>>1)&0xff;
|
||||
#if 0
|
||||
if(rxp==7 && dataptr[6] != 0x65) {
|
||||
Serial.printf("wrong start: %02x\n",dataptr[6]);
|
||||
rxsearching = true;
|
||||
}
|
||||
#endif
|
||||
if(rxp>=M10_FRAMELEN) {
|
||||
rxsearching = true;
|
||||
haveNewFrame = decodeframeM10(dataptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int M10::receive() {
|
||||
unsigned long t0 = millis();
|
||||
Serial.printf("M10::receive() start at %ld\n",t0);
|
||||
while( millis() - t0 < 1000 ) {
|
||||
uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
if ( bitRead(value, 7) ) {
|
||||
Serial.println("FIFO full");
|
||||
}
|
||||
if ( bitRead(value, 4) ) {
|
||||
Serial.println("FIFO overflow");
|
||||
}
|
||||
if ( bitRead(value, 2) == 1 ) {
|
||||
Serial.println("FIFO: ready()");
|
||||
sx1278.clearIRQFlags();
|
||||
}
|
||||
if(bitRead(value, 6) == 0) { // while FIFO not empty
|
||||
byte data = sx1278.readRegister(REG_FIFO);
|
||||
//Serial.printf("%02x",data);
|
||||
processM10data(data);
|
||||
value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
} else {
|
||||
if(headerDetected) {
|
||||
t0 = millis(); // restart timer... don't time out if header detected...
|
||||
headerDetected = 0;
|
||||
}
|
||||
if(haveNewFrame) {
|
||||
Serial.printf("M10::receive(): new frame complete after %ldms\n", millis()-t0);
|
||||
printRaw(dataptr, M10_FRAMELEN);
|
||||
int retval = haveNewFrame==1 ? RX_OK: RX_ERROR;
|
||||
haveNewFrame = 0;
|
||||
return retval;
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
Serial.printf("M10::receive() timed out\n");
|
||||
return RX_TIMEOUT; // TODO RX_OK;
|
||||
}
|
||||
|
||||
#define M10MAXLEN (240)
|
||||
int M10::waitRXcomplete() {
|
||||
// called after complete...
|
||||
#if 0
|
||||
Serial.printf("decoding frame %d\n", lastFrame);
|
||||
print_frame(lastFrame==1?data1:data2, 240);
|
||||
SondeInfo *si = sonde.sondeList+rxtask.receiveSonde;
|
||||
si->lat = gpx.lat;
|
||||
si->lon = gpx.lon;
|
||||
si->alt = gpx.alt;
|
||||
si->vs = gpx.vU;
|
||||
si->hs = gpx.vH;
|
||||
si->dir = gpx.vD;
|
||||
si->validPos = 0x3f;
|
||||
memcpy(si->id, gpx.id, 9);
|
||||
si->validID = true;
|
||||
|
||||
int res=0;
|
||||
uint32_t t0 = millis();
|
||||
while( rxtask.receiveResult == 0xFFFF && millis()-t0 < 2000) { delay(20); }
|
||||
|
||||
if( rxtask.receiveResult<0 || rxtask.receiveResult==RX_TIMEOUT) {
|
||||
res = RX_TIMEOUT;
|
||||
} else if ( rxtask.receiveResult==0) {
|
||||
res = RX_OK;
|
||||
} else {
|
||||
res = RX_ERROR;
|
||||
}
|
||||
rxtask.receiveResult = 0xFFFF;
|
||||
Serial.printf("M10::waitRXcomplete returning %d (%s)\n", res, RXstr[res]);
|
||||
return res;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int oldwaitRXcomplete() {
|
||||
Serial.println("M10: receive frame...\n");
|
||||
sx1278receiveData = true;
|
||||
delay(6000); // done in other task....
|
||||
//sx1278receiveData = false;
|
||||
#if 0
|
||||
//sx1278.setPayloadLength(518-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
|
||||
//sx1278.setPayloadLength(0); // infinite for now...
|
||||
|
||||
////// test code for continuous reception
|
||||
// sx1278.receive(); /// active FSK RX mode -- already done above...
|
||||
uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
unsigned long previous = millis();
|
||||
|
||||
byte ready=0;
|
||||
uint32_t wait = 8000;
|
||||
// while not yet done or FIFO not yet empty
|
||||
// bit 6: FIFO Empty
|
||||
// bit 2 payload ready
|
||||
int by=0;
|
||||
while( (!ready || bitRead(value,6)==0) && (millis() - previous < wait) )
|
||||
{
|
||||
if( bitRead(value, 7) ) { Serial.println("FIFO full"); }
|
||||
if( bitRead(value, 4) ) { Serial.println("FIFO overflow"); }
|
||||
if( bitRead(value,2)==1 ) ready=1;
|
||||
if( bitRead(value, 6) == 0 ) { // FIFO not empty
|
||||
byte data = sx1278.readRegister(REG_FIFO);
|
||||
process8N1data(data);
|
||||
by++;
|
||||
#if 0
|
||||
if(di==1) {
|
||||
int rssi=getRSSI();
|
||||
int fei=getFEI();
|
||||
int afc=getAFC();
|
||||
Serial.print("Test: RSSI="); Serial.println(rssi);
|
||||
Serial.print("Test: FEI="); Serial.println(fei);
|
||||
Serial.print("Test: AFC="); Serial.println(afc);
|
||||
sonde.si()->rssi = rssi;
|
||||
sonde.si()->afc = afc;
|
||||
}
|
||||
if(di>520) {
|
||||
// TODO
|
||||
Serial.println("TOO MUCH DATA");
|
||||
break;
|
||||
}
|
||||
previous = millis(); // reset timeout after receiving data
|
||||
#endif
|
||||
}
|
||||
value = sx1278.readRegister(REG_IRQ_FLAGS2);
|
||||
}
|
||||
Serial.printf("processed %d bytes before end/timeout\n", by);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/////
|
||||
#if 0
|
||||
int e = sx1278.receivePacketTimeout(1000, data+8);
|
||||
if(e) { Serial.println("TIMEOUT"); return RX_TIMEOUT; } //if timeout... return 1
|
||||
|
||||
printRaw(data, M10MAXLEN);
|
||||
//for(int i=0; i<M10MAXLEN; i++) { data[i] = reverse(data[i]); }
|
||||
//printRaw(data, MAXLEN);
|
||||
//for(int i=0; i<M10MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
|
||||
//printRaw(data, MAXLEN);
|
||||
//int res = decode41(data, M10MAXLEN);
|
||||
#endif
|
||||
int res=0;
|
||||
return res==0 ? RX_OK : RX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
M10 m10 = M10();
|
|
@ -1,556 +0,0 @@
|
|||
|
||||
/* RS41 decoder functions */
|
||||
#include "RS41.h"
|
||||
#include "SX1278FSK.h"
|
||||
#include "rsc.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
#define RS41_DEBUG 0
|
||||
|
||||
#if RS41_DEBUG
|
||||
#define RS41_DBG(x) x
|
||||
#else
|
||||
#define RS41_DBG(x)
|
||||
#endif
|
||||
|
||||
#define RS41MAXLEN (320)
|
||||
static byte data[800];
|
||||
static int dpos = 0;
|
||||
|
||||
static uint16_t CRCTAB[256];
|
||||
|
||||
#define X2C_DIVR(a, b) ((b) != 0.0f ? (a)/(b) : (a))
|
||||
#define X2C_DIVL(a, b) ((a)/(b))
|
||||
static uint32_t X2C_LSH(uint32_t a, int32_t length, int32_t n)
|
||||
{
|
||||
uint32_t m;
|
||||
|
||||
m = 0;
|
||||
m = (length == 32) ? 0xFFFFFFFFl : (1 << length) - 1;
|
||||
if (n > 0) {
|
||||
if (n >= (int32_t)length)
|
||||
return 0;
|
||||
return (a << n) & m;
|
||||
}
|
||||
|
||||
if (n <= (int32_t)-length)
|
||||
return 0;
|
||||
return (a >> -n) & m;
|
||||
}
|
||||
|
||||
static double atang2(double x, double y)
|
||||
{
|
||||
double w;
|
||||
if (fabs(x)>fabs(y)) {
|
||||
w = (double)atan((float)(X2C_DIVL(y,x)));
|
||||
if (x<0.0) {
|
||||
if (y>0.0) w = 3.1415926535898+w;
|
||||
else w = w-3.1415926535898;
|
||||
}
|
||||
}
|
||||
else if (y!=0.0) {
|
||||
w = (double)(1.5707963267949f-atan((float)(X2C_DIVL(x,
|
||||
y))));
|
||||
if (y<0.0) w = w-3.1415926535898;
|
||||
}
|
||||
else w = 0.0;
|
||||
return w;
|
||||
} /* end atang2() */
|
||||
|
||||
|
||||
static void Gencrctab(void)
|
||||
{
|
||||
uint16_t j;
|
||||
uint16_t i;
|
||||
uint16_t crc;
|
||||
for (i = 0U; i<=255U; i++) {
|
||||
crc = (uint16_t)(i*256U);
|
||||
for (j = 0U; j<=7U; j++) {
|
||||
if ((0x8000U & crc)) crc = X2C_LSH(crc,16,1)^0x1021U;
|
||||
else crc = X2C_LSH(crc,16,1);
|
||||
} /* end for */
|
||||
CRCTAB[i] = X2C_LSH(crc,16,-8)|X2C_LSH(crc,16,8);
|
||||
} /* end for */
|
||||
} /* end Gencrctab() */
|
||||
|
||||
int RS41::setup(float frequency)
|
||||
{
|
||||
#if RS41_DEBUG
|
||||
Serial.println("Setup sx1278 for RS41 sonde");
|
||||
#endif
|
||||
if(!initialized) {
|
||||
Gencrctab();
|
||||
initrsc();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if(sx1278.ON()!=0) {
|
||||
RS41_DBG(Serial.println("Setting SX1278 power on FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setFSK()!=0) {
|
||||
RS41_DBG(Serial.println("Setting FSK mode FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setBitrate(4800)!=0) {
|
||||
RS41_DBG(Serial.println("Setting bitrate 4800bit/s FAILED"));
|
||||
return 1;
|
||||
}
|
||||
#if RS41_DEBUG
|
||||
float br = sx1278.getBitrate();
|
||||
Serial.print("Exact bitrate is ");
|
||||
Serial.println(br);
|
||||
#endif
|
||||
|
||||
if(sx1278.setAFCBandwidth(sonde.config.rs41.agcbw)!=0) {
|
||||
RS41_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.rs41.agcbw));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setRxBandwidth(sonde.config.rs41.rxbw)!=0) {
|
||||
RS41_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.rs41.rxbw));
|
||||
return 1;
|
||||
}
|
||||
// Enable auto-AFC, auto-AGC, RX Trigger by preamble
|
||||
if(sx1278.setRxConf(0x1E)!=0) {
|
||||
RS41_DBG(Serial.println("Setting RX Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
// Set autostart_RX to 01, preamble 0, SYNC detect==on, syncsize=3 (==4 byte
|
||||
//char header[] = "0110.0101 0110.0110 1010.0101 1010.1010";
|
||||
|
||||
//const char *SYNC="\x10\xB6\xCA\x11\x22\x96\x12\xF8";
|
||||
const char *SYNC="\x08\x6D\x53\x88\x44\x69\x48\x1F";
|
||||
if(sx1278.setSyncConf(0x57, 8, (const uint8_t *)SYNC)!=0) {
|
||||
RS41_DBG(Serial.println("Setting SYNC Config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
if(sx1278.setPreambleDetect(0xA8)!=0) {
|
||||
RS41_DBG(Serial.println("Setting PreambleDetect FAILED"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Packet config 1: fixed len, no mancecer, no crc, no address filter
|
||||
// Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0)
|
||||
if(sx1278.setPacketConfig(0x08, 0x40)!=0) {
|
||||
RS41_DBG(Serial.println("Setting Packet config FAILED"));
|
||||
return 1;
|
||||
}
|
||||
Serial.print("RS41: setting RX frequency to ");
|
||||
Serial.println(frequency);
|
||||
int retval = sx1278.setFrequency(frequency);
|
||||
dpos = 0;
|
||||
|
||||
#if RS41_DEBUG
|
||||
RS41_DBG(Serial.println("Setting SX1278 config for RS41 finished\n"); Serial.println());
|
||||
#endif
|
||||
sx1278.clearIRQFlags();
|
||||
|
||||
// the following is already done in receivePacketTimeout()
|
||||
// sx1278.setPayloadLength(RS41MAXLEN-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
|
||||
// sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint32_t RS41::bits2val(const uint8_t *bits, int len) {
|
||||
uint32_t val = 0;
|
||||
for (int j = 0; j < len; j++) {
|
||||
val |= (bits[j] << (len-1-j));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
RS41::RS41() {
|
||||
}
|
||||
|
||||
/* RS41 reed solomon decoder, from dxlAPRS
|
||||
*/
|
||||
static int32_t reedsolomon41(byte buf[], uint32_t buf_len, uint32_t len2)
|
||||
{
|
||||
uint32_t i;
|
||||
int32_t res1;
|
||||
/*tb1, */
|
||||
int32_t res;
|
||||
char b1[256];
|
||||
char b[256];
|
||||
uint32_t eraspos[24];
|
||||
uint32_t tmp;
|
||||
for (i = 0UL; i<=255UL; i++) {
|
||||
b[i] = 0;
|
||||
b1[i] = 0;
|
||||
} /* end for */
|
||||
tmp = len2;
|
||||
i = 0UL;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
b[230UL-i] = buf[i*2UL+56UL];
|
||||
b1[230UL-i] = buf[i*2UL+57UL];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
for (i = 0UL; i<=23UL; i++) {
|
||||
b[254UL-i] = buf[i+8UL];
|
||||
b1[254UL-i] = buf[i+32UL];
|
||||
} /* end for */
|
||||
res = decodersc(b, eraspos, 0);
|
||||
res1 = decodersc(b1, eraspos, 0);
|
||||
if (res>0L && res<=12L) {
|
||||
tmp = len2;
|
||||
i = 0UL;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
buf[i*2UL+56UL] = b[230UL-i];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
for (i = 0UL; i<=23UL; i++) {
|
||||
buf[i+8UL] = b[254UL-i];
|
||||
} /* end for */
|
||||
}
|
||||
if (res1>0L && res1<=12L) {
|
||||
tmp = len2;
|
||||
i = 0UL;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
buf[i*2UL+57UL] = b1[230UL-i];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
for (i = 0UL; i<=23UL; i++) {
|
||||
buf[i+32UL] = b1[254UL-i];
|
||||
} /* end for */
|
||||
}
|
||||
if (res<0L || res1<0L) return -1L;
|
||||
else return res+res1;
|
||||
return 0;
|
||||
} /* end reedsolomon41() */
|
||||
|
||||
|
||||
|
||||
|
||||
static char crcrs(const byte frame[], uint32_t frame_len,
|
||||
int32_t from, int32_t to)
|
||||
{
|
||||
uint16_t crc;
|
||||
int32_t i;
|
||||
int32_t tmp;
|
||||
crc = 0xFFFFU;
|
||||
tmp = to-3L;
|
||||
i = from;
|
||||
if (i<=tmp) for (;; i++) {
|
||||
crc = X2C_LSH(crc,16,-8)^CRCTAB[(uint32_t)((crc^(uint16_t)(uint8_t)frame[i])&0xFFU)];
|
||||
if (i==tmp) break;
|
||||
} /* end for */
|
||||
return frame[to-1L]==(char)crc && frame[to-2L]==(char)X2C_LSH(crc,
|
||||
16,-8);
|
||||
} /* end crcrs() */
|
||||
|
||||
static int32_t getint32(const byte frame[], uint32_t frame_len,
|
||||
uint32_t p)
|
||||
{
|
||||
uint32_t n;
|
||||
uint32_t i;
|
||||
n = 0UL;
|
||||
for (i = 3UL;; i--) {
|
||||
n = n*256UL+(uint32_t)(uint8_t)frame[p+i];
|
||||
if (i==0UL) break;
|
||||
} /* end for */
|
||||
return (int32_t)n;
|
||||
} /* end getint32() */
|
||||
|
||||
|
||||
static uint32_t getcard16(const byte frame[], uint32_t frame_len,
|
||||
uint32_t p)
|
||||
{
|
||||
return (uint32_t)(uint8_t)frame[p]+256UL*(uint32_t)(uint8_t)
|
||||
frame[p+1UL];
|
||||
} /* end getcard16() */
|
||||
|
||||
|
||||
static int32_t getint16(const byte frame[], uint32_t frame_len,
|
||||
uint32_t p)
|
||||
{
|
||||
uint32_t n;
|
||||
n = (uint32_t)(uint8_t)frame[p]+256UL*(uint32_t)(uint8_t)
|
||||
frame[p+1UL];
|
||||
if (n>=32768UL) return (int32_t)(n-65536UL);
|
||||
return (int32_t)n;
|
||||
} /* end getint16() */
|
||||
|
||||
static void wgs84r(double x, double y, double z,
|
||||
double * lat, double * long0,
|
||||
double * heig)
|
||||
{
|
||||
double sl;
|
||||
double ct;
|
||||
double st;
|
||||
double t;
|
||||
double rh;
|
||||
double xh;
|
||||
double h;
|
||||
h = x*x+y*y;
|
||||
if (h>0.0) {
|
||||
rh = (double)sqrt((float)h);
|
||||
xh = x+rh;
|
||||
*long0 = atang2(xh, y)*2.0;
|
||||
if (*long0>3.1415926535898) *long0 = *long0-6.2831853071796;
|
||||
t = (double)atan((float)(X2C_DIVL(z*1.003364089821,
|
||||
rh)));
|
||||
st = (double)sin((float)t);
|
||||
ct = (double)cos((float)t);
|
||||
*lat = (double)atan((float)
|
||||
(X2C_DIVL(z+4.2841311513312E+4*st*st*st,
|
||||
rh-4.269767270718E+4*ct*ct*ct)));
|
||||
sl = (double)sin((float)*lat);
|
||||
*heig = X2C_DIVL(rh,(double)cos((float)*lat))-(double)(X2C_DIVR(6.378137E+6f,
|
||||
sqrt((float)(1.0-6.6943799901413E-3*sl*sl))));
|
||||
}
|
||||
else {
|
||||
*lat = 0.0;
|
||||
*long0 = 0.0;
|
||||
*heig = 0.0;
|
||||
}
|
||||
/* lat:=atan(z/(rh*(1.0 - E2))); */
|
||||
/* heig:=sqrt(h + z*z) - EARTHA; */
|
||||
} /* end wgs84r() */
|
||||
|
||||
// returns: 0=ok, -1=error
|
||||
static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
||||
{
|
||||
double dir;
|
||||
double vu;
|
||||
double ve;
|
||||
double vn;
|
||||
double vz;
|
||||
double vy;
|
||||
double vx;
|
||||
double heig;
|
||||
double long0;
|
||||
double lat;
|
||||
double z;
|
||||
double y;
|
||||
double x;
|
||||
x = (double)getint32(b, b_len, p)*0.01;
|
||||
y = (double)getint32(b, b_len, p+4UL)*0.01;
|
||||
z = (double)getint32(b, b_len, p+8UL)*0.01;
|
||||
wgs84r(x, y, z, &lat, &long0, &heig);
|
||||
Serial.print(" ");
|
||||
sonde.si()->lat = (float)(X2C_DIVL(lat,1.7453292519943E-2));
|
||||
Serial.print(sonde.si()->lat);
|
||||
Serial.print(" ");
|
||||
sonde.si()->lon = (float)(X2C_DIVL(long0,1.7453292519943E-2));
|
||||
Serial.print(sonde.si()->lon);
|
||||
if (heig<1.E+5 && heig>(-1.E+5)) {
|
||||
Serial.print(" ");
|
||||
Serial.print((uint32_t)heig);
|
||||
Serial.print("m");
|
||||
}
|
||||
/*speed */
|
||||
vx = (double)getint16(b, b_len, p+12UL)*0.01;
|
||||
vy = (double)getint16(b, b_len, p+14UL)*0.01;
|
||||
vz = (double)getint16(b, b_len, p+16UL)*0.01;
|
||||
vn = (-(vx*(double)sin((float)lat)*(double)
|
||||
cos((float)long0))-vy*(double)
|
||||
sin((float)lat)*(double)sin((float)
|
||||
long0))+vz*(double)cos((float)lat);
|
||||
ve = -(vx*(double)sin((float)long0))+vy*(double)
|
||||
cos((float)long0);
|
||||
vu = vx*(double)cos((float)lat)*(double)
|
||||
cos((float)long0)+vy*(double)
|
||||
cos((float)lat)*(double)sin((float)
|
||||
long0)+vz*(double)sin((float)lat);
|
||||
dir = X2C_DIVL(atang2(vn, ve),1.7453292519943E-2);
|
||||
if (dir<0.0) dir = 360.0+dir;
|
||||
sonde.si()->dir = dir;
|
||||
Serial.print(" ");
|
||||
sonde.si()->hs = sqrt((float)(vn*vn+ve*ve))*3.6f;
|
||||
Serial.print(sonde.si()->hs);
|
||||
Serial.print("km/h ");
|
||||
Serial.print(dir);
|
||||
Serial.print("deg ");
|
||||
Serial.print((float)vu);
|
||||
sonde.si()->vs = vu;
|
||||
Serial.print("m/s ");
|
||||
uint8_t sats = getcard16(b, b_len, p+18UL)&255UL;
|
||||
Serial.print(sats);
|
||||
Serial.print("Sats");
|
||||
sonde.si()->sats = sats;
|
||||
sonde.si()->alt = heig;
|
||||
if( 0==(int)(lat*10000) && 0==(int)(long0*10000) ) {
|
||||
if(sonde.si()->validPos) {
|
||||
// we have an old position, so keep previous position and mark it as old
|
||||
sonde.si()->validPos |= 0x80;
|
||||
}
|
||||
}
|
||||
else
|
||||
sonde.si()->validPos = 0x7f;
|
||||
} /* end posrs41() */
|
||||
|
||||
|
||||
|
||||
// returns: 0: ok, -1: rs or crc error
|
||||
int RS41::decode41(byte *data, int maxlen)
|
||||
{
|
||||
char buf[128];
|
||||
int crcok = 0;
|
||||
|
||||
int32_t corr = reedsolomon41(data, 560, 131); // try short frame first
|
||||
if(corr<0) {
|
||||
corr = reedsolomon41(data, 560, 230); // try long frame
|
||||
}
|
||||
#if 0
|
||||
Serial.print("RS result:");
|
||||
Serial.print(corr);
|
||||
Serial.println();
|
||||
#endif
|
||||
int p = 57; // 8 byte header, 48 byte RS
|
||||
while(p<maxlen) { /* why 555? */
|
||||
uint8_t typ = data[p++];
|
||||
uint32_t len = data[p++]+2UL;
|
||||
if(p+len>maxlen) break;
|
||||
|
||||
#if 0
|
||||
// DEBUG OUTPUT
|
||||
Serial.print("@");
|
||||
Serial.print(p-2);
|
||||
Serial.print(": ID:");
|
||||
Serial.print(typ, HEX);
|
||||
Serial.print(", len=");
|
||||
Serial.print(len);
|
||||
Serial.print(": ");
|
||||
for(int i=0; i<len-1; i++) {
|
||||
char buf[3];
|
||||
snprintf(buf, 4, "%02X|", data[p+i]);
|
||||
Serial.print(buf);
|
||||
}
|
||||
#endif
|
||||
// check CRC
|
||||
if(!crcrs(data, 560, p, p+len)) {
|
||||
Serial.println("###CRC ERROR###");
|
||||
} else {
|
||||
crcok = 1;
|
||||
switch(typ) {
|
||||
case 'y': // name
|
||||
{
|
||||
Serial.print("#");
|
||||
uint16_t fnr = data[p]+(data[p+1]<<8);
|
||||
Serial.print(fnr);
|
||||
sonde.si()->frame = fnr;
|
||||
Serial.print("; RS41 ID ");
|
||||
snprintf(buf, 10, "%.8s ", data+p+2);
|
||||
Serial.print(buf);
|
||||
sonde.si()->type=STYPE_RS41;
|
||||
strncpy(sonde.si()->id, (const char *)(data+p+2), 8);
|
||||
sonde.si()->id[8]=0;
|
||||
strncpy(sonde.si()->ser, (const char *)(data+p+2), 8);
|
||||
sonde.si()->ser[8]=0;
|
||||
sonde.si()->validID=true;
|
||||
int calnr = data[p+23];
|
||||
// not sure about this
|
||||
if(calnr==0x31) {
|
||||
uint16_t bt = data[p+30] + 256*data[p+31];
|
||||
sonde.si()->burstKT = bt;
|
||||
}
|
||||
// this should be right...
|
||||
if(calnr==0x02) {
|
||||
uint16_t kt = data[p+31] + 256*data[p+32];
|
||||
sonde.si()->launchKT = kt;
|
||||
}
|
||||
// and this seems fine as well...
|
||||
if(calnr==0x32) {
|
||||
uint16_t cntdown = data[p+24] + (data[p+25]<<8);
|
||||
uint16_t min = cntdown - (cntdown/3600)*3600;
|
||||
Serial.printf("Countdown value: %d\n [%2d:%02d:%02d]", cntdown, cntdown/3600, min/60, min-(min/60)*60);
|
||||
sonde.si()->countKT = cntdown;
|
||||
sonde.si()->crefKT = fnr;
|
||||
}
|
||||
}
|
||||
// TODO: some more data
|
||||
break;
|
||||
case '|': // date
|
||||
{
|
||||
uint32_t gpstime = getint32(data, 560, p+2);
|
||||
uint16_t gpsweek = getint16(data, 560, p);
|
||||
// UTC is GPSTIME - 18s (24*60*60-18 = 86382)
|
||||
// one week = 7*24*60*60 = 604800 seconds
|
||||
// unix epoch starts jan 1st 1970 0:00
|
||||
// gps time starts jan 6, 1980 0:00. thats 315964800 epoch seconds.
|
||||
// subtracting 86400 yields 315878400UL
|
||||
sonde.si()->time = (gpstime/1000) + 86382 + gpsweek*604800 + 315878400UL;
|
||||
sonde.si()->validTime = true;
|
||||
}
|
||||
break;
|
||||
case '{': // pos
|
||||
posrs41(data+p, len, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}}
|
||||
p += len;
|
||||
Serial.println();
|
||||
}
|
||||
return crcok ? 0 : -1;
|
||||
}
|
||||
void RS41::printRaw(uint8_t *data, int len)
|
||||
{
|
||||
char buf[3];
|
||||
int i;
|
||||
for(i=0; i<len; i++) {
|
||||
snprintf(buf, 3, "%02X", data[i]);
|
||||
Serial.print(buf);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void RS41::bitsToBytes(uint8_t *bits, uint8_t *bytes, int len)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<len*4; i++) {
|
||||
bytes[i/8] = (bytes[i/8]<<1) | (bits[i]?1:0);
|
||||
}
|
||||
bytes[(i-1)/8] &= 0x0F;
|
||||
}
|
||||
|
||||
static unsigned char lookup[16] = {
|
||||
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
|
||||
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
|
||||
|
||||
static uint8_t reverse(uint8_t n) {
|
||||
return (lookup[n&0x0f] << 4) | lookup[n>>4];
|
||||
}
|
||||
|
||||
|
||||
static uint8_t scramble[64] = {150U,131U,62U,81U,177U,73U,8U,152U,50U,5U,89U,
|
||||
14U,249U,68U,198U,38U,33U,96U,194U,234U,121U,93U,109U,161U,
|
||||
84U,105U,71U,12U,220U,232U,92U,241U,247U,118U,130U,127U,7U,
|
||||
153U,162U,44U,147U,124U,48U,99U,245U,16U,46U,97U,208U,188U,
|
||||
180U,182U,6U,170U,244U,35U,120U,110U,59U,174U,191U,123U,76U,
|
||||
193U};
|
||||
|
||||
|
||||
int RS41::receive() {
|
||||
sx1278.setPayloadLength(RS41MAXLEN-8);
|
||||
int e = sx1278.receivePacketTimeout(1000, data+8);
|
||||
if(e) { Serial.println("TIMEOUT"); return RX_TIMEOUT; }
|
||||
|
||||
for(int i=0; i<RS41MAXLEN; i++) { data[i] = reverse(data[i]); }
|
||||
for(int i=0; i<RS41MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
|
||||
return decode41(data, RS41MAXLEN);
|
||||
}
|
||||
|
||||
int RS41::waitRXcomplete() {
|
||||
// Currently not used. can be used for additinoal post-processing
|
||||
// (required for RS92 to avoid FIFO overrun in rx task)
|
||||
#if 0
|
||||
int res;
|
||||
uint32_t t0 = millis();
|
||||
while(rxtask.receiveResult<0 && millis()-t0 < 3000) { delay(50); }
|
||||
|
||||
if(rxtask.receiveResult<0 || rxtask.receiveResult==RX_TIMEOUT) {
|
||||
res = RX_TIMEOUT;
|
||||
} else if (rxtask.receiveResult==0) {
|
||||
res = RX_OK;
|
||||
} else {
|
||||
res = RX_ERROR;
|
||||
}
|
||||
rxtask.receiveResult = -1;
|
||||
Serial.printf("waitRXcomplete returning %d\n", res);
|
||||
return res;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
RS41 rs41 = RS41();
|
|
@ -1,113 +0,0 @@
|
|||
#include "Scanner.h"
|
||||
#include <SX1278FSK.h>
|
||||
#include <U8x8lib.h>
|
||||
|
||||
#include "Sonde.h"
|
||||
#include "Display.h"
|
||||
|
||||
#define CHANBW 10
|
||||
#define PIXSAMPL (50/CHANBW)
|
||||
#define SMOOTH 3
|
||||
//#define STARTF 401000000
|
||||
#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 scandisp[NCHAN/PIXSAMPL];
|
||||
|
||||
#define PLOT_N 128
|
||||
#define TICK1 (128/6)
|
||||
#define TICK2 (TICK1/4)
|
||||
//#define PLOT_MIN -250
|
||||
#define PLOT_MIN (sonde.config.noisefloor*2)
|
||||
#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 128 * 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]));
|
||||
if( ((i+j)%TICK1)==0) { row[j] |= 0x07; }
|
||||
if( ((i+j)%TICK2)==0) { row[j] |= 0x01; }
|
||||
}
|
||||
for(int y=0; y<8; y++) {
|
||||
if(sonde.config.marker && y==1) {
|
||||
// don't overwrite MHz marker text
|
||||
if(i<3*8 || (i>=7*8&&i<10*8) || i>=13*8) continue;
|
||||
}
|
||||
disp.rdis->drawTile(i/8, y, 1, row+8*y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scanner::scan()
|
||||
{
|
||||
// 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(20);
|
||||
|
||||
unsigned long start = millis();
|
||||
uint32_t lastfrf=-1;
|
||||
for(int iter=0; iter<2; iter++) { // two interations, to catch all RS41 transmissions
|
||||
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+5);
|
||||
int rssi = -(int)sx1278.readRegister(REG_RSSI_VALUE_FSK);
|
||||
if(iter==0) { scanresult[i] = rssi; } else {
|
||||
if(rssi>scanresult[i]) scanresult[i]=rssi;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned long duration = millis()-start;
|
||||
Serial.print("Scan time: ");
|
||||
Serial.println(duration);
|
||||
for(int i=0; i<NCHAN; i+=PIXSAMPL) {
|
||||
scandisp[i/PIXSAMPL]=scanresult[i];
|
||||
for(int j=1; j<PIXSAMPL; j++) { scandisp[i/PIXSAMPL]+=scanresult[i+j]; }
|
||||
//for(int j=1; j<PIXSAMPL; j++) { if(scanresult[i+j]>scandisp[i/PIXSAMPL]) scandisp[i/PIXSAMPL] = scanresult[i+j]; }
|
||||
Serial.print(scanresult[i]); Serial.print(", ");
|
||||
}
|
||||
Serial.println("\n");
|
||||
for(int i=0; i<NCHAN/PIXSAMPL; i++) {
|
||||
scandisp[i]/=PIXSAMPL;
|
||||
Serial.print(scandisp[i]); Serial.print(", ");
|
||||
}
|
||||
Serial.println("\n");
|
||||
}
|
||||
|
||||
Scanner scanner = Scanner();
|
File diff suppressed because it is too large
Load Diff
|
@ -1,468 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0
|
||||
// original source: https://github.com/Nkawu/TFT22_ILI9225
|
||||
|
||||
#ifndef TFT22_ILI9225_h
|
||||
#define TFT22_ILI9225_h
|
||||
|
||||
#ifdef __STM32F1__
|
||||
#define ARDUINO_STM32_FEATHER
|
||||
#define PROGMEM
|
||||
// if 'SPI_CHANNEL' is not defined, 'SPI' is used, only valid for STM32F1
|
||||
//#define SPI_CHANNEL SPI_2
|
||||
#endif
|
||||
|
||||
#define USE_STRING_CLASS
|
||||
|
||||
#ifdef USE_STRING_CLASS
|
||||
#define STRING String
|
||||
#else
|
||||
#define STRING const char *
|
||||
#endif
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#include <SPI.h>
|
||||
#include "gfxfont.h"
|
||||
|
||||
#if defined(ARDUINO_STM32_FEATHER) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) || defined(STM32F1)
|
||||
typedef volatile uint32 RwReg;
|
||||
#endif
|
||||
#if defined(ARDUINO_FEATHER52)
|
||||
typedef volatile uint32_t RwReg;
|
||||
#endif
|
||||
|
||||
/* ILI9225 screen size */
|
||||
#define ILI9225_LCD_WIDTH 176
|
||||
#define ILI9225_LCD_HEIGHT 220
|
||||
|
||||
/* ILI9225 LCD Registers */
|
||||
#define ILI9225_DRIVER_OUTPUT_CTRL (0x01u) // Driver Output Control
|
||||
#define ILI9225_LCD_AC_DRIVING_CTRL (0x02u) // LCD AC Driving Control
|
||||
#define ILI9225_ENTRY_MODE (0x03u) // Entry Mode
|
||||
#define ILI9225_DISP_CTRL1 (0x07u) // Display Control 1
|
||||
#define ILI9225_BLANK_PERIOD_CTRL1 (0x08u) // Blank Period Control
|
||||
#define ILI9225_FRAME_CYCLE_CTRL (0x0Bu) // Frame Cycle Control
|
||||
#define ILI9225_INTERFACE_CTRL (0x0Cu) // Interface Control
|
||||
#define ILI9225_OSC_CTRL (0x0Fu) // Osc Control
|
||||
#define ILI9225_POWER_CTRL1 (0x10u) // Power Control 1
|
||||
#define ILI9225_POWER_CTRL2 (0x11u) // Power Control 2
|
||||
#define ILI9225_POWER_CTRL3 (0x12u) // Power Control 3
|
||||
#define ILI9225_POWER_CTRL4 (0x13u) // Power Control 4
|
||||
#define ILI9225_POWER_CTRL5 (0x14u) // Power Control 5
|
||||
#define ILI9225_VCI_RECYCLING (0x15u) // VCI Recycling
|
||||
#define ILI9225_RAM_ADDR_SET1 (0x20u) // Horizontal GRAM Address Set
|
||||
#define ILI9225_RAM_ADDR_SET2 (0x21u) // Vertical GRAM Address Set
|
||||
#define ILI9225_GRAM_DATA_REG (0x22u) // GRAM Data Register
|
||||
#define ILI9225_GATE_SCAN_CTRL (0x30u) // Gate Scan Control Register
|
||||
#define ILI9225_VERTICAL_SCROLL_CTRL1 (0x31u) // Vertical Scroll Control 1 Register
|
||||
#define ILI9225_VERTICAL_SCROLL_CTRL2 (0x32u) // Vertical Scroll Control 2 Register
|
||||
#define ILI9225_VERTICAL_SCROLL_CTRL3 (0x33u) // Vertical Scroll Control 3 Register
|
||||
#define ILI9225_PARTIAL_DRIVING_POS1 (0x34u) // Partial Driving Position 1 Register
|
||||
#define ILI9225_PARTIAL_DRIVING_POS2 (0x35u) // Partial Driving Position 2 Register
|
||||
#define ILI9225_HORIZONTAL_WINDOW_ADDR1 (0x36u) // Horizontal Address Start Position
|
||||
#define ILI9225_HORIZONTAL_WINDOW_ADDR2 (0x37u) // Horizontal Address End Position
|
||||
#define ILI9225_VERTICAL_WINDOW_ADDR1 (0x38u) // Vertical Address Start Position
|
||||
#define ILI9225_VERTICAL_WINDOW_ADDR2 (0x39u) // Vertical Address End Position
|
||||
#define ILI9225_GAMMA_CTRL1 (0x50u) // Gamma Control 1
|
||||
#define ILI9225_GAMMA_CTRL2 (0x51u) // Gamma Control 2
|
||||
#define ILI9225_GAMMA_CTRL3 (0x52u) // Gamma Control 3
|
||||
#define ILI9225_GAMMA_CTRL4 (0x53u) // Gamma Control 4
|
||||
#define ILI9225_GAMMA_CTRL5 (0x54u) // Gamma Control 5
|
||||
#define ILI9225_GAMMA_CTRL6 (0x55u) // Gamma Control 6
|
||||
#define ILI9225_GAMMA_CTRL7 (0x56u) // Gamma Control 7
|
||||
#define ILI9225_GAMMA_CTRL8 (0x57u) // Gamma Control 8
|
||||
#define ILI9225_GAMMA_CTRL9 (0x58u) // Gamma Control 9
|
||||
#define ILI9225_GAMMA_CTRL10 (0x59u) // Gamma Control 10
|
||||
|
||||
#define ILI9225C_INVOFF 0x20
|
||||
#define ILI9225C_INVON 0x21
|
||||
|
||||
// autoincrement modes (register ILI9225_ENTRY_MODE, bit 5..3 )
|
||||
enum autoIncMode_t { R2L_BottomUp, BottomUp_R2L, L2R_BottomUp, BottomUp_L2R, R2L_TopDown, TopDown_R2L, L2R_TopDown, TopDown_L2R };
|
||||
|
||||
/* RGB 16-bit color table definition (RG565) */
|
||||
#define COLOR_BLACK 0x0000 /* 0, 0, 0 */
|
||||
#define COLOR_WHITE 0xFFFF /* 255, 255, 255 */
|
||||
#define COLOR_BLUE 0x001F /* 0, 0, 255 */
|
||||
#define COLOR_GREEN 0x07E0 /* 0, 255, 0 */
|
||||
#define COLOR_RED 0xF800 /* 255, 0, 0 */
|
||||
#define COLOR_NAVY 0x000F /* 0, 0, 128 */
|
||||
#define COLOR_DARKBLUE 0x0011 /* 0, 0, 139 */
|
||||
#define COLOR_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||
#define COLOR_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||
#define COLOR_CYAN 0x07FF /* 0, 255, 255 */
|
||||
#define COLOR_TURQUOISE 0x471A /* 64, 224, 208 */
|
||||
#define COLOR_INDIGO 0x4810 /* 75, 0, 130 */
|
||||
#define COLOR_DARKRED 0x8000 /* 128, 0, 0 */
|
||||
#define COLOR_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||
#define COLOR_GRAY 0x8410 /* 128, 128, 128 */
|
||||
#define COLOR_GREY 0x8410 /* 128, 128, 128 */
|
||||
#define COLOR_SKYBLUE 0x867D /* 135, 206, 235 */
|
||||
#define COLOR_BLUEVIOLET 0x895C /* 138, 43, 226 */
|
||||
#define COLOR_LIGHTGREEN 0x9772 /* 144, 238, 144 */
|
||||
#define COLOR_DARKVIOLET 0x901A /* 148, 0, 211 */
|
||||
#define COLOR_YELLOWGREEN 0x9E66 /* 154, 205, 50 */
|
||||
#define COLOR_BROWN 0xA145 /* 165, 42, 42 */
|
||||
#define COLOR_DARKGRAY 0x7BEF /* 128, 128, 128 */
|
||||
#define COLOR_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||
#define COLOR_SIENNA 0xA285 /* 160, 82, 45 */
|
||||
#define COLOR_LIGHTBLUE 0xAEDC /* 172, 216, 230 */
|
||||
#define COLOR_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||
#define COLOR_SILVER 0xC618 /* 192, 192, 192 */
|
||||
#define COLOR_LIGHTGRAY 0xC618 /* 192, 192, 192 */
|
||||
#define COLOR_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||
#define COLOR_LIGHTCYAN 0xE7FF /* 224, 255, 255 */
|
||||
#define COLOR_VIOLET 0xEC1D /* 238, 130, 238 */
|
||||
#define COLOR_AZUR 0xF7FF /* 240, 255, 255 */
|
||||
#define COLOR_BEIGE 0xF7BB /* 245, 245, 220 */
|
||||
#define COLOR_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||
#define COLOR_TOMATO 0xFB08 /* 255, 99, 71 */
|
||||
#define COLOR_GOLD 0xFEA0 /* 255, 215, 0 */
|
||||
#define COLOR_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||
#define COLOR_SNOW 0xFFDF /* 255, 250, 250 */
|
||||
#define COLOR_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||
|
||||
|
||||
/* Font defines */
|
||||
#define FONT_HEADER_SIZE 4 // 1: pixel width of 1 font character, 2: pixel height,
|
||||
#define readFontByte(x) pgm_read_byte(&cfont.font[x])
|
||||
|
||||
extern uint8_t Terminal6x8[];
|
||||
extern uint8_t Terminal11x16[];
|
||||
extern uint8_t Terminal12x16[];
|
||||
extern uint8_t Trebuchet_MS16x21[];
|
||||
|
||||
struct _currentFont
|
||||
{
|
||||
uint8_t* font;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t offset;
|
||||
uint8_t numchars;
|
||||
uint8_t nbrows;
|
||||
bool monoSp;
|
||||
};
|
||||
#define MONOSPACE 1
|
||||
|
||||
#if defined (ARDUINO_STM32_FEATHER)
|
||||
#undef USE_FAST_PINIO
|
||||
#elif defined (__AVR__) || defined(TEENSYDUINO) || defined(ESP8266) || defined(__arm__)
|
||||
#define USE_FAST_PINIO
|
||||
#endif
|
||||
|
||||
/// Main and core class
|
||||
class TFT22_ILI9225 {
|
||||
|
||||
public:
|
||||
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t SDI, int8_t CLK, int8_t LED);
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t LED);
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t SDI, int8_t CLK, int8_t LED, uint8_t brightness);
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t LED, uint8_t brightness);
|
||||
|
||||
/// Initialization
|
||||
#ifndef ESP32
|
||||
void begin(void);
|
||||
#else
|
||||
void begin(SPIClass &spi=SPI);
|
||||
#endif
|
||||
|
||||
/// Clear the screen
|
||||
void clear(void);
|
||||
|
||||
/// Invert screen
|
||||
/// @param flag true to invert, false for normal screen
|
||||
void invert(boolean flag);
|
||||
|
||||
/// Switch backlight on or off
|
||||
/// @param flag true=on, false=off
|
||||
void setBacklight(boolean flag);
|
||||
|
||||
/// Set backlight brightness
|
||||
/// @param brightness sets backlight brightness 0-255
|
||||
void setBacklightBrightness(uint8_t brightness);
|
||||
|
||||
/// Switch display on or off
|
||||
/// @param flag true=on, false=off
|
||||
void setDisplay(boolean flag);
|
||||
|
||||
/// Set orientation
|
||||
/// @param orientation orientation, 0=portrait, 1=right rotated landscape, 2=reverse portrait, 3=left rotated landscape
|
||||
void setOrientation(uint8_t orientation);
|
||||
|
||||
/// Get orientation
|
||||
/// @return orientation orientation, 0=portrait, 1=right rotated landscape, 2=reverse portrait, 3=left rotated landscape
|
||||
uint8_t getOrientation(void);
|
||||
|
||||
/// Font size, x-axis
|
||||
/// @return horizontal size of current font, in pixels
|
||||
// uint8_t fontX(void);
|
||||
|
||||
/// Font size, y-axis
|
||||
/// @return vertical size of current font, in pixels
|
||||
// uint8_t fontY(void);
|
||||
|
||||
/// Screen size, x-axis
|
||||
/// @return horizontal size of the screen, in pixels
|
||||
/// @note 240 means 240 pixels and thus 0..239 coordinates (decimal)
|
||||
uint16_t maxX(void);
|
||||
|
||||
/// Screen size, y-axis
|
||||
/// @return vertical size of the screen, in pixels
|
||||
/// @note 220 means 220 pixels and thus 0..219 coordinates (decimal)
|
||||
uint16_t maxY(void);
|
||||
|
||||
/// Draw circle
|
||||
/// @param x0 center, point coordinate, x-axis
|
||||
/// @param y0 center, point coordinate, y-axis
|
||||
/// @param radius radius
|
||||
/// @param color 16-bit color
|
||||
void drawCircle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t color);
|
||||
|
||||
/// Draw solid circle
|
||||
/// @param x0 center, point coordinate, x-axis
|
||||
/// @param y0 center, point coordinate, y-axis
|
||||
/// @param radius radius
|
||||
/// @param color 16-bit color
|
||||
void fillCircle(uint8_t x0, uint8_t y0, uint8_t radius, uint16_t color);
|
||||
|
||||
/// Set background color
|
||||
/// @param color background color, default=black
|
||||
void setBackgroundColor(uint16_t color = COLOR_BLACK);
|
||||
|
||||
/// Draw line, rectangle coordinates
|
||||
/// @param x1 start point coordinate, x-axis
|
||||
/// @param y1 start point coordinate, y-axis
|
||||
/// @param x2 end point coordinate, x-axis
|
||||
/// @param y2 end point coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
|
||||
|
||||
/// Draw rectangle, rectangle coordinates
|
||||
/// @param x1 top left coordinate, x-axis
|
||||
/// @param y1 top left coordinate, y-axis
|
||||
/// @param x2 bottom right coordinate, x-axis
|
||||
/// @param y2 bottom right coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
|
||||
|
||||
/// Draw solid rectangle, rectangle coordinates
|
||||
/// @param x1 top left coordinate, x-axis
|
||||
/// @param y1 top left coordinate, y-axis
|
||||
/// @param x2 bottom right coordinate, x-axis
|
||||
/// @param y2 bottom right coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void fillRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
|
||||
|
||||
/// Draw pixel
|
||||
/// @param x1 point coordinate, x-axis
|
||||
/// @param y1 point coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawPixel(uint16_t x1, uint16_t y1, uint16_t color);
|
||||
|
||||
/// Draw ASCII Text (pixel coordinates)
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param s text string
|
||||
/// @param color 16-bit color, default=white
|
||||
/// @return x-position behind text
|
||||
uint16_t drawText(uint16_t x, uint16_t y, STRING s, uint16_t color = COLOR_WHITE);
|
||||
|
||||
/// width of an ASCII Text (pixel )
|
||||
/// @param s text string
|
||||
uint16_t getTextWidth( STRING s ) ;
|
||||
|
||||
/// Calculate 16-bit color from 8-bit Red-Green-Blue components
|
||||
/// @param red red component, 0x00..0xff
|
||||
/// @param green green component, 0x00..0xff
|
||||
/// @param blue blue component, 0x00..0xff
|
||||
/// @return 16-bit color
|
||||
uint16_t setColor(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
/// Calculate 8-bit Red-Green-Blue components from 16-bit color
|
||||
/// @param rgb 16-bit color
|
||||
/// @param red red component, 0x00..0xff
|
||||
/// @param green green component, 0x00..0xff
|
||||
/// @param blue blue component, 0x00..0xff
|
||||
void splitColor(uint16_t rgb, uint8_t &red, uint8_t &green, uint8_t &blue);
|
||||
|
||||
/// Draw triangle, triangle coordinates
|
||||
/// @param x1 corner 1 coordinate, x-axis
|
||||
/// @param y1 corner 1 coordinate, y-axis
|
||||
/// @param x2 corner 2 coordinate, x-axis
|
||||
/// @param y2 corner 2 coordinate, y-axis
|
||||
/// @param x3 corner 3 coordinate, x-axis
|
||||
/// @param y3 corner 3 coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color);
|
||||
|
||||
/// Draw solid triangle, triangle coordinates
|
||||
/// @param x1 corner 1 coordinate, x-axis
|
||||
/// @param y1 corner 1 coordinate, y-axis
|
||||
/// @param x2 corner 2 coordinate, x-axis
|
||||
/// @param y2 corner 2 coordinate, y-axis
|
||||
/// @param x3 corner 3 coordinate, x-axis
|
||||
/// @param y3 corner 3 coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void fillTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color);
|
||||
|
||||
/// Set current font
|
||||
/// @param font Font name
|
||||
void setFont(uint8_t* font, bool monoSp=false ); // default = proportional
|
||||
|
||||
/// Get current font
|
||||
_currentFont getFont();
|
||||
|
||||
/// Draw single character (pixel coordinates)
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param ch ASCII character
|
||||
/// @param color 16-bit color, default=white
|
||||
/// @return width of character in display pixels
|
||||
uint16_t drawChar(uint16_t x, uint16_t y, uint16_t ch, uint16_t color = COLOR_WHITE);
|
||||
|
||||
/// width of an ASCII character (pixel )
|
||||
/// @param ch ASCII character
|
||||
uint16_t getCharWidth( uint16_t ch ) ;
|
||||
|
||||
/// Draw bitmap
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param bitmap
|
||||
/// @param w width
|
||||
/// @param h height
|
||||
/// @param color 16-bit color, default=white
|
||||
/// @param bg 16-bit color, background
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
|
||||
void drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
|
||||
/// Draw bitmap
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param bitmap, 2D 16bit color bitmap
|
||||
/// @param w width
|
||||
/// @param h height
|
||||
void drawBitmap(uint16_t x, uint16_t y, const uint16_t** bitmap, int16_t w, int16_t h);
|
||||
void drawBitmap(uint16_t x, uint16_t y, uint16_t** bitmap, int16_t w, int16_t h);
|
||||
|
||||
/// Draw bitmap
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param bitmap, 1D 16bit color bitmap
|
||||
/// @param w width
|
||||
/// @param h height
|
||||
void drawBitmap(uint16_t x, uint16_t y, const uint16_t* bitmap, int16_t w, int16_t h);
|
||||
void drawBitmap(uint16_t x, uint16_t y, uint16_t* bitmap, int16_t w, int16_t h);
|
||||
|
||||
/// Set current GFX font
|
||||
/// @param f GFX font name defined in include file
|
||||
void setGFXFont(const GFXfont *f = NULL);
|
||||
|
||||
/// Draw a string with the current GFX font
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param s string to print
|
||||
/// @param color 16-bit color
|
||||
void drawGFXText(int16_t x, int16_t y, STRING s, uint16_t color);
|
||||
|
||||
/// Get the width & height of a text string with the current GFX font
|
||||
/// @param str string to analyze
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param w width in pixels of string
|
||||
/// @param h height in pixels of string
|
||||
void getGFXTextExtent(STRING str, int16_t x, int16_t y, int16_t *w, int16_t *h);
|
||||
|
||||
/// Draw a single character with the current GFX font
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param c character to draw
|
||||
/// @param color 16-bit color
|
||||
/// @return width of character in display pixels
|
||||
uint16_t drawGFXChar(int16_t x, int16_t y, unsigned char c, uint16_t color);
|
||||
|
||||
uint16_t drawGFXcharBM(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t *bm, int bmwd);
|
||||
|
||||
void getGFXCharExtent(uint8_t c, int16_t *gw, int16_t *gh, int16_t *xa);
|
||||
|
||||
private:
|
||||
|
||||
void _spiWrite(uint8_t v);
|
||||
void _spiWrite16(uint16_t v);
|
||||
void _spiWriteCommand(uint8_t c);
|
||||
void _spiWriteData(uint8_t d);
|
||||
|
||||
void _swap(uint16_t &a, uint16_t &b);
|
||||
void _setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void _setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, autoIncMode_t mode);
|
||||
void _resetWindow();
|
||||
void _drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h,
|
||||
uint16_t color, uint16_t bg, bool transparent, bool progmem, bool Xbit );
|
||||
void _orientCoordinates(uint16_t &x1, uint16_t &y1);
|
||||
void _writeRegister(uint16_t reg, uint16_t data);
|
||||
void _writeData(uint8_t HI, uint8_t LO);
|
||||
void _writeData16(uint16_t HILO);
|
||||
void _writeCommand(uint8_t HI, uint8_t LO);
|
||||
void _writeCommand16(uint16_t HILO);
|
||||
uint16_t _maxX, _maxY, _bgColor;
|
||||
|
||||
#if defined (__AVR__) || defined(TEENSYDUINO)
|
||||
int8_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#ifdef USE_FAST_PINIO
|
||||
volatile uint8_t *mosiport, *clkport, *dcport, *rsport, *csport;
|
||||
uint8_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
#elif defined (__arm__)
|
||||
int32_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#ifdef USE_FAST_PINIO
|
||||
volatile RwReg *mosiport, *clkport, *dcport, *rsport, *csport;
|
||||
uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
#elif defined (ESP8266) || defined (ESP32)
|
||||
int8_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#ifdef USE_FAST_PINIO
|
||||
volatile uint32_t *mosiport, *clkport, *dcport, *rsport, *csport;
|
||||
uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
#else
|
||||
int8_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#endif
|
||||
|
||||
uint8_t _orientation, _brightness;
|
||||
|
||||
// correspondig modes if orientation changed:
|
||||
const autoIncMode_t modeTab [3][8] = {
|
||||
// { R2L_BottomUp, BottomUp_R2L, L2R_BottomUp, BottomUp_L2R, R2L_TopDown, TopDown_R2L, L2R_TopDown, TopDown_L2R }//
|
||||
/* 90° */ { BottomUp_L2R, L2R_BottomUp, TopDown_L2R, L2R_TopDown, BottomUp_R2L, R2L_BottomUp, TopDown_R2L, R2L_TopDown },
|
||||
/*180° */ { L2R_TopDown , TopDown_L2R, R2L_TopDown, TopDown_R2L, L2R_BottomUp, BottomUp_L2R, R2L_BottomUp, BottomUp_R2L},
|
||||
/*270° */ { TopDown_R2L , R2L_TopDown, BottomUp_R2L, R2L_BottomUp, TopDown_L2R, L2R_TopDown, BottomUp_L2R, L2R_BottomUp}
|
||||
};
|
||||
|
||||
|
||||
bool hwSPI, blState;
|
||||
|
||||
_currentFont cfont;
|
||||
|
||||
#ifdef ESP32
|
||||
SPIClass _spi;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
uint32_t writeFunctionLevel;
|
||||
void startWrite(void);
|
||||
void endWrite(void);
|
||||
|
||||
|
||||
GFXfont *gfxFont;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,124 +0,0 @@
|
|||
#include "FS.h"
|
||||
#include <SPIFFS.h>
|
||||
#include <WiFi.h>
|
||||
//Write data web
|
||||
|
||||
//Fonction
|
||||
void writedataweb(){
|
||||
|
||||
|
||||
String updateHost = "xavier.debert.free.fr";
|
||||
String updateDataWeb = "/RS/dataweb/index.html.txt";
|
||||
String *updateData = &updateDataWeb;
|
||||
String dispHost = updateHost.substring(0, 14);
|
||||
//disp.rdis->drawString(2, 0, dispHost.c_str());
|
||||
|
||||
Serial.println("Connecting to: " + updateHost);
|
||||
// Connect to Update host
|
||||
if (client.connect(updateHost.c_str(), updatePort)) {
|
||||
// Connection succeeded, fecthing the bin
|
||||
Serial.println("Fetching index.html: " + String(*updateData));
|
||||
|
||||
|
||||
// Get the contents of the bin file
|
||||
client.print(String("GET ") + *updateData + " HTTP/1.1\r\n" +
|
||||
"Host: " + updateHost + "\r\n" +
|
||||
"Cache-Control: no-cache\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
// Check what is being sent
|
||||
// Serial.print(String("GET ") + bin + " HTTP/1.1\r\n" +
|
||||
// "Host: " + host + "\r\n" +
|
||||
// "Cache-Control: no-cache\r\n" +
|
||||
// "Connection: close\r\n\r\n");
|
||||
|
||||
unsigned long timeout = millis();
|
||||
while (client.available() == 0) {
|
||||
if (millis() - timeout > 5000) {
|
||||
Serial.println("Client Timeout !");
|
||||
client.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Once the response is available,
|
||||
// check stuff
|
||||
|
||||
/*
|
||||
Response Structure
|
||||
HTTP/1.1 200 OK
|
||||
x-amz-id-2: NVKxnU1aIQMmpGKhSwpCBh8y2JPbak18QLIfE+OiUDOos+7UftZKjtCFqrwsGOZRN5Zee0jpTd0=
|
||||
x-amz-request-id: 2D56B47560B764EC
|
||||
Date: Wed, 14 Jun 2017 03:33:59 GMT
|
||||
Last-Modified: Fri, 02 Jun 2017 14:50:11 GMT
|
||||
ETag: "d2afebbaaebc38cd669ce36727152af9"
|
||||
Accept-Ranges: bytes
|
||||
Content-Type: application/octet-stream
|
||||
Content-Length: 357280
|
||||
Server: AmazonS3
|
||||
|
||||
{{BIN FILE CONTENTS}}
|
||||
|
||||
*/
|
||||
while (client.available()) {
|
||||
// read line till /n
|
||||
String line = client.readStringUntil('\n');
|
||||
// remove space, to check if the line is end of headers
|
||||
line.trim();
|
||||
|
||||
// if the the line is empty,
|
||||
// this is end of headers
|
||||
// break the while and feed the
|
||||
// remaining `client` to the
|
||||
// Update.writeStream();
|
||||
if (!line.length()) {
|
||||
//headers ended
|
||||
break; // and get the OTA started
|
||||
}
|
||||
|
||||
// Check if the HTTP Response is 200
|
||||
// else break and Exit Update
|
||||
if (line.startsWith("HTTP/1.1")) {
|
||||
if (line.indexOf("200") < 0) {
|
||||
Serial.println("Got a non 200 status code from server. error.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// extract headers here
|
||||
// Start with content length
|
||||
if (line.startsWith("Content-Length: ")) {
|
||||
contentLength = atoi((getHeaderValue(line, "Content-Length: ")).c_str());
|
||||
Serial.println("Got " + String(contentLength) + " bytes from server");
|
||||
}
|
||||
|
||||
// Next, the content type
|
||||
if (line.startsWith("Content-Type: ")) {
|
||||
String contentType = getHeaderValue(line, "Content-Type: ");
|
||||
Serial.println("Got " + contentType + " payload.");
|
||||
if (contentType == "application/text") {
|
||||
isValidContentType = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Connect to updateHost failed
|
||||
// May be try?
|
||||
// Probably a choppy network?
|
||||
Serial.println("Connection to " + String(updateHost) + " failed. Please check your setup");
|
||||
// retry??
|
||||
// execOTA();
|
||||
}
|
||||
|
||||
/*
|
||||
Serial.printf("\nDataWeb On\n");
|
||||
//open file for appending new blank line to EOF.
|
||||
File f = SPIFFS.open("/data.html", "w");
|
||||
|
||||
f.println("<html><body>TEST de DATAWeb1</body></html>");
|
||||
|
||||
f.close();
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
void geteph();
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
#include <FS.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <SD_MMC.h> // (or SD_MMC.h)
|
||||
|
||||
|
||||
void transfert_sd() {
|
||||
|
||||
if (!SD_MMC.begin()) {
|
||||
Serial.println("Carte SD introuvable");
|
||||
|
||||
}
|
||||
else{
|
||||
Serial.println("Carte SD détectée");
|
||||
sonde.clearDisplay();
|
||||
disp.rdis->drawString(0, 2, "Carte SD On");
|
||||
disp.rdis->drawString(0, 4, "Transfert Data");
|
||||
File sourceFile = SPIFFS.open("/data.csv", "r");
|
||||
File destFile = SD_MMC.open("/data.csv","w");
|
||||
|
||||
static uint8_t tanpon[512];
|
||||
while( sourceFile.read( tanpon, 512) ) {
|
||||
destFile.write( tanpon, 512 );
|
||||
}
|
||||
destFile.close();
|
||||
sourceFile.close();
|
||||
delay(1000);
|
||||
//sonde.updateDisplay();
|
||||
sonde.clearDisplay();
|
||||
disp.rdis->drawString(0, 2, "Sortir SD");
|
||||
disp.rdis->drawString(0, 4, "Reboot 5s");
|
||||
delay(5000);
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user