Skip to content

Commit c974cec

Browse files
authored
Merge pull request #9 from ladyada/master
Big refactor to match arduino logic separation
2 parents f447249 + 09f16e0 commit c974cec

File tree

9 files changed

+848
-328
lines changed

9 files changed

+848
-328
lines changed

adafruit_epd/epd.py

Lines changed: 271 additions & 80 deletions
Large diffs are not rendered by default.

adafruit_epd/il0373.py

Lines changed: 106 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -28,205 +28,122 @@
2828

2929
import time
3030
from micropython import const
31+
import adafruit_framebuf
3132
from adafruit_epd.epd import Adafruit_EPD
32-
from adafruit_epd.mcp_sram import Adafruit_MCP_SRAM
3333

34-
IL0373_PANEL_SETTING = const(0x00)
35-
IL0373_POWER_SETTING = const(0x01)
36-
IL0373_POWER_OFF = const(0x02)
37-
IL0373_POWER_OFF_SEQUENCE = const(0x03)
38-
IL0373_POWER_ON = const(0x04)
39-
IL0373_POWER_ON_MEASURE = const(0x05)
40-
IL0373_BOOSTER_SOFT_START = const(0x06)
41-
IL0373_DEEP_SLEEP = const(0x07)
42-
IL0373_DTM1 = const(0x10)
43-
IL0373_DATA_STOP = const(0x11)
44-
IL0373_DISPLAY_REFRESH = const(0x12)
45-
IL0373_DTM2 = const(0x13)
46-
IL0373_PDTM1 = const(0x14)
47-
IL0373_PDTM2 = const(0x15)
48-
IL0373_PDRF = const(0x16)
49-
IL0373_LUT1 = const(0x20)
50-
IL0373_LUTWW = const(0x21)
51-
IL0373_LUTBW = const(0x22)
52-
IL0373_LUTWB = const(0x23)
53-
IL0373_LUTBB = const(0x24)
54-
IL0373_PLL = const(0x30)
55-
IL0373_CDI = const(0x50)
56-
IL0373_RESOLUTION = const(0x61)
57-
IL0373_VCM_DC_SETTING = const(0x82)
34+
_IL0373_PANEL_SETTING = const(0x00)
35+
_IL0373_POWER_SETTING = const(0x01)
36+
_IL0373_POWER_OFF = const(0x02)
37+
_IL0373_POWER_OFF_SEQUENCE = const(0x03)
38+
_IL0373_POWER_ON = const(0x04)
39+
_IL0373_POWER_ON_MEASURE = const(0x05)
40+
_IL0373_BOOSTER_SOFT_START = const(0x06)
41+
_IL0373_DEEP_SLEEP = const(0x07)
42+
_IL0373_DTM1 = const(0x10)
43+
_IL0373_DATA_STOP = const(0x11)
44+
_IL0373_DISPLAY_REFRESH = const(0x12)
45+
_IL0373_DTM2 = const(0x13)
46+
_IL0373_PDTM1 = const(0x14)
47+
_IL0373_PDTM2 = const(0x15)
48+
_IL0373_PDRF = const(0x16)
49+
_IL0373_LUT1 = const(0x20)
50+
_IL0373_LUTWW = const(0x21)
51+
_IL0373_LUTBW = const(0x22)
52+
_IL0373_LUTWB = const(0x23)
53+
_IL0373_LUTBB = const(0x24)
54+
_IL0373_PLL = const(0x30)
55+
_IL0373_CDI = const(0x50)
56+
_IL0373_RESOLUTION = const(0x61)
57+
_IL0373_VCM_DC_SETTING = const(0x82)
5858

5959
class Adafruit_IL0373(Adafruit_EPD):
6060
"""driver class for Adafruit IL0373 ePaper display breakouts"""
6161
# pylint: disable=too-many-arguments
62-
def __init__(self, width, height, rst_pin, dc_pin, busy_pin, srcs_pin, cs_pin, spi):
63-
super(Adafruit_IL0373, self).__init__(width, height, rst_pin, dc_pin, busy_pin,
64-
srcs_pin, cs_pin, spi)
65-
66-
self.bw_bufsize = int(width * height / 8)
67-
self.red_bufsize = int(width * height / 8)
68-
69-
self.begin()
62+
def __init__(self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin):
63+
super(Adafruit_IL0373, self).__init__(width, height, spi, cs_pin, dc_pin,
64+
sramcs_pin, rst_pin, busy_pin)
65+
66+
self._buffer1_size = int(width * height / 8)
67+
self._buffer2_size = int(width * height / 8)
68+
69+
if sramcs_pin:
70+
self._buffer1 = self.sram.get_view(0)
71+
self._buffer2 = self.sram.get_view(self._buffer1_size)
72+
else:
73+
self._buffer1 = bytearray((width * height) // 8)
74+
self._buffer2 = bytearray((width * height) // 8)
75+
# since we have *two* framebuffers - one for red and one for black
76+
# we dont subclass but manage manually
77+
self._framebuf1 = adafruit_framebuf.FrameBuffer(self._buffer1, width, height,
78+
buf_format=adafruit_framebuf.MHMSB)
79+
self._framebuf2 = adafruit_framebuf.FrameBuffer(self._buffer2, width, height,
80+
buf_format=adafruit_framebuf.MHMSB)
81+
self.set_black_buffer(0, True)
82+
self.set_color_buffer(1, True)
7083
# pylint: enable=too-many-arguments
7184

7285
def begin(self, reset=True):
7386
"""Begin communication with the display and set basic settings"""
74-
super(Adafruit_IL0373, self).begin(reset)
75-
76-
while self._busy.value is False:
77-
pass
78-
79-
self.command(IL0373_POWER_SETTING, bytearray([0x03, 0x00, 0x2b, 0x2b, 0x09]))
80-
self.command(IL0373_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
81-
82-
def update(self):
83-
"""update the display"""
84-
self.command(IL0373_DISPLAY_REFRESH)
85-
86-
while self._busy.value is False:
87-
pass
88-
89-
self.command(IL0373_CDI, bytearray([0x17]))
90-
self.command(IL0373_VCM_DC_SETTING, bytearray([0x00]))
91-
self.command(IL0373_POWER_OFF)
92-
time.sleep(2)
87+
if reset:
88+
self.hardware_reset()
89+
self.power_down()
90+
91+
def busy_wait(self):
92+
"""Wait for display to be done with current task, either by polling the
93+
busy pin, or pausing"""
94+
if self._busy:
95+
while not self._busy.value:
96+
pass
97+
else:
98+
time.sleep(0.5)
9399

94100
def power_up(self):
95-
"""power up the display"""
96-
self.command(IL0373_POWER_ON)
97-
98-
while self._busy.value is False:
99-
pass
100-
101-
time.sleep(.2)
102-
103-
self.command(IL0373_PANEL_SETTING, bytearray([0xCF]))
104-
self.command(IL0373_CDI, bytearray([0x37]))
105-
self.command(IL0373_PLL, bytearray([0x29]))
106-
_b1 = self.height & 0xFF
107-
_b2 = (self.height >> 8) & 0xFF
108-
_b3 = self.width & 0xFF
109-
_b4 = (self.width >> 8) & 0xFF
110-
self.command(IL0373_RESOLUTION, bytearray([_b1, _b2, _b3, _b4]))
111-
self.command(IL0373_VCM_DC_SETTING, bytearray([0x0A]))
112-
113-
114-
def display(self):
115-
"""show the contents of the display buffer"""
116-
self.power_up()
117-
118-
while not self.spi_device.try_lock():
119-
pass
120-
self.sram.cs_pin.value = False
121-
#send read command
122-
self.spi_device.write(bytearray([Adafruit_MCP_SRAM.SRAM_READ]))
123-
#send start address
124-
self.spi_device.write(bytearray([0x00, 0x00]))
125-
self.spi_device.unlock()
126-
127-
#first data byte from SRAM will be transfered in at the
128-
#same time as the EPD command is transferred out
129-
cmd = self.command(IL0373_DTM1, end=False)
130-
131-
while not self.spi_device.try_lock():
132-
pass
133-
self._dc.value = True
134-
xfer = bytearray([cmd])
135-
outbuf = bytearray(1)
136-
for _ in range(self.bw_bufsize):
137-
outbuf[0] = xfer[0]
138-
self.spi_device.write_readinto(outbuf, xfer)
139-
self._cs.value = True
140-
self.sram.cs_pin.value = True
141-
142-
time.sleep(.002)
101+
"""Power up the display in preparation for writing RAM and updating"""
102+
self.hardware_reset()
103+
self.busy_wait()
104+
105+
self.command(_IL0373_POWER_SETTING, bytearray([0x03, 0x00, 0x2b, 0x2b, 0x09]))
106+
self.command(_IL0373_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
107+
self.command(_IL0373_POWER_ON)
108+
109+
self.busy_wait()
110+
time.sleep(0.2)
111+
112+
self.command(_IL0373_PANEL_SETTING, bytearray([0xCF]))
113+
self.command(_IL0373_CDI, bytearray([0x37]))
114+
self.command(_IL0373_PLL, bytearray([0x29]))
115+
_b1 = self._width & 0xFF
116+
_b2 = (self._height >> 8) & 0xFF
117+
_b3 = self._height & 0xFF
118+
self.command(_IL0373_RESOLUTION, bytearray([_b1, _b2, _b3]))
119+
self.command(_IL0373_VCM_DC_SETTING, bytearray([0x0A]))
120+
time.sleep(0.05)
121+
122+
def power_down(self):
123+
"""Power down the display - required when not actively displaying!"""
124+
self.command(_IL0373_CDI, bytearray([0x17]))
125+
self.command(_IL0373_VCM_DC_SETTING, bytearray([0x00]))
126+
self.command(_IL0373_POWER_OFF)
143127

144-
self.sram.cs_pin.value = False
145-
#send read command
146-
self.spi_device.write(bytearray([Adafruit_MCP_SRAM.SRAM_READ]))
147-
#send start address
148-
self.spi_device.write(bytearray([(self.bw_bufsize >> 8), (self.bw_bufsize & 0xFF)]))
149-
self.spi_device.unlock()
150-
151-
#first data byte from SRAM will be transfered in at the
152-
#same time as the EPD command is transferred out
153-
cmd = self.command(IL0373_DTM2, end=False)
154-
155-
while not self.spi_device.try_lock():
156-
pass
157-
self._dc.value = True
158-
xfer = bytearray([cmd])
159-
outbuf = bytearray(1)
160-
for _ in range(self.bw_bufsize):
161-
outbuf[0] = xfer[0]
162-
self.spi_device.write_readinto(outbuf, xfer)
163-
self._cs.value = True
164-
self.sram.cs_pin.value = True
165-
self.spi_device.unlock()
166-
167-
self.update()
168-
169-
def image(self, image):
170-
"""Set buffer to value of Python Imaging Library image. The image should
171-
be in RGB mode and a size equal to the display size.
172-
"""
173-
if image.mode != 'RGB':
174-
raise ValueError('Image must be in mode RGB.')
175-
imwidth, imheight = image.size
176-
if imwidth != self.width or imheight != self.height:
177-
raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
178-
.format(self.width, self.height))
179-
# Grab all the pixels from the image, faster than getpixel.
180-
pix = image.load()
181-
182-
for y in iter(range(image.size[1])):
183-
for x in iter(range(image.size[0])):
184-
if x == 0:
185-
x = 1
186-
pixel = pix[x, y]
187-
188-
addr = int(((self.width - x) * self.height + y)/8)
189-
190-
if pixel == (0xFF, 0, 0):
191-
addr = addr + self.bw_bufsize
192-
current = self.sram.read8(addr)
193-
194-
if pixel in ((0xFF, 0, 0), (0, 0, 0)):
195-
current = current & ~(1 << (7 - y%8))
196-
else:
197-
current = current | (1 << (7 - y%8))
198-
199-
self.sram.write8(addr, current)
200-
201-
def draw_pixel(self, x, y, color):
202-
"""draw a single pixel in the display buffer"""
203-
if (x < 0) or (x >= self.width) or (y < 0) or (y >= self.height):
204-
return
205-
206-
if x == 0:
207-
x = 1
208-
209-
addr = ((self.width - x) * self.height + y) // 8
210-
if color == Adafruit_EPD.RED:
211-
addr = addr + self.bw_bufsize
212-
current = self.sram.read8(addr)
213-
214-
if color == Adafruit_EPD.WHITE:
215-
current = current | (1 << (7 - y%8))
216-
elif color in (Adafruit_EPD.RED, Adafruit_EPD.BLACK):
217-
current = current & ~(1 << (7 - y%8))
218-
elif color == Adafruit_EPD.INVERSE:
219-
current = current ^ (1 << (7 - y%8))
220-
221-
self.sram.write8(addr, current)
222-
return
223-
224-
def clear_buffer(self):
225-
"""clear the display buffer"""
226-
self.sram.erase(0x00, self.bw_bufsize, 0xFF)
227-
self.sram.erase(self.bw_bufsize, self.red_bufsize, 0xFF)
228-
229-
def clear_display(self):
230-
"""clear the entire display"""
231-
self.clear_buffer()
232-
self.display()
128+
def update(self):
129+
"""Update the display from internal memory"""
130+
self.command(_IL0373_DISPLAY_REFRESH)
131+
time.sleep(0.1)
132+
self.busy_wait()
133+
if not self._busy:
134+
time.sleep(15) # wait 15 seconds
135+
136+
def write_ram(self, index):
137+
"""Send the one byte command for starting the RAM write process. Returns
138+
the byte read at the same time over SPI. index is the RAM buffer, can be
139+
0 or 1 for tri-color displays."""
140+
if index == 0:
141+
return self.command(_IL0373_DTM1, end=False)
142+
if index == 1:
143+
return self.command(_IL0373_DTM2, end=False)
144+
raise RuntimeError("RAM index must be 0 or 1")
145+
146+
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
147+
"""Set the RAM address location, not used on this chipset but required by
148+
the superclass"""
149+
return # on this chip it does nothing

0 commit comments

Comments
 (0)