diff --git a/src/graphics/SharedUIDisplay.h b/src/graphics/SharedUIDisplay.h index bf515b035..b18bb1c4f 100644 --- a/src/graphics/SharedUIDisplay.h +++ b/src/graphics/SharedUIDisplay.h @@ -9,27 +9,14 @@ namespace graphics // Shared UI Helpers // ======================= -// Compact line layout -#define compactFirstLine ((FONT_HEIGHT_SMALL - 1) * 1) -#define compactSecondLine ((FONT_HEIGHT_SMALL - 1) * 2) - 2 -#define compactThirdLine ((FONT_HEIGHT_SMALL - 1) * 3) - 4 -#define compactFourthLine ((FONT_HEIGHT_SMALL - 1) * 4) - 6 -#define compactFifthLine ((FONT_HEIGHT_SMALL - 1) * 5) - 8 -#define compactSixthLine ((FONT_HEIGHT_SMALL - 1) * 6) - 10 - -// Standard line layout -#define standardFirstLine (FONT_HEIGHT_SMALL + 1) * 1 -#define standardSecondLine (FONT_HEIGHT_SMALL + 1) * 2 -#define standardThirdLine (FONT_HEIGHT_SMALL + 1) * 3 -#define standardFourthLine (FONT_HEIGHT_SMALL + 1) * 4 - -// More Compact line layout -#define moreCompactFirstLine compactFirstLine -#define moreCompactSecondLine (moreCompactFirstLine + (FONT_HEIGHT_SMALL - 5)) -#define moreCompactThirdLine (moreCompactSecondLine + (FONT_HEIGHT_SMALL - 5)) -#define moreCompactFourthLine (moreCompactThirdLine + (FONT_HEIGHT_SMALL - 5)) -#define moreCompactFifthLine (moreCompactFourthLine + (FONT_HEIGHT_SMALL - 5)) -#define moreCompactSixthLine (moreCompactFifthLine + (FONT_HEIGHT_SMALL - 5)) +// Consistent Line Spacing +#define textZeroLine 0 +#define textFirstLine ((FONT_HEIGHT_SMALL - 1) * 1) +#define textSecondLine (textFirstLine + (FONT_HEIGHT_SMALL - 5)) +#define textThirdLine (textSecondLine + (FONT_HEIGHT_SMALL - 5)) +#define textFourthLine (textThirdLine + (FONT_HEIGHT_SMALL - 5)) +#define textFifthLine (textFourthLine + (FONT_HEIGHT_SMALL - 5)) +#define textSixthLine (textFifthLine + (FONT_HEIGHT_SMALL - 5)) // Quick screen access #define SCREEN_WIDTH display->getWidth() diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp index b8aa3e353..a90a34d99 100644 --- a/src/graphics/draw/DebugRenderer.cpp +++ b/src/graphics/draw/DebugRenderer.cpp @@ -16,6 +16,9 @@ #include "mesh/generated/meshtastic/deviceonly.pb.h" #include "sleep.h" +const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, + textFourthLine, textFifthLine, textSixthLine}; + #if HAS_WIFI && !defined(ARCH_PORTDUINO) #include "mesh/wifi/WiFiAPClient.h" #include @@ -173,6 +176,7 @@ void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, i display->clear(); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); + int line = 1; // === Set Title const char *titleStr = "WiFi"; @@ -183,13 +187,13 @@ void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, i const char *wifiName = config.network.wifi_ssid; if (WiFi.status() != WL_CONNECTED) { - display->drawString(x, moreCompactFirstLine, "WiFi: Not Connected"); + display->drawString(x, textPositions[line++], "WiFi: Not Connected"); } else { - display->drawString(x, moreCompactFirstLine, "WiFi: Connected"); + display->drawString(x, textPositions[line++], "WiFi: Connected"); char rssiStr[32]; snprintf(rssiStr, sizeof(rssiStr), "RSSI: %d", WiFi.RSSI()); - display->drawString(x, moreCompactSecondLine, rssiStr); + display->drawString(x, textPositions[line++], rssiStr); } /* @@ -207,36 +211,36 @@ void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, i if (WiFi.status() == WL_CONNECTED) { char ipStr[64]; snprintf(ipStr, sizeof(ipStr), "IP: %s", WiFi.localIP().toString().c_str()); - display->drawString(x, moreCompactThirdLine, ipStr); + display->drawString(x, textPositions[line++], ipStr); } else if (WiFi.status() == WL_NO_SSID_AVAIL) { - display->drawString(x, moreCompactThirdLine, "SSID Not Found"); + display->drawString(x, textPositions[line++], "SSID Not Found"); } else if (WiFi.status() == WL_CONNECTION_LOST) { - display->drawString(x, moreCompactThirdLine, "Connection Lost"); + display->drawString(x, textPositions[line++], "Connection Lost"); } else if (WiFi.status() == WL_IDLE_STATUS) { - display->drawString(x, moreCompactThirdLine, "Idle ... Reconnecting"); + display->drawString(x, textPositions[line++], "Idle ... Reconnecting"); } else if (WiFi.status() == WL_CONNECT_FAILED) { - display->drawString(x, moreCompactThirdLine, "Connection Failed"); + display->drawString(x, textPositions[line++], "Connection Failed"); } #ifdef ARCH_ESP32 else { // Codes: // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code - display->drawString(x, moreCompactThirdLine, + display->drawString(x, textPositions[line++], WiFi.disconnectReasonName(static_cast(getWifiDisconnectReason()))); } #else else { char statusStr[32]; snprintf(statusStr, sizeof(statusStr), "Unknown status: %d", WiFi.status()); - display->drawString(x, moreCompactThirdLine, statusStr); + display->drawString(x, textPositions[line++], statusStr); } #endif char ssidStr[64]; snprintf(ssidStr, sizeof(ssidStr), "SSID: %s", wifiName); - display->drawString(x, moreCompactFourthLine, ssidStr); + display->drawString(x, textPositions[line++], ssidStr); - display->drawString(x, moreCompactFifthLine, "URL: http://meshtastic.local"); + display->drawString(x, textPositions[line++], "URL: http://meshtastic.local"); /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS @@ -392,6 +396,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, display->clear(); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); + int line = 1; // === Set Title const char *titleStr = (SCREEN_WIDTH > 128) ? "LoRa Info" : "LoRa"; @@ -400,7 +405,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, graphics::drawCommonHeader(display, x, y, titleStr); // === First Row: Region / BLE Name === - graphics::UIRenderer::drawNodes(display, x, compactFirstLine + 2, nodeStatus, 0, true, ""); + graphics::UIRenderer::drawNodes(display, x, textPositions[line] + 2, nodeStatus, 0, true, ""); uint8_t dmac[6]; char shortnameble[35]; @@ -409,7 +414,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", screen->ourId); int textWidth = display->getStringWidth(shortnameble); int nameX = (SCREEN_WIDTH - textWidth); - display->drawString(nameX, compactFirstLine, shortnameble); + display->drawString(nameX, textPositions[line++], shortnameble); // === Second Row: Radio Preset === auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false); @@ -420,7 +425,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, } textWidth = display->getStringWidth(regionradiopreset); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, compactSecondLine, regionradiopreset); + display->drawString(nameX, textPositions[line++], regionradiopreset); // === Third Row: Frequency / ChanNum === char frequencyslot[35]; @@ -442,7 +447,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, } textWidth = display->getStringWidth(frequencyslot); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, compactThirdLine, frequencyslot); + display->drawString(nameX, textPositions[line++], frequencyslot); // === Fourth Row: Channel Utilization === const char *chUtil = "ChUtil:"; @@ -450,7 +455,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(chUtilPercentage, sizeof(chUtilPercentage), "%2.0f%%", airTime->channelUtilizationPercent()); int chUtil_x = (SCREEN_WIDTH > 128) ? display->getStringWidth(chUtil) + 10 : display->getStringWidth(chUtil) + 5; - int chUtil_y = compactFourthLine + 3; + int chUtil_y = textPositions[line] + 3; int chutil_bar_width = (SCREEN_WIDTH > 128) ? 100 : 50; int chutil_bar_height = (SCREEN_WIDTH > 128) ? 12 : 7; @@ -461,7 +466,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int total_line_content_width = (chUtil_x + chutil_bar_width + display->getStringWidth(chUtilPercentage) + extraoffset) / 2; int starting_position = centerofscreen - total_line_content_width; - display->drawString(starting_position, compactFourthLine, chUtil); + display->drawString(starting_position, textPositions[line++], chUtil); // Force 56% or higher to show a full 100% bar, text would still show related percent. if (chutil_percent >= 61) { @@ -498,7 +503,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, display->fillRect(starting_position + chUtil_x, chUtil_y, fillRight, chutil_bar_height); } - display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, compactFourthLine, chUtilPercentage); + display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, textPositions[4], chUtilPercentage); } // **************************** @@ -517,9 +522,7 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, graphics::drawCommonHeader(display, x, y, titleStr); // === Layout === - const int yPositions[6] = {moreCompactFirstLine, moreCompactSecondLine, moreCompactThirdLine, - moreCompactFourthLine, moreCompactFifthLine, moreCompactSixthLine}; - int line = 0; + int line = 1; const int barHeight = 6; const int labelX = x; const int barsOffset = (SCREEN_WIDTH > 128) ? 24 : 0; @@ -548,10 +551,10 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, // Label display->setTextAlignment(TEXT_ALIGN_LEFT); - display->drawString(labelX, yPositions[line], label); + display->drawString(labelX, textPositions[line], label); // Bar - int barY = yPositions[line] + (FONT_HEIGHT_SMALL - barHeight) / 2; + int barY = textPositions[line] + (FONT_HEIGHT_SMALL - barHeight) / 2; display->setColor(WHITE); display->drawRect(barX, barY, adjustedBarWidth, barHeight); @@ -560,7 +563,7 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, // Value string display->setTextAlignment(TEXT_ALIGN_RIGHT); - display->drawString(SCREEN_WIDTH - 2, yPositions[line], combinedStr); + display->drawString(SCREEN_WIDTH - 2, textPositions[line], combinedStr); }; // === Memory values === @@ -614,7 +617,7 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(appversionstr, sizeof(appversionstr), "Ver.: %s", optstr(APP_VERSION)); int textWidth = display->getStringWidth(appversionstr); int nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, yPositions[line], appversionstr); + display->drawString(nameX, textPositions[line], appversionstr); if (SCREEN_HEIGHT > 64 || (SCREEN_HEIGHT <= 64 && line < 4)) { // Only show uptime if the screen can show it line += 1; @@ -632,7 +635,7 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins); textWidth = display->getStringWidth(uptimeStr); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, yPositions[line], uptimeStr); + display->drawString(nameX, textPositions[line], uptimeStr); } } } // namespace DebugRenderer diff --git a/src/graphics/draw/NodeListRenderer.cpp b/src/graphics/draw/NodeListRenderer.cpp index 2d465fffa..bcc43d5b6 100644 --- a/src/graphics/draw/NodeListRenderer.cpp +++ b/src/graphics/draw/NodeListRenderer.cpp @@ -12,6 +12,9 @@ #include "meshUtils.h" #include +const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, + textFourthLine, textFifthLine, textSixthLine}; + // Forward declarations for functions defined in Screen.cpp namespace graphics { @@ -612,14 +615,12 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t graphics::drawCommonHeader(display, x, y, shortName); // Dynamic row stacking with predefined Y positions - const int yPositions[5] = {moreCompactFirstLine, moreCompactSecondLine, moreCompactThirdLine, moreCompactFourthLine, - moreCompactFifthLine}; - int line = 0; + int line = 1; // 1. Long Name (always try to show first) const char *username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr; if (username && line < 5) { - display->drawString(x, yPositions[line++], username); + display->drawString(x, textPositions[line++], username); } // 2. Signal and Hops (combined on one line, if available) @@ -644,7 +645,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } } if (signalHopsStr[0] && line < 5) { - display->drawString(x, yPositions[line++], signalHopsStr); + display->drawString(x, textPositions[line++], signalHopsStr); } // 3. Heard (last seen, skip if node never seen) @@ -661,7 +662,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t : 'm')); } if (seenStr[0] && line < 5) { - display->drawString(x, yPositions[line++], seenStr); + display->drawString(x, textPositions[line++], seenStr); } // 4. Uptime (only show if metric is present) @@ -681,7 +682,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } } if (uptimeStr[0] && line < 5) { - display->drawString(x, yPositions[line++], uptimeStr); + display->drawString(x, textPositions[line++], uptimeStr); } // 5. Distance (only if both nodes have GPS position) @@ -733,7 +734,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } // Only display if we actually have a value! if (haveDistance && distStr[0] && line < 5) { - display->drawString(x, yPositions[line++], distStr); + display->drawString(x, textPositions[line++], distStr); } // Compass rendering for different screen orientations @@ -744,7 +745,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - const int16_t topY = compactFirstLine; + const int16_t topY = textPositions[1]; const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1); const int16_t usableHeight = bottomY - topY - 5; int16_t compassRadius = usableHeight / 2; @@ -774,7 +775,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - int yBelowContent = (line > 0 && line <= 5) ? (yPositions[line - 1] + FONT_HEIGHT_SMALL + 2) : moreCompactFirstLine; + int yBelowContent = (line > 1 && line <= 6) ? (textPositions[line - 1] + FONT_HEIGHT_SMALL + 2) : textPositions[1]; const int margin = 4; #if defined(USE_EINK) diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index c10647a71..14d55eea0 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -17,6 +17,9 @@ #include #include +const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, + textFourthLine, textFifthLine, textSixthLine}; + #if !MESHTASTIC_EXCLUDE_GPS // External variables @@ -38,8 +41,8 @@ namespace UIRenderer void drawGps(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gps) { // Draw satellite image - int yOffset = (SCREEN_WIDTH > 128) ? 4 : 2; - display->drawFastImage(x + 1, y + yOffset, 8, 8, imgSatellite); + int yOffset = (SCREEN_WIDTH > 128) ? 3 : 1; + display->drawXbm(x + 1, y + yOffset, imgSatellite_width, imgSatellite_height, imgSatellite); char textString[10]; if (config.position.fixed_position) { @@ -280,15 +283,13 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t // 4. The first line is ALWAYS at your macro position; subsequent lines use the next available macro slot. // List of available macro Y positions in order, from top to bottom. - const int yPositions[5] = {moreCompactFirstLine, moreCompactSecondLine, moreCompactThirdLine, moreCompactFourthLine, - moreCompactFifthLine}; - int line = 0; // which slot to use next + int line = 1; // which slot to use next // === 1. Long Name (always try to show first) === const char *username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr; if (username && line < 5) { // Print node's long name (e.g. "Backpack Node") - display->drawString(x, yPositions[line++], username); + display->drawString(x, textPositions[line++], username); } // === 2. Signal and Hops (combined on one line, if available) === @@ -319,7 +320,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } } if (signalHopsStr[0] && line < 5) { - display->drawString(x, yPositions[line++], signalHopsStr); + display->drawString(x, textPositions[line++], signalHopsStr); } // === 3. Heard (last seen, skip if node never seen) === @@ -337,7 +338,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t : 'm')); } if (seenStr[0] && line < 5) { - display->drawString(x, yPositions[line++], seenStr); + display->drawString(x, textPositions[line++], seenStr); } // === 4. Uptime (only show if metric is present) === @@ -356,7 +357,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins); } if (uptimeStr[0] && line < 5) { - display->drawString(x, yPositions[line++], uptimeStr); + display->drawString(x, textPositions[line++], uptimeStr); } // === 5. Distance (only if both nodes have GPS position) === @@ -416,7 +417,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } // Only display if we actually have a value! if (haveDistance && distStr[0] && line < 5) { - display->drawString(x, yPositions[line++], distStr); + display->drawString(x, textPositions[line++], distStr); } // --- Compass Rendering: landscape (wide) screens use the original side-aligned logic --- @@ -426,7 +427,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - const int16_t topY = compactFirstLine; + const int16_t topY = textPositions[1]; const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1); const int16_t usableHeight = bottomY - topY - 5; int16_t compassRadius = usableHeight / 2; @@ -461,7 +462,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - int yBelowContent = (line > 0 && line <= 5) ? (yPositions[line - 1] + FONT_HEIGHT_SMALL + 2) : moreCompactFirstLine; + int yBelowContent = (line > 0 && line <= 5) ? (textPositions[line - 1] + FONT_HEIGHT_SMALL + 2) : textPositions[1]; const int margin = 4; // --------- PATCH FOR EINK NAV BAR (ONLY CHANGE BELOW) ----------- #if defined(USE_EINK) @@ -514,6 +515,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t display->clear(); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); + int line = 1; // === Header === graphics::drawCommonHeader(display, x, y, ""); @@ -531,9 +533,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t config.display.heading_bold = false; // Display Region and Channel Utilization - drawNodes(display, x + 1, - ((rows == 4) ? compactFirstLine : ((SCREEN_HEIGHT > 64) ? compactFirstLine : moreCompactFirstLine)) + 2, nodeStatus, - -1, false, "online"); + drawNodes(display, x + 1, textPositions[line] + 2, nodeStatus, -1, false, "online"); char uptimeStr[32] = ""; uint32_t uptime = millis() / 1000; @@ -547,9 +547,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t snprintf(uptimeStr, sizeof(uptimeStr), "Up: %uh %um", hours, mins); else snprintf(uptimeStr, sizeof(uptimeStr), "Up: %um", mins); - display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), - ((rows == 4) ? compactFirstLine : ((SCREEN_HEIGHT > 64) ? compactFirstLine : moreCompactFirstLine)), - uptimeStr); + display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), textPositions[line++], uptimeStr); // === Second Row: Satellites and Voltage === config.display.heading_bold = false; @@ -562,13 +560,9 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t } else { displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off"; } - display->drawString( - 0, ((rows == 4) ? compactSecondLine : ((SCREEN_HEIGHT > 64) ? compactSecondLine : moreCompactSecondLine)), - displayLine); + display->drawString(0, textPositions[line], displayLine); } else { - UIRenderer::drawGps( - display, 0, ((rows == 4) ? compactSecondLine : ((SCREEN_HEIGHT > 64) ? compactSecondLine : moreCompactSecondLine)), - gpsStatus); + UIRenderer::drawGps(display, 0, textPositions[line], gpsStatus); } #endif @@ -577,21 +571,16 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t int batV = powerStatus->getBatteryVoltageMv() / 1000; int batCv = (powerStatus->getBatteryVoltageMv() % 1000) / 10; snprintf(batStr, sizeof(batStr), "%01d.%02dV", batV, batCv); - display->drawString( - x + SCREEN_WIDTH - display->getStringWidth(batStr), - ((rows == 4) ? compactSecondLine : ((SCREEN_HEIGHT > 64) ? compactSecondLine : moreCompactSecondLine)), batStr); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth(batStr), textPositions[line++], batStr); } else { - display->drawString( - x + SCREEN_WIDTH - display->getStringWidth("USB"), - ((rows == 4) ? compactSecondLine : ((SCREEN_HEIGHT > 64) ? compactSecondLine : moreCompactSecondLine)), "USB"); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth("USB"), textPositions[line++], "USB"); } config.display.heading_bold = origBold; // === Third Row: Bluetooth Off (Only If Actually Off) === if (!config.bluetooth.enabled) { - display->drawString( - 0, ((rows == 4) ? compactThirdLine : ((SCREEN_HEIGHT > 64) ? compactThirdLine : moreCompactThirdLine)), "BT off"); + display->drawString(0, textPositions[line++], "BT off"); } // === Third & Fourth Rows: Node Identity === @@ -619,28 +608,18 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t } textWidth = display->getStringWidth(combinedName); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString( - nameX, - ((rows == 4) ? compactThirdLine : ((SCREEN_HEIGHT > 64) ? compactFourthLine : moreCompactFourthLine)) + yOffset, - combinedName); + display->drawString(nameX, ((rows == 4) ? textPositions[line++] : textPositions[line++]) + yOffset, combinedName); } else { + // === LongName Centered === textWidth = display->getStringWidth(longName); nameX = (SCREEN_WIDTH - textWidth) / 2; - yOffset = (strcmp(shortnameble, "") == 0) ? 1 : 0; - if (yOffset == 1) { - yOffset = (SCREEN_WIDTH > 128) ? 0 : 7; - } - display->drawString( - nameX, - ((rows == 4) ? compactThirdLine : ((SCREEN_HEIGHT > 64) ? compactFourthLine : moreCompactFourthLine)) + yOffset, - longName); + yOffset = (rows == 4 && SCREEN_WIDTH <= 128) ? 7 : 0; + display->drawString(nameX, textPositions[line++] + yOffset, longName); - // === Fourth Row: ShortName Centered === + // === ShortName Centered === textWidth = display->getStringWidth(shortnameble); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, - ((rows == 4) ? compactFourthLine : ((SCREEN_HEIGHT > 64) ? compactFifthLine : moreCompactFifthLine)), - shortnameble); + display->drawString(nameX, textPositions[line++] + yOffset, shortnameble); } } @@ -886,6 +865,7 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat display->clear(); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); + int line = 1; // === Set Title const char *titleStr = "GPS"; @@ -905,10 +885,11 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat } else { displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off"; } - display->drawFastImage(x + 1, y, 8, 8, imgSatellite); - display->drawString(x + 11, ((SCREEN_HEIGHT > 64) ? compactFirstLine : moreCompactFirstLine), displayLine); + int yOffset = (SCREEN_WIDTH > 128) ? 3 : 1; + display->drawXbm(x + 1, textPositions[line] + yOffset, imgSatellite_width, imgSatellite_height, imgSatellite); + display->drawString(x + 11, textPositions[line++], displayLine); } else { - UIRenderer::drawGps(display, 0, ((SCREEN_HEIGHT > 64) ? compactFirstLine : moreCompactFirstLine), gpsStatus); + UIRenderer::drawGps(display, 0, textPositions[line++], gpsStatus); } config.display.heading_bold = origBold; @@ -939,17 +920,17 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat } else { snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), " Alt: %.0im", geoCoord.getAltitude()); } - display->drawString(x, ((SCREEN_HEIGHT > 64) ? compactSecondLine : moreCompactSecondLine), DisplayLineTwo); + display->drawString(x, textPositions[line++], DisplayLineTwo); // === Third Row: Latitude === char latStr[32]; snprintf(latStr, sizeof(latStr), " Lat: %.5f", geoCoord.getLatitude() * 1e-7); - display->drawString(x, ((SCREEN_HEIGHT > 64) ? compactThirdLine : moreCompactThirdLine), latStr); + display->drawString(x, textPositions[line++], latStr); // === Fourth Row: Longitude === char lonStr[32]; snprintf(lonStr, sizeof(lonStr), " Lon: %.5f", geoCoord.getLongitude() * 1e-7); - display->drawString(x, ((SCREEN_HEIGHT > 64) ? compactFourthLine : moreCompactFourthLine), lonStr); + display->drawString(x, textPositions[line++], lonStr); // === Fifth Row: Date === uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); @@ -958,14 +939,14 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat UIRenderer::formatDateTime(datetimeStr, sizeof(datetimeStr), rtc_sec, display, showTime); char fullLine[40]; snprintf(fullLine, sizeof(fullLine), " Date: %s", datetimeStr); - display->drawString(0, ((SCREEN_HEIGHT > 64) ? compactFifthLine : moreCompactFifthLine), fullLine); + display->drawString(0, textPositions[line++], fullLine); } // === Draw Compass if heading is valid === if (validHeading) { // --- Compass Rendering: landscape (wide) screens use original side-aligned logic --- if (SCREEN_WIDTH > SCREEN_HEIGHT) { - const int16_t topY = compactFirstLine; + const int16_t topY = textPositions[1]; const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1); // nav row height const int16_t usableHeight = bottomY - topY - 5; @@ -998,7 +979,7 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat } else { // Portrait or square: put compass at the bottom and centered, scaled to fit available space // For E-Ink screens, account for navigation bar at the bottom! - int yBelowContent = ((SCREEN_HEIGHT > 64) ? compactFifthLine : moreCompactFifthLine) + FONT_HEIGHT_SMALL + 2; + int yBelowContent = textPositions[5] + FONT_HEIGHT_SMALL + 2; const int margin = 4; int availableHeight = #if defined(USE_EINK) diff --git a/src/graphics/images.h b/src/graphics/images.h index f11acc084..c1dc28c7f 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -6,7 +6,12 @@ const uint8_t SATELLITE_IMAGE[] PROGMEM = {0x00, 0x08, 0x00, 0x1C, 0x00, 0x0E, 0 0xF8, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC8, 0x01, 0x9C, 0x54, 0x0E, 0x52, 0x07, 0x48, 0x02, 0x26, 0x00, 0x10, 0x00, 0x0E}; -const uint8_t imgSatellite[] PROGMEM = {0x70, 0x71, 0x22, 0xFA, 0xFA, 0x22, 0x71, 0x70}; +#define imgSatellite_width 8 +#define imgSatellite_height 8 +const uint8_t imgSatellite[] PROGMEM = { + 0b00000000, 0b00000000, 0b00000000, 0b00011000, 0b11011011, 0b11111111, 0b11011011, 0b00011000, +}; + const uint8_t imgUSB[] PROGMEM = {0x60, 0x60, 0x30, 0x18, 0x18, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x24, 0x24, 0x24, 0x3C}; const uint8_t imgPower[] PROGMEM = {0x40, 0x40, 0x40, 0x58, 0x48, 0x08, 0x08, 0x08, 0x1C, 0x22, 0x22, 0x41, 0x7F, 0x22, 0x22, 0x22}; diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 37eeb049a..33bc98392 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -22,6 +22,9 @@ #include #include +const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, + textFourthLine, textFifthLine, textSixthLine}; + #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL // Sensors @@ -343,6 +346,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt display->clear(); display->setFont(FONT_SMALL); display->setTextAlignment(TEXT_ALIGN_LEFT); + int line = 1; // === Set Title const char *titleStr = (SCREEN_WIDTH > 128) ? "Environment" : "Env."; @@ -352,7 +356,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt // === Row spacing setup === const int rowHeight = FONT_HEIGHT_SMALL - 4; - int currentY = compactFirstLine; + int currentY = textPositions[line++]; // === Show "No Telemetry" if no data available === if (!lastMeasurementPacket) { diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp index 4de886de6..86869007a 100644 --- a/src/modules/Telemetry/PowerTelemetry.cpp +++ b/src/modules/Telemetry/PowerTelemetry.cpp @@ -16,6 +16,9 @@ #include "sleep.h" #include "target_specific.h" +const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, + textFourthLine, textFifthLine, textSixthLine}; + #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true @@ -112,6 +115,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s display->clear(); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); + int line = 1; // === Set Title const char *titleStr = (SCREEN_WIDTH > 128) ? "Power Telem." : "Power"; @@ -121,7 +125,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s if (lastMeasurementPacket == nullptr) { // In case of no valid packet, display "Power Telemetry", "No measurement" - display->drawString(x, compactFirstLine, "No measurement"); + display->drawString(x, textPositions[line++], "No measurement"); return; } @@ -132,7 +136,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s const meshtastic_Data &p = lastMeasurementPacket->decoded; if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_Telemetry_msg, &lastMeasurement)) { - display->drawString(x, compactFirstLine, "Measurement Error"); + display->drawString(x, textPositions[line++], "Measurement Error"); LOG_ERROR("Unable to decode last packet"); return; } @@ -140,11 +144,11 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s // Display "Pow. From: ..." char fromStr[64]; snprintf(fromStr, sizeof(fromStr), "Pow. From: %s (%us)", lastSender, agoSecs); - display->drawString(x, compactFirstLine, fromStr); + display->drawString(x, textPositions[line++], fromStr); // Display current and voltage based on ...power_metrics.has_[channel/voltage/current]... flags const auto &m = lastMeasurement.variant.power_metrics; - int lineY = compactSecondLine; + int lineY = textSecondLine; auto drawLine = [&](const char *label, float voltage, float current) { char lineStr[64]; diff --git a/src/modules/esp32/PaxcounterModule.cpp b/src/modules/esp32/PaxcounterModule.cpp index e83cb5b3c..dd9ab195d 100644 --- a/src/modules/esp32/PaxcounterModule.cpp +++ b/src/modules/esp32/PaxcounterModule.cpp @@ -115,12 +115,17 @@ int32_t PaxcounterModule::runOnce() #if HAS_SCREEN #include "graphics/ScreenFonts.h" +#include "graphics/SharedUIDisplay.h" + +const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, + textFourthLine, textFifthLine, textSixthLine}; void PaxcounterModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { display->clear(); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); + int line = 1; // === Set Title const char *titleStr = "Pax"; @@ -136,7 +141,7 @@ void PaxcounterModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(FONT_SMALL); - display->drawStringf(display->getWidth() / 2 + x, compactFirstLine, buffer, "WiFi: %d\nBLE: %d\nUptime: %ds", + display->drawStringf(display->getWidth() / 2 + x, textPositions[line++], buffer, "WiFi: %d\nBLE: %d\nUptime: %ds", count_from_libpax.wifi_count, count_from_libpax.ble_count, millis() / 1000); } #endif // HAS_SCREEN