partial TFT (ILI9225) support; web/data: only show active frequence

This commit is contained in:
Hansi, dl9rdz 2019-09-29 15:50:35 +02:00
parent 079cb4980d
commit f6cdf342cc
10 changed files with 295 additions and 140 deletions

View File

@ -2,8 +2,8 @@
#include <WiFiUdp.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <U8x8lib.h>
#include <U8g2lib.h>
//#include <U8x8lib.h>
//#include <U8g2lib.h>
#include <SPI.h>
#include <Update.h>
#include <ESPmDNS.h>
@ -19,12 +19,6 @@
#include "geteph.h"
#include "rs92gps.h"
// UNCOMMENT one of the constructor lines below
U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8 = NULL; // initialize later after reading config file
//U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Unbuffered, basic graphics, software I2C
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C Display(U8G2_R0, /* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Page buffer, SW I2C
//U8G2_SSD1306_128X64_NONAME_F_SW_I2C Display(U8G2_R0, /* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Full framebuffer, SW I2C
int LORA_LED = 9; // default POUT for LORA LED used as serial monitor
int e;
@ -49,7 +43,6 @@ WiFiClient client;
WiFiServer tncserver(14580);
WiFiClient tncclient;
enum KeyPress { KP_NONE = 0, KP_SHORT, KP_DOUBLE, KP_MID, KP_LONG };
// "doublepress" is now also used to eliminate key glitch on TTGO T-Beam startup (SENSOR_VN/GPIO39)
@ -351,7 +344,10 @@ const char *createStatusForm() {
strcpy(ptr, "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"><meta http-equiv=\"refresh\" content=\"5\"></head><body>");
for (int i = 0; i < sonde.nSonde; i++) {
addSondeStatus(ptr, (i + sonde.currentSonde) % sonde.nSonde);
int snum = (i + sonde.currentSonde) % sonde.nSonde;
if (sonde.sondeList[snum].active) {
addSondeStatus(ptr, snum);
}
}
strcat(ptr, "</body></html>");
return message;
@ -427,9 +423,12 @@ struct st_configitems config_list[] = {
{"dfm.rxbw", "DFM6/9 RX bandwidth", 0, &sonde.config.dfm.rxbw},
{"---", "---", -1, NULL},
/* Hardware dependeing settings */
{"oled_sda", "OLED SDA (needs reboot)", 0, &sonde.config.oled_sda},
{"oled_scl", "OLED SCL (needs reboot)", 0, &sonde.config.oled_scl},
{"oled_rst", "OLED RST (needs reboot)", 0, &sonde.config.oled_rst},
{"disptype", "Display type (0=OLED, 1=TFT/ILI9225)", 0, &sonde.config.disptype},
{"oled_sda", "OLED/TFT SDA (needs reboot)", 0, &sonde.config.oled_sda},
{"oled_scl", "OLED SCL/TFT CLK (needs reboot)", 0, &sonde.config.oled_scl},
{"oled_rst", "OLED/TFT RST (needs reboot)", 0, &sonde.config.oled_rst},
{"tft_rs", "TFT RS (needs reboot)", 0, &sonde.config.tft_rs},
{"tft_cs", "TFT CS (needs reboot)", 0, &sonde.config.tft_cs},
{"button_pin", "Button input port (needs reboot)", -4, &sonde.config.button_pin},
{"button2_pin", "Button 2 input port (needs reboot)", -4, &sonde.config.button2_pin},
{"touch_thresh", "Touch button threshold (needs reboot)", 0, &sonde.config.touch_thresh},
@ -1090,18 +1089,16 @@ void setup()
}
initTouch();
u8x8 = new U8X8_SSD1306_128X64_NONAME_SW_I2C(/* clock=*/ sonde.config.oled_scl, /* data=*/ sonde.config.oled_sda, /* reset=*/ sonde.config.oled_rst); // Unbuffered, basic graphics, software I2C
u8x8->begin();
disp.init();
delay(100);
disp.rdis->clear();
u8x8->clear();
u8x8->setFont(u8x8_font_7x14_1x2_r);
u8x8->drawString(8 - strlen(version_name) / 2, 1, version_name);
u8x8->drawString(8 - strlen(version_id) / 2, 3, version_id);
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->drawString(0, 5, "by Hansi, DL9RDZ");
u8x8->drawString(1, 6, "Mods by DL2MF");
disp.rdis->setFont(FONT_LARGE);
disp.rdis->drawString(8 - strlen(version_name) / 2, 1, version_name);
disp.rdis->drawString(8 - strlen(version_id) / 2, 3, version_id);
disp.rdis->setFont(FONT_SMALL);
disp.rdis->drawString(0, 5, "by Hansi, DL9RDZ");
disp.rdis->drawString(1, 6, "Mods by DL2MF");
delay(3000);
sonde.clearDisplay();
@ -1115,38 +1112,38 @@ void setup()
// == show initial values from config.txt ========================= //
if (sonde.config.debug == 1) {
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->drawString(0, 0, "Config:");
disp.rdis->setFont(FONT_SMALL);
disp.rdis->drawString(0, 0, "Config:");
delay(500);
itoa(sonde.config.oled_sda, buf, 10);
u8x8->drawString(0, 1, " SDA:");
u8x8->drawString(6, 1, buf);
disp.rdis->drawString(0, 1, " SDA:");
disp.rdis->drawString(6, 1, buf);
delay(500);
itoa(sonde.config.oled_scl, buf, 10);
u8x8->drawString(0, 2, " SCL:");
u8x8->drawString(6, 2, buf);
disp.rdis->drawString(0, 2, " SCL:");
disp.rdis->drawString(6, 2, buf);
delay(500);
itoa(sonde.config.oled_rst, buf, 10);
u8x8->drawString(0, 3, " RST:");
u8x8->drawString(6, 3, buf);
disp.rdis->drawString(0, 3, " RST:");
disp.rdis->drawString(6, 3, buf);
delay(1000);
itoa(sonde.config.led_pout, buf, 10);
u8x8->drawString(0, 4, " LED:");
u8x8->drawString(6, 4, buf);
disp.rdis->drawString(0, 4, " LED:");
disp.rdis->drawString(6, 4, buf);
delay(500);
itoa(sonde.config.spectrum, buf, 10);
u8x8->drawString(0, 5, " SPEC:");
u8x8->drawString(6, 5, buf);
disp.rdis->drawString(0, 5, " SPEC:");
disp.rdis->drawString(6, 5, buf);
delay(500);
itoa(sonde.config.maxsonde, buf, 10);
u8x8->drawString(0, 6, " MAX:");
u8x8->drawString(6, 6, buf);
disp.rdis->drawString(0, 6, " MAX:");
disp.rdis->drawString(6, 6, buf);
delay(5000);
sonde.clearDisplay();
@ -1229,7 +1226,7 @@ void enterMode(int mode) {
if (mainState == ST_SPECTRUM) {
Serial.println("Entering ST_SPECTRUM mode");
sonde.clearDisplay();
u8x8->setFont(u8x8_font_chroma48medium8_r);
disp.rdis->setFont(FONT_SMALL);
specTimer = millis();
//scanner.init();
} else if (mainState == ST_WIFISCAN) {
@ -1288,14 +1285,14 @@ void loopDecoder() {
if (!tncclient.connected()) {
Serial.println("TNC client not connected");
tncclient = tncserver.available();
if(tncclient.connected()) {
if (tncclient.connected()) {
Serial.println("new TCP KISS connection");
}
}
if (tncclient.available()) {
Serial.print("TCP KISS socket: recevied ");
while (tncclient.available()) {
Serial.print(tncclient.read()); // Check if we receive anything from Bluetooth
Serial.print(tncclient.read()); // Check if we receive anything from from APRSdroid
}
Serial.println("");
}
@ -1316,12 +1313,12 @@ void loopDecoder() {
udp.write((const uint8_t *)raw, rawlen);
udp.endPacket();
}
if(tncclient.connected()) {
Serial.println("Sending position via TCP");
char raw[201];
int rawlen = aprsstr_mon2kiss(str, raw, APRS_MAXLEN);
Serial.print("sending: "); Serial.println(raw);
tncclient.write(raw, rawlen);
if (tncclient.connected()) {
Serial.println("Sending position via TCP");
char raw[201];
int rawlen = aprsstr_mon2kiss(str, raw, APRS_MAXLEN);
Serial.print("sending: "); Serial.println(raw);
tncclient.write(raw, rawlen);
}
}
}
@ -1354,10 +1351,10 @@ void loopSpectrum() {
scanner.plotResult();
if (sonde.config.marker != 0) {
itoa((sonde.config.startfreq), buf, 10);
u8x8->drawString(0, 1, buf);
u8x8->drawString(7, 1, "MHz");
disp.rdis->drawString(0, 1, buf);
disp.rdis->drawString(7, 1, "MHz");
itoa((sonde.config.startfreq + 6), buf, 10);
u8x8->drawString(13, 1, buf);
disp.rdis->drawString(13, 1, buf);
}
if (sonde.config.timer) {
int remaining = sonde.config.spectrum - (millis() - specTimer) / 1000;
@ -1366,8 +1363,8 @@ void loopSpectrum() {
if (sonde.config.marker != 0) {
marker = 1;
}
u8x8->drawString(0, 1 + marker, buf);
u8x8->drawString(2, 1 + marker, "Sec.");
disp.rdis->drawString(0, 1 + marker, buf);
disp.rdis->drawString(2, 1 + marker, "Sec.");
if (remaining <= 0) {
currentDisplay = 0;
enterMode(ST_DECODER);
@ -1377,8 +1374,8 @@ void loopSpectrum() {
void startSpectrumDisplay() {
sonde.clearDisplay();
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->drawString(0, 0, "Spectrum Scan...");
disp.rdis->setFont(FONT_SMALL);
disp.rdis->drawString(0, 0, "Spectrum Scan...");
delay(500);
enterMode(ST_SPECTRUM);
}
@ -1649,8 +1646,8 @@ void loopWifiScan() {
return;
}
// wifi==3 => original mode with non-async wifi setup
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->drawString(0, 0, "WiFi Scan...");
disp.rdis->setFont(FONT_SMALL);
disp.rdis->drawString(0, 0, "WiFi Scan...");
int line = 0;
int cnt = 0;
@ -1663,7 +1660,7 @@ void loopWifiScan() {
Serial.print("Network name: ");
String ssid = WiFi.SSID(i);
Serial.println(ssid);
u8x8->drawString(0, 1 + line, ssid.c_str());
disp.rdis->drawString(0, 1 + line, ssid.c_str());
line = (line + 1) % 5;
Serial.print("Signal strength: ");
Serial.println(WiFi.RSSI(i));
@ -1683,8 +1680,8 @@ void loopWifiScan() {
Serial.print("Connecting to: "); Serial.print(fetchWifiSSID(index));
Serial.print(" with password "); Serial.println(fetchWifiPw(index));
u8x8->drawString(0, 6, "Conn:");
u8x8->drawString(6, 6, fetchWifiSSID(index));
disp.rdis->drawString(0, 6, "Conn:");
disp.rdis->drawString(6, 6, fetchWifiSSID(index));
WiFi.begin(fetchWifiSSID(index), fetchWifiPw(index));
while (WiFi.status() != WL_CONNECTED && cnt < MAXWIFIDELAY) {
delay(500);
@ -1698,7 +1695,7 @@ void loopWifiScan() {
Serial.print(" with password "); Serial.println(fetchWifiPw(index));
delay(500);
}
u8x8->drawString(15, 7, _scan[cnt & 1]);
disp.rdis->drawString(15, 7, _scan[cnt & 1]);
cnt++;
}
}
@ -1709,8 +1706,8 @@ void loopWifiScan() {
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
u8x8->drawString(0, 6, "AP: ");
u8x8->drawString(6, 6, networks[0].id.c_str());
disp.rdis->drawString(0, 6, "AP: ");
disp.rdis->drawString(6, 6, networks[0].id.c_str());
delay(3000);
} else {
Serial.println("");
@ -1756,17 +1753,17 @@ void execOTA() {
int contentLength = 0;
bool isValidContentType = false;
sonde.clearDisplay();
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->drawString(0, 0, "C:");
disp.rdis->setFont(FONT_SMALL);
disp.rdis->drawString(0, 0, "C:");
String dispHost = updateHost.substring(0, 14);
u8x8->drawString(2, 0, dispHost.c_str());
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 bin: " + String(*updateBin));
u8x8->drawString(0, 1, "Fetching update");
disp.rdis->drawString(0, 1, "Fetching update");
// Get the contents of the bin file
client.print(String("GET ") + *updateBin + " HTTP/1.1\r\n" +
@ -1859,22 +1856,22 @@ void execOTA() {
// Check what is the contentLength and if content type is `application/octet-stream`
Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType));
u8x8->drawString(0, 2, "Len: ");
disp.rdis->drawString(0, 2, "Len: ");
String cls = String(contentLength);
u8x8->drawString(5, 2, cls.c_str());
disp.rdis->drawString(5, 2, cls.c_str());
// check contentLength and content type
if (contentLength && isValidContentType) {
// Check if there is enough to OTA Update
bool canBegin = Update.begin(contentLength);
u8x8->drawString(0, 4, "Starting update");
disp.rdis->drawString(0, 4, "Starting update");
// If yes, begin
if (canBegin) {
Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!");
// No activity would appear on the Serial monitor
// So be patient. This may take 2 - 5mins to complete
u8x8->drawString(0, 5, "Please wait!");
disp.rdis->drawString(0, 5, "Please wait!");
size_t written = Update.writeStream(client);
if (written == contentLength) {
@ -1889,7 +1886,7 @@ void execOTA() {
Serial.println("OTA done!");
if (Update.isFinished()) {
Serial.println("Update successfully completed. Rebooting.");
u8x8->drawString(0, 7, "Rebooting....");
disp.rdis->drawString(0, 7, "Rebooting....");
delay(1000);
ESP.restart();
} else {

View File

@ -12,10 +12,17 @@ led_pout=9
# OLED Setup is depending on hardware of LoRa board
# TTGO v1: SDA=4 SCL=15, RST=16
# TTGO v2: SDA=21 SCL=22, RST=16
# T-BEAM, OLED: SDA=21, SCL=22, RST=16
# T-BEAM, ILI9225: SDA=4, CLK=21, RS=2, RST=22, CS=0
# No specification in config file: try autodetection (gpio4 pin level at startup)
#
# disptype: 0=OLED, 1=ILI9225
#disptype=0
#oled_sda=21
#oled_scl=22
oled_rst=16
#oled_rst=16
#tft_rs=2
#tft_cs=0
#gps_rxd=-1
gps_txd=-1
#-------------------------------#

View File

@ -1,2 +1,2 @@
const char *version_name = "RDZ_TTGO_SONDE";
const char *version_id = "devel20190911";
const char *version_id = "devel20190929";

View File

@ -6,10 +6,13 @@
#include "Display.h"
#include "Sonde.h"
#include <../fonts/FreeSans9pt7b.h>
#include <../fonts/FreeSans12pt7b.h>
extern Sonde sonde;
extern MicroNMEA nmea;
extern U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8;
const char *sondeTypeStr[5] = { "DFM6", "DFM9", "RS41", "RS92" };
@ -59,7 +62,6 @@ static uint8_t nogps_tile[8]={0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00};
static uint8_t deg_tile[8]={0x00, 0x06,0x09, 0x09, 0x06, 0x00, 0x00, 0x00};
#define SETFONT(large) u8x8->setFont((large)?u8x8_font_7x14_1x2_r:u8x8_font_chroma48medium8_r);
/* Description of display layouts.
* for each display, the content is described by a DispEntry structure
@ -162,8 +164,98 @@ DispInfo staticLayouts[5] = {
DispInfo *layouts = staticLayouts;
/////////////// Wrapper code for various display
void U8x8Display::begin() {
u8x8 = new U8X8_SSD1306_128X64_NONAME_SW_I2C(/* clock=*/ sonde.config.oled_scl, /* data=*/ sonde.config.oled_sda, /* reset=*/ sonde.config.oled_rst); // Unbuffered, basic graphics, software I2C
u8x8->begin();
}
void U8x8Display::clear() {
u8x8->clear();
}
// For u8x8 oled display: 0=small font, 1=large font 7x14
void U8x8Display::setFont(int large) {
u8x8->setFont((large)?u8x8_font_7x14_1x2_r:u8x8_font_chroma48medium8_r);
}
void U8x8Display::drawString(uint8_t x, uint8_t y, const char *s) {
u8x8->drawString(x, y, s);
}
void U8x8Display::drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) {
u8x8->drawTile(x, y, cnt, tile_ptr);
}
#define TFT_LED 0 // 0 if wired to +5V directly
#define TFT_BRIGHTNESS 100 // Initial brightness of TFT backlight (optional)
void ILI9225Display::begin() {
tft = new TFT_22_ILI9225(sonde.config.oled_rst, sonde.config.tft_rs, sonde.config.tft_cs,
sonde.config.oled_sda, sonde.config.oled_scl, TFT_LED, TFT_BRIGHTNESS);
tft->begin();
tft->setOrientation(1);
}
void ILI9225Display::clear() {
tft->clear();
}
// for now, 0=small=FreeSans9pt7b, 1=large=FreeSans18pt7b
void ILI9225Display::setFont(int large) {
tft->setGFXFont(large ? &FreeSans12pt7b : &FreeSans9pt7b);
//tft->setFont(large?Terminal12x16: Terminal6x8);
yofs = 0;
}
void ILI9225Display::drawString(uint8_t x, uint8_t y, const char *s) {
int16_t w,h;
tft->getGFXTextExtent(s, x*14, y*14, &w, &h);
tft->fillRectangle(x*14, y*14, x*14+w, y*14+h, COLOR_BLACK);
tft->drawGFXText(x*14, y*14+h, s, COLOR_WHITE);
//tft->drawText(x*12, y*12, s, COLOR_WHITE);
}
void ILI9225Display::drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) {
int i,j;
for(int i=0; i<cnt*8; i++) {
uint8_t v = tile_ptr[i];
for(j=0; j<8; j++) {
tft->drawPixel(8*x+i, 8*y+j, (v&0x01) ? COLOR_GREEN:COLOR_BLUE);
v >>= 1;
}
}
//tft->drawBitmap(x*8, y*8, tile_ptr, cnt*8, 8, COLOR_RED, COLOR_BLUE);
//???u8x8->drawTile(x, y, cnt, tile_ptr);
}
///////////////
char Display::buf[17];
RawDisplay *Display::rdis = NULL;
//TODO: maybe merge with initFromFile later?
void Display::init() {
if(sonde.config.disptype==1) {
rdis = new ILI9225Display();
} else {
rdis = new U8x8Display();
}
Serial.println("Display created");
rdis->begin();
delay(100);
Serial.println("Display initialized");
rdis->clear();
}
Display::Display() {
setLayout(0);
}
@ -372,85 +464,85 @@ void Display::setLayout(int layoutIdx) {
}
void Display::drawLat(DispEntry *de) {
SETFONT(de->fmt);
rdis->setFont(de->fmt);
if(!sonde.si()->validPos) {
u8x8->drawString(de->x,de->y,"<?""?> ");
rdis->drawString(de->x,de->y,"<?""?> ");
return;
}
snprintf(buf, 16, "%2.5f", sonde.si()->lat);
u8x8->drawString(de->x,de->y,buf);
rdis->drawString(de->x,de->y,buf);
}
void Display::drawLon(DispEntry *de) {
SETFONT(de->fmt);
rdis->setFont(de->fmt);
if(!sonde.si()->validPos) {
u8x8->drawString(de->x,de->y,"<?""?> ");
rdis->drawString(de->x,de->y,"<?""?> ");
return;
}
snprintf(buf, 16, "%2.5f", sonde.si()->lon);
u8x8->drawString(de->x,de->y,buf);
rdis->drawString(de->x,de->y,buf);
}
void Display::drawAlt(DispEntry *de) {
SETFONT(de->fmt);
rdis->setFont(de->fmt);
if(!sonde.si()->validPos) {
u8x8->drawString(de->x,de->y," ");
rdis->drawString(de->x,de->y," ");
return;
}
snprintf(buf, 16, sonde.si()->alt>=1000?" %5.0fm":" %3.1fm", sonde.si()->alt);
u8x8->drawString(de->x,de->y,buf+strlen(buf)-6);
rdis->drawString(de->x,de->y,buf+strlen(buf)-6);
}
void Display::drawHS(DispEntry *de) {
SETFONT(de->fmt);
rdis->setFont(de->fmt);
if(!sonde.si()->validPos) {
u8x8->drawString(de->x,de->y," ");
rdis->drawString(de->x,de->y," ");
return;
}
snprintf(buf, 16, sonde.si()->hs>99?" %3.0f":" %2.1f", sonde.si()->hs);
u8x8->drawString(de->x,de->y,buf+strlen(buf)-4);
u8x8->drawTile(de->x+4,de->y,2,kmh_tiles);
rdis->drawString(de->x,de->y,buf+strlen(buf)-4);
rdis->drawTile(de->x+4,de->y,2,kmh_tiles);
}
void Display::drawVS(DispEntry *de) {
SETFONT(de->fmt);
rdis->setFont(de->fmt);
if(!sonde.si()->validPos) {
u8x8->drawString(de->x,de->y," ");
rdis->drawString(de->x,de->y," ");
return;
}
snprintf(buf, 16, " %+2.1f", sonde.si()->vs);
u8x8->drawString(de->x, de->y, buf+strlen(buf)-5);
u8x8->drawTile(de->x+5,de->y,2,ms_tiles);
rdis->drawString(de->x, de->y, buf+strlen(buf)-5);
rdis->drawTile(de->x+5,de->y,2,ms_tiles);
}
void Display::drawID(DispEntry *de) {
SETFONT((de->fmt&0x01));
rdis->setFont(de->fmt);
if(!sonde.si()->validID) {
u8x8->drawString(de->x, de->y, "nnnnnnnn ");
rdis->drawString(de->x, de->y, "nnnnnnnn ");
return;
}
// TODO: handle DFM6 IDs
if(!de->extra || de->extra[0]=='s') {
// real serial number, as printed on sonde
u8x8->drawString(de->x, de->y, sonde.si()->id);
rdis->drawString(de->x, de->y, sonde.si()->id);
} else if (de->extra[0]=='a') {
// autorx sonde number ("DF9" and last 6 digits of real serial number
strcpy(buf, sonde.si()->id);
memcpy(buf, "DF9", 3);
u8x8->drawString(de->x, de->y, buf);
rdis->drawString(de->x, de->y, buf);
} else {
// dxlAPRS sonde number (DF6 (why??) and 5 last digits of serial number as hex number
uint32_t id = atoi(sonde.si()->id);
id = id&0xfffff;
snprintf(buf, 16, "DF6%05X", id);
u8x8->drawString(de->x, de->y, buf);
rdis->drawString(de->x, de->y, buf);
}
}
void Display::drawRSSI(DispEntry *de) {
SETFONT(de->fmt);
rdis->setFont(de->fmt);
snprintf(buf, 16, "-%d ", sonde.si()->rssi/2);
int len=strlen(buf)-3;
Serial.printf("drawRSSI: %d %d %d (%d)[%d]\n", de->y, de->x, sonde.si()->rssi/2, sonde.currentSonde, len);
buf[5]=0;
u8x8->drawString(de->x,de->y,buf);
u8x8->drawTile(de->x+len, de->y, 1, (sonde.si()->rssi&1)?halfdb_tile1:empty_tile1);
u8x8->drawTile(de->x+len, de->y+1, 1, (sonde.si()->rssi&1)?halfdb_tile2:empty_tile2);
rdis->drawString(de->x,de->y,buf);
rdis->drawTile(de->x+len, de->y, 1, (sonde.si()->rssi&1)?halfdb_tile1:empty_tile1);
rdis->drawTile(de->x+len, de->y+1, 1, (sonde.si()->rssi&1)?halfdb_tile2:empty_tile2);
}
void Display::drawQS(DispEntry *de) {
uint8_t *stat = sonde.si()->rxStat;
@ -458,32 +550,32 @@ void Display::drawQS(DispEntry *de) {
uint8_t tile[8];
*(uint32_t *)(&tile[0]) = *(uint32_t *)(&(stattiles[stat[i]]));
*(uint32_t *)(&tile[4]) = *(uint32_t *)(&(stattiles[stat[i+1]]));
u8x8->drawTile(de->x+i/2, de->y, 1, tile);
rdis->drawTile(de->x+i/2, de->y, 1, tile);
}
}
void Display::drawType(DispEntry *de) {
SETFONT(de->fmt);
u8x8->drawString(de->x, de->y, sondeTypeStr[sonde.si()->type]);
rdis->setFont(de->fmt);
rdis->drawString(de->x, de->y, sondeTypeStr[sonde.si()->type]);
}
void Display::drawFreq(DispEntry *de) {
SETFONT(de->fmt);
rdis->setFont(de->fmt);
snprintf(buf, 16, "%3.3f%s", sonde.si()->freq, de->extra?de->extra:"");
u8x8->drawString(de->x, de->y, buf);
rdis->drawString(de->x, de->y, buf);
}
void Display::drawAFC(DispEntry *de) {
if(!sonde.config.showafc) return;
SETFONT(de->fmt);
rdis->setFont(de->fmt);
if(sonde.si()->afc==0) { strcpy(buf, " "); }
else { snprintf(buf, 15, " %+3.2fk", sonde.si()->afc*0.001); }
u8x8->drawString(de->x, de->y, buf+strlen(buf)-8);
rdis->drawString(de->x, de->y, buf+strlen(buf)-8);
}
void Display::drawIP(DispEntry *de) {
u8x8->drawTile(de->x, de->y, 11, myIP_tiles);
rdis->drawTile(de->x, de->y, 11, myIP_tiles);
}
void Display::drawSite(DispEntry *de) {
SETFONT(de->fmt);
u8x8->drawString(de->x, de->y, sonde.si()->launchsite);
rdis->setFont(de->fmt);
rdis->drawString(de->x, de->y, sonde.si()->launchsite);
}
void Display::drawTelemetry(DispEntry *de) {
}
@ -496,13 +588,13 @@ void Display::drawTelemetry(DispEntry *de) {
void Display::drawGPS(DispEntry *de) {
if(sonde.config.gps_rxd<0) return;
SETFONT(de->fmt);
rdis->setFont(de->fmt);
switch(de->extra[0]) {
case 'V':
{
// show if GPS location is valid
uint8_t *tile = nmea.isValid()?gps_tile:nogps_tile;
u8x8->drawTile(de->x, de->y, 1, tile);
rdis->drawTile(de->x, de->y, 1, tile);
}
break;
case 'O':
@ -511,7 +603,7 @@ void Display::drawGPS(DispEntry *de) {
float lon = nmea.getLongitude()*0.000001;
Serial.print("lon: "); Serial.println(lon);
snprintf(buf, 16, "%2.5f", lon);
u8x8->drawString(de->x,de->y,buf);
rdis->drawString(de->x,de->y,buf);
}
break;
case 'A':
@ -520,7 +612,7 @@ void Display::drawGPS(DispEntry *de) {
float lat = nmea.getLatitude()*0.000001;
Serial.print("lat: "); Serial.println(lat);
snprintf(buf, 16, "%2.5f", lat);
u8x8->drawString(de->x,de->y,buf);
rdis->drawString(de->x,de->y,buf);
}
break;
case 'H':
@ -529,7 +621,7 @@ void Display::drawGPS(DispEntry *de) {
long alt = -1;
nmea.getAltitude(alt);
snprintf(buf, 16, "%5fm", alt*0.00001);
u8x8->drawString(de->x,de->y,buf);
rdis->drawString(de->x,de->y,buf);
}
break;
case 'D':
@ -559,13 +651,13 @@ void Display::drawGPS(DispEntry *de) {
buf[6]=0;
}
}
u8x8->drawString(de->x, de->y, buf);
rdis->drawString(de->x, de->y, buf);
}
break;
case 'I':
// dIrection
if( (!nmea.isValid()) || ((sonde.si()->validPos&0x03)!=0x03 ) ) {
u8x8->drawString(de->x, de->y, "---");
rdis->drawString(de->x, de->y, "---");
break;
}
{
@ -580,9 +672,9 @@ void Display::drawGPS(DispEntry *de) {
Serial.printf("direction is %.2f\n", dir);
snprintf(buf, 16, "%3d", (int)dir);
buf[3]=0;
u8x8->drawString(de->x, de->y, buf);
rdis->drawString(de->x, de->y, buf);
if(de->extra[1]==(char)176)
u8x8->drawTile(de->x+3, de->y, 1, deg_tile);
rdis->drawTile(de->x+3, de->y, 1, deg_tile);
}
break;
case 'E':
@ -591,8 +683,8 @@ void Display::drawGPS(DispEntry *de) {
}
}
void Display::drawText(DispEntry *de) {
SETFONT(de->fmt);
u8x8->drawString(de->x, de->y, de->extra);
rdis->setFont(de->fmt);
rdis->drawString(de->x, de->y, de->extra);
}

View File

@ -5,6 +5,10 @@
#define FONT_LARGE 1
#define FONT_SMALL 0
#include <SPI.h>
#include <TFT_22_ILI9225.h>
#include <U8x8lib.h>
struct DispEntry {
int8_t y;
@ -20,6 +24,40 @@ struct DispInfo {
int16_t *timeouts;
};
// Now starting towards supporting different Display types / libraries
class RawDisplay {
public:
virtual void begin() = 0;
virtual void clear() = 0;
virtual void setFont(int nr) = 0;
virtual void drawString(uint8_t x, uint8_t y, const char *s) = 0;
virtual void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) = 0;
};
class U8x8Display : public RawDisplay {
private:
U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8 = NULL; // initialize later after reading config file
public:
void begin();
void clear();
void setFont(int nr);
void drawString(uint8_t x, uint8_t y, const char *s);
void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr);
};
class ILI9225Display : public RawDisplay {
private:
TFT_22_ILI9225 *tft = NULL; // initialize later after reading config file
uint8_t yofs=0;
public:
void begin();
void clear();
void setFont(int nr);
void drawString(uint8_t x, uint8_t y, const char *s);
void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr);
};
class Display {
private:
@ -32,8 +70,10 @@ public:
void setLayout(DispInfo *layout);
DispInfo *layout;
static RawDisplay *rdis;
Display();
void init();
static char buf[17];
static void drawLat(DispEntry *de);
static void drawLon(DispEntry *de);

View File

@ -3,8 +3,7 @@
#include <U8x8lib.h>
#include "Sonde.h"
extern U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8;
#include "Display.h"
#define CHANBW 10
#define PIXSAMPL (50/CHANBW)
@ -56,7 +55,7 @@ void Scanner::plotResult()
// don't overwrite MHz marker text
if(i<3*8 || (i>=7*8&&i<10*8) || i>=13*8) continue;
}
u8x8->drawTile(i/8, y, 1, row+8*y);
disp.rdis->drawTile(i/8, y, 1, row+8*y);
}
}
}

View File

@ -8,7 +8,6 @@
#include "SX1278FSK.h"
#include "Display.h"
extern U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8;
extern SX1278FSK sx1278;
RXTask rxtask = { -1, -1, -1, 0xFFFF, 0 };
@ -51,6 +50,8 @@ Sonde::Sonde() {
// Seems like on startup, GPIO4 is 1 on v1 boards, 0 on v2.1 boards?
config.gps_rxd = -1;
config.gps_txd = -1;
config.oled_rst = 16;
config.disptype = 0;
if(initlevels[16]==0) {
config.oled_sda = 4;
config.oled_scl = 15;
@ -63,13 +64,21 @@ Sonde::Sonde() {
config.button_pin = 39;
config.button2_pin = T4 + 128; // T4 == GPIO13
config.gps_rxd = 12;
// Check if we possibly have a large display
if(initlevels[21]==0) {
config.disptype = 1;
config.oled_sda = 4;
config.oled_scl = 21;
config.oled_rst = 22;
config.tft_rs = 2;
config.tft_cs = 0;
}
} else {
config.button_pin = 2 + 128; // GPIO2 / T2
config.button2_pin = 14 + 128; // GPIO14 / T6
}
}
//
config.oled_rst = 16;
config.noisefloor = -125;
strcpy(config.call,"NOCALL");
strcpy(config.passcode, "---");
@ -496,7 +505,7 @@ void Sonde::updateDisplay()
}
void Sonde::clearDisplay() {
u8x8->clearDisplay();
disp.rdis->clear();
}
Sonde sonde = Sonde();

View File

@ -85,9 +85,12 @@ typedef struct st_rdzconfig {
int button2_pin; // PIN port number menu button (+128 for touch mode)
int touch_thresh; // Threshold value (0..100) for touch input button
int led_pout; // POUT port number of LED (used as serial monitor)
int oled_sda; // OLED data pin
int oled_scl; // OLED clock pin
int oled_rst; // OLED reset pin
int disptype; // 0=OLED; 1=ILI9225
int oled_sda; // OLED/TFT data pin
int oled_scl; // OLED/TFT clock pin
int oled_rst; // OLED/TFT reset pin
int tft_rs; // TFT RS pin
int tft_cs; // TFT CS pin
int gps_rxd; // GPS module RXD pin. We expect 9600 baud NMEA data.
int gps_txd; // GPS module TXD pin
int debug; // show port and config options after reboot

View File

@ -17,6 +17,10 @@ TTGO T-Beam
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:1 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:4 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-Beam with extern 2" ILI9225 Display
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:1 13:0 14:1 15:1 16:1 17:0 18:0 19:0 20:0 21:0 22:0 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:4 13:0 14:4 15:4 16:4 17:0 18:0 19:0 20:0 21:0 22:0 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)
1
Current autodetect strategy:
RST always set to 16
@ -30,13 +34,17 @@ GPIO16=0 (GPio22,23 would also work):
otherwise
==LORA32 v2.1 or T-Beam==
SDA,SCL set to (21,22)
GPIO17=0:
== T-BEAM =
GPS RX set to 12
Button 1 set to GPIO39
Button 2 set to Touch GPIO13 (141)
GPIO21=0:
large display connected (use ILI9225 contig: SDA4 CLK21 RS2 RST22 CS0)
else:
small display connected, set SDA,SCL to (21,22)
otherweise:
SDA,SCL set to (21,22)
GPS disabled
Button 1 set to Touch GPIO2 (130)
Button 2 set to Touch GPIO14 (142)

View File

@ -5,9 +5,9 @@
#include <rom/miniz.h>
#include <inttypes.h>
#include <WiFi.h>
#include <U8x8lib.h>
#include "Display.h"
extern U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8;
extern WiFiClient client;
static const char *ftpserver = "www.ngs.noaa.gov";
@ -72,9 +72,9 @@ void geteph() {
Serial.printf("now: %s, existing: %s => updating\n", nowstr, tsstr);
}
status.close();
u8x8->clear();
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->drawString(0, 0, "FTP ngs.noaa.gov");
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) {
@ -84,7 +84,7 @@ void geteph() {
char buf[252];
snprintf(buf, 128, "/cors/rinex/%04d/%03d/brdc%03d0.%02dn.gz", year, day, day, year-2000);
Serial.println("running geteph\n");
u8x8->drawString(0, 1, buf+21);
disp.rdis->drawString(0, 1, buf+21);
if(!client.connect(ftpserver, 21)) {
Serial.println("FTP connection to www.ngs.noaa.gov failed");
@ -145,9 +145,9 @@ void geteph() {
fh.close();
snprintf(buf, 16, "Fetched %d B ",len);
buf[16]=0;
u8x8->drawString(0,2,buf);
disp.rdis->drawString(0,2,buf);
u8x8->drawString(0,4,"Decompressing...");
disp.rdis->drawString(0,4,"Decompressing...");
// decompression
tinfl_decompressor *decomp = (tinfl_decompressor *)malloc(sizeof(tinfl_decompressor));
tinfl_init(decomp);
@ -215,7 +215,7 @@ void geteph() {
status.close();
snprintf(buf, 16, "Done: %d B ",total);
buf[16]=0;
u8x8->drawString(0,5,buf);
disp.rdis->drawString(0,5,buf);
delay(1000);
free(obuf);