pimoroni / inky

Combined library for V2/V3 Inky pHAT and Inky wHAT.
https://shop.pimoroni.com/?q=inky
MIT License
575 stars 121 forks source link

SSD1608 Custom Lookup table #160

Open lbarnard86 opened 1 year ago

lbarnard86 commented 1 year ago

It would seem that it's not possible to create custom luts for the new SSD1608 display variant. It's not possible to even get the red display to register as a black and white display as Pimoroni's own website indicates.

Does this problem require dev intervention or am I missing something when it comes to creating custom luts for quicker redraw rates?

iso2013 commented 1 year ago

I'm wondering this too - I bought the wHAT display under the impression that it could be updated monochromatically as the website states, but I haven't had any luck in getting that to actually happen.

Gadgetoid commented 9 months ago

I believe the text on the website is a holdout from an older version of wHAT that used the original (old pHAT notwithstanding) driver. New wHAT uses the SSD1683 (not SSD1608) . This has a "luts" table defined in code as a holdout from SSD1608 but it does not attempt to write them to the display.

That said the display datasheet seems to suggest a Black/White mode is possible, though from some experimentation I can't seem to get it to actually trigger. Red can be omitted by setting the DISP_CTRL1 register to 0x40, 0x00, which - when combined with some changes elsewhere- turns it into a black/white display. But it seems to take the same amount of time to update.

Writing to the "temperature" register to tell the display that it's warmer than it is doesn't seem to get much speed advantage, either.

Looks like it would involve dumping the existing LUTs and hacking them manually to get any faster, but from experience that's a great way to destroy a display (or a few dozen).

For posterity, here's what I tried:

diff --git a/inky/inky_ssd1683.py b/inky/inky_ssd1683.py
index f299be1..ea4e6ce 100644
--- a/inky/inky_ssd1683.py
+++ b/inky/inky_ssd1683.py
@@ -88,6 +88,7 @@ class Inky:
         self.cs_pin = cs_pin
         self.h_flip = h_flip
         self.v_flip = v_flip
+        self.fast_mode = True

         self._gpio = gpio
         self._gpio_setup = False
@@ -199,11 +200,21 @@ class Inky:
         self._send_command(ssd1683.SET_RAMXCOUNT, [0x00])
         self._send_command(ssd1683.SET_RAMYCOUNT, [0x00, 0x00])

-        for data in ((ssd1683.WRITE_RAM, buf_a), (ssd1683.WRITE_ALTRAM, buf_b)):
-            cmd, buf = data
-            self._send_command(cmd, buf)
+        if self.fast_mode:
+            # buf_a and buf_b should both be the same in fast mode
+            self._send_command(ssd1683.WRITE_RAM, buf_a)
+        else:
+            for data in ((ssd1683.WRITE_RAM, buf_a), (ssd1683.WRITE_ALTRAM, buf_b)):
+                cmd, buf = data
+                self._send_command(cmd, buf)

         self._busy_wait()
+
+        if self.fast_mode:
+            self._send_command(ssd1683.DISP_CTRL1, [0x40, 0x00])  # Skip updating the red
+            self._send_command(ssd1683.TEMP_WRITE, 0x7F)    # Tell the display it's really warm so it uses faster LUTs
+            self._send_command(ssd1683.DISP_CTRL2, [0xD4])  # Datasheet says 0xFF is POR but only 0xF7/0xD4/0xD7 work??
+
         self._send_command(ssd1683.MASTER_ACTIVATE)

     def set_pixel(self, x, y, v):
@@ -234,10 +245,13 @@ class Inky:
         if self.rotation:
             region = numpy.rot90(region, self.rotation // 90)

-        buf_a = numpy.packbits(numpy.where(region == BLACK, 0, 1)).tolist()
-        buf_b = numpy.packbits(numpy.where(region == RED, 1, 0)).tolist()
+        if self.fast_mode:
+            buf_b = buf_a = numpy.packbits(numpy.where(region != WHITE, 0, 1))
+        else:
+            buf_a = numpy.packbits(numpy.where(region == BLACK, 0, 1))
+            buf_b = numpy.packbits(numpy.where(region == RED, 1, 0))

-        self._update(buf_a, buf_b, busy_wait=busy_wait)
+        self._update(buf_a.tolist(), buf_b.tolist(), busy_wait=busy_wait)

     def set_border(self, colour):
         """Set the border colour."""
diff --git a/inky/ssd1683.py b/inky/ssd1683.py
index a48ea60..9aaa04f 100644
--- a/inky/ssd1683.py
+++ b/inky/ssd1683.py
@@ -24,6 +24,7 @@ VCOM_DURATION = 0x2C
 WRITE_VCOM = 0x2C
 READ_OTP = 0x2D
 WRITE_LUT = 0x32
+WRITE_DISPLAY_OPTION = 0x37
 WRITE_DUMMY = 0x3A
 WRITE_GATELINE = 0x3B
 WRITE_BORDER = 0x3C