run_harness.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #pragma once
  2. // Drives one vendor GxEPD2 driver through the same low-level calls the
  3. // GxEPD2_BW/GxEPD2_3C wrapper templates make for a single non-paged full
  4. // update (writeImage() then refresh()) - bypassing the wrapper templates
  5. // themselves (and their Adafruit_GFX dependency) since we only need the
  6. // driver-level trace, not drawing helpers. After the full update it also
  7. // runs the window-encoder sweep (window_sweep.h) - adopted as the standard
  8. // capture step for every panel, to derive and cross-check the coordinate ->
  9. // window-byte math by observation rather than by hand.
  10. #include <cstdio>
  11. #include <cstring>
  12. #include "spy/Arduino.h"
  13. #include "spy/SPI.h"
  14. #include "trace.h"
  15. #include "window_sweep.h"
  16. // Exposes GxEPD2_EPD's protected busy_level/reset_duration without needing
  17. // to parse anything - a subclass can read its own base class's protected
  18. // members directly.
  19. template<typename Driver> struct Peek : Driver {
  20. using Driver::Driver;
  21. int busy_level() const { return this->_busy_level; }
  22. uint16_t reset_duration() const { return this->_reset_duration; }
  23. };
  24. // planes=1 for monochrome drivers (color buffer still passed - harmless,
  25. // see e.g. GxEPD2_290_T94::writeImage(black,color,...) which just ignores
  26. // a non-null color pointer's absence).
  27. template<typename Driver> void run_harness(const char *name) {
  28. printf("=== %s: WIDTH=%u HEIGHT=%u ===\n", name, (unsigned) Driver::WIDTH, (unsigned) Driver::HEIGHT);
  29. constexpr int16_t CS = 10, DC = 11, RST = 12, BUSY = 13;
  30. Trace::set_dc_pin(DC);
  31. Peek<Driver> driver(CS, DC, RST, BUSY);
  32. printf("busy_level=%d reset_duration=%u\n", driver.busy_level(), driver.reset_duration());
  33. // digitalRead(BUSY) should report "released" immediately - opposite of
  34. // busy_level - so _waitWhileBusy()'s loop exits after one check.
  35. Trace::last_busy_release_value = driver.busy_level() == HIGH ? LOW : HIGH;
  36. driver.selectSPI(SPI, SPISettings());
  37. printf("--- init(0) ---\n");
  38. driver.init(0);
  39. const uint32_t plane_bytes = (static_cast<uint32_t>(Driver::WIDTH) * Driver::HEIGHT) / 8;
  40. auto *black = new uint8_t[plane_bytes];
  41. auto *color = new uint8_t[plane_bytes];
  42. // Distinctive, non-0x00/0xFF pattern - lets a plane's invert flag be
  43. // read directly off the trace (does the wire byte equal 0xA5 or 0x5A).
  44. memset(black, 0xA5, plane_bytes);
  45. memset(color, 0xA5, plane_bytes);
  46. printf("--- writeImage(black, color, 0, 0, WIDTH, HEIGHT) ---\n");
  47. driver.writeImage(black, color, 0, 0, Driver::WIDTH, Driver::HEIGHT);
  48. printf("--- refresh(false) ---\n");
  49. driver.refresh(false);
  50. // Standard window-encoder sweep for every panel (runs after the initial
  51. // full refresh above, which satisfies run_window_sweep's precondition).
  52. run_window_sweep(driver, Driver::WIDTH, Driver::HEIGHT);
  53. delete[] black;
  54. delete[] color;
  55. }