diff --git a/sketch/obd2_gauge/meter.h b/sketch/obd2_gauge/meter.h index 04cda58..1373466 100644 --- a/sketch/obd2_gauge/meter.h +++ b/sketch/obd2_gauge/meter.h @@ -67,6 +67,21 @@ void drawPidIcon(int x, int y, const String &pidStr) { } } +// Clear parameter icon for 4-quadrant view +void clearPidIcon(int x, int y, const String &pidStr) { + if (pidStr == "0105") { + tft.fillRect(x, y, 38, 37, TFT_BLACK); + } else if (pidStr == "010D") { + tft.fillRect(x, y, 42, 43, TFT_BLACK); + } else if (pidStr == "010C") { + tft.fillRect(x, y, 42, 43, TFT_BLACK); + } else if (pidStr == "0142" || pidStr == "ATRV") { + tft.fillRect(x, y, 46, 35, TFT_BLACK); + } else { + tft.fillRect(x, y, 42, 42, TFT_BLACK); + } +} + // Draw header icon (42x42 px, ~30% larger) for full screen mode void drawPidIconHeader(int x, int y, const String &pidStr) { tft.setSwapBytes(true); @@ -81,6 +96,36 @@ void drawPidIconHeader(int x, int y, const String &pidStr) { } } +// Restore blue header background over the 42x42 icon area during alarm blink OFF phase +void clearPidIconHeader(int x = 10, int y = 4, int w = 42, int h = 42) { + const float fade_w_left = 16.0f; + uint16_t lineBuf[64]; + if (w > 64) w = 64; + tft.startWrite(); + tft.setAddrWindow(x, y, w, h); + for (int16_t j = y; j < y + h; j++) { + float vy = 1.0f; + if (j >= 30) { + float t = (50.0f - (float)j) / 20.0f; + vy = t * t * (3.0f - 2.0f * t); + } + for (int16_t i = 0; i < w; i++) { + int16_t px = x + i; + float hx = 1.0f; + if (px < (int16_t)fade_w_left) { + float t = (float)px / fade_w_left; + hx = t * t * (3.0f - 2.0f * t); + } + float b = vy * hx; + uint8_t g = (uint8_t)(140.0f * b); + uint8_t bl = (uint8_t)(255.0f * b); + lineBuf[i] = tft.color565(0, g, bl); + } + tft.pushPixels(lineBuf, w); + } + tft.endWrite(); +} + // Full Screen Exponential Segmented Block Bar Graph (20 blocks: 3mm width x 4mm height, 0.5mm gap, Anti-Aliased) const uint8_t NUM_BAR_BLOCKS = 20; const int16_t blockMinX[20] PROGMEM = { 0, 5, 11, 17, 25, 34, 46, 59, 76, 95, 114, 134, 154, 174, 193, 213, 232, 251, 271, 290 }; @@ -795,8 +840,14 @@ void plotNumeric4(uint8_t cell, float data, int warn, bool digit, String unit) { uint16_t col = getMeterColor(pidIdx, data, warn); if (col == TFT_RED) { + if (!wasInRedAlarm[cell]) { + drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = true; } else { + if (wasInRedAlarm[cell]) { + drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = false; } @@ -871,10 +922,14 @@ void plotArc4(uint8_t cell, float data, int warn, int min, int max, bool digit, bool colorChanged = (col != oldCol); if (col == TFT_RED) { + if (!wasInRedAlarm[cell]) { + drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = true; if (colorChanged) { arcFlashVisible = true; lastArcFlashTime = millis(); + drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); for (uint8_t i = 0; i < newBlocks; i++) { drawQuadBarBlock(cell, i, TFT_RED); } @@ -893,6 +948,9 @@ void plotArc4(uint8_t cell, float data, int warn, int min, int max, bool digit, } } } else { + if (wasInRedAlarm[cell]) { + drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = false; if (colorChanged || old_data[cell] < min) { for (uint8_t i = 0; i < newBlocks; i++) { @@ -1031,10 +1089,14 @@ void plotFullScreen(uint8_t cell, float data, int warn, int min, int max, bool colorChanged = (col != oldCol); if (col == TFT_RED) { + if (!wasInRedAlarm[cell]) { + drawPidIconHeader(10, 4, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = true; if (colorChanged) { arcFlashVisible = true; lastArcFlashTime = millis(); + drawPidIconHeader(10, 4, pidConfig[pidIdx][2]); for (uint8_t i = 0; i < newBlocks; i++) { drawBarBlock(i, TFT_RED); } @@ -1053,6 +1115,9 @@ void plotFullScreen(uint8_t cell, float data, int warn, int min, int max, } } } else { + if (wasInRedAlarm[cell]) { + drawPidIconHeader(10, 4, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = false; if (colorChanged || old_data[cell] < min) { for (uint8_t i = 0; i < newBlocks; i++) { @@ -1084,8 +1149,14 @@ void plotFullScreen(uint8_t cell, float data, int warn, int min, int max, } else { // Digital numeric mode full screen with DSEG7 Smooth Font (Anti-Aliased) if (col == TFT_RED) { + if (!wasInRedAlarm[cell]) { + drawPidIconHeader(10, 4, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = true; } else { + if (wasInRedAlarm[cell]) { + drawPidIconHeader(10, 4, pidConfig[pidIdx][2]); + } wasInRedAlarm[cell] = false; } uint16_t txtCol = (col == TFT_RED && !arcFlashVisible) ? TFT_BLACK : col; @@ -1316,8 +1387,9 @@ void handleArcAlarmFlash() { String numStr = String(data, digit); if (wasInRedAlarm[cell] && !inRed) { - // Exited red alarm: restore steady arc and text + // Exited red alarm: restore steady arc, text, and icon wasInRedAlarm[cell] = false; + drawPidIconHeader(10, 4, pidConfig[pidIdx][2]); if (!cellIsNumeric[cell]) { int min = pidConfig[pidIdx][4].toInt(); int max = pidConfig[pidIdx][5].toInt(); @@ -1346,6 +1418,11 @@ void handleArcAlarmFlash() { wasInRedAlarm[cell] = true; if (toggleTick) { uint16_t txtCol = arcFlashVisible ? TFT_RED : TFT_BLACK; + if (arcFlashVisible) { + drawPidIconHeader(10, 4, pidConfig[pidIdx][2]); + } else { + clearPidIconHeader(10, 4, 42, 42); + } if (!cellIsNumeric[cell]) { int min = pidConfig[pidIdx][4].toInt(); int max = pidConfig[pidIdx][5].toInt(); @@ -1395,8 +1472,9 @@ void handleArcAlarmFlash() { int y = cell4_y[cell]; if (wasInRedAlarm[cell] && !inRed) { - // Exited red alarm: restore steady arc and text + // Exited red alarm: restore steady arc, text, and icon wasInRedAlarm[cell] = false; + drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); if (!cellIsNumeric[cell]) { int min = pidConfig[pidIdx][4].toInt(); int max = pidConfig[pidIdx][5].toInt(); @@ -1425,6 +1503,11 @@ void handleArcAlarmFlash() { wasInRedAlarm[cell] = true; if (toggleTick) { uint16_t txtCol = arcFlashVisible ? TFT_RED : TFT_BLACK; + if (arcFlashVisible) { + drawPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); + } else { + clearPidIcon(x + 5, y + 3, pidConfig[pidIdx][2]); + } if (!cellIsNumeric[cell]) { int min = pidConfig[pidIdx][4].toInt(); int max = pidConfig[pidIdx][5].toInt();