window_sweep.h 2.3 KB

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