diff --git a/adafruit_ssd1680.py b/adafruit_ssd1680.py index 3741f5c..f9ff6fd 100755 --- a/adafruit_ssd1680.py +++ b/adafruit_ssd1680.py @@ -42,19 +42,20 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SSD1680.git" _START_SEQUENCE = ( - b"\x12\x80\x14" # soft reset and wait 20ms - b"\x11\x01\x03" # Ram data entry mode - b"\x3c\x01\x05" # border color - b"\x2c\x01\x36" # Set vcom voltage - b"\x03\x01\x17" # Set gate voltage - b"\x04\x03\x41\x00\x32" # Set source voltage - b"\x4e\x01\x01" # ram x count - b"\x4f\x02\x00\x00" # ram y count - b"\x01\x03\x00\x00\x00" # set display size - b"\x22\x01\xf4" # display update mode + b"\x12\x80\x00\x14" # soft reset and wait 20ms + b"\x11\x00\x01\x03" # Ram data entry mode + b"\x3c\x00\x01\x03" # border color + b"\x2c\x00\x01\x36" # Set vcom voltage + b"\x03\x00\x01\x17" # Set gate voltage + b"\x04\x00\x03\x41\xae\x32" # Set source voltage + b"\x4e\x00\x01\x01" # ram x count + b"\x4f\x00\x02\x00\x00" # ram y count + b"\x01\x00\x03\x00\x00\x00" # set display size ) -_STOP_SEQUENCE = b"\x10\x81\x01\x64" # Deep Sleep +_DISPLAY_UPDATE_MODE = b"\x22\x00\x01\xf4" # display update mode + +_STOP_SEQUENCE = b"\x10\x80\x01\x01\x64" # Deep Sleep # pylint: disable=too-few-public-methods @@ -72,9 +73,17 @@ class SSD1680(EPaperDisplay): Display height * *rotation* (``int``) -- Display rotation + * *vcom* (``int``) -- + Set vcom voltage register value + * *vsh2* (``int``) -- + Set vsh2 voltage register value + * *custom_lut* (``bytes``) -- + Custom look-up table settings """ - def __init__(self, bus: FourWire, **kwargs) -> None: + def __init__( + self, bus: FourWire, vcom: int = 0x36, vsh2: int = 0x00, custom_lut: bytes = b"", **kwargs + ) -> None: if "colstart" not in kwargs: kwargs["colstart"] = 8 stop_sequence = bytearray(_STOP_SEQUENCE) @@ -83,14 +92,23 @@ def __init__(self, bus: FourWire, **kwargs) -> None: except RuntimeError: # No reset pin defined, so no deep sleeping stop_sequence = b"" + load_lut = b"" + display_update_mode = bytearray(_DISPLAY_UPDATE_MODE) + if custom_lut: + load_lut = b"\x32" + len(custom_lut).to_bytes(2) + custom_lut + display_update_mode[-1] = 0xC7 + + start_sequence = bytearray(_START_SEQUENCE + load_lut + display_update_mode) + start_sequence[15] = vcom + + start_sequence[24] = vsh2 - start_sequence = bytearray(_START_SEQUENCE) width = kwargs["width"] height = kwargs["height"] if "rotation" in kwargs and kwargs["rotation"] % 180 != 90: width, height = height, width - start_sequence[29] = (width - 1) & 0xFF - start_sequence[30] = ((width - 1) >> 8) & 0xFF + start_sequence[38] = (width - 1) & 0xFF + start_sequence[39] = ((width - 1) >> 8) & 0xFF super().__init__( bus, @@ -109,4 +127,5 @@ def __init__(self, bus: FourWire, **kwargs) -> None: refresh_display_command=0x20, always_toggle_chip_select=False, address_little_endian=True, + two_byte_sequence_length=True, ) diff --git a/examples/display-ruler-640x360.bmp b/examples/display-ruler-640x360.bmp new file mode 100644 index 0000000..a9c776e Binary files /dev/null and b/examples/display-ruler-640x360.bmp differ diff --git a/examples/display-ruler.bmp.license b/examples/display-ruler-640x360.bmp.license similarity index 100% rename from examples/display-ruler.bmp.license rename to examples/display-ruler-640x360.bmp.license diff --git a/examples/display-ruler.bmp b/examples/display-ruler.bmp deleted file mode 100644 index 726b5e0..0000000 Binary files a/examples/display-ruler.bmp and /dev/null differ diff --git a/examples/ssd1680_2.13_featherwing.py b/examples/ssd1680_2.13_featherwing.py index 9e9f5ef..9eb4faa 100644 --- a/examples/ssd1680_2.13_featherwing.py +++ b/examples/ssd1680_2.13_featherwing.py @@ -43,7 +43,7 @@ g = displayio.Group() -pic = displayio.OnDiskBitmap("/display-ruler.bmp") +pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp") t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) diff --git a/examples/ssd1680_2.13_mono_eink_bonnet.py b/examples/ssd1680_2.13_mono_eink_bonnet.py index ef58241..d573a37 100644 --- a/examples/ssd1680_2.13_mono_eink_bonnet.py +++ b/examples/ssd1680_2.13_mono_eink_bonnet.py @@ -50,7 +50,7 @@ g = displayio.Group() -pic = displayio.OnDiskBitmap("/display-ruler.bmp") +pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp") t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) g.append(t) diff --git a/examples/ssd1680_2.13_tricolor_breakout.py b/examples/ssd1680_2.13_tricolor_breakout.py index cf1230f..9c4f17a 100644 --- a/examples/ssd1680_2.13_tricolor_breakout.py +++ b/examples/ssd1680_2.13_tricolor_breakout.py @@ -42,7 +42,7 @@ g = displayio.Group() -pic = displayio.OnDiskBitmap("/display-ruler.bmp") +pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp") t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) diff --git a/examples/ssd1680_2.9_grayscale_magtag2025.py b/examples/ssd1680_2.9_grayscale_magtag2025.py new file mode 100644 index 0000000..ad4ddb6 --- /dev/null +++ b/examples/ssd1680_2.9_grayscale_magtag2025.py @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft, written for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +"""Simple test script for 2.9" 296x128 display. This example runs it in 2bit grayscale mode.""" + +import time + +import board +import busio +import displayio +from fourwire import FourWire + +import adafruit_ssd1680 + +displayio.release_displays() + +# This pinout works on a MagTag with the newer screen and may need to be altered for other boards. +spi = busio.SPI(board.EPD_SCK, board.EPD_MOSI) # Uses SCK and MOSI +epd_cs = board.EPD_CS +epd_dc = board.EPD_DC +epd_reset = board.EPD_RESET +epd_busy = board.EPD_BUSY + +display_bus = FourWire(spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000) +time.sleep(1) + +ti_290mfgn_gray4_lut_code = ( + b"\x2a\x60\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L0 + b"\x20\x60\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L1 + b"\x28\x60\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L2 + b"\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L3 + b"\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L4 + b"\x00\x02\x00\x05\x14\x00\x00" # TP, SR, RP of Group0 + b"\x1e\x1e\x00\x00\x00\x00\x01" # TP, SR, RP of Group1 + b"\x00\x02\x00\x05\x14\x00\x00" # TP, SR, RP of Group2 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group3 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group4 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group5 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group6 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group7 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group8 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group9 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group10 + b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group11 + b"\x24\x22\x22\x22\x23\x32\x00\x00\x00" # FR, XON +) + +if len(ti_290mfgn_gray4_lut_code) != 153: + raise ValueError("ti_290mfgn_gray4_lut_code is not the correct length") + +# For issues with display not updating top/bottom rows correctly set colstart to 8, 0, or -8 +display = adafruit_ssd1680.SSD1680( + display_bus, + width=296, + height=128, + busy_pin=epd_busy, + rotation=270, + colstart=0, + vcom=0x28, + vsh2=0xAE, + custom_lut=ti_290mfgn_gray4_lut_code, + grayscale=True, +) + +g = displayio.Group() + +pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp") +t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) +g.append(t) + +display.root_group = g + +display.refresh() + +print("refreshed") + +time.sleep(display.time_to_refresh + 5) +# Always refresh a little longer. It's not a problem to refresh +# a few seconds more, but it's terrible to refresh too early +# (the display will throw an exception when if the refresh +# is too soon) +print("waited correct time") + + +# Keep the display the same +while True: + time.sleep(10) diff --git a/examples/ssd1680_2.9_mono_magtag2025.py b/examples/ssd1680_2.9_mono_magtag2025.py new file mode 100644 index 0000000..c3e0a84 --- /dev/null +++ b/examples/ssd1680_2.9_mono_magtag2025.py @@ -0,0 +1,56 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft, written for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +"""Simple test script for 2.9" 296x128 display. This example runs it in mono mode.""" + +import time + +import board +import busio +import displayio +from fourwire import FourWire + +import adafruit_ssd1680 + +displayio.release_displays() + +# This pinout works on a MagTag with the newer screen and may need to be altered for other boards. +spi = busio.SPI(board.EPD_SCK, board.EPD_MOSI) # Uses SCK and MOSI +epd_cs = board.EPD_CS +epd_dc = board.EPD_DC +epd_reset = board.EPD_RESET +epd_busy = board.EPD_BUSY + +display_bus = FourWire(spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000) +time.sleep(1) + +# For issues with display not updating top/bottom rows correctly set colstart to 8, 0, or -8 +display = adafruit_ssd1680.SSD1680( + display_bus, width=296, height=128, busy_pin=epd_busy, rotation=270, colstart=0 +) + +g = displayio.Group() + +pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp") +t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) +g.append(t) + +display.root_group = g + +display.refresh() + +print("refreshed") + +time.sleep(display.time_to_refresh + 5) +# Always refresh a little longer. It's not a problem to refresh +# a few seconds more, but it's terrible to refresh too early +# (the display will throw an exception when if the refresh +# is too soon) +print("waited correct time") + + +# Keep the display the same +while True: + time.sleep(10) diff --git a/examples/ssd1680_2.9_tricolor_breakout.py b/examples/ssd1680_2.9_tricolor_breakout.py index 922878d..bf81c93 100644 --- a/examples/ssd1680_2.9_tricolor_breakout.py +++ b/examples/ssd1680_2.9_tricolor_breakout.py @@ -42,7 +42,7 @@ g = displayio.Group() -pic = displayio.OnDiskBitmap("/display-ruler.bmp") +pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp") t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) diff --git a/examples/ssd1680_simpletest.py b/examples/ssd1680_simpletest.py index 8b3bcb9..e2b776a 100644 --- a/examples/ssd1680_simpletest.py +++ b/examples/ssd1680_simpletest.py @@ -52,7 +52,7 @@ # Note: Check the name of the file. Sometimes the dash is changed to an underscore -pic = displayio.OnDiskBitmap("/display-ruler.bmp") +pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp") t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) g.append(t)