mirror of
https://github.com/pelgraine/Meck.git
synced 2026-07-06 17:51:18 +02:00
t5s3 portrait mode and dark mode
This commit is contained in:
@@ -115,6 +115,8 @@ void FastEPDDisplay::startFrame(Color bkg) {
|
||||
_canvas->setTextColor(0); // Black text
|
||||
_curr_color = GxEPD_BLACK;
|
||||
_frameCRC.reset();
|
||||
_frameCRC.update<bool>(_darkMode);
|
||||
_frameCRC.update<bool>(_portraitMode);
|
||||
}
|
||||
|
||||
void FastEPDDisplay::setTextSize(int sz) {
|
||||
@@ -290,6 +292,11 @@ void FastEPDDisplay::endFrame() {
|
||||
|
||||
memcpy(dst, src, bufSize);
|
||||
|
||||
// Dark mode: invert every byte in the buffer (white↔black)
|
||||
if (_darkMode) {
|
||||
for (size_t i = 0; i < bufSize; i++) dst[i] = ~dst[i];
|
||||
}
|
||||
|
||||
// Refresh strategy:
|
||||
// partialUpdate(true) — no flash, differential, keeps previous buffer
|
||||
// fullUpdate(false) — brief flash, clears ghosting (CLEAR_FAST)
|
||||
@@ -298,11 +305,43 @@ void FastEPDDisplay::endFrame() {
|
||||
// Use partial for most frames. Periodic full refresh every N frames
|
||||
// to clear accumulated ghosting artifacts.
|
||||
_fullRefreshCount++;
|
||||
if (_fullRefreshCount >= FULL_SLOW_PERIOD) {
|
||||
if (_forcePartial) {
|
||||
// VKB typing mode — no flash, fast differential update
|
||||
_epd->partialUpdate(true);
|
||||
_fullRefreshCount = 0; // Reset so next non-partial frame does full refresh
|
||||
} else if (_fullRefreshCount >= FULL_SLOW_PERIOD) {
|
||||
_fullRefreshCount = 0;
|
||||
_epd->fullUpdate(true); // Full clean refresh — clears all ghosting
|
||||
} else {
|
||||
_epd->partialUpdate(true); // No flash — differential
|
||||
}
|
||||
_epd->backupPlane();
|
||||
}
|
||||
|
||||
void FastEPDDisplay::setDarkMode(bool dark) {
|
||||
_darkMode = dark;
|
||||
_lastCRC = 0; // Force redraw
|
||||
Serial.printf("[FastEPD] Dark mode: %s\n", dark ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
void FastEPDDisplay::setPortraitMode(bool portrait) {
|
||||
if (_portraitMode == portrait) return;
|
||||
_portraitMode = portrait;
|
||||
|
||||
if (!_canvas) return;
|
||||
|
||||
if (portrait) {
|
||||
_canvas->setRotation(3); // 270° CW — USB-C on right when held portrait
|
||||
scale_x = (float)EPD_HEIGHT / 128.0f; // 540 / 128 = 4.21875
|
||||
scale_y = (float)EPD_WIDTH / 128.0f; // 960 / 128 = 7.5
|
||||
Serial.printf("[FastEPD] Portrait mode: ON (logical %dx%d, scale %.2f x %.2f)\n",
|
||||
EPD_HEIGHT, EPD_WIDTH, scale_x, scale_y);
|
||||
} else {
|
||||
_canvas->setRotation(0); // Normal landscape
|
||||
scale_x = (float)EPD_WIDTH / 128.0f; // 960 / 128 = 7.5
|
||||
scale_y = (float)EPD_HEIGHT / 128.0f; // 540 / 128 = 4.21875
|
||||
Serial.printf("[FastEPD] Portrait mode: OFF (logical %dx%d, scale %.2f x %.2f)\n",
|
||||
EPD_WIDTH, EPD_HEIGHT, scale_x, scale_y);
|
||||
}
|
||||
_lastCRC = 0; // Force redraw
|
||||
}
|
||||
@@ -73,11 +73,13 @@ class FastEPDDisplay : public DisplayDriver {
|
||||
uint32_t _lastCRC = 0;
|
||||
int _fullRefreshCount = 0; // Track for periodic slow refresh
|
||||
uint32_t _lastUpdateMs = 0; // Rate limiting — minimum interval between refreshes
|
||||
bool _forcePartial = false; // When true, use partial updates (VKB typing)
|
||||
bool _darkMode = false; // Invert all pixels (black bg, white text)
|
||||
bool _portraitMode = false; // Rotated 90° (540×960 logical)
|
||||
|
||||
// Virtual 128×128 → physical 960×540 mapping
|
||||
// Non-square scaling (1.78:1 aspect stretch) — acceptable for initial bringup
|
||||
static constexpr float scale_x = 7.5f; // 960 / 128
|
||||
static constexpr float scale_y = 4.21875f; // 540 / 128
|
||||
// Virtual 128×128 → physical canvas mapping (runtime, changes with portrait)
|
||||
float scale_x = 7.5f; // 960 / 128 (landscape default)
|
||||
float scale_y = 4.21875f; // 540 / 128 (landscape default)
|
||||
static constexpr float offset_x = 0.0f;
|
||||
static constexpr float offset_y = 0.0f;
|
||||
|
||||
@@ -119,4 +121,16 @@ public:
|
||||
}
|
||||
|
||||
void invalidateFrameCRC() { _lastCRC = 0; }
|
||||
|
||||
// Temporarily force partial (no-flash) updates — use during VKB typing
|
||||
void setForcePartial(bool partial) { _forcePartial = partial; }
|
||||
bool isForcePartial() const { return _forcePartial; }
|
||||
|
||||
// Dark mode — invert all pixels in endFrame (black bg, white text)
|
||||
void setDarkMode(bool dark);
|
||||
bool isDarkMode() const { return _darkMode; }
|
||||
|
||||
// Portrait mode — rotate canvas 90° (540×960 logical), swap scale factors
|
||||
void setPortraitMode(bool portrait);
|
||||
bool isPortraitMode() const { return _portraitMode; }
|
||||
};
|
||||
Reference in New Issue
Block a user