feat(ui,theme): soporte completo de temas y colores individuales en modo Yapa
- Reemplazo de tipografías por renderizado anti-aliased suave y sin parpadeo (DSEG7 y bitmaps AA)
- Títulos, unidades y guiones ('---') adaptados dinámicamente al tema de color activo
- Modo Yapa con color pastel distintivo por cada letra, dígito y símbolo en velocímetro y temperaturas
- Indicador ECO sobre RPM e icono GPS dinámico en velocímetro según origen de datos
- Temperaturas interior y exterior redondeadas a números enteros
This commit is contained in:
parent
d614ea633a
commit
674c044dd1
18 changed files with 1229 additions and 881 deletions
BIN
dop.png
Normal file
BIN
dop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 262 KiB |
|
|
@ -469,8 +469,8 @@ def run_emulator():
|
|||
sim_thread = threading.Thread(target=simulation_worker, daemon=True)
|
||||
sim_thread.start()
|
||||
|
||||
# Start GPS simulation thread if port exists or --gps requested
|
||||
if not args.no_gps and (args.gps or os.path.exists(args.gps_port)):
|
||||
# Start GPS simulation thread ONLY if --gps explicitly requested
|
||||
if args.gps and not args.no_gps:
|
||||
gps_thread = threading.Thread(
|
||||
target=gps_simulation_worker,
|
||||
args=(args.gps_port, args.gps_baud),
|
||||
|
|
|
|||
BIN
gauge_design.png
Normal file
BIN
gauge_design.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
gps_icon.png
Normal file
BIN
gps_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -21,24 +21,24 @@
|
|||
x="-25.60" y="-14.63"
|
||||
width="51.20" height="29.26"
|
||||
rx="7.31" ry="7.31"
|
||||
transform="translate(100.00, 88.00) rotate(-34.0) translate(61.44, 0)"/>
|
||||
transform="translate(100.00, 88.00) rotate(-39.5) translate(61.44, 0)"/>
|
||||
|
||||
<!-- Bottom-Left Solar Panel -->
|
||||
<rect id="panel-bottom-left"
|
||||
x="-25.60" y="-14.63"
|
||||
width="51.20" height="29.26"
|
||||
rx="7.31" ry="7.31"
|
||||
transform="translate(100.00, 88.00) rotate(-34.0) translate(-61.44, 0)"/>
|
||||
transform="translate(100.00, 88.00) rotate(-39.5) translate(-61.44, 0)"/>
|
||||
</g>
|
||||
|
||||
<!-- WAVE 1: First radio wave arc -->
|
||||
<path id="wave-1" class="sat-wave"
|
||||
d="M 167.20 84.48 A 67.29 67.29 0 0 1 86.01 153.82"
|
||||
d="M 165.40 72.18 A 67.29 67.29 0 0 1 74.14 150.12"
|
||||
stroke-width="24.14"/>
|
||||
|
||||
<!-- WAVE 2: Second radio wave arc -->
|
||||
<path id="wave-2" class="sat-wave"
|
||||
d="M 213.95 82.03 A 114.10 114.10 0 0 1 76.28 199.61"
|
||||
d="M 212.57 69.36 A 114.10 114.10 0 0 1 64.17 196.33"
|
||||
stroke-width="24.87"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
gps_icon.xcf
Normal file
BIN
gps_icon.xcf
Normal file
Binary file not shown.
|
|
@ -76,7 +76,8 @@ void scanBTdevice() {//scan bluetooth device
|
|||
bool isMatch = (dName == "OBDII") ||
|
||||
(dName.indexOf("OBD") != -1) ||
|
||||
(dName.indexOf("ELM") != -1) ||
|
||||
(dName == "DEBIAN") ||
|
||||
(dName.indexOf("DEBIAN") != -1) ||
|
||||
(dAddr == "6c:62:6d:14:08:fd") ||
|
||||
(dAddr == "e8:48:b8:c8:20:00");
|
||||
|
||||
if (isMatch) {//match name.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "DSEG7_Modern_BoldItalic_34.h"
|
||||
#include "DSEG7_Modern_BoldItalic_44.h"
|
||||
#include "rainbow_text.h"
|
||||
#include "kmh_aa_data.h"
|
||||
|
||||
extern TFT_eSPI tft;
|
||||
extern uint16_t getThemePrimaryColor();
|
||||
|
|
@ -18,6 +19,7 @@ extern int8_t fullScreenCell;
|
|||
extern float currentRpm;
|
||||
extern float last_valid_data[];
|
||||
extern float tempEngineCoolant;
|
||||
extern bool isEcoOptimal;
|
||||
extern void drawPidIcon(int x, int y, const String &pidStr);
|
||||
extern void drawPidIconToSprite(TFT_eSprite &s, int ix, int iy, const String &pidStr, int y_slice, int slice_h, int global_y);
|
||||
extern void draw7SegDegreeC(TFT_eSPI &dst, int bx, int by, uint16_t color, uint16_t bgCol, bool rainbow);
|
||||
|
|
@ -32,7 +34,7 @@ inline float getClusterRpmVal() {
|
|||
inline float getClusterSpeedVal() {
|
||||
if (isGpsSpeedValid()) return gpsSpeedKmph;
|
||||
if (last_valid_data[1] >= 0.0f) return last_valid_data[1];
|
||||
return 0.0f;
|
||||
return -999.0f;
|
||||
}
|
||||
|
||||
inline bool isClusterSpeedFromGps() {
|
||||
|
|
@ -56,29 +58,34 @@ static int oldClusterSpd = -999;
|
|||
static int oldClusterCoolant = -999;
|
||||
static float oldClusterVolt = -999.0f;
|
||||
static bool oldClusterGpsLock = false;
|
||||
static bool oldClusterEco = false;
|
||||
static uint16_t oldClusterCoolCol = 0;
|
||||
static uint16_t oldClusterVoltCol = 0;
|
||||
static int oldClusterSegs = -1;
|
||||
static uint32_t lastClusterUpdate = 0;
|
||||
|
||||
inline void syncClusterTrackers() {
|
||||
oldClusterRpm = (int)round(getClusterRpmVal());
|
||||
oldClusterSpd = (int)round(getClusterSpeedVal());
|
||||
float s = getClusterSpeedVal();
|
||||
oldClusterSpd = (s >= 0.0f) ? (int)round(s) : -999;
|
||||
float c = getClusterCoolantVal();
|
||||
oldClusterCoolant = (c > -900.0f) ? (int)round(c) : -999;
|
||||
oldClusterVolt = getClusterVoltVal();
|
||||
oldClusterGpsLock = isClusterSpeedFromGps();
|
||||
oldClusterEco = isEcoOptimal;
|
||||
lastClusterUpdate = millis();
|
||||
}
|
||||
|
||||
// Helper: draw 5 top pagination dots (page 4 active)
|
||||
// Helper: draw 4 top pagination dots (page 0 active)
|
||||
inline void drawClusterDots(int x_offset = 0) {
|
||||
uint16_t actCol = isRainbowTheme() ? getRainbowScreenColor(188, 2) : (isYapaTheme() ? getYapaColor(4) : getThemePrimaryColor());
|
||||
tft.fillCircle(132 + x_offset, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(146 + x_offset, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(160 + x_offset, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(174 + x_offset, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(188 + x_offset, 2, 2, actCol);
|
||||
uint16_t actCol = isRainbowTheme() ? getRainbowScreenColor(139, 2) : (isYapaTheme() ? getYapaColor(0) : getThemePrimaryColor());
|
||||
tft.fillCircle(139 + x_offset, 2, 2, actCol);
|
||||
tft.fillCircle(153 + x_offset, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(167 + x_offset, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(181 + x_offset, 2, 2, 0x5AEB);
|
||||
}
|
||||
|
||||
// Draw static framing of all 4 cards
|
||||
// Draw static framing of all 4 cards (units and titles drawn ONCE without flicker)
|
||||
inline void drawClusterBaseCards(int x_offset = 0) {
|
||||
uint16_t cardBg = 0x10A2;
|
||||
uint16_t border = 0x2945;
|
||||
|
|
@ -90,54 +97,47 @@ inline void drawClusterBaseCards(int x_offset = 0) {
|
|||
uint16_t cCool = isRainbowTheme() ? getRainbowScreenColor(20, 150) : (isYapaTheme() ? getYapaColor(2) : priCol);
|
||||
uint16_t cVolt = isRainbowTheme() ? getRainbowScreenColor(180, 150) : (isYapaTheme() ? getYapaColor(3) : accCol);
|
||||
|
||||
// 1. TACHOMETER CARD (x: 8, y: 10, w: 304, h: 42)
|
||||
tft.fillRoundRect(8 + x_offset, 10, 304, 42, 5, cardBg);
|
||||
tft.drawRoundRect(8 + x_offset, 10, 304, 42, 5, border);
|
||||
tft.fillRoundRect(12 + x_offset, 14, 3, 34, 1, cRpm);
|
||||
drawPidIcon(18 + x_offset, 14, "010C");
|
||||
tft.setTextColor(0x8410, cardBg);
|
||||
tft.drawString("RPM", 38 + x_offset, 16, 2);
|
||||
// Tachometer background track (x: 76 to 216, w: 140, h: 12)
|
||||
tft.fillRoundRect(76 + x_offset, 16, 140, 12, 3, 0x0841);
|
||||
// RPM ticks
|
||||
tft.drawString("1 2 3 4 5 6 7", 86 + x_offset, 31, 1);
|
||||
// 1. TACHOMETER CARD (x: 8, y: 8, w: 304, h: 50)
|
||||
tft.fillRoundRect(8 + x_offset, 8, 304, 50, 5, cardBg);
|
||||
tft.drawRoundRect(8 + x_offset, 8, 304, 50, 5, border);
|
||||
// Tachometer background rail on the LEFT (x: 18 to 90, w: 72, h: 14)
|
||||
tft.fillRoundRect(18 + x_offset, 15, 72, 14, 3, 0x0841);
|
||||
if (isYapaTheme()) {
|
||||
int sx = 20 + x_offset;
|
||||
char buf[2] = {0, 0};
|
||||
for (int i = 0; i < 7; i++) {
|
||||
buf[0] = '1' + i;
|
||||
tft.setTextColor(getYapaColor(i), cardBg);
|
||||
tft.drawString(buf, sx, 32, 1);
|
||||
sx += tft.textWidth(buf, 1) + tft.textWidth(" ", 1);
|
||||
}
|
||||
} else {
|
||||
tft.setTextColor(cRpm, cardBg);
|
||||
tft.drawString("1 2 3 4 5 6 7", 20 + x_offset, 32, 1);
|
||||
}
|
||||
// "RPM" unit on the far right in Chakra Petch Bold Italic (aligned with foot of digits at y = 55)
|
||||
drawRpm_AA(tft, 242 + x_offset, 35, cRpm, cardBg, 240, isRainbowTheme());
|
||||
|
||||
// 2. SPEEDOMETER CARD (x: 8, y: 56, w: 304, h: 76)
|
||||
tft.fillRoundRect(8 + x_offset, 56, 304, 76, 5, cardBg);
|
||||
tft.drawRoundRect(8 + x_offset, 56, 304, 76, 5, border);
|
||||
tft.fillRoundRect(12 + x_offset, 60, 3, 68, 1, cSpd);
|
||||
drawPidIcon(18 + x_offset, 60, "010D");
|
||||
tft.setTextColor(0x8410, cardBg);
|
||||
tft.drawString("VELOCIDAD", 38 + x_offset, 62, 2);
|
||||
// Background speed glow rail
|
||||
tft.fillRoundRect(18 + x_offset, 124, 284, 3, 1, 0x0841);
|
||||
// 2. SPEEDOMETER CARD (x: 8, y: 62, w: 304, h: 86)
|
||||
tft.fillRoundRect(8 + x_offset, 62, 304, 86, 5, cardBg);
|
||||
tft.drawRoundRect(8 + x_offset, 62, 304, 86, 5, border);
|
||||
// Large anti-aliased "KM/H" (Chakra Petch Bold Italic) at far right (baseline at y = 145)
|
||||
drawKmH_AA(tft, 198 + x_offset, 117, cSpd, cardBg, 240, isRainbowTheme());
|
||||
|
||||
// 3. COOLANT TEMP CARD (x: 8, y: 136, w: 148, h: 98)
|
||||
tft.fillRoundRect(8 + x_offset, 136, 148, 98, 5, cardBg);
|
||||
tft.drawRoundRect(8 + x_offset, 136, 148, 98, 5, border);
|
||||
tft.fillRoundRect(12 + x_offset, 140, 3, 90, 1, cCool);
|
||||
drawPidIcon(18 + x_offset, 140, "0105");
|
||||
tft.setTextColor(0x8410, cardBg);
|
||||
tft.drawString("REFRIG.", 38 + x_offset, 142, 2);
|
||||
// Thermal bar rail (x: 18, y: 196, w: 128, h: 8)
|
||||
tft.fillRoundRect(18 + x_offset, 196, 128, 8, 3, 0x0841);
|
||||
tft.drawString("40`C", 18 + x_offset, 210, 1);
|
||||
tft.drawString("120`C", 112 + x_offset, 210, 1);
|
||||
// 3. COOLANT TEMP CARD (x: 8, y: 152, w: 148, h: 84)
|
||||
tft.fillRoundRect(8 + x_offset, 152, 148, 84, 5, cardBg);
|
||||
tft.drawRoundRect(8 + x_offset, 152, 148, 84, 5, border);
|
||||
drawTitRef_AA(tft, 28 + x_offset, 158, cCool, cardBg, 240, isRainbowTheme());
|
||||
drawDegreeC_AA(tft, 117 + x_offset, 198, cCool, cardBg, 240, isRainbowTheme());
|
||||
|
||||
// 4. BATTERY VOLTAGE CARD (x: 164, y: 136, w: 148, h: 98)
|
||||
tft.fillRoundRect(164 + x_offset, 136, 148, 98, 5, cardBg);
|
||||
tft.drawRoundRect(164 + x_offset, 136, 148, 98, 5, border);
|
||||
tft.fillRoundRect(168 + x_offset, 140, 3, 90, 1, cVolt);
|
||||
drawPidIcon(174 + x_offset, 140, "ATRV");
|
||||
tft.setTextColor(0x8410, cardBg);
|
||||
tft.drawString("BATERIA", 194 + x_offset, 142, 2);
|
||||
// Voltage bar rail (x: 174, y: 196, w: 128, h: 8)
|
||||
tft.fillRoundRect(174 + x_offset, 196, 128, 8, 3, 0x0841);
|
||||
tft.drawString("10V", 174 + x_offset, 210, 1);
|
||||
tft.drawString("16V", 272 + x_offset, 210, 1);
|
||||
// 4. BATTERY VOLTAGE CARD (x: 164, y: 152, w: 148, h: 84)
|
||||
tft.fillRoundRect(164 + x_offset, 152, 148, 84, 5, cardBg);
|
||||
tft.drawRoundRect(164 + x_offset, 152, 148, 84, 5, border);
|
||||
drawTitBat_AA(tft, 208 + x_offset, 158, cVolt, cardBg, 240, isRainbowTheme());
|
||||
drawVolt_AA(tft, 286 + x_offset, 198, cVolt, cardBg, 240, isRainbowTheme());
|
||||
}
|
||||
|
||||
// Initial direct draw of Page 4
|
||||
// Initial direct draw of Page 0
|
||||
inline void drawClusterScreen(int x_offset = 0) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
drawClusterDots(x_offset);
|
||||
|
|
@ -149,14 +149,18 @@ inline void drawClusterScreen(int x_offset = 0) {
|
|||
oldClusterCoolant = -999;
|
||||
oldClusterVolt = -999.0f;
|
||||
oldClusterGpsLock = false;
|
||||
oldClusterEco = !isEcoOptimal;
|
||||
oldClusterCoolCol = 0;
|
||||
oldClusterVoltCol = 0;
|
||||
oldClusterSegs = -1;
|
||||
|
||||
void updateClusterScreen(bool forceRedraw = false);
|
||||
updateClusterScreen(true);
|
||||
}
|
||||
|
||||
// Live zero-flicker non-blocking update of Page 4
|
||||
// Live zero-flicker non-blocking update of Page 0 (Cockpit Instrumental)
|
||||
inline void updateClusterScreen(bool forceRedraw) {
|
||||
if (currentScreenPage != 4 || fullScreenCell != -1) return;
|
||||
if (currentScreenPage != 0 || fullScreenCell != -1) return;
|
||||
|
||||
uint16_t cardBg = 0x10A2;
|
||||
uint16_t priCol = getThemePrimaryColor();
|
||||
|
|
@ -175,33 +179,57 @@ inline void updateClusterScreen(bool forceRedraw) {
|
|||
if (forceRedraw || abs(curRpm - oldClusterRpm) >= 20 || (curRpm == 0 && oldClusterRpm != 0)) {
|
||||
oldClusterRpm = curRpm;
|
||||
|
||||
// Erase numeric text area
|
||||
tft.fillRect(222, 14, 84, 26, cardBg);
|
||||
tft.setTextPadding(0);
|
||||
if (curRpm > 0) {
|
||||
uint16_t rpmCol = (curRpm >= 6000) ? TFT_RED : ((curRpm >= 4500) ? 0xFD60 : cRpm);
|
||||
tft.setTextColor(rpmCol, cardBg);
|
||||
String rpmStr = String(curRpm);
|
||||
tft.drawRightString(rpmStr, 302, 16, 4);
|
||||
} else {
|
||||
tft.setTextColor(0x632C, cardBg);
|
||||
tft.drawRightString("---", 302, 16, 4);
|
||||
}
|
||||
|
||||
// Segmented Tachometer Bar (12 segments between x: 78 and 214)
|
||||
// 0 to 7000 RPM -> ~583 RPM per segment
|
||||
int activeSegs = map(constrain(curRpm, 0, 7000), 0, 7000, 0, 12);
|
||||
for (int s = 0; s < 12; s++) {
|
||||
int sx = 78 + s * 11;
|
||||
// Segmented Tachometer Bar on the LEFT (10 segments between x: 20 and 88)
|
||||
int activeSegs = map(constrain(curRpm, 0, 7000), 0, 7000, 0, 10);
|
||||
if (activeSegs != oldClusterSegs || forceRedraw) {
|
||||
oldClusterSegs = activeSegs;
|
||||
for (int s = 0; s < 10; s++) {
|
||||
int sx = 20 + s * 7;
|
||||
uint16_t segCol;
|
||||
if (s < activeSegs) {
|
||||
if (s >= 10) segCol = TFT_RED;
|
||||
else if (s >= 8) segCol = 0xFD60;
|
||||
else segCol = isRainbowTheme() ? getRainbowScreenColor(sx, 20) : cRpm;
|
||||
if (s >= 8) segCol = TFT_RED;
|
||||
else if (s >= 6) segCol = 0xFD60;
|
||||
else segCol = isRainbowTheme() ? getRainbowScreenColor(sx, 20) : (isYapaTheme() ? getYapaColor(s) : cRpm);
|
||||
} else {
|
||||
segCol = 0x0841; // inactive dark track
|
||||
}
|
||||
tft.fillRect(sx, 18, 9, 8, segCol);
|
||||
tft.fillRect(sx, 17, 5, 10, segCol);
|
||||
}
|
||||
}
|
||||
|
||||
// RPM Numeric Value (44pt) rendered with zero-flicker line buffer (x: 100..238, rightX: 238)
|
||||
bool rainbowTxt = isRainbowTheme();
|
||||
if (curRpm > 0) {
|
||||
uint16_t rpmCol = (curRpm >= 6000) ? TFT_RED : ((curRpm >= 4500) ? 0xFD60 : cRpm);
|
||||
String rpmStr = String(curRpm);
|
||||
drawDseg7RightFast44(tft, rpmStr.c_str(), 238, 11, rpmCol, cardBg, 138, rainbowTxt && (rpmCol != TFT_RED));
|
||||
} else {
|
||||
drawDseg7RightFast44(tft, "---", 238, 11, cRpm, cardBg, 138, rainbowTxt);
|
||||
}
|
||||
}
|
||||
|
||||
// ECO Indicator in Card 1 centered directly above RPM unit (x = 248, y = 14, w = 48, h = 17)
|
||||
if (forceRedraw || isEcoOptimal != oldClusterEco) {
|
||||
oldClusterEco = isEcoOptimal;
|
||||
if (isEcoOptimal) {
|
||||
tft.fillRoundRect(248, 14, 48, 17, 3, 0x0202);
|
||||
if (isYapaTheme()) {
|
||||
char buf[2] = {0, 0};
|
||||
const char *ecoStr = "ECO";
|
||||
int ex = 260;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
buf[0] = ecoStr[i];
|
||||
tft.setTextColor(getYapaColor(i), 0x0202);
|
||||
tft.drawString(buf, ex, 15, 2);
|
||||
ex += tft.textWidth(buf, 2);
|
||||
}
|
||||
} else {
|
||||
tft.setTextColor(TFT_WHITE, 0x0202);
|
||||
tft.drawString("ECO", 260, 15, 2);
|
||||
}
|
||||
tft.drawRoundRect(248, 14, 48, 17, 3, 0x07E0);
|
||||
} else {
|
||||
tft.fillRect(248, 14, 48, 17, cardBg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,50 +237,31 @@ inline void updateClusterScreen(bool forceRedraw) {
|
|||
// 2. SPEEDOMETER (VELOCIDAD)
|
||||
// -------------------------------------------------------------
|
||||
float curSpdF = getClusterSpeedVal();
|
||||
int curSpd = (int)round(curSpdF);
|
||||
int curSpd = (curSpdF >= 0.0f) ? (int)round(curSpdF) : -999;
|
||||
bool isGps = isClusterSpeedFromGps();
|
||||
|
||||
if (forceRedraw || curSpd != oldClusterSpd || isGps != oldClusterGpsLock) {
|
||||
oldClusterSpd = curSpd;
|
||||
// GPS Satellite icon in Card 2 centered directly above KM/H (where ECO was): x = 243, y = 82, w = 18, h = 18
|
||||
// Only shows satellite icon if speed comes from GPS; clears when speed is from OBD2
|
||||
if (forceRedraw || isGps != oldClusterGpsLock) {
|
||||
oldClusterGpsLock = isGps;
|
||||
|
||||
// Source Pill (GPS / OBD)
|
||||
tft.fillRect(116, 61, 46, 14, cardBg);
|
||||
if (isGps) {
|
||||
tft.fillRoundRect(116, 61, 42, 14, 3, 0x0254);
|
||||
tft.setTextColor(0x07FF, 0x0254);
|
||||
tft.drawString("GPS", 125, 63, 1);
|
||||
drawGpsSatelliteIcon(tft, 243, 82, 0x07FF, 0x07FF, cardBg, 2);
|
||||
} else {
|
||||
tft.fillRoundRect(116, 61, 42, 14, 3, 0x18C3);
|
||||
tft.setTextColor(0x8410, 0x18C3);
|
||||
tft.drawString("OBD", 125, 63, 1);
|
||||
tft.fillRect(238, 80, 28, 22, cardBg);
|
||||
}
|
||||
}
|
||||
|
||||
// Giant Speed Display
|
||||
tft.fillRect(166, 60, 138, 56, cardBg);
|
||||
if (forceRedraw || curSpd != oldClusterSpd) {
|
||||
oldClusterSpd = curSpd;
|
||||
|
||||
// Giant Speed Display using DSEG7 80pt rendered with zero-flicker line buffer (x: 14..194, rightX: 194)
|
||||
if (curSpd >= 0) {
|
||||
String spdStr = String(curSpd);
|
||||
|
||||
tft.loadFont(DSEG7_Modern_BoldItalic_44);
|
||||
uint16_t spdCol = isRainbowTheme() ? getRainbowScreenColor(210, 80) : cSpd;
|
||||
tft.setTextColor(spdCol, cardBg);
|
||||
tft.drawRightString(spdStr, 248, 64, 1);
|
||||
tft.unloadFont();
|
||||
|
||||
// Unit "km/h"
|
||||
tft.setTextColor(0xBDD7, cardBg);
|
||||
tft.drawString("km/h", 254, 88, 2);
|
||||
|
||||
// Dynamic Bottom Speed Rail (w = 284)
|
||||
int fillSpdW = map(constrain(curSpd, 0, 200), 0, 200, 0, 284);
|
||||
tft.fillRect(18, 124, 284, 3, 0x0841);
|
||||
if (fillSpdW > 0) {
|
||||
if (isRainbowTheme()) {
|
||||
for (int bx = 0; bx < fillSpdW; bx++) {
|
||||
tft.drawFastVLine(18 + bx, 124, 3, getRainbowScreenColor(18 + bx, 124));
|
||||
}
|
||||
uint16_t spdCol = isRainbowTheme() ? getRainbowScreenColor(194, 105) : cSpd;
|
||||
drawDseg7RightFast80(tft, spdStr.c_str(), 194, 65, spdCol, cardBg, 180, isRainbowTheme());
|
||||
} else {
|
||||
tft.fillRect(18, 124, fillSpdW, 3, cSpd);
|
||||
}
|
||||
uint16_t spdCol = isRainbowTheme() ? getRainbowScreenColor(194, 105) : cSpd;
|
||||
drawDseg7RightFast80(tft, "---", 194, 65, spdCol, cardBg, 180, isRainbowTheme());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,27 +273,18 @@ inline void updateClusterScreen(bool forceRedraw) {
|
|||
if (forceRedraw || curCool != oldClusterCoolant) {
|
||||
oldClusterCoolant = curCool;
|
||||
|
||||
tft.fillRect(20, 158, 130, 36, cardBg);
|
||||
if (curCool > -900) {
|
||||
uint16_t coolCol = (curCool >= 105) ? TFT_RED : ((curCool < 70) ? 0x05BF : cCool);
|
||||
tft.setTextColor(coolCol, cardBg);
|
||||
String valStr = String(curCool);
|
||||
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
||||
tft.drawRightString(valStr, 102, 160, 1);
|
||||
tft.unloadFont();
|
||||
bool rainbowTxt = isRainbowTheme();
|
||||
drawDseg7RightFast44(tft, valStr.c_str(), 112, 179, coolCol, cardBg, 102, rainbowTxt && (coolCol != TFT_RED));
|
||||
|
||||
draw7SegDegreeC(tft, 106, 164, coolCol, cardBg, isRainbowTheme());
|
||||
|
||||
// Progress bar (40 to 120 °C)
|
||||
int barW = map(constrain(curCool, 40, 120), 40, 120, 0, 128);
|
||||
tft.fillRect(18, 196, 128, 8, 0x0841);
|
||||
if (barW > 0) {
|
||||
tft.fillRoundRect(18, 196, barW, 8, 2, coolCol);
|
||||
if (coolCol != oldClusterCoolCol || forceRedraw) {
|
||||
oldClusterCoolCol = coolCol;
|
||||
drawDegreeC_AA(tft, 117, 198, coolCol, cardBg, 240, rainbowTxt);
|
||||
}
|
||||
} else {
|
||||
tft.setTextColor(0x632C, cardBg);
|
||||
tft.drawString("---", 60, 164, 4);
|
||||
tft.fillRect(18, 196, 128, 8, 0x0841);
|
||||
drawDseg7RightFast44(tft, "---", 112, 179, cCool, cardBg, 102, isRainbowTheme());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -295,35 +295,24 @@ inline void updateClusterScreen(bool forceRedraw) {
|
|||
if (forceRedraw || abs(curVolt - oldClusterVolt) >= 0.08f) {
|
||||
oldClusterVolt = curVolt;
|
||||
|
||||
tft.fillRect(174, 158, 130, 36, cardBg);
|
||||
if (curVolt > 0.0f) {
|
||||
uint16_t voltCol = (curVolt < 11.8f || curVolt > 15.0f) ? TFT_RED : ((curVolt >= 13.5f) ? 0x07E0 : cVolt);
|
||||
String voltStr = String(curVolt, 1);
|
||||
bool rainbowTxt = isRainbowTheme();
|
||||
drawDseg7RightFast44(tft, voltStr.c_str(), 282, 179, voltCol, cardBg, 112, rainbowTxt && (voltCol != TFT_RED));
|
||||
|
||||
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
||||
tft.setTextColor(voltCol, cardBg);
|
||||
tft.drawRightString(voltStr, 268, 160, 1);
|
||||
tft.unloadFont();
|
||||
|
||||
tft.setTextColor(0xBDD7, cardBg);
|
||||
tft.drawString("V", 274, 172, 2);
|
||||
|
||||
// Voltage bar (10.0 to 16.0 V)
|
||||
int vBarW = map(constrain((int)(curVolt * 10), 100, 160), 100, 160, 0, 128);
|
||||
tft.fillRect(174, 196, 128, 8, 0x0841);
|
||||
if (vBarW > 0) {
|
||||
tft.fillRoundRect(174, 196, vBarW, 8, 2, voltCol);
|
||||
if (voltCol != oldClusterVoltCol || forceRedraw) {
|
||||
oldClusterVoltCol = voltCol;
|
||||
drawVolt_AA(tft, 286, 198, voltCol, cardBg, 240, rainbowTxt);
|
||||
}
|
||||
} else {
|
||||
tft.setTextColor(0x632C, cardBg);
|
||||
tft.drawString("---", 216, 164, 4);
|
||||
tft.fillRect(174, 196, 128, 8, 0x0841);
|
||||
drawDseg7RightFast44(tft, "---", 282, 179, cVolt, cardBg, 112, isRainbowTheme());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render Page 4 slice-by-slice into sprite (for double-buffered transitions)
|
||||
inline void renderPage4ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int slice_h) {
|
||||
// Render Cluster Screen (Page 0) slice-by-slice into sprite (for double-buffered transitions)
|
||||
inline void renderClusterScreenToSprite(TFT_eSprite &s, int x_offset, int y_slice, int slice_h) {
|
||||
uint16_t cardBg = 0x10A2;
|
||||
uint16_t border = 0x2945;
|
||||
uint16_t priCol = getThemePrimaryColor();
|
||||
|
|
@ -334,157 +323,148 @@ inline void renderPage4ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int s
|
|||
uint16_t cCool = isRainbowTheme() ? getRainbowScreenColor(20, 150) : (isYapaTheme() ? getYapaColor(2) : priCol);
|
||||
uint16_t cVolt = isRainbowTheme() ? getRainbowScreenColor(180, 150) : (isYapaTheme() ? getYapaColor(3) : accCol);
|
||||
|
||||
// Pagination dots on top slice (page 4 active)
|
||||
// Pagination dots on top slice (page 0 active of 4 pages)
|
||||
if (y_slice == 0) {
|
||||
uint16_t actCol = isRainbowTheme() ? getRainbowScreenColor(188, 2) : (isYapaTheme() ? getYapaColor(4) : priCol);
|
||||
s.fillCircle(132, 2, 2, 0x5AEB);
|
||||
s.fillCircle(146, 2, 2, 0x5AEB);
|
||||
s.fillCircle(160, 2, 2, 0x5AEB);
|
||||
s.fillCircle(174, 2, 2, 0x5AEB);
|
||||
s.fillCircle(188, 2, 2, actCol);
|
||||
uint16_t actCol = isRainbowTheme() ? getRainbowScreenColor(139, 2) : (isYapaTheme() ? getYapaColor(0) : priCol);
|
||||
s.fillCircle(139, 2, 2, actCol);
|
||||
s.fillCircle(153, 2, 2, 0x5AEB);
|
||||
s.fillCircle(167, 2, 2, 0x5AEB);
|
||||
s.fillCircle(181, 2, 2, 0x5AEB);
|
||||
}
|
||||
|
||||
// 1. TACHOMETER CARD (y: 10 to 52)
|
||||
int c0Y = 10 - y_slice;
|
||||
if (c0Y < slice_h && c0Y + 42 > 0) {
|
||||
s.fillRoundRect(8, c0Y, 304, 42, 5, cardBg);
|
||||
s.drawRoundRect(8, c0Y, 304, 42, 5, border);
|
||||
s.fillRoundRect(12, c0Y + 4, 3, 34, 1, cRpm);
|
||||
drawPidIconToSprite(s, 18, c0Y + 4, "010C", y_slice, slice_h, 10);
|
||||
s.setTextColor(0x8410, cardBg);
|
||||
s.drawString("RPM", 38, c0Y + 6, 2);
|
||||
|
||||
// Tachometer background rail
|
||||
s.fillRoundRect(76, c0Y + 6, 140, 12, 3, 0x0841);
|
||||
s.drawString("1 2 3 4 5 6 7", 86, c0Y + 21, 1);
|
||||
// 1. TACHOMETER CARD (y: 8 to 58)
|
||||
int c0Y = 8 - y_slice;
|
||||
if (c0Y < slice_h && c0Y + 50 > 0) {
|
||||
s.fillRoundRect(8, c0Y, 304, 50, 5, cardBg);
|
||||
s.drawRoundRect(8, c0Y, 304, 50, 5, border);
|
||||
s.setTextColor(cRpm, cardBg);
|
||||
// Tachometer background rail on the LEFT
|
||||
s.fillRoundRect(18, c0Y + 7, 72, 14, 3, 0x0841);
|
||||
if (isYapaTheme()) {
|
||||
int sx = 20;
|
||||
char buf[2] = {0, 0};
|
||||
for (int i = 0; i < 7; i++) {
|
||||
buf[0] = '1' + i;
|
||||
s.setTextColor(getYapaColor(i), cardBg);
|
||||
s.drawString(buf, sx, c0Y + 24, 1);
|
||||
sx += s.textWidth(buf, 1) + s.textWidth(" ", 1);
|
||||
}
|
||||
} else {
|
||||
s.setTextColor(cRpm, cardBg);
|
||||
s.drawString("1 2 3 4 5 6 7", 20, c0Y + 24, 1);
|
||||
}
|
||||
|
||||
float curRpmF = getClusterRpmVal();
|
||||
int curRpm = (int)round(curRpmF);
|
||||
bool rainbowTxt = isRainbowTheme();
|
||||
int digitY = c0Y + 3;
|
||||
if (curRpm > 0) {
|
||||
uint16_t rpmCol = (curRpm >= 6000) ? TFT_RED : ((curRpm >= 4500) ? 0xFD60 : cRpm);
|
||||
s.setTextColor(rpmCol, cardBg);
|
||||
s.drawRightString(String(curRpm), 302, c0Y + 6, 4);
|
||||
String rpmStr = String(curRpm);
|
||||
drawDseg7RightString44(s, rpmStr.c_str(), 238, digitY, rpmCol, cardBg, 0, slice_h, rainbowTxt && (rpmCol != TFT_RED));
|
||||
|
||||
int activeSegs = map(constrain(curRpm, 0, 7000), 0, 7000, 0, 12);
|
||||
for (int seg = 0; seg < 12; seg++) {
|
||||
int sx = 78 + seg * 11;
|
||||
int activeSegs = map(constrain(curRpm, 0, 7000), 0, 7000, 0, 10);
|
||||
for (int seg = 0; seg < 10; seg++) {
|
||||
int sx = 20 + seg * 7;
|
||||
uint16_t segCol = 0x0841;
|
||||
if (seg < activeSegs) {
|
||||
if (seg >= 10) segCol = TFT_RED;
|
||||
else if (seg >= 8) segCol = 0xFD60;
|
||||
else segCol = isRainbowTheme() ? getRainbowScreenColor(sx, 20) : cRpm;
|
||||
if (seg >= 8) segCol = TFT_RED;
|
||||
else if (seg >= 6) segCol = 0xFD60;
|
||||
else segCol = isRainbowTheme() ? getRainbowScreenColor(sx, 20) : (isYapaTheme() ? getYapaColor(seg) : cRpm);
|
||||
}
|
||||
s.fillRect(sx, c0Y + 8, 9, 8, segCol);
|
||||
s.fillRect(sx, c0Y + 9, 5, 10, segCol);
|
||||
}
|
||||
} else {
|
||||
s.setTextColor(0x632C, cardBg);
|
||||
s.drawRightString("---", 302, c0Y + 6, 4);
|
||||
drawDseg7RightString44(s, "---", 238, digitY, cRpm, cardBg, 0, slice_h, rainbowTxt);
|
||||
}
|
||||
|
||||
drawRpm_AA(s, 242, c0Y + 27, cRpm, cardBg, slice_h, isRainbowTheme());
|
||||
|
||||
if (isEcoOptimal) {
|
||||
s.fillRoundRect(248, c0Y + 6, 48, 17, 3, 0x0202);
|
||||
if (isYapaTheme()) {
|
||||
char buf[2] = {0, 0};
|
||||
const char *ecoStr = "ECO";
|
||||
int ex = 260;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
buf[0] = ecoStr[i];
|
||||
s.setTextColor(getYapaColor(i), 0x0202);
|
||||
s.drawString(buf, ex, c0Y + 7, 2);
|
||||
ex += s.textWidth(buf, 2);
|
||||
}
|
||||
} else {
|
||||
s.setTextColor(TFT_WHITE, 0x0202);
|
||||
s.drawString("ECO", 260, c0Y + 7, 2);
|
||||
}
|
||||
s.drawRoundRect(248, c0Y + 6, 48, 17, 3, 0x07E0);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. SPEEDOMETER CARD (y: 56 to 132)
|
||||
int c1Y = 56 - y_slice;
|
||||
if (c1Y < slice_h && c1Y + 76 > 0) {
|
||||
s.fillRoundRect(8, c1Y, 304, 76, 5, cardBg);
|
||||
s.drawRoundRect(8, c1Y, 304, 76, 5, border);
|
||||
s.fillRoundRect(12, c1Y + 4, 3, 68, 1, cSpd);
|
||||
drawPidIconToSprite(s, 18, c1Y + 4, "010D", y_slice, slice_h, 56);
|
||||
s.setTextColor(0x8410, cardBg);
|
||||
s.drawString("VELOCIDAD", 38, c1Y + 6, 2);
|
||||
// 2. SPEEDOMETER CARD (y: 62 to 148)
|
||||
int c1Y = 62 - y_slice;
|
||||
if (c1Y < slice_h && c1Y + 86 > 0) {
|
||||
s.fillRoundRect(8, c1Y, 304, 86, 5, cardBg);
|
||||
s.drawRoundRect(8, c1Y, 304, 86, 5, border);
|
||||
|
||||
bool isGps = isClusterSpeedFromGps();
|
||||
if (isGps) {
|
||||
s.fillRoundRect(116, c1Y + 5, 42, 14, 3, 0x0254);
|
||||
s.setTextColor(0x07FF, 0x0254);
|
||||
s.drawString("GPS", 125, c1Y + 7, 1);
|
||||
} else {
|
||||
s.fillRoundRect(116, c1Y + 5, 42, 14, 3, 0x18C3);
|
||||
s.setTextColor(0x8410, 0x18C3);
|
||||
s.drawString("OBD", 125, c1Y + 7, 1);
|
||||
drawGpsSatelliteIcon(s, 243, c1Y + 20, 0x07FF, 0x07FF, cardBg, 2);
|
||||
}
|
||||
|
||||
int curSpd = (int)round(getClusterSpeedVal());
|
||||
float curSpdF = getClusterSpeedVal();
|
||||
int curSpd = (curSpdF >= 0.0f) ? (int)round(curSpdF) : -999;
|
||||
int digitY = c1Y + 3;
|
||||
uint16_t spdCol = isRainbowTheme() ? getRainbowScreenColor(240, 105) : cSpd;
|
||||
if (curSpd >= 0) {
|
||||
String spdStr = String(curSpd);
|
||||
s.loadFont(DSEG7_Modern_BoldItalic_44);
|
||||
uint16_t spdCol = isRainbowTheme() ? getRainbowScreenColor(210, 80) : cSpd;
|
||||
s.setTextColor(spdCol, cardBg);
|
||||
s.drawRightString(spdStr, 248, c1Y + 8, 1);
|
||||
s.unloadFont();
|
||||
|
||||
s.setTextColor(0xBDD7, cardBg);
|
||||
s.drawString("km/h", 254, c1Y + 32, 2);
|
||||
|
||||
int fillSpdW = map(constrain(curSpd, 0, 200), 0, 200, 0, 284);
|
||||
s.fillRect(18, c1Y + 68, 284, 3, 0x0841);
|
||||
if (fillSpdW > 0) {
|
||||
s.fillRect(18, c1Y + 68, fillSpdW, 3, cSpd);
|
||||
}
|
||||
drawDseg7RightString80(s, spdStr.c_str(), 194, digitY, spdCol, cardBg, 0, slice_h, isRainbowTheme());
|
||||
} else {
|
||||
drawDseg7RightString80(s, "---", 194, digitY, spdCol, cardBg, 0, slice_h, isRainbowTheme());
|
||||
}
|
||||
|
||||
// 3. COOLANT TEMP CARD (y: 136 to 234)
|
||||
int c2Y = 136 - y_slice;
|
||||
if (c2Y < slice_h && c2Y + 98 > 0) {
|
||||
s.fillRoundRect(8, c2Y, 148, 98, 5, cardBg);
|
||||
s.drawRoundRect(8, c2Y, 148, 98, 5, border);
|
||||
s.fillRoundRect(12, c2Y + 4, 3, 90, 1, cCool);
|
||||
drawPidIconToSprite(s, 18, c2Y + 4, "0105", y_slice, slice_h, 136);
|
||||
s.setTextColor(0x8410, cardBg);
|
||||
s.drawString("REFRIG.", 38, c2Y + 6, 2);
|
||||
drawKmH_AA(s, 198, c1Y + 55, cSpd, cardBg, slice_h, isRainbowTheme());
|
||||
}
|
||||
|
||||
s.fillRect(18, c2Y + 60, 128, 8, 0x0841);
|
||||
s.drawString("40`C", 18, c2Y + 74, 1);
|
||||
s.drawString("120`C", 112, c2Y + 74, 1);
|
||||
// 3. COOLANT TEMP CARD (y: 152 to 236)
|
||||
int c2Y = 152 - y_slice;
|
||||
if (c2Y < slice_h && c2Y + 84 > 0) {
|
||||
s.fillRoundRect(8, c2Y, 148, 84, 5, cardBg);
|
||||
s.drawRoundRect(8, c2Y, 148, 84, 5, border);
|
||||
drawTitRef_AA(s, 28, c2Y + 6, cCool, cardBg, slice_h, isRainbowTheme());
|
||||
|
||||
float curCoolF = getClusterCoolantVal();
|
||||
int curCool = (curCoolF > -900.0f) ? (int)round(curCoolF) : -999;
|
||||
if (curCool > -900) {
|
||||
uint16_t coolCol = (curCool >= 105) ? TFT_RED : ((curCool < 70) ? 0x05BF : cCool);
|
||||
s.loadFont(DSEG7_Modern_BoldItalic_34);
|
||||
s.setTextColor(coolCol, cardBg);
|
||||
s.drawRightString(String(curCool), 102, c2Y + 24, 1);
|
||||
s.unloadFont();
|
||||
String valStr = String(curCool);
|
||||
bool rainbowTxt = isRainbowTheme();
|
||||
int rightX = (valStr.length() >= 3) ? 112 : 106;
|
||||
drawDseg7RightString44(s, valStr.c_str(), rightX, c2Y + 27, coolCol, cardBg, 0, slice_h, rainbowTxt && (coolCol != TFT_RED));
|
||||
|
||||
int barW = map(constrain(curCool, 40, 120), 40, 120, 0, 128);
|
||||
if (barW > 0) {
|
||||
s.fillRoundRect(18, c2Y + 60, barW, 8, 2, coolCol);
|
||||
}
|
||||
drawDegreeC_AA(s, 117, c2Y + 46, coolCol, cardBg, slice_h, isRainbowTheme());
|
||||
} else {
|
||||
s.setTextColor(0x632C, cardBg);
|
||||
s.drawString("---", 60, c2Y + 28, 4);
|
||||
drawDseg7RightString44(s, "---", 112, c2Y + 27, cCool, cardBg, 0, slice_h, isRainbowTheme());
|
||||
}
|
||||
}
|
||||
|
||||
// 4. BATTERY VOLTAGE CARD (y: 136 to 234)
|
||||
int c3Y = 136 - y_slice;
|
||||
if (c3Y < slice_h && c3Y + 98 > 0) {
|
||||
s.fillRoundRect(164, c3Y, 148, 98, 5, cardBg);
|
||||
s.drawRoundRect(164, c3Y, 148, 98, 5, border);
|
||||
s.fillRoundRect(168, c3Y + 4, 3, 90, 1, cVolt);
|
||||
drawPidIconToSprite(s, 174, c3Y + 4, "ATRV", y_slice, slice_h, 136);
|
||||
s.setTextColor(0x8410, cardBg);
|
||||
s.drawString("BATERIA", 194, c3Y + 6, 2);
|
||||
|
||||
s.fillRect(174, c3Y + 60, 128, 8, 0x0841);
|
||||
s.drawString("10V", 174, c3Y + 74, 1);
|
||||
s.drawString("16V", 272, c3Y + 74, 1);
|
||||
// 4. BATTERY VOLTAGE CARD (y: 152 to 236)
|
||||
int c3Y = 152 - y_slice;
|
||||
if (c3Y < slice_h && c3Y + 84 > 0) {
|
||||
s.fillRoundRect(164, c3Y, 148, 84, 5, cardBg);
|
||||
s.drawRoundRect(164, c3Y, 148, 84, 5, border);
|
||||
drawTitBat_AA(s, 208, c3Y + 6, cVolt, cardBg, slice_h, isRainbowTheme());
|
||||
|
||||
float curVolt = getClusterVoltVal();
|
||||
if (curVolt > 0.0f) {
|
||||
uint16_t voltCol = (curVolt < 11.8f || curVolt > 15.0f) ? TFT_RED : ((curVolt >= 13.5f) ? 0x07E0 : cVolt);
|
||||
s.loadFont(DSEG7_Modern_BoldItalic_34);
|
||||
s.setTextColor(voltCol, cardBg);
|
||||
s.drawRightString(String(curVolt, 1), 268, c3Y + 24, 1);
|
||||
s.unloadFont();
|
||||
s.setTextColor(0xBDD7, cardBg);
|
||||
s.drawString("V", 274, c3Y + 36, 2);
|
||||
String voltStr = String(curVolt, 1);
|
||||
bool rainbowTxt = isRainbowTheme();
|
||||
drawDseg7RightString44(s, voltStr.c_str(), 282, c3Y + 27, voltCol, cardBg, 0, slice_h, rainbowTxt && (voltCol != TFT_RED));
|
||||
|
||||
int vBarW = map(constrain((int)(curVolt * 10), 100, 160), 100, 160, 0, 128);
|
||||
if (vBarW > 0) {
|
||||
s.fillRoundRect(174, c3Y + 60, vBarW, 8, 2, voltCol);
|
||||
}
|
||||
drawVolt_AA(s, 286, c3Y + 46, voltCol, cardBg, slice_h, isRainbowTheme());
|
||||
} else {
|
||||
s.setTextColor(0x632C, cardBg);
|
||||
s.drawString("---", 216, c3Y + 28, 4);
|
||||
drawDseg7RightString44(s, "---", 282, c3Y + 27, cVolt, cardBg, 0, slice_h, isRainbowTheme());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -609,6 +609,45 @@ inline void drawGpsNavSubword(T &dst, const char *str, int x, int y, uint16_t co
|
|||
}
|
||||
}
|
||||
|
||||
// Calculate exact pixel width of anti-aliased Subword string
|
||||
inline int getNavSubwordWidth(const char *str) {
|
||||
int totalW = 0;
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
char c = str[i];
|
||||
int gIdx = -1;
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
gIdx = c - 'A';
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
gIdx = c - 'a';
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
gIdx = 26 + (c - '0');
|
||||
} else if (c == ':') {
|
||||
gIdx = 36;
|
||||
} else if (c == '.') {
|
||||
gIdx = 37;
|
||||
} else if (c == '-') {
|
||||
gIdx = 38;
|
||||
} else if ((uint8_t)c == 0xC2 && (uint8_t)str[i + 1] == 0xB0) {
|
||||
gIdx = 39;
|
||||
i++;
|
||||
} else if ((uint8_t)c == 0xB0 || c == '`') {
|
||||
gIdx = 39;
|
||||
} else if (c == '/') {
|
||||
gIdx = 40;
|
||||
} else if (c == ' ') {
|
||||
gIdx = 41;
|
||||
}
|
||||
|
||||
if (gIdx >= 0) {
|
||||
CoordsGlyphAA g;
|
||||
memcpy_P(&g, &s_navSubGlyphs[gIdx], sizeof(CoordsGlyphAA));
|
||||
totalW += g.xAdv;
|
||||
}
|
||||
}
|
||||
return totalW;
|
||||
}
|
||||
|
||||
|
||||
// 3. Draw 100% anti-aliased Coordinate Value (e.g. "-34.60371°" or "--.-----°")
|
||||
template <typename T>
|
||||
inline void drawCoordsAAValue(T &dst, const char *str, int x, int y, uint16_t color, uint16_t bgCol, int clip_h = 240) {
|
||||
|
|
|
|||
|
|
@ -348,12 +348,11 @@ inline void drawGpsClockScreen(int x_offset = 0) {
|
|||
uint16_t cardBorder = 0x2945; // Subtle edge border
|
||||
bool synced = isGpsSynced();
|
||||
|
||||
// Center: 5 Pagination Indicator Dots [○ ○ ● ○ ○] (Page 2 of 5 active)
|
||||
tft.fillCircle(132 + x_offset, 2, 2, 0x5AEB); // Page 0 inactive
|
||||
tft.fillCircle(146 + x_offset, 2, 2, 0x5AEB); // Page 1 inactive
|
||||
tft.fillCircle(160 + x_offset, 2, 2, priCol); // Page 2 active
|
||||
tft.fillCircle(174 + x_offset, 2, 2, 0x5AEB); // Page 3 inactive
|
||||
tft.fillCircle(188 + x_offset, 2, 2, 0x5AEB); // Page 4 inactive
|
||||
// Center: 4 Pagination Indicator Dots [○ ○ ● ○] (Page 2 of 4 active)
|
||||
tft.fillCircle(139 + x_offset, 2, 2, 0x5AEB); // Page 0 inactive
|
||||
tft.fillCircle(153 + x_offset, 2, 2, 0x5AEB); // Page 1 inactive
|
||||
tft.fillCircle(167 + x_offset, 2, 2, priCol); // Page 2 active
|
||||
tft.fillCircle(181 + x_offset, 2, 2, 0x5AEB); // Page 3 inactive
|
||||
|
||||
// 2. MAIN CLOCK CARD (y = 19 to 121, height = 102, width = 312, x = 4)
|
||||
int clkX = 4 + x_offset;
|
||||
|
|
|
|||
|
|
@ -1,91 +1,88 @@
|
|||
// Generated from accurate vector model matching gps_icon.jpg / gps_icon.svg
|
||||
// Generated from accurate vector model matching gps_icon.png / gps_icon.svg
|
||||
// 8-bit Subpixel Antialiased Alpha Maps (0..255)
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
static const uint8_t GPS_BODY_AA_18[324] PROGMEM = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 201, 255, 99, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 48, 26, 54, 255, 255, 250, 106, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 171, 255, 238, 115, 216, 211, 55, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 77, 255, 250, 255, 223, 33, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 32, 96, 255, 251, 255, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 106, 240, 183, 165, 255, 243, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 172, 255, 255, 213, 0, 45, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 160, 255, 147, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 28, 27, 0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 2, 2, 4, 0, 56, 231, 231, 22, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 64, 252, 255, 209, 24, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 45, 184, 182, 102, 233, 174, 10, 0, 1, 0, 0, 0, 0,
|
||||
0, 0, 1, 4, 7, 209, 255, 255, 212, 34, 1, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 4, 0, 0, 233, 254, 252, 250, 13, 0, 2, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 76, 155, 128, 249, 255, 130, 1, 3, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 5, 107, 249, 255, 101, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 23, 255, 255, 153, 17, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 91, 118, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static const uint8_t GPS_WAVE1_AA_18[324] PROGMEM = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 18, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 185, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 255, 199, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 254, 137, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 255, 44, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 51, 193, 255, 151, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 29, 227, 225, 229, 255, 255, 152, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 23, 199, 234, 226, 167, 66, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 12, 201, 107, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 32, 255, 162, 0, 4, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 6, 0, 77, 253, 111, 0, 4, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 207, 252, 33, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 12, 11, 61, 198, 255, 125, 0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 174, 248, 242, 255, 255, 135, 0, 3, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 104, 191, 190, 141, 51, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 3, 2, 2, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static const uint8_t GPS_WAVE2_AA_18[324] PROGMEM = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 96, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 255, 84, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 239, 82, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 243, 53, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 229, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 245, 137, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 210, 232, 42, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 182, 248, 112, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 201, 255, 142, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 88, 124, 88, 96, 142, 198, 254, 242, 128, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 234, 255, 255, 255, 255, 244, 151, 57, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 48, 94, 111, 103, 73, 25, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 12, 15, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 187, 210, 2, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 241, 3, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 238, 212, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 51, 255, 158, 0, 4,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 162, 255, 69, 0, 3,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 73, 255, 201, 3, 2, 0,
|
||||
0, 0, 0, 0, 2, 1, 3, 3, 1, 0, 0, 69, 242, 248, 48, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 142, 255, 253, 81, 0, 3, 0, 0,
|
||||
0, 0, 3, 0, 79, 205, 175, 176, 211, 255, 255, 210, 60, 0, 3, 0, 0, 0,
|
||||
0, 0, 3, 0, 87, 239, 255, 255, 239, 184, 93, 6, 0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 7, 25, 25, 9, 0, 0, 0, 2, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 3, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static const uint8_t GPS_BODY_AA_28[784] PROGMEM = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 213, 255, 255, 66, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 255, 255, 244, 255, 201, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 49, 29, 0, 124, 255, 249, 251, 255, 220, 70, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 120, 235, 255, 242, 135, 38, 241, 255, 255, 155, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 94, 255, 255, 254, 255, 255, 106, 87, 210, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 200, 253, 251, 255, 252, 252, 227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 218, 253, 253, 255, 254, 254, 238, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 115, 40, 149, 255, 247, 252, 248, 255, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 54, 201, 255, 213, 33, 216, 255, 255, 255, 237, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 126, 250, 255, 243, 255, 133, 16, 130, 169, 137, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 155, 255, 251, 249, 255, 229, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 110, 255, 255, 255, 169, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 181, 234, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 32, 58, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 62, 231, 255, 65, 0, 3, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 3, 0, 98, 249, 255, 254, 234, 8, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 126, 255, 251, 253, 255, 127, 3, 2, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 0, 40, 114, 112, 26, 132, 255, 255, 246, 91, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 3, 0, 84, 246, 255, 255, 234, 53, 171, 225, 55, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 15, 234, 255, 249, 249, 255, 208, 5, 13, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 4, 3, 54, 255, 253, 255, 254, 253, 249, 28, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 2, 0, 0, 18, 252, 252, 251, 250, 253, 232, 13, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 4, 0, 21, 173, 87, 117, 255, 255, 255, 255, 111, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 51, 219, 255, 248, 65, 97, 187, 180, 89, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 2, 1, 84, 243, 255, 245, 255, 136, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 24, 255, 254, 251, 255, 143, 5, 5, 3, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 2, 3, 145, 255, 251, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 134, 69, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
|
@ -96,29 +93,28 @@ static const uint8_t GPS_BODY_AA_28[784] PROGMEM = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static const uint8_t GPS_WAVE1_AA_28[784] PROGMEM = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 166, 81, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 255, 245, 20, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 252, 244, 26, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 249, 213, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 249, 243, 158, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 236, 239, 106, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 240, 230, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 250, 233, 231, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 79, 76, 51, 68, 116, 193, 249, 232, 255, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 119, 255, 255, 248, 246, 255, 255, 242, 224, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 142, 255, 255, 255, 249, 255, 229, 149, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 123, 149, 157, 140, 103, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 176, 241, 83, 0, 3, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 22, 245, 255, 162, 0, 4, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 32, 245, 254, 144, 0, 4, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 83, 255, 255, 105, 0, 4, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 192, 254, 251, 38, 0, 2, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 0, 0, 117, 255, 255, 177, 0, 3, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 131, 255, 253, 247, 40, 1, 2, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 2, 0, 42, 117, 91, 95, 141, 219, 255, 255, 255, 86, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 2, 219, 255, 255, 255, 255, 255, 255, 230, 78, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 2, 1, 165, 255, 255, 255, 252, 218, 135, 24, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 50, 75, 73, 46, 7, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
|
@ -127,34 +123,33 @@ static const uint8_t GPS_WAVE1_AA_28[784] PROGMEM = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static const uint8_t GPS_WAVE2_AA_28[784] PROGMEM = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 199, 227, 71, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 255, 255, 179, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 248, 252, 171, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 225, 232, 133, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 228, 225, 106, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 224, 226, 68, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 193, 238, 179, 21, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 243, 227, 119, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 180, 228, 189, 49, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 221, 236, 154, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 243, 233, 192, 34, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 240, 243, 241, 88, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 167, 228, 232, 242, 134, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 74, 144, 225, 244, 229, 235, 121, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 84, 218, 199, 159, 175, 166, 177, 221, 238, 247, 243, 253, 183, 77, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 214, 255, 255, 255, 255, 255, 244, 237, 247, 248, 186, 126, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 107, 238, 242, 231, 255, 245, 224, 196, 175, 102, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 21, 43, 63, 80, 70, 47, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30, 88, 13, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 203, 255, 157, 0, 3, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 11, 230, 252, 197, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 15, 230, 255, 185, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 36, 248, 255, 164, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 83, 255, 255, 121, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 164, 255, 255, 58, 0, 3, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 29, 243, 254, 218, 6, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 162, 255, 255, 117, 0, 4, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 89, 255, 253, 228, 14, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 72, 248, 250, 255, 80, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 3, 3, 4, 4, 0, 0, 0, 107, 250, 250, 255, 138, 0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 67, 186, 255, 253, 255, 153, 0, 3, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 2, 0, 57, 125, 90, 71, 73, 96, 143, 207, 255, 255, 255, 254, 124, 0, 2, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 12, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 196, 62, 0, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 6, 191, 255, 255, 255, 255, 255, 255, 232, 171, 77, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 0, 8, 63, 97, 115, 113, 93, 59, 17, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 3, 4, 4, 4, 4, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ extern Preferences pref;
|
|||
|
||||
static const uint32_t CANDIDATE_BAUDS[4] = {38400, 115200, 9600, 57600};
|
||||
static const char *const CANDIDATE_LABELS[4] = {
|
||||
"BUSCANDO: 38400", "BUSCANDO: 115K", "BUSCANDO: 9600", "BUSCANDO: 57.6K"};
|
||||
"BUSCANDO: 38.4 KBPS", "BUSCANDO: 115.2 KBPS", "BUSCANDO: 9.6 KBPS", "BUSCANDO: 57.6 KBPS"};
|
||||
|
||||
static uint32_t activeGpsBaud = 38400;
|
||||
static bool gpsUartLocked = false;
|
||||
|
|
@ -305,7 +305,17 @@ inline void processGPS() {
|
|||
gpsUartLocked = true;
|
||||
activeGpsBaud = CANDIDATE_BAUDS[gpsBaudScanIdx];
|
||||
pref.putUInt("gps_baud", activeGpsBaud); // Guardar velocidad exacta en NVRAM!
|
||||
if (activeGpsBaud == 115200) {
|
||||
snprintf(gpsDiagLabel, sizeof(gpsDiagLabel), "FIJADO: 115.2 KBPS");
|
||||
} else if (activeGpsBaud == 57600) {
|
||||
snprintf(gpsDiagLabel, sizeof(gpsDiagLabel), "FIJADO: 57.6 KBPS");
|
||||
} else if (activeGpsBaud == 38400) {
|
||||
snprintf(gpsDiagLabel, sizeof(gpsDiagLabel), "FIJADO: 38.4 KBPS");
|
||||
} else if (activeGpsBaud == 9600) {
|
||||
snprintf(gpsDiagLabel, sizeof(gpsDiagLabel), "FIJADO: 9.6 KBPS");
|
||||
} else {
|
||||
snprintf(gpsDiagLabel, sizeof(gpsDiagLabel), "FIJADO: %lu BPS", (unsigned long)activeGpsBaud);
|
||||
}
|
||||
configureGpsModule();
|
||||
}
|
||||
}
|
||||
|
|
@ -533,6 +543,26 @@ inline bool isGpsSerialReceiving() {
|
|||
}
|
||||
inline bool isGpsUartLocked() { return gpsUartLocked; }
|
||||
|
||||
// DOP Precision Rating matching standard DOP table (dop.png)
|
||||
inline const char *getGpsDopRating() {
|
||||
if (gpsHdop < 1.0f) return "IDEAL";
|
||||
if (gpsHdop < 2.0f) return "EXCELENTE";
|
||||
if (gpsHdop < 5.0f) return "BUENA";
|
||||
if (gpsHdop < 10.0f) return "MODERADA";
|
||||
if (gpsHdop <= 20.0f) return "REGULAR";
|
||||
return "POBRE";
|
||||
}
|
||||
|
||||
inline uint16_t getGpsDopColor() {
|
||||
if (!isGpsSynced()) return 0x9CD3;
|
||||
if (gpsHdop < 1.0f) return 0x07FF; // Cyan (Ideal)
|
||||
if (gpsHdop < 2.0f) return 0x07E0; // Verde (Excelente)
|
||||
if (gpsHdop < 5.0f) return 0xFFE0; // Amarillo (Buena)
|
||||
if (gpsHdop < 10.0f) return 0xFD20; // Naranja (Moderada)
|
||||
if (gpsHdop <= 20.0f) return 0xFA60; // Naranja oscuro (Regular)
|
||||
return TFT_RED; // Rojo (Pobre)
|
||||
}
|
||||
|
||||
inline const char *getGpsDiagMessage() {
|
||||
if (gpsIsSleeping)
|
||||
return "MODO REPOSO";
|
||||
|
|
@ -543,7 +573,7 @@ inline const char *getGpsDiagMessage() {
|
|||
return "SIN DATOS RX";
|
||||
}
|
||||
if (isGpsSynced()) {
|
||||
return "PRECISION OPTIMA";
|
||||
return getGpsDopRating();
|
||||
}
|
||||
if (gpsSats > 0) {
|
||||
return "SINTONIZANDO SATS";
|
||||
|
|
|
|||
|
|
@ -40,9 +40,22 @@ static uint8_t oldNavWaveState = 255;
|
|||
static bool oldNavSynced = false;
|
||||
static uint32_t lastNavPageEnterTime = 0;
|
||||
|
||||
static TFT_eSprite sprNavDiag(&tft);
|
||||
static bool sprNavDiagAllocated = false;
|
||||
|
||||
inline void initNavDiagSprite() {
|
||||
if (!sprNavDiagAllocated) {
|
||||
if (sprNavDiag.createSprite(138, 16) != nullptr) {
|
||||
sprNavDiagAllocated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronize tracking variables without touching TFT display (zero flicker)
|
||||
inline void syncGpsNavTrackers() {
|
||||
inline void syncGpsNavTrackers(bool isPageEnter = false) {
|
||||
if (isPageEnter) {
|
||||
lastNavPageEnterTime = millis();
|
||||
}
|
||||
bool synced = isGpsSynced();
|
||||
bool altValid = isGpsAltitudeValid();
|
||||
lastNavAltRound = altValid ? (int)round(gpsAltitudeM) : -999;
|
||||
|
|
@ -85,6 +98,32 @@ inline void drawLargeSatelliteIconSprite(TFT_eSprite &s, int x, int y, uint16_t
|
|||
drawLargeGpsSatelliteIcon(s, x, y, TFT_WHITE, color, bgColor, waveState);
|
||||
}
|
||||
|
||||
// Draw diagnostic message with static, right-justified "KBPS" unit for scanning/locked baud
|
||||
template <typename T>
|
||||
inline void drawGpsNavDiag(T &dst, const char *msg, int c2X, int c2Y, uint16_t color, uint16_t bgCol, int clip_h = 240) {
|
||||
if (strncmp(msg, "BUSCANDO", 8) == 0 || strncmp(msg, "FIJADO", 6) == 0) {
|
||||
bool isBuscando = (strncmp(msg, "BUSCANDO", 8) == 0);
|
||||
const char *prefix = isBuscando ? "BUSCANDO:" : "FIJADO:";
|
||||
drawGpsNavSubword(dst, prefix, c2X + 16, c2Y + 90, color, bgCol, clip_h);
|
||||
drawGpsNavSubword(dst, "KBPS", c2X + 116, c2Y + 90, color, bgCol, clip_h);
|
||||
|
||||
const char *p = msg + (isBuscando ? 8 : 6);
|
||||
while (*p == ':' || *p == ' ') p++;
|
||||
char valBuf[10];
|
||||
int vi = 0;
|
||||
while (*p != '\0' && *p != ' ' && vi < (int)sizeof(valBuf) - 1) {
|
||||
valBuf[vi++] = *p++;
|
||||
}
|
||||
valBuf[vi] = '\0';
|
||||
|
||||
int valW = getNavSubwordWidth(valBuf);
|
||||
int valX = c2X + 113 - valW;
|
||||
drawGpsNavSubword(dst, valBuf, valX, c2Y + 90, color, bgCol, clip_h);
|
||||
} else {
|
||||
drawGpsNavSubword(dst, msg, c2X + 16, c2Y + 90, color, bgCol, clip_h);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw full Page 3 (GPS Navigation & Telemetry Screen: Altitud, Rumbo, Satélites, Coordenadas)
|
||||
inline void drawGpsNavScreen(int x_offset = 0) {
|
||||
if (x_offset == 0) {
|
||||
|
|
@ -103,12 +142,11 @@ inline void drawGpsNavScreen(int x_offset = 0) {
|
|||
uint16_t cardBorder = 0x2945; // Subtle edge border
|
||||
bool synced = isGpsSynced();
|
||||
|
||||
// Center: 5 Pagination Indicator Dots [○ ○ ○ ● ○] (Page 3 of 5 active)
|
||||
tft.fillCircle(132 + x_offset, 2, 2, 0x5AEB); // Page 0 inactive
|
||||
tft.fillCircle(146 + x_offset, 2, 2, 0x5AEB); // Page 1 inactive
|
||||
tft.fillCircle(160 + x_offset, 2, 2, 0x5AEB); // Page 2 inactive
|
||||
tft.fillCircle(174 + x_offset, 2, 2, priCol); // Page 3 active
|
||||
tft.fillCircle(188 + x_offset, 2, 2, 0x5AEB); // Page 4 inactive
|
||||
// Center: 4 Pagination Indicator Dots [○ ○ ○ ●] (Page 3 of 4 active)
|
||||
tft.fillCircle(139 + x_offset, 2, 2, 0x5AEB); // Page 0 inactive
|
||||
tft.fillCircle(153 + x_offset, 2, 2, 0x5AEB); // Page 1 inactive
|
||||
tft.fillCircle(167 + x_offset, 2, 2, 0x5AEB); // Page 2 inactive
|
||||
tft.fillCircle(181 + x_offset, 2, 2, priCol); // Page 3 active
|
||||
|
||||
// 2. CARD 0 (Top Left): ALTITUD (x = 4, y = 19, w = 152, h = 102)
|
||||
int c0X = 4 + x_offset;
|
||||
|
|
@ -124,7 +162,7 @@ inline void drawGpsNavScreen(int x_offset = 0) {
|
|||
|
||||
bool altValid = isGpsAltitudeValid();
|
||||
String altStr = altValid ? String((int)round(gpsAltitudeM)) : "---";
|
||||
drawDseg7RightString34(tft, altStr.c_str(), c0X + 140, c0Y + 28, c0Col, cardBg, 0, 240, isRainbowTheme());
|
||||
drawDseg7RightString34(tft, altStr.c_str(), c0X + 140, c0Y + 28, c0Col, cardBg, 126, 240, isRainbowTheme());
|
||||
|
||||
// 3. CARD 1 (Top Right): RUMBO / BRÚJULA (x = 164, y = 19, w = 152, h = 102)
|
||||
int c1X = 164 + x_offset;
|
||||
|
|
@ -137,7 +175,7 @@ inline void drawGpsNavScreen(int x_offset = 0) {
|
|||
|
||||
bool hasCourse = synced && isGpsCourseValid();
|
||||
String crsStr = hasCourse ? String((int)round(gpsCourseDeg)) : "---";
|
||||
drawDseg7RightString34(tft, crsStr.c_str(), c1X + 130, c1Y + 28, c1Col, cardBg, 0, 240, isRainbowTheme());
|
||||
drawDseg7RightString34(tft, crsStr.c_str(), c1X + 130, c1Y + 28, c1Col, cardBg, 95, 240, isRainbowTheme());
|
||||
if (hasCourse) {
|
||||
tft.drawCircle(c1X + 137, c1Y + 33, 3, c1Col);
|
||||
tft.drawCircle(c1X + 137, c1Y + 33, 2, c1Col);
|
||||
|
|
@ -164,13 +202,21 @@ inline void drawGpsNavScreen(int x_offset = 0) {
|
|||
|
||||
// Large Satellites Count (DSEG7 34pt): Shows "---" while scanning/probing UART, "0" or count when locked
|
||||
String satStr = isGpsUartLocked() ? String(gpsSats) : "---";
|
||||
drawDseg7RightString34(tft, satStr.c_str(), c2X + 140, c2Y + 26, c2Col, cardBg, 0, 240, isRainbowTheme());
|
||||
drawDseg7RightString34(tft, satStr.c_str(), c2X + 140, c2Y + 26, c2Col, cardBg, 85, 240, isRainbowTheme());
|
||||
|
||||
// Telemetry details: HDOP precision & live diagnostic status
|
||||
String hdopStr = "HDOP: " + (synced ? String(gpsHdop, 1) : "---");
|
||||
drawGpsNavSubword(tft, hdopStr.c_str(), c2X + 16, c2Y + 70, TFT_WHITE, cardBg, 240);
|
||||
|
||||
drawGpsNavSubword(tft, getGpsDiagMessage(), c2X + 16, c2Y + 90, synced ? 0x9CD3 : priCol, cardBg, 240);
|
||||
uint16_t diagCol = synced ? getGpsDopColor() : priCol;
|
||||
initNavDiagSprite();
|
||||
if (sprNavDiagAllocated) {
|
||||
sprNavDiag.fillSprite(cardBg);
|
||||
drawGpsNavDiag(sprNavDiag, getGpsDiagMessage(), -12, -88, diagCol, cardBg, 16);
|
||||
sprNavDiag.pushSprite(c2X + 12, c2Y + 88);
|
||||
} else {
|
||||
drawGpsNavDiag(tft, getGpsDiagMessage(), c2X, c2Y, diagCol, cardBg, 240);
|
||||
}
|
||||
|
||||
// 5. CARD 3 (Bottom Right): COORDENADAS GPS (x = 164, y = 125, w = 152, h = 110)
|
||||
int c3X = 164 + x_offset;
|
||||
|
|
@ -190,7 +236,7 @@ inline void drawGpsNavScreen(int x_offset = 0) {
|
|||
drawCoordsAAValue(tft, lonStr.c_str(), c3X + 16, c3Y + 76, c3Col, cardBg, 240);
|
||||
|
||||
// Sync state trackers
|
||||
syncGpsNavTrackers();
|
||||
syncGpsNavTrackers(true);
|
||||
}
|
||||
|
||||
// 100% Flicker-Free Live Refresh for resting Page 3 (GPS Navigation & Telemetry)
|
||||
|
|
@ -201,7 +247,7 @@ inline void updateGpsNavScreen(bool forceRedraw = false) {
|
|||
// 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();
|
||||
syncGpsNavTrackers(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +284,7 @@ inline void updateGpsNavScreen(bool forceRedraw = false) {
|
|||
oldNavCourse = gpsCourseDeg;
|
||||
lastNavHasCourse = hasCourse;
|
||||
String crsStr = hasCourse ? String(curCrsRound) : "---";
|
||||
drawDseg7RightString34(tft, crsStr.c_str(), c1X + 130, c1Y + 28, c1Col, cardBg, 85, 240, isRainbowTheme());
|
||||
drawDseg7RightString34(tft, crsStr.c_str(), c1X + 130, c1Y + 28, c1Col, cardBg, 95, 240, isRainbowTheme());
|
||||
|
||||
if (hasCourse) {
|
||||
tft.drawCircle(c1X + 137, c1Y + 33, 3, c1Col);
|
||||
|
|
@ -287,8 +333,16 @@ inline void updateGpsNavScreen(bool forceRedraw = false) {
|
|||
strncpy(lastNavCardDiag, curDiag, sizeof(lastNavCardDiag) - 1);
|
||||
lastNavCardDiag[sizeof(lastNavCardDiag) - 1] = '\0';
|
||||
lastNavDiagSynced = synced;
|
||||
tft.fillRect(c2X + 16, c2Y + 88, 130, 16, cardBg);
|
||||
drawGpsNavSubword(tft, curDiag, c2X + 16, c2Y + 90, synced ? 0x9CD3 : c2Col, cardBg, 240);
|
||||
uint16_t diagCol = synced ? getGpsDopColor() : c2Col;
|
||||
initNavDiagSprite();
|
||||
if (sprNavDiagAllocated) {
|
||||
sprNavDiag.fillSprite(cardBg);
|
||||
drawGpsNavDiag(sprNavDiag, curDiag, -12, -88, diagCol, cardBg, 16);
|
||||
sprNavDiag.pushSprite(c2X + 12, c2Y + 88);
|
||||
} else {
|
||||
tft.fillRect(c2X + 12, c2Y + 88, 138, 16, cardBg);
|
||||
drawGpsNavDiag(tft, curDiag, c2X, c2Y, diagCol, cardBg, 240);
|
||||
}
|
||||
}
|
||||
|
||||
// 3d. Large Satellite Icon: only redrawn if waveState or sync changes
|
||||
|
|
@ -344,7 +398,7 @@ inline void renderPage3ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int s
|
|||
String altStr = altValid ? String((int)round(gpsAltitudeM)) : "---";
|
||||
int valY = c0Y + 28;
|
||||
if (valY < slice_h && valY + 38 > 0) {
|
||||
drawDseg7RightString34(s, altStr.c_str(), c0X + 140, valY, c0Col, cardBg, 0, slice_h, isRainbowTheme());
|
||||
drawDseg7RightString34(s, altStr.c_str(), c0X + 140, valY, c0Col, cardBg, 126, slice_h, isRainbowTheme());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,7 +415,7 @@ inline void renderPage3ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int s
|
|||
String crsStr = hasCourse ? String((int)round(gpsCourseDeg)) : "---";
|
||||
int valY = c1Y + 28;
|
||||
if (valY < slice_h && valY + 38 > 0) {
|
||||
drawDseg7RightString34(s, crsStr.c_str(), c1X + 130, valY, c1Col, cardBg, 0, slice_h, isRainbowTheme());
|
||||
drawDseg7RightString34(s, crsStr.c_str(), c1X + 130, valY, c1Col, cardBg, 95, slice_h, isRainbowTheme());
|
||||
if (hasCourse) {
|
||||
int circY = c1Y + 33;
|
||||
if (circY + 4 > 0 && circY - 4 < slice_h) {
|
||||
|
|
@ -392,11 +446,12 @@ inline void renderPage3ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int s
|
|||
int satY = c2Y + 26;
|
||||
if (satY < slice_h && satY + 38 > 0) {
|
||||
String satStr = isGpsUartLocked() ? String(gpsSats) : "---";
|
||||
drawDseg7RightString34(s, satStr.c_str(), c2X + 140, satY, c2Col, cardBg, 0, slice_h, isRainbowTheme());
|
||||
drawDseg7RightString34(s, satStr.c_str(), c2X + 140, satY, c2Col, cardBg, 85, slice_h, isRainbowTheme());
|
||||
}
|
||||
String hdopStr = "HDOP: " + (synced ? String(gpsHdop, 1) : "---");
|
||||
drawGpsNavSubword(s, hdopStr.c_str(), c2X + 16, c2Y + 70, TFT_WHITE, cardBg, slice_h);
|
||||
drawGpsNavSubword(s, getGpsDiagMessage(), c2X + 16, c2Y + 90, synced ? 0x9CD3 : c2Col, cardBg, slice_h);
|
||||
uint16_t diagCol = synced ? getGpsDopColor() : c2Col;
|
||||
drawGpsNavDiag(s, getGpsDiagMessage(), c2X, c2Y, diagCol, cardBg, slice_h);
|
||||
}
|
||||
|
||||
// 5. CARD 3 (Bottom Right): COORDENADAS (y = 125 to 235)
|
||||
|
|
|
|||
234
sketch/obd2_gauge/kmh_aa_data.h
Normal file
234
sketch/obd2_gauge/kmh_aa_data.h
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
#define KMH_AA_WIDTH 108
|
||||
#define KMH_AA_HEIGHT 28
|
||||
|
||||
#define RPM_AA_WIDTH 60
|
||||
#define RPM_AA_HEIGHT 20
|
||||
|
||||
#define DEGC_AA_WIDTH 33
|
||||
#define DEGC_AA_HEIGHT 25
|
||||
|
||||
#define VOLT_AA_WIDTH 22
|
||||
#define VOLT_AA_HEIGHT 25
|
||||
|
||||
#define TIT_REF_WIDTH 108
|
||||
#define TIT_REF_HEIGHT 11
|
||||
|
||||
#define TIT_BAT_WIDTH 60
|
||||
#define TIT_BAT_HEIGHT 11
|
||||
|
||||
// 8-bit Anti-Aliased 'kmh' (108x28)
|
||||
static const uint8_t s_kmhAlpha[3024] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0x10, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xB5, 0x01, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x64,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x2F, 0x00, 0x00, 0x00, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x15, 0x00, 0x00, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFA, 0xFF, 0xFF, 0xFF, 0xFD, 0x44, 0x00, 0x00, 0x00, 0xA5, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x05, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x04, 0x00, 0x00, 0x00, 0x05, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xCB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xB3, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xFF, 0xFF, 0xFF, 0xFF, 0xD8, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x00, 0x00, 0x58, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xFE, 0xFF, 0xFF, 0xFF, 0xF8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x27, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA2, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x91, 0x6C, 0x6C, 0x6C, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xAA, 0xFF, 0xFF, 0xFF, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xF2, 0xFF, 0xFF, 0xFF, 0xEA, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x91, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x67, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x51, 0xFF, 0xFF, 0xFF, 0xFE, 0x18, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xE5, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xAC, 0x0A, 0xF6, 0xFF, 0xFF, 0xFF, 0x60, 0x00, 0x00, 0x00, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x07, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xFB, 0xFF, 0xFF, 0xFF, 0xFD, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x10, 0xE6, 0xFF, 0xFF, 0xFF, 0xEB, 0x15, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0x52, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xEF, 0x03, 0x00, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0x00, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x45, 0x00, 0x00, 0x00, 0x00, 0xD3, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x25, 0x00, 0x15, 0xFD, 0xFF, 0xFF, 0xFF, 0x3C, 0x3D, 0xFE, 0xFF, 0xFF, 0xFF, 0xAC, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0x94, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x62, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x02, 0x00, 0x00, 0xC4, 0xFF, 0xFF, 0xFF, 0x8C, 0xD7, 0xFF, 0xFF, 0xFF, 0xEC, 0x16, 0x00, 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0xFF, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x00, 0x00, 0x00, 0x74, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00, 0x11, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, 0x00, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0x17, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x44, 0x00, 0x00, 0x00, 0x00, 0x85, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x29, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x02, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0x86, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x56, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x17, 0x00, 0x00, 0x00, 0x00, 0x56, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE5, 0xFF, 0xFF, 0xED, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0x79, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x82, 0x00, 0x00, 0x00, 0x00, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x14, 0x14, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0x4C, 0x00, 0x00, 0x00, 0x3B, 0xFC, 0xFF, 0xFF, 0xFF, 0xFD, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD3, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x09, 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x10, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x05, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x00, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x00, 0x00, 0x00, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0B, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xD8, 0x01, 0x00, 0x0B, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x00, 0x00, 0x67, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
// 8-bit Anti-Aliased 'rpm' (60x20)
|
||||
static const uint8_t s_rpmAlpha[1200] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x09, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFD, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xFF, 0xFF, 0xFF, 0xB9,
|
||||
0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xD8, 0xFF, 0xFF, 0xFF, 0x8D,
|
||||
0x00, 0x00, 0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x3C, 0x00, 0x00, 0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x3C, 0x00, 0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFC, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x61,
|
||||
0x00, 0x00, 0x00, 0x8B, 0xFF, 0xFF, 0xFF, 0x4E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xA3, 0xFF, 0xFF, 0xFF, 0xB1, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0xFF, 0xFF, 0x4E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xA6, 0xFF, 0xFF, 0xFF, 0xB1, 0x00, 0x00, 0x8B, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x35,
|
||||
0x00, 0x00, 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xFF, 0xFF, 0xFF, 0x88, 0x00, 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x0B,
|
||||
0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x5B, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0x5B, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x00,
|
||||
0x00, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x11, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x00,
|
||||
0x00, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xFF, 0xFF, 0xFB, 0x06, 0x00, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB9, 0xFF, 0xFF, 0xFB, 0x07, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0x74, 0x00, 0x00, 0x00, 0x00, 0x99, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0x85, 0x00,
|
||||
0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0xFC, 0xFF, 0xFF, 0xD5, 0x00, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xD6, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xA2, 0xFF, 0xFF, 0xBB, 0x00, 0x00, 0x00, 0x39, 0xFE, 0xFF, 0xFF, 0x9D, 0xFF, 0xFF, 0xFF, 0x59, 0x00,
|
||||
0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x59, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8E, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0x2B, 0xFB, 0xFF, 0xF8, 0x0A, 0x00, 0x04, 0xD2, 0xFF, 0xFF, 0xA8, 0x7A, 0xFF, 0xFF, 0xFF, 0x2D, 0x00,
|
||||
0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x40, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x45, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xED, 0x00, 0xC0, 0xFF, 0xFF, 0x4A, 0x00, 0x77, 0xFF, 0xFF, 0xEC, 0x15, 0xA7, 0xFF, 0xFF, 0xFB, 0x06, 0x00,
|
||||
0x00, 0x00, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0x10, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x36, 0x00, 0x00, 0x00, 0xEC, 0xFF, 0xFF, 0xC0, 0x00, 0x72, 0xFF, 0xFF, 0x92, 0x20, 0xF5, 0xFF, 0xFF, 0x5B, 0x00, 0xD3, 0xFF, 0xFF, 0xD5, 0x00, 0x00,
|
||||
0x00, 0x19, 0xFF, 0xFF, 0xFF, 0xB0, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xC2, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA, 0x22, 0x00, 0x00, 0x00, 0x19, 0xFF, 0xFF, 0xFF, 0x94, 0x00, 0x23, 0xFF, 0xFF, 0xDA, 0xB5, 0xFF, 0xFF, 0xB4, 0x00, 0x05, 0xFA, 0xFF, 0xFF, 0xA9, 0x00, 0x00,
|
||||
0x00, 0x45, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF4, 0xFF, 0xFF, 0xFF, 0x12, 0x00, 0x00, 0x45, 0xFF, 0xFF, 0xFF, 0x8F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xFF, 0xFF, 0x68, 0x00, 0x00, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x1C, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0x7D, 0x00, 0x00,
|
||||
0x00, 0x71, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0xFF, 0xE9, 0x00, 0x00, 0x00, 0x71, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0xFF, 0xFF, 0xFF, 0x3B, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x00, 0x00, 0x58, 0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00,
|
||||
0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xBE, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xBE, 0x01, 0x00, 0x00, 0x85, 0xFF, 0xFF, 0xFF, 0x25, 0x00, 0x00,
|
||||
0x00, 0xCA, 0xFF, 0xFF, 0xFA, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0x93, 0x00, 0x00, 0x00, 0xCA, 0xFF, 0xFF, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFF, 0xFF, 0xE3, 0x00, 0x00, 0x00, 0x02, 0xE8, 0xFF, 0xF5, 0x23, 0x00, 0x00, 0x00, 0xB1, 0xFF, 0xFF, 0xF6, 0x02, 0x00, 0x00,
|
||||
0x01, 0xF4, 0xFF, 0xFF, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x01, 0xF4, 0xFF, 0xFF, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4, 0xFF, 0xFF, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x26, 0x34, 0x24, 0x00, 0x00, 0x00, 0x00, 0xDD, 0xFF, 0xFF, 0xCD, 0x00, 0x00, 0x00,
|
||||
0x22, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xFF, 0xFF, 0xFF, 0x3C, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xFE, 0xFF, 0xFF, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x4E, 0xFF, 0xFF, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0x11, 0x00, 0x00, 0x4E, 0xFF, 0xFF, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xFF, 0xFF, 0xFF, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
// 8-bit Anti-Aliased 'degc' (33x25)
|
||||
static const uint8_t s_degcAlpha[825] PROGMEM = {
|
||||
0x00, 0x00, 0x1A, 0xCB, 0xFF, 0xFF, 0xFF, 0xFE, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x33, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3B, 0x00, 0x00, 0x00,
|
||||
0x2C, 0xF5, 0xFF, 0xFF, 0xF7, 0xE8, 0xF8, 0xFF, 0xFF, 0xE0, 0x14, 0x00, 0x00, 0x00, 0x01, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x21, 0x00, 0x00,
|
||||
0x6A, 0xFF, 0xFF, 0xDA, 0x24, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x00, 0x08, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x0F, 0x00,
|
||||
0x9A, 0xFF, 0xFF, 0x7D, 0x00, 0x00, 0x1A, 0xFF, 0xFF, 0xFA, 0x06, 0x00, 0x08, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x04,
|
||||
0xC9, 0xFF, 0xFF, 0x9E, 0x00, 0x04, 0x95, 0xFF, 0xFF, 0xD1, 0x00, 0x00, 0x35, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x22,
|
||||
0x9B, 0xFF, 0xFF, 0xFF, 0xE9, 0xEE, 0xFF, 0xFF, 0xFF, 0x93, 0x00, 0x00, 0x62, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFF, 0xFF, 0xFF, 0xF3, 0x01,
|
||||
0x06, 0xC2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x92, 0x03, 0x00, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0xFD, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0xFF, 0xFF, 0xFF, 0xC5, 0x00,
|
||||
0x00, 0x14, 0xDE, 0xFF, 0xFF, 0xFF, 0xFA, 0x65, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFF, 0xFF, 0xFF, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x68, 0x68, 0x68, 0x43, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xFF, 0xFF, 0xFF, 0xFF, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xFF, 0xFF, 0xFF, 0xFA, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0xFF, 0xFF, 0xFF, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF3, 0xFF, 0xFF, 0xFF, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x6C, 0x6C, 0x6C, 0x6C, 0x04, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB9, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xEB, 0xFF, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x3C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE8, 0x37, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD4, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
// 8-bit Anti-Aliased 'volt' (22x25)
|
||||
static const uint8_t s_voltAlpha[550] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xDA, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0x38,
|
||||
0xAC, 0xFF, 0xFF, 0xFF, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x00,
|
||||
0x7E, 0xFF, 0xFF, 0xFF, 0xF7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB9, 0xFF, 0xFF, 0xFF, 0xFD, 0x2C, 0x00,
|
||||
0x51, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xA2, 0x00, 0x00,
|
||||
0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0xFA, 0x21, 0x00, 0x00,
|
||||
0x01, 0xF3, 0xFF, 0xFF, 0xFF, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFF, 0xFF, 0xFF, 0xFF, 0x94, 0x00, 0x00, 0x00,
|
||||
0x00, 0xC8, 0xFF, 0xFF, 0xFF, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xF5, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x9A, 0xFF, 0xFF, 0xFF, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0x86, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x6C, 0xFF, 0xFF, 0xFF, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xEF, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFA, 0x03, 0x00, 0x00, 0x00, 0x00, 0x31, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x11, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xFF, 0xFF, 0xE7, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xE3, 0xFF, 0xFF, 0xFF, 0x48, 0x00, 0x00, 0x00, 0x2F, 0xFE, 0xFF, 0xFF, 0xFF, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xB6, 0xFF, 0xFF, 0xFF, 0x6D, 0x00, 0x00, 0x00, 0xAD, 0xFF, 0xFF, 0xFF, 0xDE, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0x92, 0x00, 0x00, 0x2D, 0xFE, 0xFF, 0xFF, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5A, 0xFF, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0xAB, 0xFF, 0xFF, 0xFF, 0xD3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x2D, 0xFF, 0xFF, 0xFF, 0xDD, 0x00, 0x2B, 0xFE, 0xFF, 0xFF, 0xFF, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x05, 0xF9, 0xFF, 0xFF, 0xFC, 0x06, 0xA8, 0xFF, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xD1, 0xFF, 0xFF, 0xFF, 0x51, 0xFD, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xA4, 0xFF, 0xFF, 0xFF, 0xE6, 0xFF, 0xFF, 0xFF, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x76, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
// 8-bit Anti-Aliased 'titRef' (108x11)
|
||||
static const uint8_t s_titRefAlpha[1188] PROGMEM = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x0F, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x0A, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x0B, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x41, 0xFF, 0xEE, 0x06, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFA, 0x31, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
|
||||
0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xDC, 0xFF, 0xC7, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xDC, 0xFF, 0xC7, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xBB, 0xFF, 0xEE, 0xC4, 0xC4, 0xC4, 0xEB, 0xFF, 0xBC, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xDC, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xFF, 0xFF, 0x4D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xD5, 0x08, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xC4, 0xC4, 0xC4, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0A, 0xFD, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0A, 0xFD, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x2D, 0x00, 0x00, 0x00, 0x26, 0xFF, 0xFC, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0A, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x05, 0xED, 0xF6, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7E, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x4D, 0xFF, 0x91, 0xE4, 0xF4, 0x0A, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xEF, 0xFE, 0x42, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x22, 0xFE, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x22, 0xFE, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x22, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0xA7, 0xFF, 0x40, 0x93, 0xFF, 0x58, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x5B, 0xFF, 0xE2, 0x0F, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0x0B, 0xF4, 0xEC, 0x03, 0x40, 0xFF, 0xB1, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0xA9, 0xFF, 0xA2, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
|
||||
0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xF1, 0xFF, 0x4E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xF1, 0xFF, 0x4E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x4F, 0xC4, 0xC4, 0xFF, 0xFC, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xF1, 0xFF, 0x4E, 0x00, 0x00, 0x5A, 0xFF, 0xA0, 0x00, 0x03, 0xEA, 0xF9, 0x11, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x12, 0xE5, 0xFF, 0x53, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xF4, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xF4, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xF4, 0x00, 0x00, 0xB3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x47, 0xFE, 0xEC, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x28, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFC, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x12, 0xFA, 0xFE, 0xD0, 0xD0, 0xD0, 0xDD, 0xFF, 0xBC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xBB, 0xFF, 0xEE, 0xC4, 0xC4, 0xC4, 0xE9, 0xFF, 0xB7, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x66, 0xFF, 0xBA, 0x00, 0x00, 0x00, 0x12, 0xF8, 0xFD, 0x18, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0A, 0xD8, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x0A, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x09, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0xBF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xFF, 0x6F, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFB, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
|
||||
};
|
||||
|
||||
// 8-bit Anti-Aliased 'titBat' (60x11)
|
||||
static const uint8_t s_titBatAlpha[660] PROGMEM = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x00, 0x00, 0x00, 0x00, 0x41, 0xFF, 0xEE, 0x06, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x0F, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xFF, 0xEE, 0x06, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xDA, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xFF, 0xFF, 0x4D, 0x00, 0x00, 0xC4, 0xC4, 0xC4, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xDC, 0xFF, 0xC7, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xFF, 0xFF, 0x4D, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x05, 0xED, 0xF6, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0A, 0xFD, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x05, 0xED, 0xF6, 0xFF, 0xA6, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x08, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x4D, 0xFF, 0x91, 0xE4, 0xF4, 0x0A, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xFF, 0x91, 0xE4, 0xF4, 0x0A, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xDB, 0xFF, 0xDA, 0x00, 0x00, 0x00, 0xA7, 0xFF, 0x40, 0x93, 0xFF, 0x58, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x22, 0xFE, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xA7, 0xFF, 0x40, 0x93, 0xFF, 0x58, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x4C, 0x00, 0x0B, 0xF4, 0xEC, 0x03, 0x40, 0xFF, 0xB1, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0B, 0xF4, 0xEC, 0x03, 0x40, 0xFF, 0xB1, 0x00, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x02, 0x6D, 0xFF, 0xF9, 0x00, 0x5A, 0xFF, 0xA0, 0x00, 0x03, 0xEA, 0xF9, 0x11, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xF1, 0xFF, 0x4E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x5A, 0xFF, 0xA0, 0x00, 0x03, 0xEA, 0xF9, 0x11, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0xB3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xF4, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0xB3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x00,
|
||||
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFF, 0xFC, 0x12, 0xFA, 0xFE, 0xD0, 0xD0, 0xD0, 0xDD, 0xFF, 0xBC, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x12, 0xFA, 0xFE, 0xD0, 0xD0, 0xD0, 0xDD, 0xFF, 0xBC, 0x00,
|
||||
0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC5, 0xFC, 0xFF, 0xBF, 0x66, 0xFF, 0xBA, 0x00, 0x00, 0x00, 0x12, 0xF8, 0xFD, 0x18, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0x62, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x66, 0xFF, 0xBA, 0x00, 0x00, 0x00, 0x12, 0xF8, 0xFD, 0x18,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x0A, 0xBF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xFF, 0x6F, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xBF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xFF, 0x6F,
|
||||
};
|
||||
|
||||
// Draw anti-aliased bitmap to destination (TFT or Sprite) with alpha blending, rainbow and Yapa multi-color per letter
|
||||
template <typename T>
|
||||
inline void drawKmhAaBitmap(T &dst, int bx, int by, int w, int h, const uint8_t *alpha,
|
||||
uint16_t color, uint16_t bgCol = 0x10A2, int clip_h = 240, bool rainbow = false) {
|
||||
dst.startWrite();
|
||||
for (int j = 0; j < h; j++) {
|
||||
int py = by + j;
|
||||
if (py < 0 || py >= clip_h) continue;
|
||||
int rowOffset = j * w;
|
||||
for (int i = 0; i < w; i++) {
|
||||
int px = bx + i;
|
||||
if (px < 0 || px >= 320) continue;
|
||||
uint8_t a = pgm_read_byte(alpha + rowOffset + i);
|
||||
if (a > 6) {
|
||||
uint16_t curCol = color;
|
||||
if (rainbow) {
|
||||
curCol = getRainbowScreenColor(px, py);
|
||||
} else if (isYapaTheme()) {
|
||||
if (alpha == s_rpmAlpha) {
|
||||
curCol = (i < 20) ? getYapaColor(0) : ((i < 39) ? getYapaColor(1) : getYapaColor(2));
|
||||
} else if (alpha == s_kmhAlpha) {
|
||||
curCol = (i < 31) ? getYapaColor(0) : ((i < 63) ? getYapaColor(1) : ((i < 76) ? getYapaColor(2) : getYapaColor(3)));
|
||||
} else if (alpha == s_degcAlpha) {
|
||||
curCol = (i < 13) ? getYapaColor(0) : getYapaColor(1);
|
||||
} else if (alpha == s_voltAlpha) {
|
||||
curCol = getYapaColor(2);
|
||||
} else if (alpha == s_titRefAlpha) {
|
||||
curCol = getYapaColor((i * 12) / 108);
|
||||
} else if (alpha == s_titBatAlpha) {
|
||||
curCol = getYapaColor((i * 7) / 60);
|
||||
}
|
||||
}
|
||||
uint16_t pixCol = (a >= 250) ? curCol : dst.alphaBlend(a, curCol, bgCol);
|
||||
dst.drawPixel(px, py, pixCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
dst.endWrite();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void drawKmH_AA(T &dst, int bx, int by, uint16_t color = 0xBDD7, uint16_t bgCol = 0x10A2, int clip_h = 240, bool rainbow = false) {
|
||||
drawKmhAaBitmap(dst, bx, by, KMH_AA_WIDTH, KMH_AA_HEIGHT, s_kmhAlpha, color, bgCol, clip_h, rainbow);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void drawRpm_AA(T &dst, int bx, int by, uint16_t color = 0xBDD7, uint16_t bgCol = 0x10A2, int clip_h = 240, bool rainbow = false) {
|
||||
drawKmhAaBitmap(dst, bx, by, RPM_AA_WIDTH, RPM_AA_HEIGHT, s_rpmAlpha, color, bgCol, clip_h, rainbow);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void drawDegreeC_AA(T &dst, int bx, int by, uint16_t color = 0xC618, uint16_t bgCol = 0x10A2, int clip_h = 240, bool rainbow = false) {
|
||||
drawKmhAaBitmap(dst, bx, by, DEGC_AA_WIDTH, DEGC_AA_HEIGHT, s_degcAlpha, color, bgCol, clip_h, rainbow);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void drawVolt_AA(T &dst, int bx, int by, uint16_t color = 0xC618, uint16_t bgCol = 0x10A2, int clip_h = 240, bool rainbow = false) {
|
||||
drawKmhAaBitmap(dst, bx, by, VOLT_AA_WIDTH, VOLT_AA_HEIGHT, s_voltAlpha, color, bgCol, clip_h, rainbow);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void drawTitRef_AA(T &dst, int bx, int by, uint16_t color = 0xBDD7, uint16_t bgCol = 0x10A2, int clip_h = 240, bool rainbow = false) {
|
||||
drawKmhAaBitmap(dst, bx, by, TIT_REF_WIDTH, TIT_REF_HEIGHT, s_titRefAlpha, color, bgCol, clip_h, rainbow);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void drawTitBat_AA(T &dst, int bx, int by, uint16_t color = 0xBDD7, uint16_t bgCol = 0x10A2, int clip_h = 240, bool rainbow = false) {
|
||||
drawKmhAaBitmap(dst, bx, by, TIT_BAT_WIDTH, TIT_BAT_HEIGHT, s_titBatAlpha, color, bgCol, clip_h, rainbow);
|
||||
}
|
||||
|
|
@ -256,76 +256,9 @@ void drawFullScreenTitle(const String &label, uint16_t color) {
|
|||
// Tactical ECO / OPT Badge (Ford Ka Endura 1.3 Sweet Spot: 1900 - 2550 RPM &
|
||||
// 45% - 82% Load)
|
||||
void updateEcoBadge(bool forceRedraw = false) {
|
||||
// CRITICAL: ECO badge ONLY belongs on Page 0 (RPM quadrant or fullscreen
|
||||
// RPM), NEVER on Page 1 (Tri-Temp)!
|
||||
if (currentScreenPage != 0) {
|
||||
badgeEcoDrawn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If in fullscreen on Page 0, only display if the fullscreen cell is RPM
|
||||
bool isQuad = (fullScreenCell < 0 || fullScreenCell >= 4);
|
||||
if (!isQuad && pidConfig[pidInCell[fullScreenCell]][3].toInt() != 3) {
|
||||
badgeEcoDrawn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool newEco = (ignitionOn && currentRpm >= 1900.0f && currentRpm <= 2550.0f &&
|
||||
currentEngineLoad >= 45.0f && currentEngineLoad <= 82.0f);
|
||||
isEcoOptimal = newEco;
|
||||
|
||||
if (forceRedraw) {
|
||||
badgeEcoDrawn = !newEco; // Force redraw/re-erase
|
||||
}
|
||||
|
||||
if (newEco == badgeEcoDrawn) {
|
||||
return;
|
||||
}
|
||||
|
||||
int bx = 0, by = 0, bw = 0, bh = 0;
|
||||
|
||||
if (isQuad) {
|
||||
// 4-Quadrant View: Positioned in top-right of RPM Quadrant (Cell 2)
|
||||
int rpmCell = 2;
|
||||
for (int c = 0; c < 4; c++) {
|
||||
if (pidConfig[pidInCell[c]][3].toInt() == 3) {
|
||||
rpmCell = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bx = cell4_x[rpmCell] + 100;
|
||||
by = cell4_y[rpmCell] + 4;
|
||||
bw = 48;
|
||||
bh = 18;
|
||||
} else {
|
||||
// Full-Screen View: Positioned in top-right header band
|
||||
bx = 260;
|
||||
by = 11;
|
||||
bw = 50;
|
||||
bh = 20;
|
||||
}
|
||||
|
||||
if (newEco) {
|
||||
// Elegant tactical pill badge [ ECO ]
|
||||
const uint16_t bgFill = 0x0202; // Deep dark forest emerald green
|
||||
const uint16_t borderCol = 0x07E0; // Vibrant emerald neon green
|
||||
tft.fillRoundRect(bx, by, bw, bh, 4, bgFill);
|
||||
tft.drawRoundRect(bx, by, bw, bh, 4, borderCol);
|
||||
tft.setTextColor(TFT_WHITE, bgFill);
|
||||
if (isQuad) {
|
||||
tft.drawCentreString("ECO", bx + (bw / 2), by + 1, 2);
|
||||
} else {
|
||||
tft.drawCentreString("ECO", bx + (bw / 2), by + 2, 2);
|
||||
}
|
||||
} else {
|
||||
// Cleanly restore background gradient lines with zero visual trace
|
||||
int ry = (isQuad && by >= 120) ? 121 : 0;
|
||||
for (int y = by; y < by + bh; y++) {
|
||||
uint16_t bgCol = getInstrumentBgColor(y, isQuad, ry);
|
||||
tft.drawFastHLine(bx, y, bw, bgCol);
|
||||
}
|
||||
}
|
||||
|
||||
badgeEcoDrawn = newEco;
|
||||
}
|
||||
|
||||
|
|
@ -1052,13 +985,12 @@ inline int calcMeterBlocks(float val, int min, int max) {
|
|||
return b;
|
||||
}
|
||||
|
||||
// Restore natural vignette vertical gradient where GPS icon sits
|
||||
inline void clearPage0GpsIcon() {
|
||||
uint16_t c1 = tft.alphaBlend((uint8_t)(255 * (82 - 3) / 82),
|
||||
getThemeBgColor(), TFT_BLACK);
|
||||
uint16_t c2 = tft.alphaBlend((uint8_t)(255 * (82 - 25) / 82),
|
||||
getThemeBgColor(), TFT_BLACK);
|
||||
tft.fillRectVGradient(294, 3, 24, 22, c1, c2);
|
||||
// Page 0 uses the integrated GPS/OBD status pill inside the speedometer card
|
||||
}
|
||||
|
||||
inline void drawPage0GpsIcon(uint8_t waveState, bool synced) {
|
||||
// Page 0 uses the integrated GPS/OBD status pill inside the speedometer card
|
||||
}
|
||||
|
||||
inline void clearFullscreenGpsIcon() {
|
||||
|
|
@ -1069,19 +1001,6 @@ inline void clearFullscreenGpsIcon() {
|
|||
tft.fillRectVGradient(294, 3, 24, 22, c1, c2);
|
||||
}
|
||||
|
||||
// Draw animated GPS satellite icon in top right of Quadrant 1 (Velocidad: cell
|
||||
// 1)
|
||||
inline void drawPage0GpsIcon(uint8_t waveState, bool synced) {
|
||||
if (currentScreenPage != 0 || fullScreenCell != -1)
|
||||
return;
|
||||
clearPage0GpsIcon();
|
||||
uint16_t waveCol = getThemePrimaryColor();
|
||||
uint16_t bodyCol = TFT_WHITE;
|
||||
uint16_t bgCol = tft.alphaBlend((uint8_t)(255 * (82 - 3) / 82),
|
||||
getThemeBgColor(), TFT_BLACK);
|
||||
drawGpsSatelliteIcon(tft, 296, 3, bodyCol, waveCol, bgCol, waveState);
|
||||
}
|
||||
|
||||
// Draw animated GPS satellite icon in top right of Fullscreen Velocidad (cell
|
||||
// 1)
|
||||
inline void drawFullscreenGpsIcon(uint8_t waveState, bool synced) {
|
||||
|
|
@ -1187,7 +1106,7 @@ void arcMeter4(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
|
|||
int warn = warningValue[pid].toInt();
|
||||
String unit = pidConfig[pid][1];
|
||||
|
||||
if (last_valid_data[cell] != -999) {
|
||||
if (last_valid_data[cell] > -900.0f) {
|
||||
old_data[cell] = -999;
|
||||
plotArc4(cell, last_valid_data[cell], warn, min, max, digit, unit);
|
||||
} else {
|
||||
|
|
@ -1325,7 +1244,7 @@ void fullScreenMeter(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
|
|||
bool digit = pidConfig[pid][7].toInt();
|
||||
int warn = warningValue[pid].toInt();
|
||||
|
||||
if (last_valid_data[cell] != -999) {
|
||||
if (last_valid_data[cell] > -900.0f) {
|
||||
old_data[cell] = -999;
|
||||
plotFullScreen(cell, last_valid_data[cell], warn, min, max, digit, unit);
|
||||
} else {
|
||||
|
|
@ -1440,6 +1359,12 @@ void plotNoData(uint8_t cell) {
|
|||
wasInRedAlarm[cell] = false;
|
||||
|
||||
uint8_t pidIdx = pidInCell[cell];
|
||||
if (pidIdx == 0) {
|
||||
tempEngineCoolant = -999.0f;
|
||||
if (currentScreenPage == 1 && fullScreenCell == -1) {
|
||||
updateTriTempCoolant(-999.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (fullScreenCell >= 0 && fullScreenCell < 4) {
|
||||
if (cell == fullScreenCell) {
|
||||
|
|
@ -1456,19 +1381,7 @@ void plotNoData(uint8_t cell) {
|
|||
tft.unloadFont();
|
||||
}
|
||||
} else if (currentScreenPage == 0) {
|
||||
int x = cell4_x[cell];
|
||||
int y = cell4_y[cell];
|
||||
clearPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]);
|
||||
drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]);
|
||||
for (uint8_t i = 0; i < NUM_BAR_BLOCKS; i++) {
|
||||
drawQuadBarBlock(cell, i, METER_INACTIVE_COLOR);
|
||||
}
|
||||
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
||||
tft.setTextColor(getThemeCellColor(cell), TFT_BLACK);
|
||||
tft.setTextPadding(114);
|
||||
tft.drawRightString("---", x + 152, y + 74, 1);
|
||||
tft.setTextPadding(0);
|
||||
tft.unloadFont();
|
||||
updateClusterScreen(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1597,103 +1510,10 @@ inline void drawQuadBarBlockToSprite(TFT_eSprite &s, int16_t qx, int16_t qy,
|
|||
}
|
||||
}
|
||||
|
||||
// Render Page 0 (4 Quadrants) into double-buffered Sprite slice
|
||||
// Render Page 0 (Cockpit Instrumental) into double-buffered Sprite slice
|
||||
inline void renderPage0ToSprite(TFT_eSprite &s, int x_offset, int y_slice,
|
||||
int slice_h) {
|
||||
checkUpdateThemeGradients();
|
||||
uint16_t divCol = getThemeDivColor();
|
||||
uint16_t priCol = getThemePrimaryColor();
|
||||
|
||||
for (uint8_t c = 0; c < 4; c++) {
|
||||
int qx = cell4_x[c] + x_offset;
|
||||
int qy = cell4_y[c] - y_slice;
|
||||
int rx = (c & 1) ? (161 + x_offset) : (0 + x_offset);
|
||||
int global_ry = (c & 2) ? 121 : 0;
|
||||
int ry = global_ry - y_slice;
|
||||
|
||||
if (qx + 160 <= 0 || qx >= 320 || ry + 119 <= 0 || ry >= slice_h)
|
||||
continue;
|
||||
|
||||
// 1. Exact dark vignette gradient matching real arcMeter4
|
||||
s.fillRect(rx, ry, 159, 119, TFT_BLACK);
|
||||
int gradStartY = (ry < 0) ? -ry : 0;
|
||||
int gradEndY = (ry + 82 > slice_h) ? (slice_h - ry) : 82;
|
||||
for (int j = gradStartY; j < gradEndY; j++) {
|
||||
int curY = ry + j;
|
||||
if (curY >= 0 && curY < slice_h) {
|
||||
s.drawFastHLine(rx, curY, 159, themeGradQuad[j]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t pidIdx = pidInCell[c];
|
||||
|
||||
// 2. Real high-definition parameter icon (thermometer, speedometer,
|
||||
// tachometer, battery)
|
||||
drawPidIconToSprite(s, qx + 5, qy + 3, pidConfig[pidIdx][2], y_slice,
|
||||
slice_h, global_ry);
|
||||
|
||||
// 3. Exact 20 curved segmented gauge blocks along the arc (true
|
||||
// mathematical polygons)
|
||||
int warn = warningValue[pidIdx].toInt();
|
||||
int min = pidConfig[pidIdx][4].toInt();
|
||||
int max = pidConfig[pidIdx][5].toInt();
|
||||
bool digit = pidConfig[pidIdx][7].toInt();
|
||||
float val = last_valid_data[c];
|
||||
|
||||
int numActive = (val > -900.0f) ? calcMeterBlocks(val, min, max) : 0;
|
||||
uint16_t activeCol =
|
||||
(val > -900.0f) ? getMeterColor(pidIdx, val, warn) : priCol;
|
||||
|
||||
for (uint8_t i = 0; i < NUM_BAR_BLOCKS; i++) {
|
||||
uint16_t bCol = (i < numActive) ? activeCol : METER_INACTIVE_COLOR;
|
||||
drawQuadBarBlockToSprite(s, qx, qy, i, bCol, slice_h);
|
||||
}
|
||||
|
||||
// 4. Digital value string using authentic DSEG7 34pt font with rainbow gradient
|
||||
String numStr = (val <= -900.0f) ? "---" : String(val, digit);
|
||||
uint16_t txtCol = (activeCol == TFT_RED) ? TFT_RED : getThemeCellColor(c);
|
||||
bool rainbowTxt = isRainbowTheme() && (activeCol != TFT_RED);
|
||||
int textY = qy + 74;
|
||||
if (textY < slice_h && textY + 40 > 0) {
|
||||
drawDseg7RightString34(s, numStr.c_str(), qx + 152, textY, txtCol, TFT_BLACK, 0, slice_h, rainbowTxt);
|
||||
}
|
||||
|
||||
// GPS Satellite icon in top right of Quadrant 1 (Velocidad: cell 1)
|
||||
if (c == 1 && isGpsSpeedValid() && y_slice == 0) {
|
||||
uint16_t waveCol = isRainbowTheme() ? (uint16_t)0x07E0 : priCol;
|
||||
uint16_t bodyCol = TFT_WHITE;
|
||||
uint16_t bgCol = themeGradQuad[3];
|
||||
drawGpsSatelliteIcon(s, qx + 136, 3, bodyCol, waveCol, bgCol,
|
||||
getGpsWaveAnimState());
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Eco Badge if active
|
||||
if (isEcoOptimal) {
|
||||
int rpmCell = 2;
|
||||
for (int c = 0; c < 4; c++) {
|
||||
if (pidConfig[pidInCell[c]][3].toInt() == 3) {
|
||||
rpmCell = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int bx = cell4_x[rpmCell] + 100 + x_offset;
|
||||
int by = cell4_y[rpmCell] + 4 - y_slice;
|
||||
int bw = 48, bh = 18;
|
||||
if (by + bh > 0 && by < slice_h && bx + bw > 0 && bx < 320) {
|
||||
s.fillRoundRect(bx, by, bw, bh, 4, 0x0202);
|
||||
s.drawRoundRect(bx, by, bw, bh, 4, 0x07E0);
|
||||
s.setTextColor(TFT_WHITE, 0x0202);
|
||||
s.drawCentreString("ECO", bx + (bw / 2), by + 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Crosshair dividers
|
||||
s.fillRect(159 + x_offset, 0, 2, slice_h, divCol);
|
||||
int hLineY = 119 - y_slice;
|
||||
if (hLineY >= 0 && hLineY < slice_h) {
|
||||
s.fillRect(x_offset, hLineY, 320, 2, divCol);
|
||||
}
|
||||
renderClusterScreenToSprite(s, x_offset, y_slice, slice_h);
|
||||
}
|
||||
|
||||
// Render Page 1 (3 Temperature Cards) into double-buffered Sprite slice
|
||||
|
|
@ -1761,14 +1581,18 @@ inline void renderPage1ToSprite(TFT_eSprite &s, int x_offset, int y_slice,
|
|||
initTriTempTitles();
|
||||
if (sprTriTitleReady && sprTriTitle[cardIdx].created()) {
|
||||
sprTriTitle[cardIdx].pushToSprite(&s, cardX + 16, cardY + 5);
|
||||
} else {
|
||||
if (isYapaTheme()) {
|
||||
drawYapaStringToSprite(s, titleStr, cardX + 16, cardY + 5, 4);
|
||||
} else {
|
||||
s.setTextColor(TFT_WHITE, cardBg);
|
||||
s.drawString(titleStr, cardX + 16, cardY + 5, 4);
|
||||
}
|
||||
}
|
||||
if (isYapaTheme()) {
|
||||
drawYapaStringToSprite(s, subStr, cardX + 16, cardY + 32, 1);
|
||||
} else {
|
||||
s.setTextColor(0x8410, cardBg);
|
||||
s.setTextColor(accentCol, cardBg);
|
||||
s.drawString(subStr, cardX + 16, cardY + 32, 1);
|
||||
}
|
||||
|
||||
|
|
@ -1782,24 +1606,26 @@ inline void renderPage1ToSprite(TFT_eSprite &s, int x_offset, int y_slice,
|
|||
ratio = 0.0f;
|
||||
if (ratio > 1.0f)
|
||||
ratio = 1.0f;
|
||||
int fillW = (int)(barW * ratio);
|
||||
if (fillW < 4)
|
||||
int fillW = (val <= -900.0f) ? 0 : (int)(barW * ratio);
|
||||
if (fillW < 4 && val > -900.0f)
|
||||
fillW = 4;
|
||||
if (fillW > 0)
|
||||
s.fillRoundRect(barX, barY, fillW, 8, 3, accentCol);
|
||||
|
||||
// Value text using authentic DSEG7 34pt font with rainbow gradient
|
||||
String numStr =
|
||||
(val <= -900.0f) ? "---" : (isInt ? String((int)val) : String(val, 1));
|
||||
(val <= -900.0f) ? "---" : String((int)round(val));
|
||||
uint16_t numCol = accentCol;
|
||||
bool rainbowTxt = isRainbowTheme() && (accentCol != TFT_RED);
|
||||
int numY = cardY + 20;
|
||||
if (numY < slice_h && numY + 40 > 0) {
|
||||
drawDseg7RightString34(s, numStr.c_str(), cardX + 262, numY, accentCol, cardBg, 0, slice_h, rainbowTxt);
|
||||
drawDseg7RightString34(s, numStr.c_str(), cardX + 262, numY, numCol, cardBg, 0, slice_h, rainbowTxt);
|
||||
}
|
||||
|
||||
int unitY = cardY + 22;
|
||||
if (unitY < slice_h && unitY + 26 > 0) {
|
||||
bool rainbowUnit = isRainbowTheme() && (accentCol != TFT_RED);
|
||||
uint16_t unitCol = rainbowUnit ? getRainbowScreenColor(cardX + 268, unitY) : (isYapaTheme() && accentCol != TFT_RED ? getYapaColor(numStr.length()) : (accentCol == TFT_RED ? TFT_RED : 0xC618));
|
||||
uint16_t unitCol = rainbowUnit ? getRainbowScreenColor(cardX + 268, unitY) : (isYapaTheme() && accentCol != TFT_RED ? getYapaColor(numStr.length()) : (accentCol == TFT_RED ? TFT_RED : accentCol));
|
||||
draw7SegDegreeC(s, cardX + 268, unitY, unitCol, cardBg, rainbowUnit);
|
||||
}
|
||||
}
|
||||
|
|
@ -1839,28 +1665,24 @@ inline void animateBlackTransition(int8_t toPage = -1) {
|
|||
sprTrans.fillSprite(TFT_BLACK);
|
||||
|
||||
if (toPage == 0)
|
||||
renderPage0ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
renderClusterScreenToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else if (toPage == 1)
|
||||
renderPage1ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else if (toPage == 2)
|
||||
renderPage2ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else if (toPage == 3)
|
||||
renderPage3ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else
|
||||
renderPage4ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
renderPage3ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
|
||||
// Pagination indicator dots on top slice (5 dots for 5 pages)
|
||||
// Pagination indicator dots on top slice (4 dots for 4 pages)
|
||||
if (y_slice == 0) {
|
||||
sprTrans.fillCircle(132, 2, 2,
|
||||
sprTrans.fillCircle(139, 2, 2,
|
||||
(toPage == 0) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(146, 2, 2,
|
||||
sprTrans.fillCircle(153, 2, 2,
|
||||
(toPage == 1) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(160, 2, 2,
|
||||
sprTrans.fillCircle(167, 2, 2,
|
||||
(toPage == 2) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(174, 2, 2,
|
||||
sprTrans.fillCircle(181, 2, 2,
|
||||
(toPage == 3) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(188, 2, 2,
|
||||
(toPage == 4) ? getThemePrimaryColor() : 0x5AEB);
|
||||
}
|
||||
|
||||
sprTrans.pushSprite(0, y_slice);
|
||||
|
|
@ -1915,26 +1737,22 @@ inline void animateFadeTransition(int8_t fromPage = -1, int8_t toPage = -1) {
|
|||
sprFadeB.fillSprite(TFT_BLACK);
|
||||
|
||||
if (fromPage == 0)
|
||||
renderPage0ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
renderClusterScreenToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else if (fromPage == 1)
|
||||
renderPage1ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else if (fromPage == 2)
|
||||
renderPage2ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else if (fromPage == 3)
|
||||
renderPage3ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
else
|
||||
renderPage4ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
renderPage3ToSprite(sprTrans, 0, y_slice, slice_h);
|
||||
|
||||
if (toPage == 0)
|
||||
renderPage0ToSprite(sprFadeB, 0, y_slice, slice_h);
|
||||
renderClusterScreenToSprite(sprFadeB, 0, y_slice, slice_h);
|
||||
else if (toPage == 1)
|
||||
renderPage1ToSprite(sprFadeB, 0, y_slice, slice_h);
|
||||
else if (toPage == 2)
|
||||
renderPage2ToSprite(sprFadeB, 0, y_slice, slice_h);
|
||||
else if (toPage == 3)
|
||||
renderPage3ToSprite(sprFadeB, 0, y_slice, slice_h);
|
||||
else
|
||||
renderPage4ToSprite(sprFadeB, 0, y_slice, slice_h);
|
||||
renderPage3ToSprite(sprFadeB, 0, y_slice, slice_h);
|
||||
|
||||
uint16_t *pA = (uint16_t *)sprTrans.getPointer();
|
||||
uint16_t *pB = (uint16_t *)sprFadeB.getPointer();
|
||||
|
|
@ -1964,19 +1782,17 @@ inline void animateFadeTransition(int8_t fromPage = -1, int8_t toPage = -1) {
|
|||
}
|
||||
}
|
||||
|
||||
// Pagination indicator dots on top slice (5 dots for 5 pages)
|
||||
// Pagination indicator dots on top slice (4 dots for 4 pages)
|
||||
if (y_slice == 0) {
|
||||
uint8_t activeDot = (alpha < 16) ? fromPage : toPage;
|
||||
sprTrans.fillCircle(132, 2, 2,
|
||||
sprTrans.fillCircle(139, 2, 2,
|
||||
(activeDot == 0) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(146, 2, 2,
|
||||
sprTrans.fillCircle(153, 2, 2,
|
||||
(activeDot == 1) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(160, 2, 2,
|
||||
sprTrans.fillCircle(167, 2, 2,
|
||||
(activeDot == 2) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(174, 2, 2,
|
||||
sprTrans.fillCircle(181, 2, 2,
|
||||
(activeDot == 3) ? getThemePrimaryColor() : 0x5AEB);
|
||||
sprTrans.fillCircle(188, 2, 2,
|
||||
(activeDot == 4) ? getThemePrimaryColor() : 0x5AEB);
|
||||
}
|
||||
|
||||
sprTrans.pushSprite(0, y_slice);
|
||||
|
|
@ -1997,7 +1813,7 @@ inline void performScreenTransition(bool swipeLeft, int8_t fromPage = -1,
|
|||
if (fromPage < 0)
|
||||
fromPage = currentScreenPage;
|
||||
if (toPage < 0)
|
||||
toPage = (fromPage + 1) % 5;
|
||||
toPage = (fromPage + 1) % 4;
|
||||
if (transitionType == 1) {
|
||||
animateFadeTransition(fromPage, toPage);
|
||||
} else {
|
||||
|
|
@ -2030,16 +1846,14 @@ void initScreen(bool redrawTFT) {
|
|||
// Screen is ALREADY 100% rendered with zero flicker by the double-buffered
|
||||
// transition engine! ONLY sync tracking variables so live updates continue
|
||||
// seamlessly without redrawing or blanking!
|
||||
if (currentScreenPage == 1) {
|
||||
if (currentScreenPage == 0) {
|
||||
syncClusterTrackers();
|
||||
} else if (currentScreenPage == 1) {
|
||||
syncTriTempTrackers();
|
||||
} else if (currentScreenPage == 2) {
|
||||
syncGpsClockTrackers();
|
||||
} else if (currentScreenPage == 3) {
|
||||
syncGpsNavTrackers();
|
||||
} else if (currentScreenPage == 4) {
|
||||
syncClusterTrackers();
|
||||
} else if (currentScreenPage == 0 && fullScreenCell == -1) {
|
||||
syncPage0Trackers();
|
||||
syncGpsNavTrackers(true);
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.printf(">>> [DB] initScreen (NO REDRAW) FINISHED OK (heap: %u)\n",
|
||||
|
|
@ -2052,11 +1866,11 @@ void initScreen(bool redrawTFT) {
|
|||
old_data[i] = -999;
|
||||
}
|
||||
|
||||
if (fullScreenCell >= 0 && fullScreenCell < 4) {
|
||||
if (currentScreenPage == 0) {
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.println(">>> [DB] initScreen: drawing fullScreenMeter");
|
||||
Serial.println(">>> [DB] initScreen: drawing drawClusterScreen(0)");
|
||||
#endif
|
||||
fullScreenMeter(fullScreenCell, pidInCell[fullScreenCell]);
|
||||
drawClusterScreen(0);
|
||||
} else if (currentScreenPage == 1) {
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.println(">>> [DB] initScreen: drawing drawTriTempScreen(0)");
|
||||
|
|
@ -2072,27 +1886,6 @@ void initScreen(bool redrawTFT) {
|
|||
Serial.println(">>> [DB] initScreen: drawing drawGpsNavScreen(0)");
|
||||
#endif
|
||||
drawGpsNavScreen(0);
|
||||
} else if (currentScreenPage == 4) {
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.println(">>> [DB] initScreen: drawing drawClusterScreen(0)");
|
||||
#endif
|
||||
drawClusterScreen(0);
|
||||
} else {
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.println(">>> [DB] initScreen: drawing Page 0 quadrants");
|
||||
#endif
|
||||
tft.fillScreen(TFT_BLACK); // clear screen
|
||||
for (uint8_t c = 0; c < 4; c++) {
|
||||
uint8_t pid = pidInCell[c];
|
||||
arcMeter4(c, pid);
|
||||
}
|
||||
drawQuadrantDividers();
|
||||
// Pagination indicator dots [● ○ ○ ○ ○] (Page 0 active)
|
||||
tft.fillCircle(132, 2, 2, getThemePrimaryColor());
|
||||
tft.fillCircle(146, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(160, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(174, 2, 2, 0x5AEB);
|
||||
tft.fillCircle(188, 2, 2, 0x5AEB);
|
||||
}
|
||||
if (currentScreenPage == 0 && fullScreenCell == -1) {
|
||||
badgeEcoDrawn = false;
|
||||
|
|
@ -2232,10 +2025,8 @@ inline void updateGpsSpeedometer() {
|
|||
last_valid_data[1] = spd;
|
||||
|
||||
int warn = warningValue[3].toInt();
|
||||
if (fullScreenCell == 1) {
|
||||
plotFullScreen(1, spd, warn, 0, 160, false, "km/h");
|
||||
} else if (currentScreenPage == 0 && fullScreenCell == -1) {
|
||||
plotArc4(1, spd, warn, 0, 160, false, "km/h");
|
||||
if (currentScreenPage == 0) {
|
||||
updateClusterScreen(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2420,13 +2211,7 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
|
|||
|
||||
last_valid_data[pidNo] = data;
|
||||
|
||||
if (fullScreenCell >= 0 && fullScreenCell < 4) {
|
||||
if (pidNo == fullScreenCell) {
|
||||
plotFullScreen(fullScreenCell, data, warn, min, max, digit, unit);
|
||||
}
|
||||
} else if (currentScreenPage == 0) {
|
||||
plotArc4(pidNo, data, warn, min, max, digit, unit);
|
||||
} else if (currentScreenPage == 4) {
|
||||
if (currentScreenPage == 0) {
|
||||
updateClusterScreen(false);
|
||||
}
|
||||
bt_message = ""; // reset
|
||||
|
|
@ -2656,7 +2441,7 @@ void handleArcAlarmFlash() {
|
|||
|
||||
if (fullScreenCell >= 0 && fullScreenCell < 4) {
|
||||
uint8_t cell = fullScreenCell;
|
||||
if (last_valid_data[cell] != -999) {
|
||||
if (last_valid_data[cell] > -900.0f) {
|
||||
uint8_t pidIdx = pidInCell[cell];
|
||||
int warn = warningValue[pidIdx].toInt();
|
||||
float data = last_valid_data[cell];
|
||||
|
|
@ -2720,9 +2505,9 @@ void handleArcAlarmFlash() {
|
|||
}
|
||||
}
|
||||
} else if (currentScreenPage == 0) {
|
||||
// 4 quadrants mode
|
||||
// Cockpit Instrumental: check alarms for buzzer without drawing old quadrants
|
||||
for (uint8_t cell = 0; cell < 4; cell++) {
|
||||
if (last_valid_data[cell] != -999) {
|
||||
if (last_valid_data[cell] > -900.0f) {
|
||||
uint8_t pidIdx = pidInCell[cell];
|
||||
int warn = warningValue[pidIdx].toInt();
|
||||
float data = last_valid_data[cell];
|
||||
|
|
@ -2731,65 +2516,13 @@ void handleArcAlarmFlash() {
|
|||
bool isAlarmActive = alarmEnabled[pidIdx];
|
||||
if (inRed && isAlarmActive)
|
||||
anyInRedAlarm = true;
|
||||
bool digit = pidConfig[pidIdx][7].toInt();
|
||||
String numStr = String(data, digit);
|
||||
int x = cell4_x[cell];
|
||||
int y = cell4_y[cell];
|
||||
|
||||
if (wasInRedAlarm[cell] && !inRed) {
|
||||
// Exited red alarm: restore steady arc, text, and icon
|
||||
wasInRedAlarm[cell] = false;
|
||||
drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]);
|
||||
int min = pidConfig[pidIdx][4].toInt();
|
||||
int max = pidConfig[pidIdx][5].toInt();
|
||||
int newBlocks = calcMeterBlocks(data, min, max);
|
||||
for (uint8_t i = 0; i < newBlocks; i++) {
|
||||
drawQuadBarBlock(cell, i, col);
|
||||
}
|
||||
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
|
||||
drawQuadBarBlock(cell, i, METER_INACTIVE_COLOR);
|
||||
}
|
||||
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
||||
tft.setTextColor(getThemeCellColor(cell), TFT_BLACK);
|
||||
tft.setTextPadding(114);
|
||||
tft.drawRightString(numStr.c_str(), x + 152, y + 74, 1);
|
||||
tft.setTextPadding(0);
|
||||
tft.unloadFont();
|
||||
} else if (inRed) {
|
||||
wasInRedAlarm[cell] = true;
|
||||
if (isAlarmActive) {
|
||||
if (toggleTick) {
|
||||
if (arcFlashVisible) {
|
||||
drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]);
|
||||
} else {
|
||||
clearPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]);
|
||||
}
|
||||
int min = pidConfig[pidIdx][4].toInt();
|
||||
int max = pidConfig[pidIdx][5].toInt();
|
||||
int newBlocks = calcMeterBlocks(data, min, max);
|
||||
|
||||
if (arcFlashVisible) {
|
||||
for (uint8_t i = 0; i < newBlocks; i++) {
|
||||
drawQuadBarBlock(cell, i, TFT_RED);
|
||||
}
|
||||
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
|
||||
drawQuadBarBlock(cell, i, METER_INACTIVE_COLOR);
|
||||
}
|
||||
} else {
|
||||
for (uint8_t i = 0; i < NUM_BAR_BLOCKS; i++) {
|
||||
drawQuadBarBlock(cell, i, TFT_BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Page 1 (Tri-Temperature screen): check alarm conditions for acoustic
|
||||
// warning without touching screen graphics
|
||||
for (uint8_t cell = 0; cell < 4; cell++) {
|
||||
if (last_valid_data[cell] != -999) {
|
||||
if (last_valid_data[cell] > -900.0f) {
|
||||
uint8_t pidIdx = pidInCell[cell];
|
||||
int warn = warningValue[pidIdx].toInt();
|
||||
float data = last_valid_data[cell];
|
||||
|
|
|
|||
|
|
@ -301,16 +301,16 @@ int8_t currentScreenPage =
|
|||
inline void setScreenPage(int8_t page) {
|
||||
if (page < 0)
|
||||
page = 0;
|
||||
if (page > 4)
|
||||
page = 4;
|
||||
if (page > 3)
|
||||
page = 3;
|
||||
currentScreenPage = page;
|
||||
pref.begin("setting", false);
|
||||
pref.putChar("scr_page", page);
|
||||
pref.end();
|
||||
}
|
||||
float tempEngineCoolant = 88.0f; // Temperatura de refrigerante de motor (OBD2)
|
||||
float tempInterior = 22.5f; // Temperatura interior habitáculo (DS18B20 #1)
|
||||
float tempExterior = 16.8f; // Temperatura exterior ambiente (DS18B20 #2)
|
||||
float tempEngineCoolant = -999.0f; // Temperatura de refrigerante de motor (OBD2)
|
||||
float tempInterior = -999.0f; // Temperatura interior habitáculo (DS18B20 #1)
|
||||
float tempExterior = -999.0f; // Temperatura exterior ambiente (DS18B20 #2)
|
||||
uint8_t dsSensorCount = 0; // Cantidad de sensores 1-Wire detectados
|
||||
// User configuration here to change display >
|
||||
|
||||
|
|
@ -344,12 +344,12 @@ uint8_t btDeviceCount = 0; // discovered bluetooth devices counter
|
|||
esp_bd_addr_t client_addr = {0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00}; // obdII mac addr
|
||||
esp_bd_addr_t recent_client_addr = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // keep last btaddr in RTC memory
|
||||
0x6C, 0x62, 0x6D, 0x14, 0x08, 0xFD}; // Default to PC emulator MAC
|
||||
const String client_name = "OBDII"; // adaptor name to search
|
||||
esp_spp_sec_t sec_mask =
|
||||
ESP_SPP_SEC_NONE; // or ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE to
|
||||
// request pincode confirmation
|
||||
esp_spp_role_t role = ESP_SPP_ROLE_SLAVE; // or ESP_SPP_ROLE_MASTER
|
||||
esp_spp_role_t role = ESP_SPP_ROLE_MASTER; // Initiator is SPP MASTER
|
||||
bool foundOBD2 = false;
|
||||
BluetoothSerial BTSerial; // bluetooth serial device
|
||||
|
||||
|
|
@ -548,8 +548,12 @@ volatile bool btConnectedTrigger = false;
|
|||
volatile bool systemSleeping = false;
|
||||
|
||||
void btBackgroundTask(void *pvParameters) {
|
||||
const esp_bd_addr_t EMU_ADDR = {0x6C, 0x62, 0x6D, 0x14, 0x08, 0xFD};
|
||||
while (true) {
|
||||
if (!systemSleeping && !foundOBD2) {
|
||||
bool connected = false;
|
||||
|
||||
// 1. Intentar conectar a la direccion reciente guardada si es valida
|
||||
bool hasRecentAddr = false;
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (recent_client_addr[i] != 0) {
|
||||
|
|
@ -563,6 +567,48 @@ void btBackgroundTask(void *pvParameters) {
|
|||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
if (BTSerial.connect(recent_client_addr, 0, sec_mask, role)) {
|
||||
if (BTSerial.connected() && !systemSleeping) {
|
||||
connected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Si fallo o no habia direccion, intentar conectar a la MAC del emulador PC
|
||||
if (!connected && !systemSleeping) {
|
||||
bool isRecentSameAsEmu = true;
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (recent_client_addr[i] != EMU_ADDR[i]) {
|
||||
isRecentSameAsEmu = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isRecentSameAsEmu) {
|
||||
setRearLedColor(0, 0, 200);
|
||||
BTSerial.disconnect();
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
if (BTSerial.connect(const_cast<uint8_t*>(EMU_ADDR), 0, sec_mask, role)) {
|
||||
if (BTSerial.connected() && !systemSleeping) {
|
||||
connected = true;
|
||||
memcpy(recent_client_addr, EMU_ADDR, 6);
|
||||
pref.putBytes("recent_client", recent_client_addr, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Si aun no conecto, buscar y conectar por nombre "OBDII" (inquiry scan)
|
||||
if (!connected && !systemSleeping) {
|
||||
setRearLedColor(0, 0, 200);
|
||||
BTSerial.disconnect();
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
if (BTSerial.connect("OBDII")) {
|
||||
if (BTSerial.connected() && !systemSleeping) {
|
||||
connected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Si logro conectar con cualquiera de los metodos:
|
||||
if (connected && !systemSleeping) {
|
||||
sendATCommand("ATE0", 800);
|
||||
sendATCommand("ATL0", 800);
|
||||
sendATCommand("ATH0", 800);
|
||||
|
|
@ -581,11 +627,6 @@ void btBackgroundTask(void *pvParameters) {
|
|||
setRearLedOff();
|
||||
foundOBD2 = false;
|
||||
}
|
||||
} else {
|
||||
setRearLedOff();
|
||||
foundOBD2 = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(3500));
|
||||
}
|
||||
|
|
@ -711,7 +752,7 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
|
|||
if (transitionType > 1)
|
||||
transitionType = 0;
|
||||
currentScreenPage = pref.getChar("scr_page", 0);
|
||||
if (currentScreenPage < 0 || currentScreenPage > 4)
|
||||
if (currentScreenPage < 0 || currentScreenPage > 3)
|
||||
currentScreenPage = 0;
|
||||
if (brightnessIndex > 0) {
|
||||
targetBacklight = BRIGHTNESS_PWM_TABLE[brightnessIndex];
|
||||
|
|
@ -853,6 +894,11 @@ void loop() {
|
|||
updateGpsSpeedometer();
|
||||
updateGpsIconAnim();
|
||||
|
||||
// Non-blocking live refresh for resting Page 0 (Cockpit Instrumental Deportivo)
|
||||
if (currentScreenPage == 0 && fullScreenCell == -1) {
|
||||
updateClusterScreen(false);
|
||||
}
|
||||
|
||||
// Non-blocking live refresh for resting Page 2 (GPS Clock & Date)
|
||||
if (currentScreenPage == 2 && fullScreenCell == -1) {
|
||||
updateGpsClockScreen(false);
|
||||
|
|
@ -863,11 +909,6 @@ void loop() {
|
|||
updateGpsNavScreen(false);
|
||||
}
|
||||
|
||||
// Non-blocking live refresh for resting Page 4 (Cockpit Instrumental Deportivo)
|
||||
if (currentScreenPage == 4 && fullScreenCell == -1) {
|
||||
updateClusterScreen(false);
|
||||
}
|
||||
|
||||
if (wokeFromSleep) {
|
||||
wokeFromSleep = false;
|
||||
lastActivityTime = millis();
|
||||
|
|
@ -927,10 +968,10 @@ void loop() {
|
|||
// (disabled in full-screen mode)
|
||||
if (!longPressHandled) {
|
||||
if (fullScreenCell == -1 && liveDeltaX < -28 && abs(liveDeltaY) < 85) {
|
||||
// SWIPE LEFT: Transition to next page (0 -> 1 -> 2 -> 3 -> 4 -> 0)
|
||||
// SWIPE LEFT: Transition to next page (0 -> 1 -> 2 -> 3 -> 0)
|
||||
longPressHandled = true;
|
||||
touchBeep();
|
||||
uint8_t nextPage = (currentScreenPage + 1) % 5;
|
||||
uint8_t nextPage = (currentScreenPage + 1) % 4;
|
||||
performScreenTransition(true, currentScreenPage, nextPage);
|
||||
setScreenPage(nextPage);
|
||||
initScreen(false); // Seamless: keep transition frame without blanking
|
||||
|
|
@ -940,11 +981,11 @@ void loop() {
|
|||
lastActivityTime = millis();
|
||||
} else if (fullScreenCell == -1 && liveDeltaX > 28 &&
|
||||
abs(liveDeltaY) < 85) {
|
||||
// SWIPE RIGHT: Transition to previous page (0 -> 4 -> 3 -> 2 -> 1 -> 0)
|
||||
// SWIPE RIGHT: Transition to previous page (0 -> 3 -> 2 -> 1 -> 0)
|
||||
longPressHandled = true;
|
||||
touchBeep();
|
||||
uint8_t nextPage =
|
||||
(currentScreenPage == 0) ? 4 : (currentScreenPage - 1);
|
||||
(currentScreenPage == 0) ? 3 : (currentScreenPage - 1);
|
||||
performScreenTransition(false, currentScreenPage, nextPage);
|
||||
setScreenPage(nextPage);
|
||||
initScreen(false); // Seamless: keep transition frame without blanking
|
||||
|
|
@ -984,7 +1025,7 @@ void loop() {
|
|||
// SWIPE LEFT
|
||||
longPressHandled = true;
|
||||
touchBeep();
|
||||
uint8_t nextPage = (currentScreenPage + 1) % 5;
|
||||
uint8_t nextPage = (currentScreenPage + 1) % 4;
|
||||
performScreenTransition(true, currentScreenPage, nextPage);
|
||||
setScreenPage(nextPage);
|
||||
initScreen(false); // Seamless: keep transition frame without blanking
|
||||
|
|
@ -997,7 +1038,7 @@ void loop() {
|
|||
longPressHandled = true;
|
||||
touchBeep();
|
||||
uint8_t nextPage =
|
||||
(currentScreenPage == 0) ? 4 : (currentScreenPage - 1);
|
||||
(currentScreenPage == 0) ? 3 : (currentScreenPage - 1);
|
||||
performScreenTransition(false, currentScreenPage, nextPage);
|
||||
setScreenPage(nextPage);
|
||||
initScreen(false); // Seamless: keep transition frame without blanking
|
||||
|
|
@ -1010,16 +1051,8 @@ void loop() {
|
|||
// Valid TAP detected!
|
||||
touchBeep();
|
||||
if (currentScreenPage == 0) {
|
||||
if (fullScreenCell == -1) {
|
||||
// Switch to full screen for tapped quadrant
|
||||
int quad = (lastTouchX < 160) ? ((lastTouchY < 120) ? 0 : 2)
|
||||
: ((lastTouchY < 120) ? 1 : 3);
|
||||
fullScreenCell = quad;
|
||||
} else {
|
||||
// Return to 4 quadrants view
|
||||
fullScreenCell = -1;
|
||||
}
|
||||
initScreen();
|
||||
// Tap on Cockpit Instrumental: immediate cluster refresh
|
||||
updateClusterScreen(true);
|
||||
} else if (currentScreenPage == 1) {
|
||||
// Tap on Tri-Temp screen: immediate sensor refresh
|
||||
updateTriTempSensors(true);
|
||||
|
|
@ -1029,9 +1062,6 @@ void loop() {
|
|||
} else if (currentScreenPage == 3) {
|
||||
// Tap on GPS Navigation screen: immediate telemetry refresh
|
||||
updateGpsNavScreen(true);
|
||||
} else if (currentScreenPage == 4) {
|
||||
// Tap on Cockpit Instrumental: immediate cluster refresh
|
||||
updateClusterScreen(true);
|
||||
}
|
||||
waitForTouchRelease();
|
||||
lastActivityTime = millis();
|
||||
|
|
@ -1075,6 +1105,12 @@ void loop() {
|
|||
if (!isBtConnected && wasBtConnected) {
|
||||
wasBtConnected = false;
|
||||
currentRpm = 0.0f;
|
||||
tempEngineCoolant = -999.0f;
|
||||
for (uint8_t c = 0; c < 4; c++) {
|
||||
if (c != 1 || !isGpsSpeedValid()) {
|
||||
last_valid_data[c] = -999.0f;
|
||||
}
|
||||
}
|
||||
ignitionOn = false;
|
||||
foundOBD2 = false;
|
||||
uint8_t fallbackPage = isGpsSynced() ? 2 : 1;
|
||||
|
|
@ -1089,14 +1125,16 @@ void loop() {
|
|||
|
||||
if (!isBtConnected) {
|
||||
currentRpm = 0.0f;
|
||||
ignitionOn = false;
|
||||
if (currentScreenPage == 0 || fullScreenCell != -1) {
|
||||
tempEngineCoolant = -999.0f;
|
||||
for (uint8_t c = 0; c < 4; c++) {
|
||||
if (c == 1 && isGpsSpeedValid())
|
||||
continue; // Mantener la velocidad de GPS en el velocimetro
|
||||
plotNoData(c);
|
||||
if (c != 1 || !isGpsSpeedValid()) {
|
||||
last_valid_data[c] = -999.0f;
|
||||
}
|
||||
}
|
||||
ignitionOn = false;
|
||||
if (currentScreenPage == 0) {
|
||||
updateClusterScreen(false);
|
||||
}
|
||||
foundOBD2 =
|
||||
false; // Core 0 background task will handle reconnection smoothly!
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <Arduino.h>
|
||||
#include <TFT_eSPI.h>
|
||||
#include "DSEG7_Modern_BoldItalic_34.h"
|
||||
#include "DSEG7_Modern_BoldItalic_44.h"
|
||||
#include "DSEG7_Modern_BoldItalic_80.h"
|
||||
|
||||
extern bool isRainbowTheme();
|
||||
|
|
@ -132,9 +133,9 @@ inline void drawDseg7RightString34(T &dst, const char *str, int rightX, int y0,
|
|||
int totalW = getDseg7StringWidth34(str);
|
||||
int startX = rightX - totalW;
|
||||
|
||||
if (padding > totalW) {
|
||||
int clearW = padding - totalW;
|
||||
int clearX = rightX - padding;
|
||||
if (padding > 0) {
|
||||
int clearW = (padding > totalW) ? padding : totalW;
|
||||
int clearX = rightX - clearW;
|
||||
if (clearX < 0) {
|
||||
clearW += clearX;
|
||||
clearX = 0;
|
||||
|
|
@ -154,10 +155,93 @@ inline void drawDseg7RightString34(T &dst, const char *str, int rightX, int y0,
|
|||
}
|
||||
}
|
||||
|
||||
// Measure width in pixels of a string rendered in DSEG7 44pt (tight tracking adv=31)
|
||||
inline int getDseg7StringWidth44(const char *str) {
|
||||
int w = 0;
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
char c = str[i];
|
||||
if (c == '.') w += 10;
|
||||
else if (c == ' ') w += 31;
|
||||
else w += 31;
|
||||
}
|
||||
return w + 5;
|
||||
}
|
||||
|
||||
// Draw a single DSEG7 44pt character directly to destination
|
||||
template <typename T>
|
||||
inline void drawDseg7Digit44(T &dst, int x0, int y0, char c, uint16_t color,
|
||||
uint16_t bgCol, int clip_h = 240, bool rainbow = false, int screen_offset_x = 0) {
|
||||
uint32_t offset = 0;
|
||||
uint8_t w = 36;
|
||||
if (c >= '0' && c <= '9') {
|
||||
offset = 388 + (c - '0') * 1584;
|
||||
} else if (c == '.') {
|
||||
offset = 16228;
|
||||
w = 10;
|
||||
} else if (c == '-') {
|
||||
offset = 16668;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
dst.startWrite();
|
||||
for (int dy = 0; dy < 44; dy++) {
|
||||
int curY = y0 + dy;
|
||||
if (curY < 0 || curY >= clip_h)
|
||||
continue;
|
||||
const uint8_t *row = &DSEG7_Modern_BoldItalic_44[offset + dy * w];
|
||||
for (int dx = 0; dx < w; dx++) {
|
||||
int curX = x0 + dx;
|
||||
if (curX < 0 || curX >= 320)
|
||||
continue;
|
||||
uint8_t a = pgm_read_byte(row + dx);
|
||||
if (a == 0)
|
||||
continue;
|
||||
uint16_t fg = rainbow ? getRainbowScreenColor(curX + screen_offset_x, curY) : color;
|
||||
if (a >= 240) {
|
||||
dst.drawPixel(curX, curY, fg);
|
||||
} else {
|
||||
dst.drawPixel(curX, curY, dst.alphaBlend(a, fg, bgCol));
|
||||
}
|
||||
}
|
||||
}
|
||||
dst.endWrite();
|
||||
}
|
||||
|
||||
// Draw a DSEG7 44pt string right-aligned with automatic background padding and rainbow support
|
||||
template <typename T>
|
||||
inline void drawDseg7RightString44(T &dst, const char *str, int rightX, int y0,
|
||||
uint16_t color, uint16_t bgCol, int padding = 0,
|
||||
int clip_h = 240, bool rainbow = false, int screen_offset_x = 0) {
|
||||
int totalW = getDseg7StringWidth44(str);
|
||||
int startX = rightX - totalW;
|
||||
|
||||
if (padding > 0) {
|
||||
int clearW = (padding > totalW) ? padding : totalW;
|
||||
int clearX = rightX - clearW;
|
||||
if (clearX < 0) {
|
||||
clearW += clearX;
|
||||
clearX = 0;
|
||||
}
|
||||
if (clearW > 0) {
|
||||
dst.fillRect(clearX, y0, clearW, 44, bgCol);
|
||||
}
|
||||
}
|
||||
|
||||
int curX = startX;
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
char c = str[i];
|
||||
uint16_t charColor = isYapaTheme() ? getYapaColor(i) : color;
|
||||
drawDseg7Digit44(dst, curX, y0, c, charColor, bgCol, clip_h, rainbow, screen_offset_x);
|
||||
if (c == '.') curX += 10;
|
||||
else curX += 31;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a single DSEG7 80pt digit directly to destination with rainbow gradient
|
||||
template <typename T>
|
||||
inline void drawDseg7Digit80(T &dst, int x0, int y0, uint8_t digit,
|
||||
uint16_t color, uint16_t bgCol, int clip_h = 240, bool rainbow = false) {
|
||||
uint16_t color, uint16_t bgCol, int clip_h = 240, bool rainbow = false, int screen_offset_x = 0) {
|
||||
if (digit > 9) return;
|
||||
const uint8_t *bmp = &DSEG7_Modern_BoldItalic_80[388 + digit * 5200];
|
||||
dst.startWrite();
|
||||
|
|
@ -173,7 +257,7 @@ inline void drawDseg7Digit80(T &dst, int x0, int y0, uint8_t digit,
|
|||
continue;
|
||||
uint8_t a = pgm_read_byte(row + dx);
|
||||
if (a == 0) continue;
|
||||
uint16_t fg = rainbow ? getRainbowScreenColor(curX, curY) : color;
|
||||
uint16_t fg = rainbow ? getRainbowScreenColor(curX + screen_offset_x, curY) : color;
|
||||
if (a >= 240) {
|
||||
dst.drawPixel(curX, curY, fg);
|
||||
} else {
|
||||
|
|
@ -188,16 +272,17 @@ inline void drawDseg7Digit80(T &dst, int x0, int y0, uint8_t digit,
|
|||
template <typename T>
|
||||
inline void drawDseg7RightString80(T &dst, const char *str, int rightX, int y0,
|
||||
uint16_t color, uint16_t bgCol, int padding = 0,
|
||||
int clip_h = 240, bool rainbow = false) {
|
||||
// Ancho aproximado por digito 80pt: advance de 65px
|
||||
int len = 0;
|
||||
for (int i = 0; str[i] != '\0'; i++) len++;
|
||||
int totalW = len * 65;
|
||||
int clip_h = 240, bool rainbow = false, int screen_offset_x = 0) {
|
||||
int totalW = 0;
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
if (str[i] == '-') totalW += 50;
|
||||
else totalW += 65;
|
||||
}
|
||||
int startX = rightX - totalW;
|
||||
|
||||
if (padding > totalW) {
|
||||
int clearW = padding - totalW;
|
||||
int clearX = rightX - padding;
|
||||
if (padding > 0) {
|
||||
int clearW = (padding > totalW) ? padding : totalW;
|
||||
int clearX = rightX - clearW;
|
||||
if (clearX < 0) {
|
||||
clearW += clearX;
|
||||
clearX = 0;
|
||||
|
|
@ -212,14 +297,158 @@ inline void drawDseg7RightString80(T &dst, const char *str, int rightX, int y0,
|
|||
char c = str[i];
|
||||
uint16_t charColor = isYapaTheme() ? getYapaColor(i) : color;
|
||||
if (c >= '0' && c <= '9') {
|
||||
drawDseg7Digit80(dst, curX, y0, c - '0', charColor, bgCol, clip_h, rainbow);
|
||||
drawDseg7Digit80(dst, curX, y0, c - '0', charColor, bgCol, clip_h, rainbow, screen_offset_x);
|
||||
curX += 65;
|
||||
} else if (c == '-') {
|
||||
// Si es '-', dibujamos barra horizontal central de DSEG7
|
||||
dst.fillRect(curX + 10, y0 + 36, 45, 8, rainbow ? getRainbowScreenColor(curX + 32, y0 + 40) : charColor);
|
||||
for (int dy = 0; dy < 6; dy++) {
|
||||
int py = y0 + 37 + dy;
|
||||
if (py >= 0 && py < clip_h) {
|
||||
int startDx = 11 - dy / 2;
|
||||
dst.fillRect(curX + startDx, py, 28, 1, rainbow ? getRainbowScreenColor(curX + screen_offset_x + startDx + 14, py) : charColor);
|
||||
}
|
||||
}
|
||||
curX += 50;
|
||||
} else {
|
||||
curX += 65;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fast zero-flicker line-buffered DSEG7 44pt renderer (direct to TFT, NO heap allocation!)
|
||||
template <typename T>
|
||||
inline void drawDseg7RightFast44(T &dst, const char *str, int rightX, int y0,
|
||||
uint16_t color, uint16_t bgCol, int minTotalW = 0,
|
||||
bool rainbow = false) {
|
||||
int totalW = getDseg7StringWidth44(str);
|
||||
int renderW = (minTotalW > totalW) ? minTotalW : totalW;
|
||||
if (renderW > 160) renderW = 160;
|
||||
int startX = rightX - renderW;
|
||||
int textOffsetX = renderW - totalW;
|
||||
|
||||
uint16_t lineBuf[160];
|
||||
|
||||
dst.startWrite();
|
||||
for (int dy = 0; dy < 44; dy++) {
|
||||
int curY = y0 + dy;
|
||||
if (curY < 0 || curY >= 240) continue;
|
||||
|
||||
for (int i = 0; i < renderW; i++) {
|
||||
lineBuf[i] = bgCol;
|
||||
}
|
||||
|
||||
int curX = textOffsetX;
|
||||
for (int idx = 0; str[idx] != '\0'; idx++) {
|
||||
char c = str[idx];
|
||||
uint32_t offset = 0;
|
||||
uint8_t w = 36;
|
||||
uint8_t adv = 31;
|
||||
if (c >= '0' && c <= '9') {
|
||||
offset = 388 + (c - '0') * 1584;
|
||||
} else if (c == '.') {
|
||||
offset = 16228;
|
||||
w = 10;
|
||||
adv = 10;
|
||||
} else if (c == '-') {
|
||||
offset = 16668;
|
||||
} else {
|
||||
curX += adv;
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint8_t *row = &DSEG7_Modern_BoldItalic_44[offset + dy * w];
|
||||
uint16_t charColor = isYapaTheme() ? getYapaColor(idx) : color;
|
||||
|
||||
for (int dx = 0; dx < w; dx++) {
|
||||
int bufX = curX + dx;
|
||||
if (bufX < 0 || bufX >= renderW) continue;
|
||||
uint8_t a = pgm_read_byte(row + dx);
|
||||
if (a == 0) continue;
|
||||
int screenX = startX + bufX;
|
||||
uint16_t fg = rainbow ? getRainbowScreenColor(screenX, curY) : charColor;
|
||||
if (a >= 240) {
|
||||
lineBuf[bufX] = fg;
|
||||
} else {
|
||||
lineBuf[bufX] = dst.alphaBlend(a, fg, bgCol);
|
||||
}
|
||||
}
|
||||
curX += adv;
|
||||
}
|
||||
|
||||
dst.pushImage(startX, curY, renderW, 1, lineBuf);
|
||||
}
|
||||
dst.endWrite();
|
||||
}
|
||||
|
||||
// Fast zero-flicker line-buffered DSEG7 80pt renderer (direct to TFT, NO heap allocation!)
|
||||
template <typename T>
|
||||
inline void drawDseg7RightFast80(T &dst, const char *str, int rightX, int y0,
|
||||
uint16_t color, uint16_t bgCol, int minTotalW = 0,
|
||||
bool rainbow = false) {
|
||||
int totalW = 0;
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
if (str[i] == '-') totalW += 50;
|
||||
else totalW += 65;
|
||||
}
|
||||
int renderW = (minTotalW > totalW) ? minTotalW : totalW;
|
||||
if (renderW > 184) renderW = 184;
|
||||
int startX = rightX - renderW;
|
||||
if (startX < 10) {
|
||||
renderW -= (10 - startX);
|
||||
startX = 10;
|
||||
}
|
||||
int textOffsetX = renderW - totalW;
|
||||
|
||||
uint16_t lineBuf[200];
|
||||
|
||||
dst.startWrite();
|
||||
for (int dy = 0; dy < 80; dy++) {
|
||||
int curY = y0 + dy;
|
||||
if (curY < 0 || curY >= 240) continue;
|
||||
|
||||
for (int i = 0; i < renderW; i++) {
|
||||
lineBuf[i] = bgCol;
|
||||
}
|
||||
|
||||
int curX = textOffsetX;
|
||||
for (int idx = 0; str[idx] != '\0'; idx++) {
|
||||
char c = str[idx];
|
||||
uint16_t charColor = isYapaTheme() ? getYapaColor(idx) : color;
|
||||
if (c >= '0' && c <= '9') {
|
||||
const uint8_t *bmp = &DSEG7_Modern_BoldItalic_80[388 + (c - '0') * 5200 + dy * 65];
|
||||
for (int dx = 0; dx < 65; dx++) {
|
||||
int bufX = curX + dx;
|
||||
if (bufX < 0 || bufX >= renderW) continue;
|
||||
uint8_t a = pgm_read_byte(bmp + dx);
|
||||
if (a == 0) continue;
|
||||
int screenX = startX + bufX;
|
||||
uint16_t fg = rainbow ? getRainbowScreenColor(screenX, curY) : charColor;
|
||||
if (a >= 240) {
|
||||
lineBuf[bufX] = fg;
|
||||
} else {
|
||||
lineBuf[bufX] = dst.alphaBlend(a, fg, bgCol);
|
||||
}
|
||||
}
|
||||
curX += 65;
|
||||
} else if (c == '-') {
|
||||
if (dy >= 37 && dy < 43) {
|
||||
int startDx = 11 - (dy - 37) / 2;
|
||||
for (int dx = startDx; dx < startDx + 28; dx++) {
|
||||
int bufX = curX + dx;
|
||||
if (bufX >= 0 && bufX < renderW) {
|
||||
lineBuf[bufX] = rainbow ? getRainbowScreenColor(startX + bufX, curY) : charColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
curX += 50;
|
||||
} else {
|
||||
curX += 65;
|
||||
}
|
||||
}
|
||||
|
||||
dst.pushImage(startX, curY, renderW, 1, lineBuf);
|
||||
}
|
||||
dst.endWrite();
|
||||
}
|
||||
|
||||
// Apply spectral rainbow coloring to any pre-rendered text sprite with 100% anti-aliasing preservation
|
||||
inline void applyRainbowToSprite(TFT_eSprite &s, int screenX, int screenY, uint16_t bgCol = 0x10A2) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,11 @@ static TFT_eSprite sprTriTitle[3] = { TFT_eSprite(&tft), TFT_eSprite(&tft), TFT_
|
|||
static bool sprTriTitleReady = false;
|
||||
|
||||
inline void invalidateTriTempTitles() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (sprTriTitle[i].created()) {
|
||||
sprTriTitle[i].deleteSprite();
|
||||
}
|
||||
}
|
||||
sprTriTitleReady = false;
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +172,12 @@ inline void draw7SegDegreeC(TFT_eSPI &dst, int bx, int by, uint16_t color = 0xC6
|
|||
if (px < 0 || px >= dst.width()) continue;
|
||||
uint8_t a = pgm_read_byte(&s_dsegUnitAlpha[rowOffset + i]);
|
||||
if (a > 8) {
|
||||
uint16_t curCol = rainbow ? getRainbowScreenColor(px, py) : color;
|
||||
uint16_t curCol = color;
|
||||
if (rainbow) {
|
||||
curCol = getRainbowScreenColor(px, py);
|
||||
} else if (isYapaTheme()) {
|
||||
curCol = (i < 12) ? getYapaColor(0) : getYapaColor(1);
|
||||
}
|
||||
uint16_t pixCol = (a >= 250) ? curCol : fastBlend(a, curCol, bgCol);
|
||||
dst.drawPixel(px, py, pixCol);
|
||||
}
|
||||
|
|
@ -247,13 +257,13 @@ inline void drawTriTempCard(uint8_t cardIdx, float val, int x_offset = 0) {
|
|||
else accentCol = TFT_RED;
|
||||
} else if (cardIdx == 1) {
|
||||
titleStr = "INTERIOR";
|
||||
subStr = (dsSensorCount > 0) ? "DS18B20 SENSOR 1 (GPIO 22)" : "DS18B20 SENSOR 1";
|
||||
subStr = (dsSensorCount > 0) ? "DS18B20 SENSOR 1 (GPIO 22)" : "DS18B20 NO DETECTADO";
|
||||
minRange = 10.0f;
|
||||
maxRange = 40.0f;
|
||||
accentCol = isRainbowTheme() ? (uint16_t)0x07E0 : (isYapaTheme() ? getYapaColor(1) : getThemeAccentColor());
|
||||
} else {
|
||||
titleStr = "EXTERIOR";
|
||||
subStr = (dsSensorCount > 1) ? "DS18B20 SENSOR 2 (GPIO 22)" : (dsSensorCount == 1 ? "ESTIMADA (-4.5`C)" : "DS18B20 SENSOR 2");
|
||||
subStr = (dsSensorCount > 1) ? "DS18B20 SENSOR 2 (GPIO 22)" : "DS18B20 NO DETECTADO";
|
||||
minRange = -10.0f;
|
||||
maxRange = 50.0f;
|
||||
accentCol = isRainbowTheme() ? (uint16_t)0xFD20 : (isYapaTheme() ? getYapaColor(2) : getThemePrimaryColor());
|
||||
|
|
@ -298,7 +308,7 @@ inline void drawTriTempCard(uint8_t cardIdx, float val, int x_offset = 0) {
|
|||
tft.unloadFont();
|
||||
}
|
||||
|
||||
tft.setTextColor(0x8410, cardBg); // Soft gray
|
||||
tft.setTextColor(accentCol, cardBg);
|
||||
tft.drawString(subStr, cardX + 16, cardY + 32, 1);
|
||||
}
|
||||
|
||||
|
|
@ -310,34 +320,35 @@ inline void drawTriTempCard(uint8_t cardIdx, float val, int x_offset = 0) {
|
|||
float ratio = (val - minRange) / (maxRange - minRange);
|
||||
if (ratio < 0.0f) ratio = 0.0f;
|
||||
if (ratio > 1.0f) ratio = 1.0f;
|
||||
int fillW = (int)(barW * ratio);
|
||||
if (fillW < 4) fillW = 4;
|
||||
int fillW = (val <= -900.0f) ? 0 : (int)(barW * ratio);
|
||||
if (fillW < 4 && val > -900.0f) fillW = 4;
|
||||
|
||||
if (x_offset == 0) {
|
||||
drawTriTempBar(barX, barY, fillW, accentCol);
|
||||
drawTriTempBar(barX, barY, fillW, (val <= -900.0f) ? (uint16_t)0x18C3 : accentCol);
|
||||
oldTriFillW[cardIdx] = fillW;
|
||||
oldTriAccentCol[cardIdx] = accentCol;
|
||||
} else {
|
||||
tft.fillRoundRect(barX, barY, barW, 8, 3, 0x18C3);
|
||||
if (fillW > 0) {
|
||||
tft.fillRoundRect(barX, barY, fillW, 8, 3, accentCol);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Digital Number using DSEG7 Modern Bold Italic 34pt
|
||||
String numStr;
|
||||
uint16_t numCol = accentCol;
|
||||
if (val <= -900.0f) {
|
||||
numStr = "---";
|
||||
} else if (isInt) {
|
||||
numStr = String((int)val);
|
||||
} else {
|
||||
numStr = String(val, 1);
|
||||
numStr = String((int)round(val));
|
||||
}
|
||||
|
||||
bool rainbowTxt = isRainbowTheme() && (accentCol != TFT_RED);
|
||||
drawDseg7RightString34(tft, numStr.c_str(), cardX + 262, cardY + 20, accentCol, cardBg, 100, 240, rainbowTxt);
|
||||
drawDseg7RightString34(tft, numStr.c_str(), cardX + 262, cardY + 20, numCol, cardBg, 100, 240, rainbowTxt);
|
||||
|
||||
// Unit "°C" in authentic digital 7-segment italic typography matching numbers
|
||||
bool rainbowUnit = isRainbowTheme() && (accentCol != TFT_RED);
|
||||
uint16_t unitCol = rainbowUnit ? getRainbowScreenColor(cardX + 268, cardY + 22) : (isYapaTheme() && accentCol != TFT_RED ? getYapaColor(numStr.length()) : (accentCol == TFT_RED ? TFT_RED : 0xC618));
|
||||
uint16_t unitCol = rainbowUnit ? getRainbowScreenColor(cardX + 268, cardY + 22) : (isYapaTheme() && accentCol != TFT_RED ? getYapaColor(numStr.length()) : (accentCol == TFT_RED ? TFT_RED : accentCol));
|
||||
draw7SegDegreeC(tft, cardX + 268, cardY + 22, unitCol, cardBg, rainbowUnit);
|
||||
}
|
||||
|
||||
|
|
@ -388,7 +399,7 @@ inline void updateTriTempCardValue(uint8_t cardIdx, float val, float oldVal) {
|
|||
sX += cw;
|
||||
}
|
||||
} else {
|
||||
tft.setTextColor(0x8410, cardBg);
|
||||
tft.setTextColor(accentCol, cardBg);
|
||||
tft.drawString(subStr, cardX + 16, cardY + 32, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -420,27 +431,26 @@ inline void updateTriTempCardValue(uint8_t cardIdx, float val, float oldVal) {
|
|||
float ratio = (val - minRange) / (maxRange - minRange);
|
||||
if (ratio < 0.0f) ratio = 0.0f;
|
||||
if (ratio > 1.0f) ratio = 1.0f;
|
||||
int fillW = (int)(barW * ratio);
|
||||
if (fillW < 4) fillW = 4;
|
||||
int fillW = (val <= -900.0f) ? 0 : (int)(barW * ratio);
|
||||
if (fillW < 4 && val > -900.0f) fillW = 4;
|
||||
|
||||
if (fillW != oldTriFillW[cardIdx] || accentCol != oldTriAccentCol[cardIdx]) {
|
||||
drawTriTempBar(barX, barY, fillW, accentCol);
|
||||
drawTriTempBar(barX, barY, fillW, (val <= -900.0f) ? (uint16_t)0x18C3 : accentCol);
|
||||
oldTriFillW[cardIdx] = fillW;
|
||||
oldTriAccentCol[cardIdx] = accentCol;
|
||||
}
|
||||
|
||||
// 3. Digital Number update using DSEG7 Modern Bold Italic 34pt (setTextPadding prevents flicker)
|
||||
String numStr;
|
||||
uint16_t numCol = accentCol;
|
||||
if (val <= -900.0f) {
|
||||
numStr = "---";
|
||||
} else if (isInt) {
|
||||
numStr = String((int)val);
|
||||
} else {
|
||||
numStr = String(val, 1);
|
||||
numStr = String((int)round(val));
|
||||
}
|
||||
|
||||
bool rainbowTxt = isRainbowTheme() && (accentCol != TFT_RED);
|
||||
drawDseg7RightString34(tft, numStr.c_str(), cardX + 262, cardY + 20, accentCol, cardBg, 100, 240, rainbowTxt);
|
||||
drawDseg7RightString34(tft, numStr.c_str(), cardX + 262, cardY + 20, numCol, cardBg, 100, 240, rainbowTxt);
|
||||
}
|
||||
|
||||
// Synchronize tracking variables without touching TFT display (zero flicker)
|
||||
|
|
@ -463,8 +473,8 @@ inline void syncTriTempTrackers() {
|
|||
float ratio = (vals[i] - minR[i]) / (maxR[i] - minR[i]);
|
||||
if (ratio < 0.0f) ratio = 0.0f;
|
||||
if (ratio > 1.0f) ratio = 1.0f;
|
||||
int fillW = (int)(120 * ratio);
|
||||
if (fillW < 4) fillW = 4;
|
||||
int fillW = (vals[i] <= -900.0f) ? 0 : (int)(120 * ratio);
|
||||
if (fillW < 4 && vals[i] > -900.0f) fillW = 4;
|
||||
oldTriFillW[i] = fillW;
|
||||
|
||||
uint16_t acc = defAcc[i];
|
||||
|
|
@ -492,12 +502,11 @@ inline void drawTriTempScreen(int x_offset = 0) {
|
|||
|
||||
syncTriTempTrackers();
|
||||
|
||||
// Draw Page Indicator: [○ ● ○ ○ ○] (Page 2 of 5 active)
|
||||
tft.fillCircle(132 + x_offset, 2, 2, 0x5AEB); // Page 0 inactive
|
||||
tft.fillCircle(146 + x_offset, 2, 2, getThemePrimaryColor()); // Page 1 active
|
||||
tft.fillCircle(160 + x_offset, 2, 2, 0x5AEB); // Page 2 inactive
|
||||
tft.fillCircle(174 + x_offset, 2, 2, 0x5AEB); // Page 3 inactive
|
||||
tft.fillCircle(188 + x_offset, 2, 2, 0x5AEB); // Page 4 inactive
|
||||
// Draw Page Indicator: [○ ● ○ ○] (Page 1 of 4 active)
|
||||
tft.fillCircle(139 + x_offset, 2, 2, 0x5AEB); // Page 0 inactive
|
||||
tft.fillCircle(153 + x_offset, 2, 2, getThemePrimaryColor()); // Page 1 active
|
||||
tft.fillCircle(167 + x_offset, 2, 2, 0x5AEB); // Page 2 inactive
|
||||
tft.fillCircle(181 + x_offset, 2, 2, 0x5AEB); // Page 3 inactive
|
||||
}
|
||||
|
||||
// Update coolant reading dynamically without redrawing entire screen
|
||||
|
|
@ -529,23 +538,25 @@ inline void updateTriTempSensors(bool forceRedraw = false) {
|
|||
|
||||
if (dsSensorCount > 0) {
|
||||
float t1 = dsSensors.getTempCByIndex(0);
|
||||
if (t1 > -50.0f && t1 < 100.0f) {
|
||||
if (t1 > -50.0f && t1 < 100.0f && t1 != 85.0f && t1 != -127.0f) {
|
||||
tempInterior = t1;
|
||||
} else {
|
||||
tempInterior = -999.0f;
|
||||
}
|
||||
if (dsSensorCount > 1) {
|
||||
float t2 = dsSensors.getTempCByIndex(1);
|
||||
if (t2 > -50.0f && t2 < 100.0f) {
|
||||
if (t2 > -50.0f && t2 < 100.0f && t2 != 85.0f && t2 != -127.0f) {
|
||||
tempExterior = t2;
|
||||
} else {
|
||||
tempExterior = -999.0f;
|
||||
}
|
||||
} else {
|
||||
// Demo exterior offset if only 1 physical sensor connected
|
||||
tempExterior = tempInterior - 4.5f;
|
||||
tempExterior = -999.0f;
|
||||
}
|
||||
dsSensors.requestTemperatures(); // non-blocking next reading request
|
||||
} else {
|
||||
// Simulated demo readings if sensors not yet plugged in
|
||||
tempInterior = 22.4f + 0.3f * sin(millis() / 4000.0f);
|
||||
tempExterior = 16.8f + 0.2f * cos(millis() / 5000.0f);
|
||||
tempInterior = -999.0f;
|
||||
tempExterior = -999.0f;
|
||||
}
|
||||
|
||||
if (currentScreenPage == 1 && fullScreenCell == -1) {
|
||||
|
|
@ -557,11 +568,15 @@ inline void updateTriTempSensors(bool forceRedraw = false) {
|
|||
oldTriInterior = tempInterior;
|
||||
oldTriExterior = tempExterior;
|
||||
} else {
|
||||
if (forceRedraw || abs(tempInterior - oldTriInterior) >= 0.1f) {
|
||||
int curI = (tempInterior > -900.0f) ? (int)round(tempInterior) : -999;
|
||||
int oldI = (oldTriInterior > -900.0f) ? (int)round(oldTriInterior) : -999;
|
||||
if (forceRedraw || curI != oldI) {
|
||||
updateTriTempCardValue(1, tempInterior, oldTriInterior);
|
||||
oldTriInterior = tempInterior;
|
||||
}
|
||||
if (forceRedraw || abs(tempExterior - oldTriExterior) >= 0.1f) {
|
||||
int curE = (tempExterior > -900.0f) ? (int)round(tempExterior) : -999;
|
||||
int oldE = (oldTriExterior > -900.0f) ? (int)round(oldTriExterior) : -999;
|
||||
if (forceRedraw || curE != oldE) {
|
||||
updateTriTempCardValue(2, tempExterior, oldTriExterior);
|
||||
oldTriExterior = tempExterior;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue