#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 #include template 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(W / 2)), static_cast(H / 2), 16, 24, "mid block"}, {align8_down(static_cast(W - 8)), static_cast(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); } }