tdpro dark mode

This commit is contained in:
pelgraine
2026-03-13 22:09:59 +11:00
parent a6f0052b89
commit b77059706b
5 changed files with 42 additions and 17 deletions

View File

@@ -35,6 +35,6 @@ struct NodePrefs { // persisted to file
uint8_t autoadd_max_hops; // 0=no limit, N=up to N-1 hops (max 64)
uint32_t gps_baudrate; // GPS baud rate (0 = use compile-time GPS_BAUDRATE default)
uint8_t interference_threshold; // Interference threshold in dB (0=disabled, 14+=enabled)
uint8_t dark_mode; // 0=off (white bg), 1=on (black bg) — T5S3 only
uint8_t dark_mode; // 0=off (white bg), 1=on (black bg)
uint8_t portrait_mode; // 0=landscape, 1=portrait — T5S3 only
};

View File

@@ -64,8 +64,8 @@ enum SettingsRowType : uint8_t {
ROW_TX_POWER, // TX power (1-20 dBm)
ROW_UTC_OFFSET, // UTC offset (-12 to +14)
ROW_MSG_NOTIFY, // Keyboard flash on new msg toggle
#if defined(LilyGo_T5S3_EPaper_Pro)
ROW_DARK_MODE, // Dark mode toggle (inverted display)
#if defined(LilyGo_T5S3_EPaper_Pro)
ROW_PORTRAIT_MODE, // Portrait orientation toggle
#endif
ROW_PATH_HASH_SIZE, // Path hash size (1, 2, or 3 bytes per hop)
@@ -250,8 +250,8 @@ private:
addRow(ROW_UTC_OFFSET);
addRow(ROW_MSG_NOTIFY);
addRow(ROW_PATH_HASH_SIZE);
#if defined(LilyGo_T5S3_EPaper_Pro)
addRow(ROW_DARK_MODE);
#if defined(LilyGo_T5S3_EPaper_Pro)
addRow(ROW_PORTRAIT_MODE);
#endif
#ifdef MECK_WIFI_COMPANION
@@ -773,13 +773,13 @@ public:
display.print(tmp);
break;
#if defined(LilyGo_T5S3_EPaper_Pro)
case ROW_DARK_MODE:
snprintf(tmp, sizeof(tmp), "Dark Mode: %s",
_prefs->dark_mode ? "ON" : "OFF");
display.print(tmp);
break;
#if defined(LilyGo_T5S3_EPaper_Pro)
case ROW_PORTRAIT_MODE:
snprintf(tmp, sizeof(tmp), "Portrait Mode: %s",
_prefs->portrait_mode ? "ON" : "OFF");
@@ -1583,13 +1583,13 @@ public:
case ROW_PATH_HASH_SIZE:
startEditInt(_prefs->path_hash_mode + 1); // display as 1-3
break;
#if defined(LilyGo_T5S3_EPaper_Pro)
case ROW_DARK_MODE:
_prefs->dark_mode = _prefs->dark_mode ? 0 : 1;
the_mesh.savePrefs();
Serial.printf("Settings: Dark mode = %s\n",
_prefs->dark_mode ? "ON" : "OFF");
break;
#if defined(LilyGo_T5S3_EPaper_Pro)
case ROW_PORTRAIT_MODE:
_prefs->portrait_mode = _prefs->portrait_mode ? 0 : 1;
the_mesh.savePrefs();

View File

@@ -1175,11 +1175,11 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
map_screen = nullptr;
#endif
#if defined(LilyGo_T5S3_EPaper_Pro)
// Apply saved display preferences before first render
// Apply saved dark mode preference before first render
if (_node_prefs->dark_mode) {
::display.setDarkMode(true);
}
#if defined(LilyGo_T5S3_EPaper_Pro)
if (_node_prefs->portrait_mode) {
::display.setPortraitMode(true);
}
@@ -1541,11 +1541,11 @@ if (curr) curr->poll();
if (_display != NULL && _display->isOn()) {
if (millis() >= _next_refresh && curr) {
#if defined(LilyGo_T5S3_EPaper_Pro)
// Sync display modes with prefs (settings toggles take effect here)
// Sync dark mode with prefs (settings toggle takes effect here)
if (_node_prefs && display.isDarkMode() != (_node_prefs->dark_mode != 0)) {
display.setDarkMode(_node_prefs->dark_mode != 0);
}
#if defined(LilyGo_T5S3_EPaper_Pro)
if (_node_prefs && display.isPortraitMode() != (_node_prefs->portrait_mode != 0)) {
display.setPortraitMode(_node_prefs->portrait_mode != 0);
// Text reader layout depends on orientation — force recalculation

View File

@@ -70,14 +70,24 @@ void GxEPDDisplay::turnOff() {
}
void GxEPDDisplay::clear() {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
if (_darkMode) {
display.fillScreen(GxEPD_BLACK);
display.setTextColor(GxEPD_WHITE);
} else {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
}
display_crc.reset();
}
void GxEPDDisplay::startFrame(Color bkg) {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(_curr_color = GxEPD_BLACK);
if (_darkMode) {
display.fillScreen(GxEPD_BLACK);
display.setTextColor(_curr_color = GxEPD_WHITE);
} else {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(_curr_color = GxEPD_BLACK);
}
display_crc.reset();
}
@@ -105,11 +115,20 @@ void GxEPDDisplay::setTextSize(int sz) {
void GxEPDDisplay::setColor(Color c) {
display_crc.update<Color> (c);
// colours need to be inverted for epaper displays
if (c == DARK) {
display.setTextColor(_curr_color = GxEPD_WHITE);
if (_darkMode) {
// Dark mode: DARK = black (background), LIGHT/GREEN/YELLOW = white (foreground)
if (c == DARK) {
display.setTextColor(_curr_color = GxEPD_BLACK);
} else {
display.setTextColor(_curr_color = GxEPD_WHITE);
}
} else {
display.setTextColor(_curr_color = GxEPD_BLACK);
// Normal e-paper: DARK = white (background), LIGHT/GREEN/YELLOW = black (foreground)
if (c == DARK) {
display.setTextColor(_curr_color = GxEPD_WHITE);
} else {
display.setTextColor(_curr_color = GxEPD_BLACK);
}
}
}

View File

@@ -63,6 +63,7 @@ class GxEPDDisplay : public DisplayDriver {
#endif
bool _init = false;
bool _isOn = false;
bool _darkMode = false;
uint16_t _curr_color;
FrameCRC32 display_crc;
int last_display_crc_value = 0;
@@ -79,6 +80,11 @@ public:
bool isOn() override {return _isOn;};
void turnOn() override;
void turnOff() override;
// Dark mode — inverts background/foreground for e-ink
bool isDarkMode() const { return _darkMode; }
void setDarkMode(bool on) { _darkMode = on; }
void clear() override;
void startFrame(Color bkg = DARK) override;
void setTextSize(int sz) override;