fix(screenshot): use GxEPD2 visible dimensions; fix phys_x formula

Firmware: add screenshotWidth()/screenshotHeight() virtual pair to
DisplayDriver (default: width()/height()).  GxEPDDisplay overrides to
return display.width()/display.height() — the GxEPD2-reported values
that use WIDTH_VISIBLE (e.g. 122 for GxEPD2_213_B74), not the full
physical WIDTH stored in DisplayDriver (128).  MyMesh uses these
instead of display->width()/height() for the screenshot header bytes.

Result for GxEPD2_213_B74 + DISPLAY_ROTATION=1:
  header was 250×128 → now 250×122  (correct visible canvas)

Python decoder (tools/screenshot.py):
- Remove hardcoded EINK_PHYS_WIDTH=128 / EINK_VISIBLE_W=122 constants.
- Derive phys_stride from buffer_size / log_width (works for any panel).
- Fix phys_x formula: was (EINK_PHYS_WIDTH-1-ly = 127-ly),
  now (vis_w-1-ly = log_height-1-ly = 121-ly for 213_B74).
  Old formula addressed invisible columns 122-127; new formula correctly
  maps logical rows 0..121 to visible physical columns 121..0.
- vis_w = log_height (no hardcoded trim; header now carries correct value).

This also works for square panels (e.g. 128×128 where WIDTH=WIDTH_VISIBLE):
  header will carry 128×128, decoder produces a correct 128×128 image.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-28 01:19:22 +02:00
parent 7d9d5f847d
commit 1332358ee7
4 changed files with 39 additions and 22 deletions

View File

@@ -254,5 +254,11 @@ public:
virtual const uint8_t* getBuffer() { return nullptr; }
virtual uint16_t getBufferSize() { return 0; }
virtual uint8_t getDisplayType() { return 0; }
// Visible pixel dimensions to embed in the screenshot header.
// Override in e-ink drivers to return the GxEPD2-reported dimensions (which use
// WIDTH_VISIBLE instead of the full physical WIDTH used by DisplayDriver).
// OLED drivers: width()/height() already reflect the visible canvas, so no override needed.
virtual int screenshotWidth() { return width(); }
virtual int screenshotHeight() { return height(); }
#endif
};

View File

@@ -82,6 +82,10 @@ public:
const uint8_t* getBuffer() override { return display.getBuffer(); }
uint16_t getBufferSize() override { return display.getBufferSize(); }
uint8_t getDisplayType() override { return 1; } // 1 = e-ink
// Return GxEPD2's own reported dimensions (uses WIDTH_VISIBLE, not the full physical WIDTH
// stored in DisplayDriver). After setRotation(1): width()=HEIGHT, height()=WIDTH_VISIBLE.
int screenshotWidth() override { return (int)display.width(); }
int screenshotHeight() override { return (int)display.height(); }
#endif
// Line height and approx. char width for each font size: