Skip to content

Commit 0941ed9

Browse files
authored
Merge pull request #86 from joxl/jm/ssd1680b-driver-module
Move new SSD1680 driver variant to dedicated module and update examples
2 parents 25d0186 + a4db20c commit 0941ed9

11 files changed

+344
-77
lines changed

adafruit_epd/ssd1680.py

Lines changed: 5 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
from adafruit_epd.epd import Adafruit_EPD
1818

19+
# for backwards compatibility
20+
from adafruit_epd.ssd1680b import Adafruit_SSD1680B as Adafruit_SSD1680Z
21+
1922
try:
2023
"""Needed for type annotations"""
2124
import typing
@@ -71,13 +74,14 @@
7174
_SSD1680_OTP_PROGMODE = const(0x39)
7275
_SSD1680_WRITE_BORDER = const(0x3C)
7376
_SSD1680_END_OPTION = const(0x3F)
77+
_SSD1680_READ_RAM_OPT = const(0x41)
7478
_SSD1680_SET_RAMXPOS = const(0x44)
7579
_SSD1680_SET_RAMYPOS = const(0x45)
7680
_SSD1680_AUTOWRITE_RED = const(0x46)
7781
_SSD1680_AUTOWRITE_BW = const(0x47)
7882
_SSD1680_SET_RAMXCOUNT = const(0x4E)
7983
_SSD1680_SET_RAMYCOUNT = const(0x4F)
80-
_SSD1680_NOP = const(0xFF)
84+
_SSD1680_NOP = const(0x7F)
8185

8286

8387
class Adafruit_SSD1680(Adafruit_EPD):
@@ -212,72 +216,3 @@ def set_ram_address(self, x: int, y: int) -> None: # noqa: PLR6301, F841
212216
self.command(_SSD1680_SET_RAMXCOUNT, bytearray([0]))
213217
# Set RAM Y address counter
214218
self.command(_SSD1680_SET_RAMYCOUNT, bytearray([0, 0]))
215-
216-
217-
class Adafruit_SSD1680Z(Adafruit_SSD1680):
218-
"""Driver for SSD1680Z ePaper display, overriding SSD1680 settings."""
219-
220-
def __init__(self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin):
221-
# Call the parent class's __init__() to initialize attributes
222-
super().__init__(
223-
width,
224-
height,
225-
spi,
226-
cs_pin=cs_pin,
227-
dc_pin=dc_pin,
228-
sramcs_pin=sramcs_pin,
229-
rst_pin=rst_pin,
230-
busy_pin=busy_pin,
231-
)
232-
self.busy_pin = busy_pin # Ensure busy_pin is set
233-
234-
# pylint: enable=too-many-arguments, useless-parent-delegation
235-
236-
def power_up(self):
237-
"""Power up sequence specifically for SSD1680Z."""
238-
self.hardware_reset()
239-
self.busy_wait()
240-
self.command(_SSD1680_SW_RESET)
241-
self.busy_wait()
242-
243-
self.command(
244-
_SSD1680_DRIVER_CONTROL,
245-
bytearray([self._height & 0xFF, (self._height) >> 8, 0x00]),
246-
)
247-
self.command(_SSD1680_DATA_MODE, bytearray([0x03]))
248-
249-
# Set voltages
250-
self.command(_SSD1680_WRITE_VCOM_REG, bytearray([0x36]))
251-
self.command(_SSD1680_GATE_VOLTAGE, bytearray([0x17]))
252-
self.command(_SSD1680_SOURCE_VOLTAGE, bytearray([0x41, 0x00, 0x32]))
253-
254-
self.command(_SSD1680_SET_RAMXPOS, bytearray([0x00, (self._width // 8) - 1]))
255-
self.command(
256-
_SSD1680_SET_RAMYPOS,
257-
bytearray([0x00, 0x00, (self._height - 1) & 0xFF, (self._height - 1) >> 8]),
258-
)
259-
260-
# Set border waveform
261-
self.command(_SSD1680_WRITE_BORDER, bytearray([0x05]))
262-
263-
# Set ram X count
264-
self.command(_SSD1680_SET_RAMXCOUNT, bytearray([0x00]))
265-
# Set ram Y count
266-
self.command(_SSD1680_SET_RAMYCOUNT, bytearray([0x00, 0x00]))
267-
self.busy_wait()
268-
269-
def update(self):
270-
"""Update the display specifically for SSD1680Z."""
271-
self.command(_SSD1680_DISP_CTRL2, bytearray([0xF7])) # Full update for SSD1680Z
272-
self.command(_SSD1680_MASTER_ACTIVATE)
273-
self.busy_wait()
274-
if not self.busy_pin:
275-
time.sleep(3) # Wait for update to complete
276-
277-
def set_ram_address(self, x: int, y: int) -> None: # noqa: PLR6301, F841
278-
"""Set the RAM address location, not used on this chipset but required by
279-
the superclass"""
280-
# Set RAM X address counter
281-
self.command(_SSD1680_SET_RAMXCOUNT, bytearray([x]))
282-
# Set RAM Y address counter
283-
self.command(_SSD1680_SET_RAMYCOUNT, bytearray([y, y >> 8]))

adafruit_epd/ssd1680b.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# SPDX-FileCopyrightText: 2018 Dean Miller for Adafruit Industries
2+
# SPDX-FileCopyrightText: 2024 Joel Miller for Adafruit Industries
3+
#
4+
# SPDX-License-Identifier: MIT
5+
6+
"""
7+
`adafruit_epd.ssd1680b` - Adafruit SSD1680B - ePaper display driver
8+
====================================================================================
9+
CircuitPython driver for Adafruit SSD1680B displays (GDEY0213B74 display module)
10+
* Author(s): Melissa LeBlanc-Williams, Joel Miller, Mikey Sklar
11+
"""
12+
13+
import time
14+
15+
import adafruit_framebuf
16+
from micropython import const
17+
18+
from adafruit_epd.epd import Adafruit_EPD
19+
20+
try:
21+
"""Needed for type annotations"""
22+
import typing
23+
24+
from busio import SPI
25+
from digitalio import DigitalInOut
26+
from typing_extensions import Literal
27+
28+
except ImportError:
29+
pass
30+
31+
__version__ = "0.0.0+auto.0"
32+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
33+
34+
_SSD1680B_DRIVER_CONTROL = const(0x01)
35+
_SSD1680B_GATE_VOLTAGE = const(0x03)
36+
_SSD1680B_SOURCE_VOLTAGE = const(0x04)
37+
_SSD1680B_INIT_SETTING = const(0x08)
38+
_SSD1680B_INIT_WRITE_REG = const(0x09)
39+
_SSD1680B_INIT_READ_REG = const(0x0A)
40+
_SSD1680B_BOOSTER_SOFT_START = const(0x0C)
41+
_SSD1680B_DEEP_SLEEP = const(0x10)
42+
_SSD1680B_DATA_MODE = const(0x11)
43+
_SSD1680B_SW_RESET = const(0x12)
44+
_SSD1680B_HV_DETECT = const(0x14)
45+
_SSD1680B_VCI_DETECT = const(0x15)
46+
_SSD1680B_TEMP_CONTROL = const(0x18)
47+
_SSD1680B_TEMP_WRITE = const(0x1A)
48+
_SSD1680B_TEMP_READ = const(0x1B)
49+
_SSD1680B_EXTTEMP_WRITE = const(0x1C)
50+
_SSD1680B_MASTER_ACTIVATE = const(0x20)
51+
_SSD1680B_DISP_CTRL1 = const(0x21)
52+
_SSD1680B_DISP_CTRL2 = const(0x22)
53+
_SSD1680B_WRITE_BWRAM = const(0x24)
54+
_SSD1680B_WRITE_REDRAM = const(0x26)
55+
_SSD1680B_READ_RAM = const(0x27)
56+
_SSD1680B_VCOM_SENSE = const(0x28)
57+
_SSD1680B_VCOM_DURATION = const(0x29)
58+
_SSD1680B_WRITE_VCOM_OTP = const(0x2A)
59+
_SSD1680B_WRITE_VCOM_CTRL = const(0x2B)
60+
_SSD1680B_WRITE_VCOM_REG = const(0x2C)
61+
_SSD1680B_READ_OTP = const(0x2D)
62+
_SSD1680B_READ_USERID = const(0x2E)
63+
_SSD1680B_READ_STATUS = const(0x2F)
64+
_SSD1680B_WRITE_WS_OTP = const(0x30)
65+
_SSD1680B_LOAD_WS_OTP = const(0x31)
66+
_SSD1680B_WRITE_LUT = const(0x32)
67+
_SSD1680B_CRC_CALC = const(0x34)
68+
_SSD1680B_CRC_READ = const(0x35)
69+
_SSD1680B_PROG_OTP = const(0x36)
70+
_SSD1680B_WRITE_DISPLAY_OPT = const(0x37)
71+
_SSD1680B_WRITE_USERID = const(0x38)
72+
_SSD1680B_OTP_PROGMODE = const(0x39)
73+
_SSD1680B_WRITE_BORDER = const(0x3C)
74+
_SSD1680B_END_OPTION = const(0x3F)
75+
_SSD1680B_READ_RAM_OPT = const(0x41)
76+
_SSD1680B_SET_RAMXPOS = const(0x44)
77+
_SSD1680B_SET_RAMYPOS = const(0x45)
78+
_SSD1680B_AUTOWRITE_RED = const(0x46)
79+
_SSD1680B_AUTOWRITE_BW = const(0x47)
80+
_SSD1680B_SET_RAMXCOUNT = const(0x4E)
81+
_SSD1680B_SET_RAMYCOUNT = const(0x4F)
82+
_SSD1680B_NOP = const(0x7F)
83+
84+
85+
class Adafruit_SSD1680B(Adafruit_EPD):
86+
"""
87+
Driver class for Adafruit SSD1680 "B" ePaper displays. This class is meant
88+
to be used with Adafruit boards equipped with an SSD1680 driver chip paired
89+
with a GDEY0213B74 display module.
90+
"""
91+
92+
def __init__(
93+
self,
94+
width: int,
95+
height: int,
96+
spi: SPI,
97+
*,
98+
cs_pin: DigitalInOut,
99+
dc_pin: DigitalInOut,
100+
sramcs_pin: DigitalInOut,
101+
rst_pin: DigitalInOut,
102+
busy_pin: DigitalInOut,
103+
) -> None:
104+
super().__init__(width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin)
105+
106+
stride = width
107+
if stride % 8 != 0:
108+
stride += 8 - stride % 8
109+
110+
self._buffer1_size = int(stride * height / 8)
111+
self._buffer2_size = self._buffer1_size
112+
113+
if sramcs_pin:
114+
self._buffer1 = self.sram.get_view(0)
115+
self._buffer2 = self.sram.get_view(self._buffer1_size)
116+
else:
117+
self._buffer1 = bytearray(self._buffer1_size)
118+
self._buffer2 = bytearray(self._buffer2_size)
119+
120+
self._framebuf1 = adafruit_framebuf.FrameBuffer(
121+
self._buffer1,
122+
width,
123+
height,
124+
stride=stride,
125+
buf_format=adafruit_framebuf.MHMSB,
126+
)
127+
self._framebuf2 = adafruit_framebuf.FrameBuffer(
128+
self._buffer2,
129+
width,
130+
height,
131+
stride=stride,
132+
buf_format=adafruit_framebuf.MHMSB,
133+
)
134+
self.set_black_buffer(0, True)
135+
self.set_color_buffer(1, False)
136+
137+
def begin(self, reset: bool = True) -> None:
138+
"""Begin communication with the display and set basic settings"""
139+
if reset:
140+
self.hardware_reset()
141+
self.power_down()
142+
143+
def busy_wait(self) -> None:
144+
"""
145+
Wait for display to be done with current task, either by polling the
146+
busy pin, or pausing
147+
"""
148+
if self._busy:
149+
while self._busy.value:
150+
time.sleep(0.01)
151+
else:
152+
time.sleep(0.5)
153+
154+
def power_up(self) -> None:
155+
"""Power up the display in preparation for writing RAM and updating"""
156+
self.hardware_reset()
157+
self.busy_wait()
158+
self.command(_SSD1680B_SW_RESET)
159+
self.busy_wait()
160+
# driver output control
161+
self.command(
162+
_SSD1680B_DRIVER_CONTROL,
163+
bytearray([self._height, self._height >> 8, 0x00]),
164+
)
165+
# data entry mode
166+
self.command(_SSD1680B_DATA_MODE, bytearray([0x03]))
167+
168+
# Set voltages
169+
self.command(_SSD1680B_WRITE_VCOM_REG, bytearray([0x36]))
170+
self.command(_SSD1680B_GATE_VOLTAGE, bytearray([0x17]))
171+
self.command(_SSD1680B_SOURCE_VOLTAGE, bytearray([0x41, 0x00, 0x32]))
172+
173+
# Set ram X start/end postion
174+
self.command(_SSD1680B_SET_RAMXPOS, bytearray([0x00, self._width // 8]))
175+
# Set ram Y start/end postion
176+
self.command(
177+
_SSD1680B_SET_RAMYPOS,
178+
bytearray([0, 0, self._height, self._height >> 8]),
179+
)
180+
# Set border waveform
181+
self.command(_SSD1680B_WRITE_BORDER, bytearray([0x05]))
182+
183+
# Set ram X count
184+
self.command(_SSD1680B_SET_RAMXCOUNT, bytearray([0x01]))
185+
# Set ram Y count
186+
self.command(_SSD1680B_SET_RAMYCOUNT, bytearray([self._height, 0]))
187+
self.busy_wait()
188+
189+
def power_down(self) -> None:
190+
"""Power down the display - required when not actively displaying!"""
191+
self.command(_SSD1680B_DEEP_SLEEP, bytearray([0x01]))
192+
time.sleep(0.1)
193+
194+
def update(self) -> None:
195+
"""Update the display from internal memory"""
196+
self.command(_SSD1680B_DISP_CTRL2, bytearray([0xF7]))
197+
self.command(_SSD1680B_MASTER_ACTIVATE)
198+
self.busy_wait()
199+
if not self._busy:
200+
time.sleep(3) # wait 3 seconds
201+
202+
def write_ram(self, index: Literal[0, 1]) -> int:
203+
"""
204+
Send the one byte command for starting the RAM write process. Returns
205+
the byte read at the same time over SPI. index is the RAM buffer, can
206+
be 0 or 1 for tri-color displays.
207+
"""
208+
if index == 0:
209+
return self.command(_SSD1680B_WRITE_BWRAM, end=False)
210+
if index == 1:
211+
return self.command(_SSD1680B_WRITE_REDRAM, end=False)
212+
raise RuntimeError("RAM index must be 0 or 1")
213+
214+
def set_ram_address(self, x: int, y: int) -> None: # noqa: PLR6301, F841
215+
"""Set the RAM address location"""
216+
# Set RAM X address counter
217+
self.command(_SSD1680B_SET_RAMXCOUNT, bytearray([x]))
218+
# Set RAM Y address counter
219+
self.command(_SSD1680B_SET_RAMYCOUNT, bytearray([y, y >> 8]))

examples/epd_bitmap.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from adafruit_epd.ssd1608 import Adafruit_SSD1608
1414
from adafruit_epd.ssd1675 import Adafruit_SSD1675
1515
from adafruit_epd.ssd1680 import Adafruit_SSD1680
16+
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
1617
from adafruit_epd.ssd1681 import Adafruit_SSD1681
1718
from adafruit_epd.ssd1683 import Adafruit_SSD1683
1819
from adafruit_epd.uc8151d import Adafruit_UC8151D
@@ -31,6 +32,7 @@
3132
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
3233
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
3334
# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display
35+
# display = Adafruit_SSD1680B(122, 250 # Newer 2.13" HD (Tri-color or mono) with GDEY0213B74
3436
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
3537
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
3638
# display = Adafruit_EK79686(176, 264, # 2.7" Tri-color display

examples/epd_blinka.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from adafruit_epd.ssd1675 import Adafruit_SSD1675
1717
from adafruit_epd.ssd1675b import Adafruit_SSD1675B
1818
from adafruit_epd.ssd1680 import Adafruit_SSD1680
19+
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
1920
from adafruit_epd.ssd1681 import Adafruit_SSD1681
2021
from adafruit_epd.ssd1683 import Adafruit_SSD1683
2122
from adafruit_epd.uc8151d import Adafruit_UC8151D
@@ -35,6 +36,7 @@
3536
# display = Adafruit_JD79661(122, 150, # 2.13" Quad-color display
3637
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
3738
# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display
39+
# display = Adafruit_SSD1680B(122, 250 # Newer 2.13" HD (Tri-color or mono) with GDEY0213B74
3840
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
3941
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
4042
# display = Adafruit_SSD1683(400, 300, # 4.2" 300x400 Tri-Color display

examples/epd_bonnet.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
from adafruit_epd.epd import Adafruit_EPD
1212
from adafruit_epd.ssd1675b import Adafruit_SSD1675B
13-
from adafruit_epd.ssd1680 import Adafruit_SSD1680, Adafruit_SSD1680Z
13+
from adafruit_epd.ssd1680 import Adafruit_SSD1680
14+
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
1415

1516
# create two buttons
1617
switch1 = DigitalInOut(board.D6)
@@ -28,7 +29,7 @@
2829
# give them all to our driver
2930
# display = Adafruit_SSD1675B( # Oldest 2.13" Bonnet
3031
# display = Adafruit_SSD1680( # Old 2.13" Bonnet
31-
display = Adafruit_SSD1680Z( # Newer 2.13" mono display
32+
display = Adafruit_SSD1680B( # Newer 2.13" HD (Tri-color or mono) with GDEY0213B74
3233
122,
3334
250,
3435
spi, # 2.13" HD mono display (rev B)
89.6 KB
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-FileCopyrightText: 2024 Joel Miller for Adafruit Industries
2+
# SPDX-License-Identifier: MIT

examples/epd_pillow_demo.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
from adafruit_epd.jd79661 import Adafruit_JD79661
1919
from adafruit_epd.ssd1608 import Adafruit_SSD1608
2020
from adafruit_epd.ssd1675 import Adafruit_SSD1675
21-
from adafruit_epd.ssd1680 import Adafruit_SSD1680, Adafruit_SSD1680Z
21+
from adafruit_epd.ssd1680 import Adafruit_SSD1680
22+
from adafruit_epd.ssd1680b import Adafruit_SSD1680B
2223
from adafruit_epd.ssd1681 import Adafruit_SSD1681
2324
from adafruit_epd.ssd1683 import Adafruit_SSD1683
2425
from adafruit_epd.uc8151d import Adafruit_UC8151D
@@ -49,7 +50,7 @@
4950
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
5051
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
5152
# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color or mono display
52-
# display = Adafruit_SSD1680Z(122, 250, # Newer 2.13" mono display
53+
# display = Adafruit_SSD1680B(122, 250 # Newer 2.13" HD (Tri-color or mono) with GDEY0213B74
5354
# display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display
5455
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
5556
# display = Adafruit_EK79686(176, 264, # 2.7" Tri-color display

0 commit comments

Comments
 (0)