634 lines
25 KiB
C++
634 lines
25 KiB
C++
#include <logger.h>
|
|
#include <Wire.h>
|
|
#include "custom_characters.h"
|
|
#include "custom_colors.h"
|
|
#include "configuration.h"
|
|
#include "board_pinout.h"
|
|
#include "display.h"
|
|
#include "TimeLib.h"
|
|
|
|
|
|
#ifdef HAS_TFT
|
|
#include <TFT_eSPI.h>
|
|
|
|
TFT_eSPI tft = TFT_eSPI();
|
|
TFT_eSprite sprite = TFT_eSprite(&tft);
|
|
|
|
|
|
int brightnessValues[6] = {70, 90, 120, 160, 200, 250};
|
|
int tftBrightness = 5;
|
|
unsigned short grays[13];
|
|
|
|
#ifdef HELTEC_WIRELESS_TRACKER
|
|
#define bigSizeFont 2
|
|
#define smallSizeFont 1
|
|
#define lineSpacing 12
|
|
#endif
|
|
#if defined(TTGO_T_DECK_GPS) || defined(TTGO_T_DECK_PLUS)
|
|
#define color1 TFT_BLACK
|
|
#define color2 0x0249
|
|
#define green 0x1B08
|
|
|
|
#define bigSizeFont 4
|
|
#define normalSizeFont 2
|
|
#define smallSizeFont 1
|
|
#define lineSpacing 22
|
|
|
|
extern String topHeader1;
|
|
extern String topHeader1_1;
|
|
extern String topHeader1_2;
|
|
extern String topHeader1_3;
|
|
extern String topHeader2;
|
|
#endif
|
|
#else
|
|
#include <Adafruit_GFX.h>
|
|
|
|
#define ssd1306 //comment this line with "//" when using SH1106 screen instead of SSD1306
|
|
|
|
#if defined(TTGO_T_Beam_S3_SUPREME_V3)
|
|
#undef ssd1306
|
|
#endif
|
|
#if defined(HELTEC_V3_GPS) || defined(HELTEC_V3_TNC)
|
|
#define OLED_DISPLAY_HAS_RST_PIN
|
|
#endif
|
|
|
|
#ifdef ssd1306
|
|
#include <Adafruit_SSD1306.h>
|
|
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RST);
|
|
#else
|
|
#include <Adafruit_SH110X.h>
|
|
Adafruit_SH1106G display(128, 64, &Wire, OLED_RST);
|
|
#endif
|
|
#endif
|
|
|
|
#define SYMBOL_HEIGHT 14
|
|
#define SYMBOL_WIDTH 16
|
|
|
|
extern Configuration Config;
|
|
extern Beacon *currentBeacon;
|
|
extern int menuDisplay;
|
|
extern bool bluetoothConnected;
|
|
|
|
const char* symbolArray[] = { "[", ">", "j", "b", "<", "s", "u", "R", "v", "(", ";", "-", "k",
|
|
"C", "a", "Y", "O", "'", "=", "y", "U", "p"};
|
|
int symbolArraySize = sizeof(symbolArray)/sizeof(symbolArray[0]);
|
|
const uint8_t *symbolsAPRS[] = {runnerSymbol, carSymbol, jeepSymbol, bikeSymbol, motorcycleSymbol, shipSymbol,
|
|
truck18Symbol, recreationalVehicleSymbol, vanSymbol, carsateliteSymbol, tentSymbol,
|
|
houseSymbol, truckSymbol, canoeSymbol, ambulanceSymbol, yatchSymbol, baloonSymbol,
|
|
aircraftSymbol, trainSymbol, yagiSymbol, busSymbol, dogSymbol};
|
|
// T-Beams bought with soldered OLED Screen comes with only 4 pins (VCC, GND, SDA, SCL)
|
|
// If your board didn't come with 4 pins OLED Screen and comes with 5 and one of them is RST...
|
|
// Uncomment Next Line (Remember ONLY if your OLED Screen has a RST pin). This is to avoid memory issues.
|
|
//#define OLED_DISPLAY_HAS_RST_PIN
|
|
|
|
int lastMenuDisplay = 0;
|
|
uint8_t screenBrightness = 1; //from 1 to 255 to regulate brightness of oled scren
|
|
bool symbolAvailable = true;
|
|
|
|
extern logging::Logger logger;
|
|
|
|
|
|
#if defined(HAS_TFT) && (defined(TTGO_T_DECK_PLUS) || defined(TTGO_T_DECK_GPS))
|
|
void drawButton(int xPos, int yPos, int wide, int height, String buttonText, int color) {
|
|
uint16_t baseColor, lightColor, darkColor;
|
|
switch (color) {
|
|
case 0: // Grey Theme
|
|
baseColor = greyColor;
|
|
lightColor = greyColorLight;
|
|
darkColor = greyColorDark;
|
|
break;
|
|
case 1: // Green Theme
|
|
baseColor = greenColor;
|
|
lightColor = greenColorLight;
|
|
darkColor = greenColorDark;
|
|
break;
|
|
case 2: // Red Theme
|
|
baseColor = redColor;
|
|
lightColor = redColorLight;
|
|
darkColor = redColorDark;
|
|
break;
|
|
default: // Fallback color
|
|
baseColor = 0x0000; // Black
|
|
lightColor = 0xFFFF; // White
|
|
darkColor = 0x0000; // Black
|
|
break;
|
|
}
|
|
|
|
sprite.fillRect(xPos, yPos, wide, height, baseColor); // Dibuja el fondo del botón
|
|
sprite.fillRect(xPos, yPos + height - 2, wide, 2, darkColor); // Línea inferior
|
|
sprite.fillRect(xPos, yPos, wide, 2, lightColor); // Línea superior
|
|
sprite.fillRect(xPos, yPos, 2, height, lightColor); // Línea izquierda
|
|
sprite.fillRect(xPos + wide - 2, yPos, 2, height, darkColor); // Línea derecha
|
|
|
|
sprite.setTextSize(2);
|
|
sprite.setTextColor(TFT_WHITE, baseColor);
|
|
|
|
// Calcula la posición del texto para que esté centrado
|
|
int textWidth = sprite.textWidth(buttonText); // Ancho del texto
|
|
int textHeight = 16; // Altura aproximada (depende de `setTextSize`)
|
|
int textX = xPos + (wide - textWidth) / 2; // Centrado horizontal
|
|
int textY = yPos + (height - textHeight) / 2; // Centrado vertical
|
|
|
|
sprite.drawString(buttonText, textX, textY);
|
|
}
|
|
|
|
void draw_T_DECK_Top() {//const String& header, const String& datetime, const String& location) {
|
|
sprite.fillSprite(TFT_BLACK);
|
|
sprite.fillRect(0, 0, 320, 38, redColor);
|
|
sprite.setTextFont(0);
|
|
sprite.setTextSize(bigSizeFont);
|
|
sprite.setTextColor(TFT_WHITE, redColor);
|
|
sprite.drawString(topHeader1, 3, 5);
|
|
|
|
sprite.setTextSize(smallSizeFont);
|
|
sprite.setTextColor(TFT_WHITE, redColor);
|
|
//String date = datetime.substring(0, datetime.indexOf(" "));
|
|
sprite.drawString(topHeader1_1, 258, 5);
|
|
//String time = datetime.substring(datetime.indexOf(" ") + 3);
|
|
sprite.drawString("UTC:" + topHeader1_2, 246, 15);
|
|
|
|
sprite.fillRect(0, 38, 320, 2, redColorDark);//TFT_ORANGE);
|
|
|
|
sprite.fillRect(0, 40, 320, 2, greyColorLight);
|
|
sprite.fillRect(0, 42, 320, 20, greyColor);
|
|
sprite.setTextSize(2);
|
|
sprite.setTextColor(TFT_WHITE, greyColor);
|
|
sprite.drawString(topHeader2, 8, 44);
|
|
sprite.fillRect(0, 60, 320, 2, greyColorDark);
|
|
}
|
|
|
|
|
|
void draw_T_DECK_MenuButtons(int menu) {
|
|
int ladoCuadrado = 45;
|
|
int curvaCuadrado = 8;
|
|
int espacioEntreCuadrados = 18;
|
|
int margenLineaCuadrados = 10;
|
|
int alturaPrimeraLinea = 75;
|
|
int alturaSegundaLinea = 145;
|
|
int16_t colorCuadrados = 0x2925;
|
|
int16_t colorDestacado = greyColor;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
if (i == menu - 1) {
|
|
sprite.fillRoundRect(
|
|
margenLineaCuadrados + (i * (ladoCuadrado + espacioEntreCuadrados)) - 1,
|
|
alturaPrimeraLinea - 1,
|
|
ladoCuadrado + 2,
|
|
ladoCuadrado + 2,
|
|
curvaCuadrado,
|
|
TFT_WHITE
|
|
);
|
|
sprite.fillRoundRect(
|
|
margenLineaCuadrados + (i * (ladoCuadrado + espacioEntreCuadrados)),
|
|
alturaPrimeraLinea,
|
|
ladoCuadrado,
|
|
ladoCuadrado,
|
|
curvaCuadrado,
|
|
TFT_BLACK
|
|
);
|
|
sprite.fillRoundRect(
|
|
margenLineaCuadrados + (i * (ladoCuadrado + espacioEntreCuadrados)), // x-coordinate
|
|
alturaPrimeraLinea, // y-coordinate
|
|
ladoCuadrado, // width
|
|
ladoCuadrado, // height
|
|
curvaCuadrado, // corner radius
|
|
colorDestacado // color
|
|
);
|
|
} else {
|
|
sprite.fillRoundRect(
|
|
margenLineaCuadrados + (i * (ladoCuadrado + espacioEntreCuadrados)), // x-coordinate
|
|
alturaPrimeraLinea, // y-coordinate
|
|
ladoCuadrado, // width
|
|
ladoCuadrado, // height
|
|
curvaCuadrado, // corner radius
|
|
colorCuadrados // color
|
|
);
|
|
}
|
|
sprite.fillRoundRect(
|
|
margenLineaCuadrados + (i * (ladoCuadrado + espacioEntreCuadrados)), // x-coordinate
|
|
alturaSegundaLinea, // y-coordinate
|
|
ladoCuadrado, // width
|
|
ladoCuadrado, // height
|
|
curvaCuadrado, // corner radius
|
|
colorCuadrados // color
|
|
);
|
|
}
|
|
}
|
|
|
|
void draw_T_DECK_Body(const String& line1, const String& line2, const String& line3, const String& line4, const String& line5, const String& line6) {
|
|
|
|
/*if (menuDisplay > 0 && menuDisplay < 6) {
|
|
draw_T_DECK_MenuButtons(menuDisplay);
|
|
} else {*/
|
|
sprite.setTextSize(normalSizeFont);
|
|
sprite.setTextColor(TFT_WHITE, TFT_BLACK);
|
|
|
|
const String* const lines[] = {&line1, &line2, &line3, &line4, &line5, &line6};
|
|
for (int i = 0; i < 6; i++) {
|
|
sprite.drawString(*lines[i], 35, 70 + (i * 20));
|
|
}
|
|
|
|
//drawButton(125, 210, 80, 28, "Menu", 0);
|
|
|
|
drawButton(30, 210, 80, 28, "Send", 1);
|
|
drawButton(125, 210, 80, 28, "Menu", 0);
|
|
drawButton(220, 210, 80, 28, "Exit", 2);
|
|
//}
|
|
}
|
|
|
|
#endif
|
|
|
|
//sprite.fillRect(0, 38, 320, 2, TFT_DARKGREY);
|
|
//sprite.fillRect(0, 20, 320, 2, color2); // linea bajo techo
|
|
//sprite.fillRect(0, 202, 320, 2, 0xBC81); // linea abajo amarilla
|
|
|
|
//sprite.fillSmoothRoundRect( 0, 218, 320, 22 , 2, redColor, TFT_BLACK); // piso
|
|
|
|
//sprite.fillSmoothRoundRect( 4, 2, 56, 14 , 2, grays[6], grays[9]); // cuadrado gris izquierda arriba
|
|
//sprite.fillSmoothRoundRect( 2, 2, 16, 14 , 2, TFT_BLUE, grays[9]); // cuadrado rojo izquierda arriba
|
|
|
|
//sprite.fillSmoothRoundRect(272, 2, 40, 16 , 2, green, grays[9]); // bateria
|
|
//sprite.fillSmoothRoundRect(308, 6, 8, 8 , 2, green, grays[9]); // bateria
|
|
//sprite.fillSmoothRoundRect(275, 4, 34, 12 , 2, TFT_BLACK, green); // centro bateria
|
|
|
|
/*for (int i = 0; i < 5; i++) { // cubos que muestran el brillo (abajo a la derecha)
|
|
if(i < tftBrightness) {
|
|
sprite.fillRect(282+(i*8), 207, 5, 8, grays[3]);
|
|
} else {
|
|
sprite.fillRect(282+(i*8), 207, 5, 8, grays[7]);
|
|
}
|
|
}*/
|
|
|
|
//for (int i = 0; i < 9; i++) sprite.drawFastHLine(4, 38+(i*18), 312, grays[8]); // draw horizonatl lines
|
|
|
|
/*sprite.setTextFont(0);
|
|
sprite.setTextSize(1);
|
|
sprite.setTextColor(TFT_WHITE, TFT_BLUE);
|
|
sprite.drawString("LoRa", 6, 4);
|
|
sprite.setTextColor(TFT_BLACK, grays[6]);
|
|
sprite.drawString("APRS", 21, 4); // escribir DECK en x=21 , y=4*/
|
|
|
|
/*sprite.setTextColor(grays[1],c olor2);
|
|
sprite.drawString(notice, 6, 223, 2);
|
|
|
|
for (int i = 0; i < nMsg + 1; i++) {
|
|
if (msg[i].length() > 0) {
|
|
if (writer[i] == 1) {
|
|
sprite.setTextColor(grays[1], color1); else sprite.setTextColor(0x663C, color1);
|
|
sprite.drawString(msg[i], 6, 25 + (i*18), 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
sprite.setTextColor(grays[5], TFT_BLACK);
|
|
sprite.unloadFont();
|
|
sprite.drawString("Your ID: " + name, 2, 208);
|
|
sprite.setTextColor(grays[4],grays[9]);
|
|
sprite.drawString("VOLOS", 210, 2);
|
|
sprite.setTextColor(grays[5], grays[9]);
|
|
sprite.drawString("projects", 210, 9);
|
|
sprite.setTextColor(grays[2], TFT_BLACK);
|
|
sprite.drawString(String(analogRead(4)), 280, 7);
|
|
|
|
sprite.setTextColor(grays[8], color2);
|
|
sprite.drawString("ENTER YOUR MESSAGE", 200, 226);
|
|
|
|
sprite.setTextColor(grays[7], TFT_BLACK);
|
|
sprite.drawString("SND:", 120, 208);
|
|
sprite.drawString(String(sndN), 145, 8);
|
|
|
|
sprite.drawString("REC:",190,208);
|
|
sprite.drawString(String(recN), 215, 208);*/
|
|
|
|
String fillStringLength(const String& line, uint8_t length) {
|
|
String outputLine = line;
|
|
for (int a = line.length(); a < length; a++) {
|
|
outputLine += " ";
|
|
}
|
|
return outputLine;
|
|
}
|
|
|
|
void displaySetup() {
|
|
delay(500);
|
|
#ifdef HAS_TFT
|
|
tft.init();
|
|
tft.begin();
|
|
if (Config.display.turn180) {
|
|
tft.setRotation(3);
|
|
} else {
|
|
tft.setRotation(1);
|
|
}
|
|
pinMode(TFT_BL, OUTPUT);
|
|
digitalWrite(TFT_BL, HIGH);
|
|
//analogWrite(BOARD_BL_PIN, brightnessValues[tftBrightness]);
|
|
tft.setTextFont(0);
|
|
tft.fillScreen(TFT_BLACK);
|
|
#if defined(TTGO_T_DECK_PLUS) || defined(TTGO_T_DECK_GPS)
|
|
sprite.createSprite(320,240);
|
|
#else
|
|
sprite.createSprite(160,80);
|
|
#endif
|
|
int co = 210;
|
|
for (int i = 0; i < 13; i++) {
|
|
grays[i] = tft.color565(co, co, co);
|
|
co = co - 20;
|
|
}
|
|
#else
|
|
#ifdef OLED_DISPLAY_HAS_RST_PIN
|
|
pinMode(OLED_RST, OUTPUT);
|
|
digitalWrite(OLED_RST, LOW);
|
|
delay(20);
|
|
digitalWrite(OLED_RST, HIGH);
|
|
#endif
|
|
|
|
Wire.begin(OLED_SDA, OLED_SCL);
|
|
#ifdef ssd1306
|
|
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) {
|
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "SSD1306", "allocation failed!");
|
|
while (true) {
|
|
}
|
|
}
|
|
#else
|
|
if (!display.begin(0x3c, false)) {
|
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "SH1106", "allocation failed!");
|
|
while (true) {
|
|
}
|
|
}
|
|
#endif
|
|
if (Config.display.turn180) display.setRotation(2);
|
|
display.clearDisplay();
|
|
#ifdef ssd1306
|
|
display.setTextColor(WHITE);
|
|
#else
|
|
display.setTextColor(SH110X_WHITE);
|
|
#endif
|
|
display.setTextSize(1);
|
|
display.setCursor(0, 0);
|
|
#ifdef ssd1306
|
|
display.ssd1306_command(SSD1306_SETCONTRAST);
|
|
display.ssd1306_command(screenBrightness);
|
|
#else
|
|
display.setContrast(screenBrightness);
|
|
#endif
|
|
display.display();
|
|
#endif
|
|
}
|
|
|
|
void displayToggle(bool toggle) {
|
|
if (toggle) {
|
|
#ifdef HAS_TFT
|
|
digitalWrite(TFT_BL, HIGH);
|
|
#else
|
|
#ifdef ssd1306
|
|
display.ssd1306_command(SSD1306_DISPLAYON);
|
|
#else
|
|
display.oled_command(SH110X_DISPLAYON);
|
|
#endif
|
|
#endif
|
|
} else {
|
|
#ifdef HAS_TFT
|
|
digitalWrite(TFT_BL, LOW);
|
|
#else
|
|
#ifdef ssd1306
|
|
display.ssd1306_command(SSD1306_DISPLAYOFF);
|
|
#else
|
|
display.oled_command(SH110X_DISPLAYOFF);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void displayShow(const String& header, const String& line1, const String& line2, int wait) {
|
|
#ifdef HAS_TFT
|
|
#if defined(TTGO_T_DECK_PLUS) || defined(TTGO_T_DECK_GPS)
|
|
draw_T_DECK_Top();
|
|
String tftLine1, tftLine2, tftLine3, tftLine4;
|
|
if (line1.length() > 22 && line2.length() > 22) {
|
|
tftLine1 = line1.substring(0,22);
|
|
tftLine2 = line1.substring(22);
|
|
tftLine3 = line2.substring(0,22);
|
|
tftLine4 = line2.substring(22);
|
|
} else if (line1.length() > 22) {
|
|
tftLine1 = line1.substring(0,22);
|
|
tftLine2 = line1.substring(22);
|
|
tftLine3 = line2;
|
|
tftLine4 = "";
|
|
} else if (line2.length() > 22) {
|
|
tftLine1 = line1;
|
|
tftLine2 = line2.substring(0,22);
|
|
tftLine3 = line2.substring(22);
|
|
tftLine4 = "";
|
|
} else {
|
|
tftLine1 = line1;
|
|
tftLine2 = line2;
|
|
tftLine3 = "";
|
|
tftLine4 = "";
|
|
}
|
|
draw_T_DECK_Body(header, tftLine1, tftLine2, tftLine3, tftLine4, "");
|
|
#endif
|
|
#if defined(HELTEC_WIRELESS_TRACKER)
|
|
sprite.fillSprite(TFT_BLACK);
|
|
sprite.fillRect(0, 0, 160, 19, redColor);
|
|
sprite.setTextFont(0);
|
|
sprite.setTextSize(bigSizeFont);
|
|
sprite.setTextColor(TFT_WHITE, redColor);
|
|
sprite.drawString(header, 3, 3);
|
|
|
|
const String* const lines[] = {&line1, &line2};
|
|
|
|
sprite.setTextSize(smallSizeFont);
|
|
sprite.setTextColor(TFT_WHITE, TFT_BLACK);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
sprite.drawString(*lines[i], 3,(lineSpacing * (2 + i)) - 2);
|
|
}
|
|
#endif
|
|
sprite.pushSprite(0,0);
|
|
#else
|
|
const String* const lines[] = {&line1, &line2};
|
|
|
|
display.clearDisplay();
|
|
#ifdef ssd1306
|
|
display.setTextColor(WHITE);
|
|
#else
|
|
display.setTextColor(SH110X_WHITE);
|
|
#endif
|
|
display.setTextSize(2);
|
|
display.setCursor(0, 0);
|
|
display.println(header);
|
|
display.setTextSize(1);
|
|
for (int i = 0; i < 2; i++) {
|
|
display.setCursor(0, 16 + (10 * i));
|
|
display.println(*lines[i]);
|
|
}
|
|
#ifdef ssd1306
|
|
display.ssd1306_command(SSD1306_SETCONTRAST);
|
|
display.ssd1306_command(screenBrightness);
|
|
#else
|
|
display.setContrast(screenBrightness);
|
|
#endif
|
|
display.display();
|
|
#endif
|
|
delay(wait);
|
|
}
|
|
|
|
|
|
void drawSymbol(int symbolIndex, bool bluetoothActive) {
|
|
const uint8_t *bitMap = symbolsAPRS[symbolIndex];
|
|
#ifdef HAS_TFT
|
|
if (bluetoothActive) bitMap = bluetoothSymbol;
|
|
#if defined(HELTEC_WIRELESS_TRACKER)
|
|
sprite.drawBitmap(128 - SYMBOL_WIDTH, 3, bitMap, SYMBOL_WIDTH, SYMBOL_HEIGHT, TFT_WHITE);
|
|
#endif
|
|
#if defined(TTGO_T_DECK_GPS) || defined(TTGO_T_DECK_PLUS)
|
|
sprite.drawBitmap(280, 70, bitMap, SYMBOL_WIDTH, SYMBOL_HEIGHT, TFT_WHITE);
|
|
#endif
|
|
#else
|
|
display.drawBitmap((display.width() - SYMBOL_WIDTH), 0, bitMap, SYMBOL_WIDTH, SYMBOL_HEIGHT, 1);
|
|
#endif
|
|
}
|
|
|
|
|
|
void displayShow(const String& header, const String& line1, const String& line2, const String& line3, const String& line4, const String& line5, int wait) {
|
|
#ifdef HAS_TFT
|
|
#if defined(TTGO_T_DECK_PLUS)
|
|
draw_T_DECK_Top();//header, line1, line2);
|
|
draw_T_DECK_Body(header, line1, line2, line3, line4, line5);
|
|
#endif
|
|
#if defined(HELTEC_WIRELESS_TRACKER)
|
|
sprite.fillSprite(TFT_BLACK);
|
|
sprite.fillRect(0, 0, 160, 19, redColor);
|
|
sprite.setTextFont(0);
|
|
sprite.setTextSize(bigSizeFont);
|
|
sprite.setTextColor(TFT_WHITE, redColor);
|
|
sprite.drawString(header, 3, 3);
|
|
|
|
const String* const lines[] = {&line1, &line2, &line3, &line4, &line5};
|
|
|
|
sprite.setTextSize(smallSizeFont);
|
|
sprite.setTextColor(TFT_WHITE, TFT_BLACK);
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
sprite.drawString(*lines[i], 3,(lineSpacing * (2 + i)) - 2);
|
|
}
|
|
#endif
|
|
if (menuDisplay == 0 && Config.display.showSymbol) {
|
|
int symbol = 100;
|
|
for (int i = 0; i < symbolArraySize; i++) {
|
|
if (currentBeacon->symbol == symbolArray[i]) {
|
|
symbol = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
symbolAvailable = symbol != 100;
|
|
|
|
/* Symbol alternate every 5s
|
|
* If bluetooth is disconnected or if we are in the first part of the clock, then we show the APRS symbol
|
|
* Otherwise, we are in the second part of the clock, then we show BT connected */
|
|
|
|
const auto time_now = now();
|
|
if (!bluetoothConnected || time_now % 10 < 5) {
|
|
if (symbolAvailable) drawSymbol(symbol, false);
|
|
} else if (bluetoothConnected) { // TODO In this case, the text symbol stay displayed due to symbolAvailable false in menu_utils
|
|
drawSymbol(symbol, true);
|
|
}
|
|
}
|
|
sprite.pushSprite(0,0);
|
|
#else
|
|
const String* const lines[] = {&line1, &line2, &line3, &line4, &line5};
|
|
|
|
display.clearDisplay();
|
|
#ifdef ssd1306
|
|
display.setTextColor(WHITE);
|
|
display.drawLine(0, 16, 128, 16, WHITE);
|
|
display.drawLine(0, 17, 128, 17, WHITE);
|
|
#else
|
|
display.setTextColor(SH110X_WHITE);
|
|
display.drawLine(0, 16, 128, 16, SH110X_WHITE);
|
|
display.drawLine(0, 17, 128, 17, SH110X_WHITE);
|
|
#endif
|
|
display.setTextSize(2);
|
|
display.setCursor(0, 0);
|
|
display.println(header);
|
|
display.setTextSize(1);
|
|
for (int i = 0; i < 5; i++) {
|
|
display.setCursor(0, 20 + (9 * i));
|
|
display.println(*lines[i]);
|
|
}
|
|
#ifdef ssd1306
|
|
display.ssd1306_command(SSD1306_SETCONTRAST);
|
|
display.ssd1306_command(screenBrightness);
|
|
#else
|
|
display.setContrast(screenBrightness);
|
|
#endif
|
|
|
|
if (menuDisplay == 0 && Config.display.showSymbol) {
|
|
int symbol = 100;
|
|
for (int i = 0; i < symbolArraySize; i++) {
|
|
if (currentBeacon->symbol == symbolArray[i]) {
|
|
symbol = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
symbolAvailable = symbol != 100;
|
|
|
|
/*
|
|
* Symbol alternate every 5s
|
|
* If bluetooth is disconnected or if we are in the first part of the clock, then we show the APRS symbol
|
|
* Otherwise, we are in the second part of the clock, then we show BT connected
|
|
*/
|
|
const auto time_now = now();
|
|
if (!bluetoothConnected || time_now % 10 < 5) {
|
|
if (symbolAvailable) drawSymbol(symbol, false);
|
|
} else if (bluetoothConnected) { // TODO In this case, the text symbol stay displayed due to symbolAvailable false in menu_utils
|
|
drawSymbol(symbol, true);
|
|
}
|
|
}
|
|
display.display();
|
|
#endif
|
|
delay(wait);
|
|
}
|
|
|
|
void startupScreen(uint8_t index, const String& version) {
|
|
String workingFreq = " LoRa Freq [";
|
|
switch (index) {
|
|
case 0: workingFreq += "Eu]"; break;
|
|
case 1: workingFreq += "PL]"; break;
|
|
case 2: workingFreq += "UK]"; break;
|
|
}
|
|
displayShow(" LoRa APRS", " (TRACKER)", workingFreq, "", "", " CA2RXU " + version, 4000);
|
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "RichonGuzman (CA2RXU) --> LoRa APRS Tracker/Station");
|
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Version: %s", version);
|
|
}
|
|
|
|
String fillMessageLine(const String& line, const int& length) {
|
|
String completeLine = line;
|
|
for (int i = 0; completeLine.length() <= length; i++) {
|
|
completeLine = completeLine + " ";
|
|
}
|
|
return completeLine;
|
|
}
|
|
|
|
void displayMessage(const String& sender, const String& message, const int& lineLength, bool next, int wait) {
|
|
String messageLine1, messageLine2, messageLine3;
|
|
int messageLength = message.length();
|
|
|
|
if (message.length() > 0) {
|
|
messageLine1 = message.substring(0, min(lineLength, messageLength));
|
|
if (messageLength > lineLength) {
|
|
messageLine2 = message.substring(lineLength, min(2 * lineLength, messageLength));
|
|
if (messageLength > 2 * lineLength) {
|
|
messageLine3 = message.substring(2 * lineLength);
|
|
}
|
|
}
|
|
}
|
|
if (next) {
|
|
String nextLine = fillMessageLine("Next=Down", lineLength);
|
|
displayShow("MSG_APRS>", "From --> " + sender, fillMessageLine(messageLine1, lineLength), fillMessageLine(messageLine2, lineLength), fillMessageLine(messageLine3, lineLength), nextLine);
|
|
} else {
|
|
displayShow("< MSG Rx >", "From --> " + sender, "", fillMessageLine(messageLine1, lineLength) , fillMessageLine(messageLine2, lineLength), fillMessageLine(messageLine3, lineLength), wait);
|
|
}
|
|
|
|
} |