Skip to content

Commit 29cfedc

Browse files
committed
back to original
plus 1680Z subclass at bottom
1 parent a3b3346 commit 29cfedc

File tree

1 file changed

+137
-53
lines changed

1 file changed

+137
-53
lines changed

adafruit_epd/ssd1680.py

Lines changed: 137 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,129 +6,212 @@
66
`adafruit_epd.ssd1680` - Adafruit SSD1680 - ePaper display driver
77
====================================================================================
88
CircuitPython driver for Adafruit SSD1680 display breakouts
9-
* Author(s): Melissa LeBlanc-Williams Mikey Sklar
9+
* Author(s): Melissa LeBlanc-Williams
1010
"""
11+
1112
import time
1213
from micropython import const
1314
import adafruit_framebuf
1415
from adafruit_epd.epd import Adafruit_EPD
1516

16-
# Define all SSD1680 constants
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+
1730
_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)
1838
_SSD1680_DATA_MODE = const(0x11)
1939
_SSD1680_SW_RESET = const(0x12)
20-
_SSD1680_SET_RAMXPOS = const(0x44)
21-
_SSD1680_SET_RAMYPOS = const(0x45)
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)
2249
_SSD1680_WRITE_BWRAM = const(0x24)
2350
_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)
71+
_SSD1680_SET_RAMXPOS = const(0x44)
72+
_SSD1680_SET_RAMYPOS = const(0x45)
73+
_SSD1680_AUTOWRITE_RED = const(0x46)
74+
_SSD1680_AUTOWRITE_BW = const(0x47)
2475
_SSD1680_SET_RAMXCOUNT = const(0x4E)
2576
_SSD1680_SET_RAMYCOUNT = const(0x4F)
26-
_SSD1680_DISP_CTRL2 = const(0x22)
27-
_SSD1680_MASTER_ACTIVATE = const(0x20)
28-
_SSD1680_DEEP_SLEEP = const(0x10)
77+
_SSD1680_NOP = const(0xFF)
2978

3079

3180
class Adafruit_SSD1680(Adafruit_EPD):
32-
"""Driver for SSD1680 ePaper display, default driver."""
81+
"""driver class for Adafruit SSD1680 ePaper display breakouts"""
3382

34-
# pylint: disable=too-many-arguments, useless-parent-delegation
83+
# pylint: disable=too-many-arguments
3584
def __init__(
36-
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
37-
):
38-
# Call parent class's __init__ to initialize sram and other attributes
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:
3996
super().__init__(
4097
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
4198
)
4299

43-
self.cs_pin = cs_pin
44-
self.dc_pin = dc_pin
45-
self.sramcs_pin = sramcs_pin
46-
self.rst_pin = rst_pin
47-
self.busy_pin = busy_pin
48-
49-
self.initialize_buffers(width, height)
50-
51-
# pylint: enable=too-many-arguments, useless-parent-delegation
52-
53-
def initialize_buffers(self, width, height):
54-
"""Initialize width height stride buffers"""
55100
stride = width
56101
if stride % 8 != 0:
57102
stride += 8 - stride % 8
58103

59104
self._buffer1_size = int(stride * height / 8)
60105
self._buffer2_size = self._buffer1_size
61106

62-
if self.sramcs_pin:
107+
if sramcs_pin:
63108
self._buffer1 = self.sram.get_view(0)
64109
self._buffer2 = self.sram.get_view(self._buffer1_size)
65110
else:
66111
self._buffer1 = bytearray(self._buffer1_size)
67112
self._buffer2 = bytearray(self._buffer2_size)
68113

69114
self._framebuf1 = adafruit_framebuf.FrameBuffer(
70-
self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
115+
self._buffer1,
116+
width,
117+
height,
118+
stride=stride,
119+
buf_format=adafruit_framebuf.MHMSB,
71120
)
72121
self._framebuf2 = adafruit_framebuf.FrameBuffer(
73-
self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB
122+
self._buffer2,
123+
width,
124+
height,
125+
stride=stride,
126+
buf_format=adafruit_framebuf.MHMSB,
74127
)
75128
self.set_black_buffer(0, True)
76129
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()
77137

78-
def busy_wait(self):
79-
"""Wait for the display to complete its current task."""
80-
if self.busy_pin:
81-
while self.busy_pin.value:
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:
82143
time.sleep(0.01)
83144
else:
84145
time.sleep(0.5)
85146

86-
def power_up(self):
87-
"""Power up sequence for SSD1680."""
147+
def power_up(self) -> None:
148+
"""Power up the display in preparation for writing RAM and updating"""
88149
self.hardware_reset()
89150
self.busy_wait()
90151
self.command(_SSD1680_SW_RESET)
91152
self.busy_wait()
92-
153+
# driver output control
93154
self.command(
94155
_SSD1680_DRIVER_CONTROL,
95156
bytearray([self._height - 1, (self._height - 1) >> 8, 0x00]),
96157
)
158+
# data entry mode
97159
self.command(_SSD1680_DATA_MODE, bytearray([0x03]))
160+
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]))
165+
166+
# Set ram X start/end postion
98167
self.command(_SSD1680_SET_RAMXPOS, bytearray([0x01, 0x10]))
168+
# Set ram Y start/end postion
99169
self.command(
100170
_SSD1680_SET_RAMYPOS,
101171
bytearray([0, 0, self._height - 1, (self._height - 1) >> 8]),
102172
)
173+
# Set border waveform
174+
self.command(_SSD1680_WRITE_BORDER, bytearray([0x05]))
175+
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]))
180+
self.busy_wait()
181+
182+
def power_down(self) -> None:
183+
"""Power down the display - required when not actively displaying!"""
184+
self.command(_SSD1680_DEEP_SLEEP, bytearray([0x01]))
185+
time.sleep(0.1)
186+
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)
191+
self.busy_wait()
192+
if not self._busy:
193+
time.sleep(3) # wait 3 seconds
103194

104-
def write_ram(self, index):
105-
"""Write to RAM for SSD1680."""
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."""
106199
if index == 0:
107200
return self.command(_SSD1680_WRITE_BWRAM, end=False)
108201
if index == 1:
109202
return self.command(_SSD1680_WRITE_REDRAM, end=False)
110-
111-
# Raise an error if the index is not 0 or 1
112203
raise RuntimeError("RAM index must be 0 or 1")
113204

114-
def set_ram_address(self, x, y):
115-
"""Set RAM address location for SSD1680."""
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
116211
self.command(_SSD1680_SET_RAMXCOUNT, bytearray([x + 1]))
212+
# Set RAM Y address counter
117213
self.command(_SSD1680_SET_RAMYCOUNT, bytearray([y, y >> 8]))
118214

119-
def update(self):
120-
"""Update the display from internal memory."""
121-
self.command(_SSD1680_DISP_CTRL2, bytearray([0xF4])) # Full update
122-
self.command(_SSD1680_MASTER_ACTIVATE)
123-
self.busy_wait()
124-
if not self.busy_pin:
125-
time.sleep(3) # Wait for update to complete
126-
127-
def power_down(self):
128-
"""Power down the display."""
129-
self.command(_SSD1680_DEEP_SLEEP, bytearray([0x01]))
130-
time.sleep(0.1)
131-
132215

133216
class Adafruit_SSD1680Z(Adafruit_SSD1680):
134217
"""Driver for SSD1680Z ePaper display, overriding SSD1680 settings."""
@@ -148,6 +231,7 @@ def __init__(
148231
rst_pin=rst_pin,
149232
busy_pin=busy_pin,
150233
)
234+
self.busy_pin = busy_pin # Ensure busy_pin is set
151235

152236
# pylint: enable=too-many-arguments, useless-parent-delegation
153237

0 commit comments

Comments
 (0)