Skip to content

Commit d6aa01c

Browse files
authored
Merge pull request #36 from tannewt/magtag2025
Support newer 2.9" grayscale
2 parents 8731c1b + ddd3f0f commit d6aa01c

11 files changed

+184
-20
lines changed

adafruit_ssd1680.py

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,20 @@
4242
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SSD1680.git"
4343

4444
_START_SEQUENCE = (
45-
b"\x12\x80\x14" # soft reset and wait 20ms
46-
b"\x11\x01\x03" # Ram data entry mode
47-
b"\x3c\x01\x05" # border color
48-
b"\x2c\x01\x36" # Set vcom voltage
49-
b"\x03\x01\x17" # Set gate voltage
50-
b"\x04\x03\x41\x00\x32" # Set source voltage
51-
b"\x4e\x01\x01" # ram x count
52-
b"\x4f\x02\x00\x00" # ram y count
53-
b"\x01\x03\x00\x00\x00" # set display size
54-
b"\x22\x01\xf4" # display update mode
45+
b"\x12\x80\x00\x14" # soft reset and wait 20ms
46+
b"\x11\x00\x01\x03" # Ram data entry mode
47+
b"\x3c\x00\x01\x03" # border color
48+
b"\x2c\x00\x01\x36" # Set vcom voltage
49+
b"\x03\x00\x01\x17" # Set gate voltage
50+
b"\x04\x00\x03\x41\xae\x32" # Set source voltage
51+
b"\x4e\x00\x01\x01" # ram x count
52+
b"\x4f\x00\x02\x00\x00" # ram y count
53+
b"\x01\x00\x03\x00\x00\x00" # set display size
5554
)
5655

57-
_STOP_SEQUENCE = b"\x10\x81\x01\x64" # Deep Sleep
56+
_DISPLAY_UPDATE_MODE = b"\x22\x00\x01\xf4" # display update mode
57+
58+
_STOP_SEQUENCE = b"\x10\x80\x01\x01\x64" # Deep Sleep
5859

5960

6061
# pylint: disable=too-few-public-methods
@@ -72,9 +73,17 @@ class SSD1680(EPaperDisplay):
7273
Display height
7374
* *rotation* (``int``) --
7475
Display rotation
76+
* *vcom* (``int``) --
77+
Set vcom voltage register value
78+
* *vsh2* (``int``) --
79+
Set vsh2 voltage register value
80+
* *custom_lut* (``bytes``) --
81+
Custom look-up table settings
7582
"""
7683

77-
def __init__(self, bus: FourWire, **kwargs) -> None:
84+
def __init__(
85+
self, bus: FourWire, vcom: int = 0x36, vsh2: int = 0x00, custom_lut: bytes = b"", **kwargs
86+
) -> None:
7887
if "colstart" not in kwargs:
7988
kwargs["colstart"] = 8
8089
stop_sequence = bytearray(_STOP_SEQUENCE)
@@ -83,14 +92,23 @@ def __init__(self, bus: FourWire, **kwargs) -> None:
8392
except RuntimeError:
8493
# No reset pin defined, so no deep sleeping
8594
stop_sequence = b""
95+
load_lut = b""
96+
display_update_mode = bytearray(_DISPLAY_UPDATE_MODE)
97+
if custom_lut:
98+
load_lut = b"\x32" + len(custom_lut).to_bytes(2) + custom_lut
99+
display_update_mode[-1] = 0xC7
100+
101+
start_sequence = bytearray(_START_SEQUENCE + load_lut + display_update_mode)
102+
start_sequence[15] = vcom
103+
104+
start_sequence[24] = vsh2
86105

87-
start_sequence = bytearray(_START_SEQUENCE)
88106
width = kwargs["width"]
89107
height = kwargs["height"]
90108
if "rotation" in kwargs and kwargs["rotation"] % 180 != 90:
91109
width, height = height, width
92-
start_sequence[29] = (width - 1) & 0xFF
93-
start_sequence[30] = ((width - 1) >> 8) & 0xFF
110+
start_sequence[38] = (width - 1) & 0xFF
111+
start_sequence[39] = ((width - 1) >> 8) & 0xFF
94112

95113
super().__init__(
96114
bus,
@@ -109,4 +127,5 @@ def __init__(self, bus: FourWire, **kwargs) -> None:
109127
refresh_display_command=0x20,
110128
always_toggle_chip_select=False,
111129
address_little_endian=True,
130+
two_byte_sequence_length=True,
112131
)

examples/display-ruler-640x360.bmp

225 KB
Binary file not shown.

examples/display-ruler.bmp

-352 KB
Binary file not shown.

examples/ssd1680_2.13_featherwing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
g = displayio.Group()
4444

4545

46-
pic = displayio.OnDiskBitmap("/display-ruler.bmp")
46+
pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp")
4747

4848
t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
4949

examples/ssd1680_2.13_mono_eink_bonnet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
g = displayio.Group()
5151

5252

53-
pic = displayio.OnDiskBitmap("/display-ruler.bmp")
53+
pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp")
5454
t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
5555
g.append(t)
5656

examples/ssd1680_2.13_tricolor_breakout.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
g = displayio.Group()
4343

4444

45-
pic = displayio.OnDiskBitmap("/display-ruler.bmp")
45+
pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp")
4646

4747
t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
4848

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# SPDX-FileCopyrightText: 2025 Scott Shawcroft, written for Adafruit Industries
2+
# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries
3+
#
4+
# SPDX-License-Identifier: Unlicense
5+
6+
"""Simple test script for 2.9" 296x128 display. This example runs it in 2bit grayscale mode."""
7+
8+
import time
9+
10+
import board
11+
import busio
12+
import displayio
13+
from fourwire import FourWire
14+
15+
import adafruit_ssd1680
16+
17+
displayio.release_displays()
18+
19+
# This pinout works on a MagTag with the newer screen and may need to be altered for other boards.
20+
spi = busio.SPI(board.EPD_SCK, board.EPD_MOSI) # Uses SCK and MOSI
21+
epd_cs = board.EPD_CS
22+
epd_dc = board.EPD_DC
23+
epd_reset = board.EPD_RESET
24+
epd_busy = board.EPD_BUSY
25+
26+
display_bus = FourWire(spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000)
27+
time.sleep(1)
28+
29+
ti_290mfgn_gray4_lut_code = (
30+
b"\x2a\x60\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L0
31+
b"\x20\x60\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L1
32+
b"\x28\x60\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L2
33+
b"\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L3
34+
b"\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # VS L4
35+
b"\x00\x02\x00\x05\x14\x00\x00" # TP, SR, RP of Group0
36+
b"\x1e\x1e\x00\x00\x00\x00\x01" # TP, SR, RP of Group1
37+
b"\x00\x02\x00\x05\x14\x00\x00" # TP, SR, RP of Group2
38+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group3
39+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group4
40+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group5
41+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group6
42+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group7
43+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group8
44+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group9
45+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group10
46+
b"\x00\x00\x00\x00\x00\x00\x00" # TP, SR, RP of Group11
47+
b"\x24\x22\x22\x22\x23\x32\x00\x00\x00" # FR, XON
48+
)
49+
50+
if len(ti_290mfgn_gray4_lut_code) != 153:
51+
raise ValueError("ti_290mfgn_gray4_lut_code is not the correct length")
52+
53+
# For issues with display not updating top/bottom rows correctly set colstart to 8, 0, or -8
54+
display = adafruit_ssd1680.SSD1680(
55+
display_bus,
56+
width=296,
57+
height=128,
58+
busy_pin=epd_busy,
59+
rotation=270,
60+
colstart=0,
61+
vcom=0x28,
62+
vsh2=0xAE,
63+
custom_lut=ti_290mfgn_gray4_lut_code,
64+
grayscale=True,
65+
)
66+
67+
g = displayio.Group()
68+
69+
pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp")
70+
t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
71+
g.append(t)
72+
73+
display.root_group = g
74+
75+
display.refresh()
76+
77+
print("refreshed")
78+
79+
time.sleep(display.time_to_refresh + 5)
80+
# Always refresh a little longer. It's not a problem to refresh
81+
# a few seconds more, but it's terrible to refresh too early
82+
# (the display will throw an exception when if the refresh
83+
# is too soon)
84+
print("waited correct time")
85+
86+
87+
# Keep the display the same
88+
while True:
89+
time.sleep(10)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# SPDX-FileCopyrightText: 2025 Scott Shawcroft, written for Adafruit Industries
2+
# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries
3+
#
4+
# SPDX-License-Identifier: Unlicense
5+
6+
"""Simple test script for 2.9" 296x128 display. This example runs it in mono mode."""
7+
8+
import time
9+
10+
import board
11+
import busio
12+
import displayio
13+
from fourwire import FourWire
14+
15+
import adafruit_ssd1680
16+
17+
displayio.release_displays()
18+
19+
# This pinout works on a MagTag with the newer screen and may need to be altered for other boards.
20+
spi = busio.SPI(board.EPD_SCK, board.EPD_MOSI) # Uses SCK and MOSI
21+
epd_cs = board.EPD_CS
22+
epd_dc = board.EPD_DC
23+
epd_reset = board.EPD_RESET
24+
epd_busy = board.EPD_BUSY
25+
26+
display_bus = FourWire(spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000)
27+
time.sleep(1)
28+
29+
# For issues with display not updating top/bottom rows correctly set colstart to 8, 0, or -8
30+
display = adafruit_ssd1680.SSD1680(
31+
display_bus, width=296, height=128, busy_pin=epd_busy, rotation=270, colstart=0
32+
)
33+
34+
g = displayio.Group()
35+
36+
pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp")
37+
t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
38+
g.append(t)
39+
40+
display.root_group = g
41+
42+
display.refresh()
43+
44+
print("refreshed")
45+
46+
time.sleep(display.time_to_refresh + 5)
47+
# Always refresh a little longer. It's not a problem to refresh
48+
# a few seconds more, but it's terrible to refresh too early
49+
# (the display will throw an exception when if the refresh
50+
# is too soon)
51+
print("waited correct time")
52+
53+
54+
# Keep the display the same
55+
while True:
56+
time.sleep(10)

examples/ssd1680_2.9_tricolor_breakout.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
g = displayio.Group()
4343

4444

45-
pic = displayio.OnDiskBitmap("/display-ruler.bmp")
45+
pic = displayio.OnDiskBitmap("/display-ruler-640x360.bmp")
4646

4747
t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader)
4848

0 commit comments

Comments
 (0)