From 1bad37d1adbf3283beaeb9d2c67e814d0dbe4b5c Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Sun, 13 Sep 2026 21:10:08 +1000 Subject: [PATCH] Large font channel message view word wrap bug fix: What changed: Driver: setTextWrap(false) once at init. GFX no longer moves text to the next line by itself, anywhere. This is what put the stray "t" on the margin; without it, a line the screen miscounts is clipped at the edge instead, which is the lesser evil for a UI that does all its own wrapping. Applies to every e-ink build, Pro and Max. Compose: the usable line width is now the panel width less the driver's 2-unit x offset, so the compose wrap and the glyphs' real positions agree and lines wrap one word earlier when they need to. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GxEPD2_310_GDEQ031T10_FAST.cpp → fingerprint 473 (was 464). The 9-frame bytes (0x89 / 0x49 / 0x09) become 0x8C / 0x4C / 0x0C: same level bits, count 12. Improves colour density in Max fastlut test build. --- examples/companion_radio/main.cpp | 6 ++++- src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.cpp | 25 +++++++++++++------ src/helpers/ui/GxEPDDisplay.cpp | 7 ++++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 820f05a2..d0b8a474 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -6239,7 +6239,11 @@ void drawComposeScreen() { char dblStr[3] = {0, 0, 0}; int px = 0; - int lineW = display.width(); + // The e-ink driver draws everything 2 virtual units to the right of the + // cursor it is given (its x offset), so a line measured against the full + // width can run a few physical pixels past the panel edge. Leave that + // margin out of the usable width. + int lineW = display.width() - 2; bool atWordBoundary = true; for (int i = 0; i < composePos; i++) { diff --git a/src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.cpp b/src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.cpp index bceb8eb7..1f48554c 100644 --- a/src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.cpp +++ b/src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.cpp @@ -398,22 +398,31 @@ void GxEPD2_310_GDEQ031T10_FAST::_Update_Full() // 42 bytes: VCOM (0x20), WW (0x21), BW (0x22), WB (0x23), BB (0x24). UC8253 // group layout per Larry Bank's comment: group repeat, level+count 1, // level+count 1, level+count 2, level+count 2, repeat 1, repeat 2. Only the -// first group is used; the other five are zero. 0x89 = 9 frames towards -// white, 0x49 = 9 frames towards black, 0x09 = 9 frames at VCOM DC. +// first group is used; the other five are zero. Each level+count byte is +// the level in bits 7:6 (10 = towards white, 01 = towards black, 00 = VCOM +// DC) and the frame count in bits 5:0. bb_epaper ships 9 frames (0x89 / +// 0x49 / 0x09, measured 244 ms per partial on the Max); FAST_LUT_FRAMES +// is the tuning knob: more frames, darker blacks, longer refresh. +#ifndef FAST_LUT_FRAMES +#define FAST_LUT_FRAMES 12 +#endif +#define FAST_TO_WHITE (uint8_t)(0x80 | FAST_LUT_FRAMES) +#define FAST_TO_BLACK (uint8_t)(0x40 | FAST_LUT_FRAMES) +#define FAST_VCOM_DC (uint8_t)(0x00 | FAST_LUT_FRAMES) static const uint8_t fast_lut_vcom[42] = { - 0x01, 0x09, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x01, FAST_VCOM_DC, 0x01, 0x00, 0x00, 0x01, 0x00, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0 }; static const uint8_t fast_lut_ww[42] = { - 0x01, 0x89, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x01, FAST_TO_WHITE, 0x01, 0x00, 0x00, 0x01, 0x00, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0 }; static const uint8_t fast_lut_bw[42] = { - 0x01, 0x89, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x01, FAST_TO_WHITE, 0x01, 0x00, 0x00, 0x01, 0x00, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0 }; static const uint8_t fast_lut_wb[42] = { - 0x01, 0x49, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x01, FAST_TO_BLACK, 0x01, 0x00, 0x00, 0x01, 0x00, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0 }; static const uint8_t fast_lut_bb[42] = { - 0x01, 0x49, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x01, FAST_TO_BLACK, 0x01, 0x00, 0x00, 0x01, 0x00, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0 }; void GxEPD2_310_GDEQ031T10_FAST::_writeLut(uint8_t command, const uint8_t* lut) @@ -461,4 +470,4 @@ void GxEPD2_310_GDEQ031T10_FAST::_Update_Part() _writeCommand(0x12); //display refresh _waitWhileBusy("_Update_Part", partial_refresh_time); _init_display_done = false; // needed, reason unknown -} +} \ No newline at end of file diff --git a/src/helpers/ui/GxEPDDisplay.cpp b/src/helpers/ui/GxEPDDisplay.cpp index ac33e5cd..20897ae3 100644 --- a/src/helpers/ui/GxEPDDisplay.cpp +++ b/src/helpers/ui/GxEPDDisplay.cpp @@ -134,6 +134,13 @@ bool GxEPDDisplay::begin() { display.init(115200, true, 2, false); display.setRotation(DISPLAY_ROTATION); setTextSize(1); // Default to size 1 + // Adafruit GFX wraps text to the next line by itself when a glyph would + // cross the right edge. Every Meck screen positions and wraps its own + // text, so that behaviour only ever corrupts a layout: a glyph the + // screen's wrap thought fitted lands on the next line's left margin on + // top of the real text (seen with Larger Noto in compose). Off: an + // over-wide line clips at the edge instead. + display.setTextWrap(false); #ifdef EINK_FULL_REFRESH_ONLY display.setFullWindow(); display.fillScreen(GxEPD_WHITE);