Skip to content

Commit 76814b0

Browse files
committed
1680z sub-class
dropped separate ssd1680z lib for a combined 1680 + 1680z.
1 parent d17ab9f commit 76814b0

File tree

2 files changed

+80
-360
lines changed

2 files changed

+80
-360
lines changed

adafruit_epd/ssd1680.py

Lines changed: 80 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -6,208 +6,136 @@
66
`adafruit_epd.ssd1680` - Adafruit SSD1680 - ePaper display driver
77
====================================================================================
88
CircuitPython driver for Adafruit SSD1680 display breakouts
9-
* Author(s): Melissa LeBlanc-Williams
9+
* Author(s): Melissa LeBlanc-Williams Mikey Sklar
1010
"""
11-
12-
import time
1311
from micropython import const
1412
import adafruit_framebuf
1513
from adafruit_epd.epd import Adafruit_EPD
14+
import time
1615

17-
try:
18-
"""Needed for type annotations"""
19-
import typing # pylint: disable=unused-import
20-
from typing_extensions import Literal
21-
from busio import SPI
22-
from digitalio import DigitalInOut
23-
24-
except ImportError:
25-
pass
26-
27-
__version__ = "0.0.0+auto.0"
28-
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
29-
16+
# Define all SSD1680 constants
3017
_SSD1680_DRIVER_CONTROL = const(0x01)
31-
_SSD1680_GATE_VOLTAGE = const(0x03)
32-
_SSD1680_SOURCE_VOLTAGE = const(0x04)
33-
_SSD1680_INIT_SETTING = const(0x08)
34-
_SSD1680_INIT_WRITE_REG = const(0x09)
35-
_SSD1680_INIT_READ_REG = const(0x0A)
36-
_SSD1680_BOOSTER_SOFT_START = const(0x0C)
37-
_SSD1680_DEEP_SLEEP = const(0x10)
3818
_SSD1680_DATA_MODE = const(0x11)
3919
_SSD1680_SW_RESET = const(0x12)
40-
_SSD1680_HV_DETECT = const(0x14)
41-
_SSD1680_VCI_DETECT = const(0x15)
42-
_SSD1680_TEMP_CONTROL = const(0x18)
43-
_SSD1680_TEMP_WRITE = const(0x1A)
44-
_SSD1680_TEMP_READ = const(0x1B)
45-
_SSD1680_EXTTEMP_WRITE = const(0x1C)
46-
_SSD1680_MASTER_ACTIVATE = const(0x20)
47-
_SSD1680_DISP_CTRL1 = const(0x21)
48-
_SSD1680_DISP_CTRL2 = const(0x22)
49-
_SSD1680_WRITE_BWRAM = const(0x24)
50-
_SSD1680_WRITE_REDRAM = const(0x26)
51-
_SSD1680_READ_RAM = const(0x27)
52-
_SSD1680_VCOM_SENSE = const(0x28)
53-
_SSD1680_VCOM_DURATION = const(0x29)
54-
_SSD1680_WRITE_VCOM_OTP = const(0x2A)
55-
_SSD1680_WRITE_VCOM_CTRL = const(0x2B)
56-
_SSD1680_WRITE_VCOM_REG = const(0x2C)
57-
_SSD1680_READ_OTP = const(0x2D)
58-
_SSD1680_READ_USERID = const(0x2E)
59-
_SSD1680_READ_STATUS = const(0x2F)
60-
_SSD1680_WRITE_WS_OTP = const(0x30)
61-
_SSD1680_LOAD_WS_OTP = const(0x31)
62-
_SSD1680_WRITE_LUT = const(0x32)
63-
_SSD1680_CRC_CALC = const(0x34)
64-
_SSD1680_CRC_READ = const(0x35)
65-
_SSD1680_PROG_OTP = const(0x36)
66-
_SSD1680_WRITE_DISPLAY_OPT = const(0x37)
67-
_SSD1680_WRITE_USERID = const(0x38)
68-
_SSD1680_OTP_PROGMODE = const(0x39)
69-
_SSD1680_WRITE_BORDER = const(0x3C)
70-
_SSD1680_END_OPTION = const(0x3F)
7120
_SSD1680_SET_RAMXPOS = const(0x44)
7221
_SSD1680_SET_RAMYPOS = const(0x45)
73-
_SSD1680_AUTOWRITE_RED = const(0x46)
74-
_SSD1680_AUTOWRITE_BW = const(0x47)
22+
_SSD1680_WRITE_BWRAM = const(0x24)
23+
_SSD1680_WRITE_REDRAM = const(0x26)
7524
_SSD1680_SET_RAMXCOUNT = const(0x4E)
7625
_SSD1680_SET_RAMYCOUNT = const(0x4F)
77-
_SSD1680_NOP = const(0xFF)
78-
26+
_SSD1680_DISP_CTRL2 = const(0x22)
27+
_SSD1680_MASTER_ACTIVATE = const(0x20)
28+
_SSD1680_DEEP_SLEEP = const(0x10)
7929

8030
class Adafruit_SSD1680(Adafruit_EPD):
81-
"""driver class for Adafruit SSD1680 ePaper display breakouts"""
82-
83-
# pylint: disable=too-many-arguments
84-
def __init__(
85-
self,
86-
width: int,
87-
height: int,
88-
spi: SPI,
89-
*,
90-
cs_pin: DigitalInOut,
91-
dc_pin: DigitalInOut,
92-
sramcs_pin: DigitalInOut,
93-
rst_pin: DigitalInOut,
94-
busy_pin: DigitalInOut
95-
) -> None:
96-
super().__init__(
97-
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
98-
)
31+
"""Driver for SSD1680 ePaper display, default driver."""
32+
33+
def __init__(self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin):
34+
super().__init__(width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin)
9935

36+
self.cs_pin = cs_pin
37+
self.dc_pin = dc_pin
38+
self.sramcs_pin = sramcs_pin
39+
self.rst_pin = rst_pin
40+
self.busy_pin = busy_pin
41+
42+
self.initialize_buffers(width, height)
43+
44+
def initialize_buffers(self, width, height):
10045
stride = width
10146
if stride % 8 != 0:
10247
stride += 8 - stride % 8
10348

10449
self._buffer1_size = int(stride * height / 8)
10550
self._buffer2_size = self._buffer1_size
10651

107-
if sramcs_pin:
52+
if self.sramcs_pin:
10853
self._buffer1 = self.sram.get_view(0)
10954
self._buffer2 = self.sram.get_view(self._buffer1_size)
11055
else:
11156
self._buffer1 = bytearray(self._buffer1_size)
11257
self._buffer2 = bytearray(self._buffer2_size)
11358

11459
self._framebuf1 = adafruit_framebuf.FrameBuffer(
115-
self._buffer1,
116-
width,
117-
height,
118-
stride=stride,
119-
buf_format=adafruit_framebuf.MHMSB,
60+
self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
12061
)
12162
self._framebuf2 = adafruit_framebuf.FrameBuffer(
122-
self._buffer2,
123-
width,
124-
height,
125-
stride=stride,
126-
buf_format=adafruit_framebuf.MHMSB,
63+
self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB
12764
)
12865
self.set_black_buffer(0, True)
12966
self.set_color_buffer(1, False)
130-
# pylint: enable=too-many-arguments
131-
132-
def begin(self, reset: bool = True) -> None:
133-
"""Begin communication with the display and set basic settings"""
134-
if reset:
135-
self.hardware_reset()
136-
self.power_down()
137-
138-
def busy_wait(self) -> None:
139-
"""Wait for display to be done with current task, either by polling the
140-
busy pin, or pausing"""
141-
if self._busy:
142-
while self._busy.value:
67+
68+
def busy_wait(self):
69+
"""Wait for the display to complete its current task."""
70+
if self.busy_pin:
71+
while self.busy_pin.value:
14372
time.sleep(0.01)
14473
else:
14574
time.sleep(0.5)
14675

147-
def power_up(self) -> None:
148-
"""Power up the display in preparation for writing RAM and updating"""
76+
def power_up(self):
77+
"""Power up sequence for SSD1680."""
14978
self.hardware_reset()
15079
self.busy_wait()
15180
self.command(_SSD1680_SW_RESET)
15281
self.busy_wait()
153-
# driver output control
154-
self.command(
155-
_SSD1680_DRIVER_CONTROL,
156-
bytearray([self._height - 1, (self._height - 1) >> 8, 0x00]),
157-
)
158-
# data entry mode
82+
83+
self.command(_SSD1680_DRIVER_CONTROL, bytearray([self._height - 1, (self._height - 1) >> 8, 0x00]))
15984
self.command(_SSD1680_DATA_MODE, bytearray([0x03]))
85+
self.command(_SSD1680_SET_RAMXPOS, bytearray([0x01, 0x10]))
86+
self.command(_SSD1680_SET_RAMYPOS, bytearray([0, 0, self._height - 1, (self._height - 1) >> 8]))
16087

161-
# Set voltages
162-
self.command(_SSD1680_WRITE_VCOM_REG, bytearray([0x36]))
163-
self.command(_SSD1680_GATE_VOLTAGE, bytearray([0x17]))
164-
self.command(_SSD1680_SOURCE_VOLTAGE, bytearray([0x41, 0x00, 0x32]))
88+
def write_ram(self, index):
89+
"""Write to RAM for SSD1680."""
90+
if index == 0:
91+
return self.command(_SSD1680_WRITE_BWRAM, end=False)
92+
elif index == 1:
93+
return self.command(_SSD1680_WRITE_REDRAM, end=False)
94+
else:
95+
raise RuntimeError("RAM index must be 0 or 1")
16596

166-
# Set ram X start/end postion
167-
self.command(_SSD1680_SET_RAMXPOS, bytearray([0x01, 0x10]))
168-
# Set ram Y start/end postion
169-
self.command(
170-
_SSD1680_SET_RAMYPOS,
171-
bytearray([0, 0, self._height - 1, (self._height - 1) >> 8]),
172-
)
173-
# Set border waveform
174-
self.command(_SSD1680_WRITE_BORDER, bytearray([0x05]))
97+
def set_ram_address(self, x, y):
98+
"""Set RAM address location for SSD1680."""
99+
self.command(_SSD1680_SET_RAMXCOUNT, bytearray([x + 1]))
100+
self.command(_SSD1680_SET_RAMYCOUNT, bytearray([y, y >> 8]))
175101

176-
# Set ram X count
177-
self.command(_SSD1680_SET_RAMXCOUNT, bytearray([0x01]))
178-
# Set ram Y count
179-
self.command(_SSD1680_SET_RAMYCOUNT, bytearray([self._height - 1, 0]))
102+
def update(self):
103+
"""Update the display from internal memory."""
104+
self.command(_SSD1680_DISP_CTRL2, bytearray([0xF4])) # Full update
105+
self.command(_SSD1680_MASTER_ACTIVATE)
180106
self.busy_wait()
107+
if not self.busy_pin:
108+
time.sleep(3) # Wait for update to complete
181109

182-
def power_down(self) -> None:
183-
"""Power down the display - required when not actively displaying!"""
110+
def power_down(self):
111+
"""Power down the display."""
184112
self.command(_SSD1680_DEEP_SLEEP, bytearray([0x01]))
185113
time.sleep(0.1)
186114

187-
def update(self) -> None:
188-
"""Update the display from internal memory"""
189-
self.command(_SSD1680_DISP_CTRL2, bytearray([0xF4]))
190-
self.command(_SSD1680_MASTER_ACTIVATE)
115+
116+
class Adafruit_SSD1680Z(Adafruit_SSD1680):
117+
"""Driver for SSD1680Z ePaper display, overriding SSD1680 settings."""
118+
119+
def __init__(self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin):
120+
super().__init__(width, height, spi, cs_pin=cs_pin, dc_pin=dc_pin,
121+
sramcs_pin=sramcs_pin, rst_pin=rst_pin, busy_pin=busy_pin)
122+
123+
def power_up(self):
124+
"""Power up sequence specifically for SSD1680Z."""
125+
self.hardware_reset()
126+
self.busy_wait()
127+
self.command(_SSD1680_SW_RESET)
191128
self.busy_wait()
192-
if not self._busy:
193-
time.sleep(3) # wait 3 seconds
194129

195-
def write_ram(self, index: Literal[0, 1]) -> int:
196-
"""Send the one byte command for starting the RAM write process. Returns
197-
the byte read at the same time over SPI. index is the RAM buffer, can be
198-
0 or 1 for tri-color displays."""
199-
if index == 0:
200-
return self.command(_SSD1680_WRITE_BWRAM, end=False)
201-
if index == 1:
202-
return self.command(_SSD1680_WRITE_REDRAM, end=False)
203-
raise RuntimeError("RAM index must be 0 or 1")
204-
205-
def set_ram_address(
206-
self, x: int, y: int
207-
) -> None: # pylint: disable=unused-argument, no-self-use
208-
"""Set the RAM address location, not used on this chipset but required by
209-
the superclass"""
210-
# Set RAM X address counter
211-
self.command(_SSD1680_SET_RAMXCOUNT, bytearray([x + 1]))
212-
# Set RAM Y address counter
213-
self.command(_SSD1680_SET_RAMYCOUNT, bytearray([y, y >> 8]))
130+
self.command(_SSD1680_DRIVER_CONTROL, bytearray([self._height - 1, (self._height - 1) >> 8, 0x00]))
131+
self.command(_SSD1680_DATA_MODE, bytearray([0x03]))
132+
self.command(_SSD1680_SET_RAMXPOS, bytearray([0x00, (self._width // 8) - 1]))
133+
self.command(_SSD1680_SET_RAMYPOS, bytearray([0x00, 0x00, self._height - 1, (self._height - 1) >> 8]))
134+
135+
def update(self):
136+
"""Update the display specifically for SSD1680Z."""
137+
self.command(_SSD1680_DISP_CTRL2, bytearray([0xF7])) # Full update for SSD1680Z
138+
self.command(_SSD1680_MASTER_ACTIVATE)
139+
self.busy_wait()
140+
if not self.busy_pin:
141+
time.sleep(3) # Wait for update to complete

0 commit comments

Comments
 (0)