- Buffer de transicion persistente (sprTrans) de 25KB asignado una sola vez en setup() para evitar fallos de memoria heap contigua - Eliminacion de carga y descarga dinamica de fuentes en renderPage2ToSprite durante las transiciones para evitar fugas de RAM - Timeout de seguridad por hardware de 250ms en waitForTouchRelease() para prevenir bloqueos por ruido en la lamina resistiva - Pantallas 2 y 3: Reloj atomico GPS con DSEG7 de 80pt y Telemetria satelital completa (rumbo, satelites, altitud, coordenadas) - Documentacion de conexion y pines para modulo GPS N32+/U-blox
502 lines
18 KiB
C
502 lines
18 KiB
C
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
#include <TFT_eSPI.h>
|
|
#include "gps_module.h"
|
|
#include "DSEG7_Modern_BoldItalic_34.h"
|
|
|
|
extern TFT_eSPI tft;
|
|
extern uint16_t getThemePrimaryColor();
|
|
extern uint16_t getThemeBgColor();
|
|
extern int8_t currentScreenPage;
|
|
extern int8_t fullScreenCell;
|
|
|
|
// Previous values for flicker-free redrawing of Page 3
|
|
static float oldNavAlt = -999.0f;
|
|
static float oldNavCourse = -999.0f;
|
|
static uint8_t oldNavSats = 255;
|
|
static float oldNavHdop = -999.0f;
|
|
static double oldNavLat = 0.0;
|
|
static double oldNavLon = 0.0;
|
|
static bool oldNavFix = false;
|
|
|
|
static int lastNavAltRound = -999;
|
|
static bool lastNavAltValid = false;
|
|
static int lastNavCrsRound = -999;
|
|
static bool lastNavHasCourse = false;
|
|
static const char* lastNavCardDir = "";
|
|
static uint8_t lastNavCardSats = 255;
|
|
static bool lastNavSatsSync = false;
|
|
static float lastNavCardHdop = -999.0f;
|
|
static char lastNavCardDiag[32] = "";
|
|
static bool lastNavDiagSynced = false;
|
|
static uint8_t oldNavWaveState = 255;
|
|
static bool oldNavSynced = false;
|
|
static uint32_t lastNavPageEnterTime = 0;
|
|
|
|
// Synchronize tracking variables without touching TFT display (zero flicker)
|
|
inline void syncGpsNavTrackers() {
|
|
lastNavPageEnterTime = millis();
|
|
bool synced = isGpsSynced();
|
|
bool altValid = isGpsAltitudeValid();
|
|
lastNavAltRound = altValid ? (int)round(gpsAltitudeM) : -999;
|
|
lastNavAltValid = altValid;
|
|
oldNavAlt = gpsAltitudeM;
|
|
|
|
bool hasCourse = synced && isGpsCourseValid();
|
|
lastNavCrsRound = hasCourse ? (int)round(gpsCourseDeg) : -999;
|
|
lastNavHasCourse = hasCourse;
|
|
oldNavCourse = gpsCourseDeg;
|
|
lastNavCardDir = hasCourse ? getCompassDirectionFull(gpsCourseDeg) : "---";
|
|
|
|
lastNavCardSats = gpsSats;
|
|
lastNavSatsSync = synced;
|
|
oldNavSats = gpsSats;
|
|
|
|
lastNavCardHdop = gpsHdop;
|
|
oldNavHdop = gpsHdop;
|
|
|
|
strncpy(lastNavCardDiag, getGpsDiagMessage(), sizeof(lastNavCardDiag) - 1);
|
|
lastNavCardDiag[sizeof(lastNavCardDiag) - 1] = '\0';
|
|
lastNavDiagSynced = synced;
|
|
|
|
oldNavWaveState = getGpsWaveAnimState();
|
|
oldNavSynced = synced;
|
|
|
|
oldNavLat = gpsLatitude;
|
|
oldNavLon = gpsLongitude;
|
|
oldNavFix = synced;
|
|
}
|
|
|
|
// Large animated satellite icon faithful to gps_icon.jpg for the Navigation Dashboard
|
|
inline void drawLargeSatelliteIcon(int x, int y, uint16_t color, uint8_t waveState = 2, uint16_t bgColor = 0x10A2) {
|
|
drawLargeGpsSatelliteIcon(tft, x, y, TFT_WHITE, color, bgColor, waveState);
|
|
}
|
|
|
|
// Large animated satellite icon for double-buffered sprite slice
|
|
inline void drawLargeSatelliteIconSprite(TFT_eSprite &s, int x, int y, uint16_t color, uint8_t waveState = 2, uint16_t bgColor = 0x10A2) {
|
|
drawLargeGpsSatelliteIcon(s, x, y, TFT_WHITE, color, bgColor, waveState);
|
|
}
|
|
|
|
// Draw full Page 3 (GPS Navigation & Telemetry Screen: Altitud, Rumbo, Satélites, Coordenadas)
|
|
inline void drawGpsNavScreen(int x_offset = 0) {
|
|
if (x_offset == 0) {
|
|
tft.fillScreen(TFT_BLACK);
|
|
} else {
|
|
tft.fillRect(0, 0, x_offset, 240, TFT_BLACK);
|
|
}
|
|
|
|
uint16_t priCol = getThemePrimaryColor();
|
|
uint16_t cardBg = 0x10A2; // Dark graphite navy
|
|
uint16_t cardBorder = 0x2945; // Subtle edge border
|
|
bool synced = isGpsSynced();
|
|
|
|
// 1. TOP BAR (y = 0 to 18)
|
|
// Left: Screen Title
|
|
tft.setTextColor(0x8410, TFT_BLACK);
|
|
tft.drawString("TELEMETRIA GPS", 8 + x_offset, 5, 1);
|
|
|
|
// Center: 4 Pagination Indicator Dots [○ ○ ○ ●] (Page 4 active)
|
|
tft.fillCircle(139 + x_offset, 2, 2, 0x5AEB); // Page 1 inactive
|
|
tft.fillCircle(153 + x_offset, 2, 2, 0x5AEB); // Page 2 inactive
|
|
tft.fillCircle(167 + x_offset, 2, 2, 0x5AEB); // Page 3 inactive
|
|
tft.fillCircle(181 + x_offset, 2, 2, priCol); // Page 4 active
|
|
|
|
// 2. CARD 0 (Top Left): ALTITUD (x = 4, y = 19, w = 152, h = 102)
|
|
int c0X = 4 + x_offset;
|
|
int c0Y = 19;
|
|
int cW = 152;
|
|
int cH1 = 102;
|
|
tft.fillRoundRect(c0X, c0Y, cW, cH1, 6, cardBg);
|
|
tft.drawRoundRect(c0X, c0Y, cW, cH1, 6, cardBorder);
|
|
tft.fillRoundRect(c0X + 6, c0Y + 8, 4, cH1 - 16, 2, priCol);
|
|
|
|
tft.setTextColor(0x8410, cardBg);
|
|
tft.drawString("ALTITUD", c0X + 16, c0Y + 8, 2);
|
|
tft.setTextColor(0x9CD3, cardBg);
|
|
tft.drawString("MSNM", c0X + 96, c0Y + 8, 2);
|
|
|
|
bool altValid = isGpsAltitudeValid();
|
|
String altStr = altValid ? String((int)round(gpsAltitudeM)) : "---";
|
|
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.setTextPadding(0);
|
|
tft.drawRightString(altStr.c_str(), c0X + 140, c0Y + 28, 1);
|
|
tft.unloadFont();
|
|
|
|
// 3. CARD 1 (Top Right): RUMBO / BRÚJULA (x = 164, y = 19, w = 152, h = 102)
|
|
int c1X = 164 + x_offset;
|
|
int c1Y = 19;
|
|
tft.fillRoundRect(c1X, c1Y, cW, cH1, 6, cardBg);
|
|
tft.drawRoundRect(c1X, c1Y, cW, cH1, 6, cardBorder);
|
|
tft.fillRoundRect(c1X + 6, c1Y + 8, 4, cH1 - 16, 2, priCol);
|
|
|
|
tft.setTextColor(0x8410, cardBg);
|
|
tft.drawString("RUMBO / BRUJULA", c1X + 16, c1Y + 8, 2);
|
|
|
|
bool hasCourse = synced && isGpsCourseValid();
|
|
String crsStr = hasCourse ? String((int)round(gpsCourseDeg)) : "---";
|
|
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.setTextPadding(0);
|
|
tft.drawRightString(crsStr.c_str(), c1X + 130, c1Y + 28, 1);
|
|
tft.unloadFont();
|
|
if (hasCourse) {
|
|
tft.drawCircle(c1X + 137, c1Y + 33, 3, priCol);
|
|
tft.drawCircle(c1X + 137, c1Y + 33, 2, priCol);
|
|
} else {
|
|
tft.fillCircle(c1X + 137, c1Y + 33, 4, cardBg);
|
|
}
|
|
|
|
const char* cardDir = hasCourse ? getCompassDirectionFull(gpsCourseDeg) : "---";
|
|
tft.setTextColor(TFT_WHITE, cardBg);
|
|
tft.drawString(cardDir, c1X + 16, c1Y + 74, 2);
|
|
|
|
// 4. CARD 2 (Bottom Left): SATÉLITES GPS EN GRANDE (x = 4, y = 125, w = 152, h = 110)
|
|
int c2X = 4 + x_offset;
|
|
int c2Y = 125;
|
|
int cH2 = 110;
|
|
tft.fillRoundRect(c2X, c2Y, cW, cH2, 6, cardBg);
|
|
tft.drawRoundRect(c2X, c2Y, cW, cH2, 6, cardBorder);
|
|
tft.fillRoundRect(c2X + 6, c2Y + 8, 4, cH2 - 16, 2, priCol);
|
|
|
|
tft.setTextColor(0x8410, cardBg);
|
|
tft.drawString("SATELITES GPS", c2X + 16, c2Y + 8, 2);
|
|
|
|
// Large Satellite Icon (animated body + waves)
|
|
uint8_t waveState = getGpsWaveAnimState();
|
|
drawLargeSatelliteIcon(c2X + 16, c2Y + 32, priCol, waveState, cardBg);
|
|
|
|
// Large Satellites Count (DSEG7 34pt)
|
|
String satStr = String(gpsSats);
|
|
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.setTextPadding(0);
|
|
tft.drawRightString(satStr.c_str(), c2X + 140, c2Y + 26, 1);
|
|
tft.unloadFont();
|
|
|
|
// Telemetry details: HDOP precision & live diagnostic status
|
|
String hdopStr = "HDOP: " + (synced ? String(gpsHdop, 1) : "---");
|
|
tft.setTextColor(TFT_WHITE, cardBg);
|
|
tft.drawString(hdopStr.c_str(), c2X + 16, c2Y + 68, 2);
|
|
|
|
tft.setTextColor(synced ? 0x9CD3 : priCol, cardBg);
|
|
tft.drawString(getGpsDiagMessage(), c2X + 16, c2Y + 90, 1);
|
|
|
|
// 5. CARD 3 (Bottom Right): COORDENADAS GPS (x = 164, y = 125, w = 152, h = 110)
|
|
int c3X = 164 + x_offset;
|
|
int c3Y = 125;
|
|
tft.fillRoundRect(c3X, c3Y, cW, cH2, 6, cardBg);
|
|
tft.drawRoundRect(c3X, c3Y, cW, cH2, 6, cardBorder);
|
|
tft.fillRoundRect(c3X + 6, c3Y + 8, 4, cH2 - 16, 2, priCol);
|
|
|
|
tft.setTextColor(0x8410, cardBg);
|
|
tft.drawString("COORDENADAS", c3X + 16, c3Y + 8, 2);
|
|
|
|
tft.setTextColor(0x8410, cardBg);
|
|
tft.drawString("LAT", c3X + 16, c3Y + 26, 1);
|
|
String latStr = gpsLocationValid ? (String(gpsLatitude, 5) + "°") : "--.-----°";
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.drawString(latStr.c_str(), c3X + 16, c3Y + 38, 2);
|
|
|
|
tft.setTextColor(0x8410, cardBg);
|
|
tft.drawString("LON", c3X + 16, c3Y + 64, 1);
|
|
String lonStr = gpsLocationValid ? (String(gpsLongitude, 5) + "°") : "--.-----°";
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.drawString(lonStr.c_str(), c3X + 16, c3Y + 76, 2);
|
|
|
|
// Sync state trackers
|
|
syncGpsNavTrackers();
|
|
}
|
|
|
|
// 100% Flicker-Free Live Refresh for resting Page 3 (GPS Navigation & Telemetry)
|
|
inline void updateGpsNavScreen(bool forceRedraw = false) {
|
|
if (currentScreenPage != 3 || fullScreenCell != -1) return;
|
|
|
|
// Post-transition stabilization: during the first 400ms after landing on Page 3,
|
|
// do not wipe or repaint cards over SPI. Any incoming serial bytes from GPS
|
|
// are safely absorbed into tracking variables so there is ZERO blackout/blink!
|
|
if (!forceRedraw && (millis() - lastNavPageEnterTime < 400)) {
|
|
syncGpsNavTrackers();
|
|
return;
|
|
}
|
|
|
|
uint16_t priCol = getThemePrimaryColor();
|
|
uint16_t cardBg = 0x10A2;
|
|
bool synced = isGpsSynced();
|
|
|
|
// 1. Altitude changed: update Card 0 digits only
|
|
bool altValid = isGpsAltitudeValid();
|
|
int curAltRound = altValid ? (int)round(gpsAltitudeM) : -999;
|
|
if (forceRedraw || curAltRound != lastNavAltRound || altValid != lastNavAltValid) {
|
|
lastNavAltRound = curAltRound;
|
|
lastNavAltValid = altValid;
|
|
oldNavAlt = gpsAltitudeM;
|
|
int c0X = 4;
|
|
int c0Y = 19;
|
|
String altStr = altValid ? String(curAltRound) : "---";
|
|
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.setTextPadding(126);
|
|
tft.drawRightString(altStr.c_str(), c0X + 140, c0Y + 28, 1);
|
|
tft.setTextPadding(0);
|
|
tft.unloadFont();
|
|
}
|
|
|
|
// 2. Course / Heading changed: update Card 1
|
|
bool hasCourse = synced && isGpsCourseValid();
|
|
int curCrsRound = hasCourse ? (int)round(gpsCourseDeg) : -999;
|
|
int c1X = 164;
|
|
int c1Y = 19;
|
|
|
|
if (forceRedraw || curCrsRound != lastNavCrsRound || hasCourse != lastNavHasCourse) {
|
|
lastNavCrsRound = curCrsRound;
|
|
oldNavCourse = gpsCourseDeg;
|
|
lastNavHasCourse = hasCourse;
|
|
String crsStr = hasCourse ? String(curCrsRound) : "---";
|
|
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.setTextPadding(85);
|
|
tft.drawRightString(crsStr.c_str(), c1X + 130, c1Y + 28, 1);
|
|
tft.setTextPadding(0);
|
|
tft.unloadFont();
|
|
|
|
if (hasCourse) {
|
|
tft.drawCircle(c1X + 137, c1Y + 33, 3, priCol);
|
|
tft.drawCircle(c1X + 137, c1Y + 33, 2, priCol);
|
|
} else {
|
|
tft.fillCircle(c1X + 137, c1Y + 33, 4, cardBg);
|
|
}
|
|
}
|
|
|
|
// Direction name changed (e.g. NORTE, SUR)
|
|
const char* cardDir = hasCourse ? getCompassDirectionFull(gpsCourseDeg) : "---";
|
|
if (forceRedraw || strcmp(cardDir, lastNavCardDir) != 0) {
|
|
lastNavCardDir = cardDir;
|
|
tft.setTextPadding(128);
|
|
tft.setTextColor(TFT_WHITE, cardBg);
|
|
tft.drawString(cardDir, c1X + 16, c1Y + 74, 2);
|
|
tft.setTextPadding(0);
|
|
}
|
|
|
|
// 3. Card 2: Satellites, HDOP and Diagnostic status
|
|
int c2X = 4;
|
|
int c2Y = 125;
|
|
|
|
// 3a. Satellites Count (DSEG7 34pt)
|
|
if (forceRedraw || gpsSats != lastNavCardSats || synced != lastNavSatsSync) {
|
|
lastNavCardSats = gpsSats;
|
|
lastNavSatsSync = synced;
|
|
oldNavSats = gpsSats;
|
|
String satStr = String(gpsSats);
|
|
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.setTextPadding(85);
|
|
tft.drawRightString(satStr.c_str(), c2X + 140, c2Y + 26, 1);
|
|
tft.setTextPadding(0);
|
|
tft.unloadFont();
|
|
}
|
|
|
|
// 3b. HDOP precision
|
|
if (forceRedraw || abs(gpsHdop - lastNavCardHdop) >= 0.2f) {
|
|
lastNavCardHdop = gpsHdop;
|
|
oldNavHdop = gpsHdop;
|
|
String hdopStr = "HDOP: " + (synced ? String(gpsHdop, 1) : "---");
|
|
tft.setTextPadding(130);
|
|
tft.setTextColor(TFT_WHITE, cardBg);
|
|
tft.drawString(hdopStr.c_str(), c2X + 16, c2Y + 68, 2);
|
|
tft.setTextPadding(0);
|
|
}
|
|
|
|
// 3c. Diagnostic status message ("PRECISION OPTIMA", "SIN SEÑAL GPS", etc.)
|
|
// Decoupled: only redrawn when message text actually changes, with setTextPadding (zero flicker!)
|
|
const char* curDiag = getGpsDiagMessage();
|
|
if (forceRedraw || strcmp(curDiag, lastNavCardDiag) != 0 || synced != lastNavDiagSynced) {
|
|
strncpy(lastNavCardDiag, curDiag, sizeof(lastNavCardDiag) - 1);
|
|
lastNavCardDiag[sizeof(lastNavCardDiag) - 1] = '\0';
|
|
lastNavDiagSynced = synced;
|
|
tft.setTextPadding(130);
|
|
tft.setTextColor(synced ? 0x9CD3 : priCol, cardBg);
|
|
tft.drawString(curDiag, c2X + 16, c2Y + 90, 1);
|
|
tft.setTextPadding(0);
|
|
}
|
|
|
|
// 3d. Large Satellite Icon: only redrawn if waveState or sync changes
|
|
uint8_t curWaveState = getGpsWaveAnimState();
|
|
if (forceRedraw || curWaveState != oldNavWaveState || synced != oldNavSynced) {
|
|
oldNavWaveState = curWaveState;
|
|
oldNavSynced = synced;
|
|
drawLargeSatelliteIcon(c2X + 16, c2Y + 32, priCol, curWaveState, cardBg);
|
|
}
|
|
|
|
// 4. Coordinates changed: update Card 3 (setTextPadding avoids fillRect flicker)
|
|
if (forceRedraw || abs(gpsLatitude - oldNavLat) >= 0.00005 || abs(gpsLongitude - oldNavLon) >= 0.00005) {
|
|
oldNavLat = gpsLatitude;
|
|
oldNavLon = gpsLongitude;
|
|
int c3X = 164;
|
|
int c3Y = 125;
|
|
String latStr = gpsLocationValid ? (String(gpsLatitude, 5) + "°") : "--.-----°";
|
|
tft.setTextPadding(130);
|
|
tft.setTextColor(priCol, cardBg);
|
|
tft.drawString(latStr.c_str(), c3X + 16, c3Y + 38, 2);
|
|
|
|
String lonStr = gpsLocationValid ? (String(gpsLongitude, 5) + "°") : "--.-----°";
|
|
tft.drawString(lonStr.c_str(), c3X + 16, c3Y + 76, 2);
|
|
tft.setTextPadding(0);
|
|
}
|
|
}
|
|
|
|
// Render Page 3 into double-buffered sprite slice for slide / fade transitions
|
|
inline void renderPage3ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int slice_h) {
|
|
uint16_t priCol = getThemePrimaryColor();
|
|
uint16_t cardBg = 0x10A2;
|
|
uint16_t cardBorder = 0x2945;
|
|
bool synced = isGpsSynced();
|
|
|
|
// 1. TOP BAR in top slice
|
|
if (y_slice == 0) {
|
|
s.setTextColor(0x8410, TFT_BLACK);
|
|
s.drawString("TELEMETRIA GPS", 8 + x_offset, 5, 1);
|
|
}
|
|
|
|
// 2. CARD 0 (Top Left): ALTITUD (y = 19 to 121)
|
|
int c0X = 4 + x_offset;
|
|
int c0Y = 19 - y_slice;
|
|
int cW = 152;
|
|
int cH1 = 102;
|
|
if (c0X + cW > 0 && c0X < 320 && c0Y + cH1 > 0 && c0Y < slice_h) {
|
|
s.fillRoundRect(c0X, c0Y, cW, cH1, 6, cardBg);
|
|
s.drawRoundRect(c0X, c0Y, cW, cH1, 6, cardBorder);
|
|
s.fillRoundRect(c0X + 6, c0Y + 8, 4, cH1 - 16, 2, priCol);
|
|
|
|
if (c0Y + 24 > 0 && c0Y + 8 < slice_h) {
|
|
s.setTextColor(0x8410, cardBg);
|
|
s.drawString("ALTITUD", c0X + 16, c0Y + 8, 2);
|
|
s.setTextColor(0x9CD3, cardBg);
|
|
s.drawString("MSNM", c0X + 96, c0Y + 8, 2);
|
|
}
|
|
bool altValid = isGpsAltitudeValid();
|
|
String altStr = altValid ? String((int)round(gpsAltitudeM)) : "---";
|
|
int valY = c0Y + 28;
|
|
if (valY < slice_h && valY + 38 > 0) {
|
|
s.fontLoaded = true;
|
|
s.setTextColor(priCol, cardBg);
|
|
s.setTextPadding(0);
|
|
s.drawRightString(altStr.c_str(), c0X + 140, valY, 1);
|
|
s.fontLoaded = false;
|
|
}
|
|
}
|
|
|
|
// 3. CARD 1 (Top Right): RUMBO (y = 19 to 121)
|
|
int c1X = 164 + x_offset;
|
|
int c1Y = 19 - y_slice;
|
|
if (c1X + cW > 0 && c1X < 320 && c1Y + cH1 > 0 && c1Y < slice_h) {
|
|
s.fillRoundRect(c1X, c1Y, cW, cH1, 6, cardBg);
|
|
s.drawRoundRect(c1X, c1Y, cW, cH1, 6, cardBorder);
|
|
s.fillRoundRect(c1X + 6, c1Y + 8, 4, cH1 - 16, 2, priCol);
|
|
|
|
if (c1Y + 24 > 0 && c1Y + 8 < slice_h) {
|
|
s.setTextColor(0x8410, cardBg);
|
|
s.drawString("RUMBO / BRUJULA", c1X + 16, c1Y + 8, 2);
|
|
}
|
|
bool hasCourse = synced && isGpsCourseValid();
|
|
String crsStr = hasCourse ? String((int)round(gpsCourseDeg)) : "---";
|
|
int valY = c1Y + 28;
|
|
if (valY < slice_h && valY + 38 > 0) {
|
|
s.fontLoaded = true;
|
|
s.setTextColor(priCol, cardBg);
|
|
s.setTextPadding(0);
|
|
s.drawRightString(crsStr.c_str(), c1X + 130, valY, 1);
|
|
s.fontLoaded = false;
|
|
if (hasCourse) {
|
|
int circY = c1Y + 33;
|
|
if (circY + 4 > 0 && circY - 4 < slice_h) {
|
|
s.drawCircle(c1X + 137, circY, 3, priCol);
|
|
s.drawCircle(c1X + 137, circY, 2, priCol);
|
|
}
|
|
}
|
|
}
|
|
int dirY = c1Y + 74;
|
|
if (dirY + 16 > 0 && dirY < slice_h) {
|
|
const char* cardDir = hasCourse ? getCompassDirectionFull(gpsCourseDeg) : "---";
|
|
s.setTextColor(TFT_WHITE, cardBg);
|
|
s.drawString(cardDir, c1X + 16, dirY, 2);
|
|
}
|
|
}
|
|
|
|
// 4. CARD 2 (Bottom Left): SATÉLITES GPS (y = 125 to 235)
|
|
int c2X = 4 + x_offset;
|
|
int c2Y = 125 - y_slice;
|
|
int cH2 = 110;
|
|
if (c2X + cW > 0 && c2X < 320 && c2Y + cH2 > 0 && c2Y < slice_h) {
|
|
s.fillRoundRect(c2X, c2Y, cW, cH2, 6, cardBg);
|
|
s.drawRoundRect(c2X, c2Y, cW, cH2, 6, cardBorder);
|
|
s.fillRoundRect(c2X + 6, c2Y + 8, 4, cH2 - 16, 2, priCol);
|
|
|
|
if (c2Y + 24 > 0 && c2Y + 8 < slice_h) {
|
|
s.setTextColor(0x8410, cardBg);
|
|
s.drawString("SATELITES GPS", c2X + 16, c2Y + 8, 2);
|
|
}
|
|
uint8_t waveState = getGpsWaveAnimState();
|
|
int icnY = c2Y + 32;
|
|
if (icnY + 28 > 0 && icnY < slice_h) {
|
|
drawLargeSatelliteIconSprite(s, c2X + 16, icnY, priCol, waveState, cardBg);
|
|
}
|
|
int satY = c2Y + 26;
|
|
if (satY < slice_h && satY + 38 > 0) {
|
|
String satStr = String(gpsSats);
|
|
s.fontLoaded = true;
|
|
s.setTextColor(priCol, cardBg);
|
|
s.setTextPadding(0);
|
|
s.drawRightString(satStr.c_str(), c2X + 140, satY, 1);
|
|
s.fontLoaded = false;
|
|
}
|
|
int hdopY = c2Y + 68;
|
|
if (hdopY < slice_h && hdopY + 16 > 0) {
|
|
String hdopStr = "HDOP: " + (synced ? String(gpsHdop, 1) : "---");
|
|
s.setTextColor(TFT_WHITE, cardBg);
|
|
s.drawString(hdopStr.c_str(), c2X + 16, hdopY, 2);
|
|
}
|
|
int qualY = c2Y + 90;
|
|
if (qualY + 10 > 0 && qualY < slice_h) {
|
|
s.setTextColor(synced ? 0x9CD3 : priCol, cardBg);
|
|
s.drawString(getGpsDiagMessage(), c2X + 16, qualY, 1);
|
|
}
|
|
}
|
|
|
|
// 5. CARD 3 (Bottom Right): COORDENADAS (y = 125 to 235)
|
|
int c3X = 164 + x_offset;
|
|
int c3Y = 125 - y_slice;
|
|
if (c3X + cW > 0 && c3X < 320 && c3Y + cH2 > 0 && c3Y < slice_h) {
|
|
s.fillRoundRect(c3X, c3Y, cW, cH2, 6, cardBg);
|
|
s.drawRoundRect(c3X, c3Y, cW, cH2, 6, cardBorder);
|
|
s.fillRoundRect(c3X + 6, c3Y + 8, 4, cH2 - 16, 2, priCol);
|
|
|
|
if (c3Y + 24 > 0 && c3Y + 8 < slice_h) {
|
|
s.setTextColor(0x8410, cardBg);
|
|
s.drawString("COORDENADAS", c3X + 16, c3Y + 8, 2);
|
|
}
|
|
int latHdrY = c3Y + 26;
|
|
if (latHdrY < slice_h && latHdrY + 10 > 0) {
|
|
s.setTextColor(0x8410, cardBg);
|
|
s.drawString("LAT", c3X + 16, latHdrY, 1);
|
|
}
|
|
int latValY = c3Y + 38;
|
|
if (latValY < slice_h && latValY + 18 > 0) {
|
|
String latStr = gpsLocationValid ? (String(gpsLatitude, 5) + "°") : "--.-----°";
|
|
s.setTextColor(priCol, cardBg);
|
|
s.drawString(latStr.c_str(), c3X + 16, latValY, 2);
|
|
}
|
|
int lonHdrY = c3Y + 64;
|
|
if (lonHdrY < slice_h && lonHdrY + 10 > 0) {
|
|
s.setTextColor(0x8410, cardBg);
|
|
s.drawString("LON", c3X + 16, lonHdrY, 1);
|
|
}
|
|
int lonValY = c3Y + 76;
|
|
if (lonValY < slice_h && lonValY + 18 > 0) {
|
|
String lonStr = gpsLocationValid ? (String(gpsLongitude, 5) + "°") : "--.-----°";
|
|
s.setTextColor(priCol, cardBg);
|
|
s.drawString(lonStr.c_str(), c3X + 16, lonValY, 2);
|
|
}
|
|
}
|
|
}
|