|
|
@@ -0,0 +1,49 @@
|
|
|
+#pragma once
|
|
|
+
|
|
|
+// Reusable window-encoder sweep, shared by run_harness.h (every panel) and
|
|
|
+// run_partial_harness.h. Calls the driver's PUBLIC refresh(x,y,w,h) at
|
|
|
+// several distinct in-bounds rects, with x/w kept multiples of 8 so the
|
|
|
+// driver's own coordinate rounding is a no-op and the window bytes in each
|
|
|
+// trace are exactly the rect. Diff the per-rect traces to DERIVE the
|
|
|
+// coordinate -> window-byte encoder by observation, instead of hand-
|
|
|
+// computing it (the latter produced the GDEQ0583T31 0x8F-vs-0x87 smear).
|
|
|
+//
|
|
|
+// Not fast-partial-specific: every panel sets a RAM window from
|
|
|
+// coordinates, so this works for any driver. On a panel whose refresh
|
|
|
+// ignores the rect and always refreshes full, every sweep point simply
|
|
|
+// emits the same (full) window - itself the informative result ("no
|
|
|
+// coordinate-parameterized window here"). The full (0,0,W,H) point is a
|
|
|
+// built-in cross-check against the window the normal full-refresh capture
|
|
|
+// already records.
|
|
|
+//
|
|
|
+// Precondition: run AFTER an initial full refresh - some drivers force the
|
|
|
+// very first refresh to be full regardless of the rect (e.g. the
|
|
|
+// _initial_refresh gate in GxEPD2_290_T94::refresh).
|
|
|
+
|
|
|
+#include <cstdint>
|
|
|
+#include <cstdio>
|
|
|
+
|
|
|
+template<typename Driver> void run_window_sweep(Driver &d, uint16_t W, uint16_t H) {
|
|
|
+ auto align8_down = [](uint16_t v) -> uint16_t { return v & ~uint16_t(7); }; // to multiple of 8
|
|
|
+ struct Rect {
|
|
|
+ uint16_t x, y, w, h;
|
|
|
+ const char *label;
|
|
|
+ };
|
|
|
+ const Rect rects[] = {
|
|
|
+ {0, 0, W, H, "full (0,0,W,H) - cross-check vs full-refresh window"},
|
|
|
+ {0, 0, 8, 8, "origin-unit (0,0,8,8)"},
|
|
|
+ {8, 3, 8, 5, "small-offset (x/8=1, non-round y/h -> inclusive-end math)"},
|
|
|
+ {align8_down(static_cast<uint16_t>(W / 2)), static_cast<uint16_t>(H / 2), 16, 24, "mid block"},
|
|
|
+ {align8_down(static_cast<uint16_t>(W - 8)), static_cast<uint16_t>(H - 8), 8, 8, "far-corner - high bytes"},
|
|
|
+ };
|
|
|
+
|
|
|
+ printf("\n--- [WINDOW SWEEP] refresh(x,y,w,h) per rect (window bytes precede each refresh trigger) ---\n");
|
|
|
+ for (const auto &r : rects) {
|
|
|
+ if (r.w == 0 || r.h == 0 || r.x + r.w > W || r.y + r.h > H) {
|
|
|
+ printf(">>> SWEEP skip %s = (%u,%u,%u,%u) - out of bounds for %ux%u\n", r.label, r.x, r.y, r.w, r.h, W, H);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ printf(">>> SWEEP %s = (%u,%u,%u,%u)\n", r.label, r.x, r.y, r.w, r.h);
|
|
|
+ d.refresh(r.x, r.y, r.w, r.h);
|
|
|
+ }
|
|
|
+}
|