Implement Fixes for Meshnology W12's Two Color Display (#11288)

* Round 1 Fixes

* Update GPS icon

* Update calculations for revised GPS icon after regression testing

* Add BICOLOR_OLED_DISPLAY and actually use it

---------

Co-authored-by: Austin <vidplace7@gmail.com>
This commit is contained in:
Jason P
2026-07-31 04:54:54 +00:00
committed by GitHub
co-authored by Austin
parent ecd59e3120
commit 575788ae7b
5 changed files with 32 additions and 11 deletions
+6 -1
View File
@@ -178,13 +178,15 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
snprintf(secondString, sizeof(secondString), "%02d", second);
static bool scaleInitialized = false;
static float scale = 0.75f;
static float scale = 0.50f;
static float segmentWidth = SEGMENT_WIDTH * 0.75f;
static float segmentHeight = SEGMENT_HEIGHT * 0.75f;
if (!scaleInitialized) {
#ifdef DISPLAY_FORCE_SMALL_FONTS
float screenwidth_target_ratio = 0.70f; // Target 70% of display width (adjustable)
#elif defined(BICOLOR_OLED_DISPLAY)
float screenwidth_target_ratio = 0.60f; // Forced for BICOLOR_OLED_DISPLAY due to two color display
#else
float screenwidth_target_ratio = 0.80f; // Target 80% of display width (adjustable)
#endif
@@ -315,6 +317,9 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
int16_t radius = (std::min(display->getWidth(), display->getHeight()) / 2) * 0.9;
#ifdef T_WATCH_S3
radius = (display->getWidth() / 2) * 0.8;
#elif defined(BICOLOR_OLED_DISPLAY)
centerY += 6;
radius = (display->getHeight() / 2) * 0.7;
#endif
// noon (0 deg) coordinates (outermost circle)
+14 -1
View File
@@ -28,6 +28,10 @@ namespace graphics
namespace NodeListRenderer
{
// Y position of the first row (either column) in the current list screen, set by
// drawNodeListScreen(). Used by entry renderers that need to special-case the top row.
static int16_t firstRowY = 0;
// Function moved from Screen.cpp to NodeListRenderer.cpp since it's primarily used here
void drawScaledXBitmap16x16(int x, int y, int width, int height, const uint8_t *bitmapXBM, OLEDDisplay *display)
{
@@ -363,10 +367,18 @@ void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
const int gap = 1;
const int totalWidth = hopCountWidth + gap + hop_width;
const int hopX = barsRightEdge - totalWidth;
#if defined(BICOLOR_OLED_DISPLAY)
int iconY = y + (FONT_HEIGHT_SMALL - hop_height) / 2;
if (y == firstRowY) {
iconY += 1; // Nudge the hop icon down 1px on the top row to avoid the two color display
}
#else
const int iconY = y + (FONT_HEIGHT_SMALL - hop_height) / 2;
#endif
display->drawString(hopX, y, hopCount);
display->drawXbm(hopX + hopCountWidth + gap, iconY, hop_width, hop_height, hop);
display->drawXbm(hopX + hopCountWidth + gap, iconY, hop_width, hop_height, imghop);
}
}
@@ -606,6 +618,7 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
// Space below header
y += COMMON_HEADER_HEIGHT;
firstRowY = y;
int totalColumns = 1; // Default to 1 column
+8 -6
View File
@@ -40,7 +40,7 @@ static bool gBootSplashBoldPass = false;
static inline void drawSatelliteIcon(OLEDDisplay *display, int16_t x, int16_t y)
{
int yOffset = (currentResolution == ScreenResolution::High) ? -5 : 1;
int yOffset = (currentResolution == ScreenResolution::High) ? 0 : 1;
if (currentResolution == ScreenResolution::High) {
NodeListRenderer::drawScaledXBitmap16x16(x, y + yOffset, imgGPS_width, imgGPS_height, imgGPS, display);
} else {
@@ -521,9 +521,9 @@ void UIRenderer::drawGps(OLEDDisplay *display, int16_t x, int16_t y, const mesht
{
// Draw satellite image
if (currentResolution == ScreenResolution::High) {
NodeListRenderer::drawScaledXBitmap16x16(x, y - 2, imgGPS_width, imgGPS_height, imgGPS, display);
NodeListRenderer::drawScaledXBitmap16x16(x, y + 1, imgGPS_width, imgGPS_height, imgGPS, display);
} else {
display->drawXbm(x + 1, y + 1, imgGPS_width, imgGPS_height, imgGPS);
display->drawXbm(x + 1, y + 3, imgGPS_width, imgGPS_height, imgGPS);
}
char textString[10];
@@ -963,7 +963,7 @@ void UIRenderer::drawFavoriteNode(OLEDDisplay *display, OLEDDisplayUiState *stat
curX += display->getStringWidth(hopCount) + 2;
const int iconY = yPos + (FONT_HEIGHT_SMALL - hop_height) / 2;
display->drawXbm(curX, iconY, hop_width, hop_height, hop);
display->drawXbm(curX, iconY, hop_width, hop_height, imghop);
curX += hop_width + 1;
}
}
@@ -1195,7 +1195,8 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
} else {
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
}
drawSatelliteIcon(display, x, getTextPositions(display)[line]);
int yOffset = (currentResolution == ScreenResolution::High) ? 0 : 2;
drawSatelliteIcon(display, x, getTextPositions(display)[line] + yOffset);
int xOffset = (currentResolution == ScreenResolution::High) ? 6 : 0;
display->drawString(x + 11 + xOffset, getTextPositions(display)[line], displayLine);
} else {
@@ -1586,7 +1587,8 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
} else {
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
}
drawSatelliteIcon(display, x, textPos[line]);
int yOffset = (currentResolution == ScreenResolution::High) ? 1 : 3;
drawSatelliteIcon(display, x, textPos[line] + yOffset);
int xOffset = (currentResolution == ScreenResolution::High) ? 6 : 0;
display->drawString(x + 11 + xOffset, textPos[line++], displayLine);
} else {
+3 -3
View File
@@ -13,7 +13,7 @@ const uint8_t imgSatellite[] PROGMEM = {
};
#define imgGPS_width 8
#define imgGPS_height 8
const unsigned char imgGPS[] PROGMEM = {0x00, 0x07, 0x39, 0x2D, 0xFF, 0x48, 0x48, 0x60};
const unsigned char imgGPS[] PROGMEM = {0x03, 0x05, 0x07, 0x38, 0x38, 0xC8, 0x40, 0x60};
const uint8_t imgUSB[] PROGMEM = {0x00, 0xfc, 0xf0, 0xfc, 0x88, 0xff, 0x86, 0xfe, 0x85, 0xfe, 0x89, 0xff, 0xf1, 0xfc, 0x00, 0xfc};
const uint8_t imgUSB_HighResolution[] PROGMEM = {0x00, 0x3e, 0xf8, 0x80, 0x43, 0xf8, 0xc0, 0xc2, 0xff, 0x60, 0x42, 0xfc,
@@ -86,8 +86,8 @@ static const unsigned char mail[] PROGMEM = {
// Hop icon (9x10)
#define hop_width 9
#define hop_height 10
const uint8_t hop[] PROGMEM = {0x05, 0x00, 0x07, 0x00, 0x05, 0x00, 0x38, 0x00, 0x28, 0x00,
0x38, 0x00, 0xC0, 0x01, 0x40, 0x01, 0xC0, 0x01, 0x40, 0x00};
const uint8_t imghop[] PROGMEM = {0x05, 0x00, 0x07, 0x00, 0x05, 0x00, 0x38, 0x00, 0x28, 0x00,
0x38, 0x00, 0xC0, 0x01, 0x40, 0x01, 0xC0, 0x01, 0x40, 0x00};
// 📬 Mail / Message
const uint8_t icon_mail[] PROGMEM = {
@@ -8,6 +8,7 @@
#define USE_SSD1306
#define I2C_SDA 17
#define I2C_SCL 18
#define BICOLOR_OLED_DISPLAY
// Powers the OLED/peripheral rail; active LOW
#define VEXT_ENABLE 45