Jelajahi Sumber

Fix red-plane bit convention: was inverted, painting solid red for any frame with no red pixels

Third hardware run: after fixing the busy-timeout ceiling, the cycle
completed cleanly but came out solid red instead of white-background/
black-text. The test lambda draws no red at all, so the color plane
buffer ends up one uniform value across the whole frame either way -
whichever convention is backwards paints the entire panel that color
instead of "no red anywhere".

Compared against the working epaper_spi driver for this exact panel
(waveshare-2.13in-bv4): its EpaperWaveshareB::transform_red_byte is
documented "Waveshare uses 0=red, 1=no-red", applied on top of
EPaperWeAct3C's internal 1=red/0=no-red buffer convention. Our code had
the internal bit assignment backwards (setting the "not red" bit and
clearing the "red" bit), which combined with plane_invert[1]=true
produced the opposite of the intended wire value. Swapped the bit
assignment and the plane1 buffer's default fill value to match.
ZiB 1 bulan lalu
induk
melakukan
136b1c892f
1 mengubah file dengan 16 tambahan dan 4 penghapusan
  1. 16 4
      components/gxepd2/gxepd2_display.h

+ 16 - 4
components/gxepd2/gxepd2_display.h

@@ -35,9 +35,9 @@ class GxEPD2Display : public display::DisplayBuffer {
       this->mark_failed();
       return;
     }
-    memset(this->plane0_, 0xFF, this->plane_bytes_);
+    memset(this->plane0_, 0xFF, this->plane_bytes_);  // 1 = white
     if (this->plane1_ != nullptr)
-      memset(this->plane1_, 0xFF, this->plane_bytes_);
+      memset(this->plane1_, 0x00, this->plane_bytes_);  // 0 = not-red
 
     this->spi_.spi_setup();
     this->engine_.begin(desc, this->cs_, this->dc_, this->rst_, this->busy_, &this->spi_);
@@ -74,12 +74,24 @@ class GxEPD2Display : public display::DisplayBuffer {
     // pixels go to the color plane, everything else is black/white on the
     // black plane. get_display_type() reports DISPLAY_TYPE_COLOR, so
     // callers draw literal RGB colors, not the on/off is_on() convention.
+    //
+    // Buffer convention here is 1=red/0=not-red (matching the reference
+    // epaper_spi driver's EPaperWeAct3C internal convention), transformed
+    // to the wire value by PANEL_213_Z98C's plane_invert[1]=true - this
+    // panel (waveshare-2.13in-bv4) puts "red" on the wire as 0, not 1 (see
+    // EpaperWaveshareB::transform_red_byte in the working epaper_spi
+    // config's driver: "Waveshare uses 0=red, 1=no-red"). Getting this
+    // backwards was the actual bug behind the solid-red/black hardware
+    // runs: with zero red pixels in a frame, the whole color plane comes
+    // out as one uniform value either way - so whichever convention is
+    // backwards paints the entire panel that color instead of the intended
+    // "no red anywhere".
     bool red = color.red > color.green && color.red > color.blue && color.red > 0x7f;
     bool bright = color.red > 0x7f || color.green > 0x7f || color.blue > 0x7f;
     if (red) {
-      this->plane1_[idx] &= ~mask;  // 0 bit = colored, per GxEPD2_213_Z98c::writeImage's color plane
-    } else {
       this->plane1_[idx] |= mask;
+    } else {
+      this->plane1_[idx] &= ~mask;
       if (bright) {
         this->plane0_[idx] |= mask;
       } else {