Skip to content

Commit 7fd35d0

Browse files
committed
big refactor but now works with ram or sram
1 parent 2c20e84 commit 7fd35d0

File tree

3 files changed

+242
-248
lines changed

3 files changed

+242
-248
lines changed

adafruit_epd/epd.py

Lines changed: 151 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"""
2828

2929
import time
30-
import digitalio
30+
from digitalio import Direction
3131
import adafruit_framebuf
3232
from adafruit_epd import mcp_sram
3333

@@ -50,43 +50,113 @@ def __init__(self, width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy
5050
# Setup reset pin, if we have one
5151
self._rst = rst_pin
5252
if rst_pin:
53-
self._rst.direction = digitalio.Direction.OUTPUT
53+
self._rst.direction = Direction.OUTPUT
5454

5555
# Setup busy pin, if we have one
5656
self._busy = busy_pin
5757
if busy_pin:
58-
self._busy.direction = digitalio.Direction.INPUT
58+
self._busy.direction = Direction.INPUT
5959

6060
# Setup dc pin (required)
6161
self._dc = dc_pin
62-
self._dc.direction = digitalio.Direction.OUTPUT
62+
self._dc.direction = Direction.OUTPUT
6363
self._dc.value = False
6464

6565
# Setup cs pin (required)
6666
self._cs = cs_pin
67-
self._cs.direction = digitalio.Direction.OUTPUT
67+
self._cs.direction = Direction.OUTPUT
6868
self._cs.value = True
6969

7070
# SPI interface (required)
7171
self.spi_device = spi
7272

73+
self.sram = None
7374
if sramcs_pin:
7475
self.sram = mcp_sram.Adafruit_MCP_SRAM(sramcs_pin, spi)
76+
77+
self._buffer1_size = self._buffer2_size = 0
78+
self._buffer1 = self._buffer2 = None
79+
self.hardware_reset()
80+
81+
def display(self):
82+
"""show the contents of the display buffer"""
83+
self.power_up()
84+
85+
self.set_ram_address(0, 0)
86+
87+
if self.sram:
88+
while not self.spi_device.try_lock():
89+
pass
90+
self.sram.cs_pin.value = False
91+
#send read command
92+
self.spi_device.write(bytearray([mcp_sram.Adafruit_MCP_SRAM.SRAM_READ]))
93+
#send start address
94+
self.spi_device.write(bytearray([0x00, 0x00]))
95+
self.spi_device.unlock()
96+
97+
#first data byte from SRAM will be transfered in at the
98+
#same time as the EPD command is transferred out
99+
cmd = self.write_ram(0)
100+
101+
while not self.spi_device.try_lock():
102+
pass
103+
self._dc.value = True
104+
105+
if self.sram:
106+
xfer = bytearray([cmd])
107+
outbuf = bytearray(1)
108+
for _ in range(self._buffer1_size):
109+
outbuf[0] = xfer[0]
110+
self.spi_device.write_readinto(outbuf, xfer)
111+
self.sram.cs_pin.value = True
112+
else:
113+
self.spi_device.write(self._buffer1)
114+
115+
self._cs.value = True
116+
self.spi_device.unlock()
117+
time.sleep(.002)
118+
119+
120+
if self.sram:
121+
while not self.spi_device.try_lock():
122+
pass
123+
self.sram.cs_pin.value = False
124+
#send read command
125+
self.spi_device.write(bytearray([mcp_sram.Adafruit_MCP_SRAM.SRAM_READ]))
126+
#send start address
127+
self.spi_device.write(bytearray([(self._buffer1_size >> 8), (self._buffer1_size & 0xFF)]))
128+
self.spi_device.unlock()
129+
130+
#first data byte from SRAM will be transfered in at the
131+
#same time as the EPD command is transferred out
132+
cmd = self.write_ram(1)
133+
134+
while not self.spi_device.try_lock():
135+
pass
136+
self._dc.value = True
137+
138+
if self.sram:
139+
xfer = bytearray([cmd])
140+
outbuf = bytearray(1)
141+
for _ in range(self._buffer1_size):
142+
outbuf[0] = xfer[0]
143+
self.spi_device.write_readinto(outbuf, xfer)
144+
self.sram.cs_pin.value = True
75145
else:
76-
self.sram = None
77-
self._bw_buffer = bytearray((width * height) // 8)
78-
self._red_buffer = bytearray((width * height) // 8)
79-
# since we have *two* framebuffers - one for red and one for black, we dont subclass but manage manually
80-
self._red_framebuf = adafruit_framebuf.FrameBuffer(self._red_buffer, width, height, buf_format=adafruit_framebuf.MHMSB)
81-
self._bw_framebuf = adafruit_framebuf.FrameBuffer(self._bw_buffer, width, height, buf_format=adafruit_framebuf.MHMSB)
82-
83-
# if we hav ea reset pin, do a hardware reset
146+
self.spi_device.write(self._buffer2)
147+
148+
self._cs.value = True
149+
self.spi_device.unlock()
150+
self.update()
151+
152+
153+
def hardware_reset(self):
154+
# if we have a reset pin, do a hardware reset
84155
if self._rst:
85156
self._rst.value = False
86-
time.sleep(.1)
157+
time.sleep(0.1)
87158
self._rst.value = True
88-
time.sleep(.1)
89-
159+
time.sleep(0.1)
90160

91161
def command(self, cmd, data=None, end=True):
92162
"""Send command byte to display."""
@@ -100,50 +170,54 @@ def command(self, cmd, data=None, end=True):
100170
self.spi_device.write_readinto(bytearray([cmd]), outbuf)
101171

102172
if data is not None:
103-
self.data(data)
104-
else:
105-
self.spi_device.unlock()
106-
173+
self._dc.value = True
174+
self.spi_device.write(data)
107175
if end:
108176
self._cs.value = True
177+
self.spi_device.unlock()
109178

110179
return outbuf[0]
111180

112-
def data(self, dat):
113-
"""Send data to display."""
114-
self._dc.value = True
115-
self.spi_device.write(dat)
116-
self._cs.value = True
117-
self.spi_device.unlock()
181+
182+
def pixel(self, x, y, color):
183+
"""draw a single pixel in the display buffer"""
184+
self._framebuf1.pixel(x, y, (color == Adafruit_EPD.BLACK) != self.black_invert)
185+
self._framebuf2.pixel(x, y, (color == Adafruit_EPD.RED) != self.red_invert)
118186

119187
def fill(self, color):
120-
#This should be overridden in the subclass
121-
self._bw_framebuf.fill((color == Adafruit_EPD.BLACK) != self.black_invert)
122-
self._red_framebuf.fill((color == Adafruit_EPD.RED) != self.red_invert)
188+
"""fill the screen with the passed color"""
189+
red_fill = (color == Adafruit_EPD.RED) != self.red_invert
190+
black_fill = (color == Adafruit_EPD.BLACK) != self.black_invert
191+
if red_fill:
192+
red_fill = 0xFF
193+
if black_fill:
194+
black_fill = 0xFF
123195

124-
def pixel(self, x, y, color=None):
125-
"""This should be overridden in the subclass"""
126-
self._bw_framebuf.pixel(x, y, (color == Adafruit_EPD.BLACK) != self.black_invert)
127-
self._red_framebuf.pixel(x, y, (color == Adafruit_EPD.RED) != self.red_invert)
196+
if self.sram:
197+
self.sram.erase(0x00, self._buffer1_size, black_fill)
198+
self.sram.erase(self._buffer1_size, self._buffer2_size, red_fill)
199+
else:
200+
self._framebuf1.fill(black_fill)
201+
self._framebuf2.fill(red_fill)
128202

129203
def rect(self, x, y, width, height, color):
130204
"""draw a rectangle"""
131-
self._bw_framebuf.rect(x, y, width, height, (color == Adafruit_EPD.BLACK) != self.black_invert)
132-
self._red_framebuf.rect(x, y, width, height, (color == Adafruit_EPD.RED) != self.red_invert)
205+
self._framebuf1.rect(x, y, width, height, (color == Adafruit_EPD.BLACK) != self.black_invert)
206+
self._framebuf2.rect(x, y, width, height, (color == Adafruit_EPD.RED) != self.red_invert)
133207

134208
# pylint: disable=too-many-arguments
135209
def fill_rect(self, x, y, width, height, color):
136210
"""fill a rectangle with the passed color"""
137-
self._bw_framebuf.fill_rect(x, y, width, height, (color == Adafruit_EPD.BLACK) != self.black_invert)
138-
self._red_framebuf.fill_rect(x, y, width, height, (color == Adafruit_EPD.RED) != self.red_invert)
211+
self._framebuf1.fill_rect(x, y, width, height, (color == Adafruit_EPD.BLACK) != self.black_invert)
212+
self._framebuf2.fill_rect(x, y, width, height, (color == Adafruit_EPD.RED) != self.red_invert)
139213

140214
def line(self, x_0, y_0, x_1, y_1, color):
141-
self._bw_framebuf.line(x_0, y_0, x_1, y_1, (color == Adafruit_EPD.BLACK) != self.black_invert)
142-
self._red_framebuf.line(x_0, y_0, x_1, y_1, (color == Adafruit_EPD.RED) != self.red_invert)
215+
self._framebuf1.line(x_0, y_0, x_1, y_1, (color == Adafruit_EPD.BLACK) != self.black_invert)
216+
self._framebuf2.line(x_0, y_0, x_1, y_1, (color == Adafruit_EPD.RED) != self.red_invert)
143217

144218
def text(self, string, x, y, color, *, font_name="font5x8.bin"):
145-
self._bw_framebuf.text(string, x, y, (color == Adafruit_EPD.BLACK) != self.black_invert, font_name=font_name)
146-
self._red_framebuf.text(string, x, y, (color == Adafruit_EPD.RED) != self.red_invert, font_name=font_name)
219+
self._framebuf1.text(string, x, y, (color == Adafruit_EPD.BLACK) != self.black_invert, font_name=font_name)
220+
self._framebuf2.text(string, x, y, (color == Adafruit_EPD.RED) != self.red_invert, font_name=font_name)
147221

148222
@property
149223
def width(self):
@@ -159,12 +233,12 @@ def height(self):
159233

160234
@property
161235
def rotation(self):
162-
return self._bw_framebuf._rotation
236+
return self._framebuf1._rotation
163237

164238
@rotation.setter
165239
def rotation(self, val):
166-
self._bw_framebuf.rotation = val
167-
self._red_framebuf.rotation = val
240+
self._framebuf1.rotation = val
241+
self._framebuf2.rotation = val
168242

169243
def hline(self, x, y, width, color):
170244
"""draw a horizontal line"""
@@ -173,3 +247,36 @@ def hline(self, x, y, width, color):
173247
def vline(self, x, y, height, color):
174248
"""draw a vertical line"""
175249
self.fill_rect(x, y, 1, height, color)
250+
251+
252+
def image(self, image):
253+
"""Set buffer to value of Python Imaging Library image. The image should
254+
be in RGB mode and a size equal to the display size.
255+
"""
256+
if image.mode != 'RGB':
257+
raise ValueError('Image must be in mode RGB.')
258+
imwidth, imheight = image.size
259+
if imwidth != self.width or imheight != self.height:
260+
raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
261+
.format(self.width, self.height))
262+
# Grab all the pixels from the image, faster than getpixel.
263+
pix = image.load()
264+
265+
for y in iter(range(image.size[1])):
266+
for x in iter(range(image.size[0])):
267+
if x == 0:
268+
x = 1
269+
pixel = pix[x, y]
270+
271+
addr = int(((self._width - x) * self._height + y)/8)
272+
273+
if pixel == (0xFF, 0, 0):
274+
addr = addr + self.bw_bufsize
275+
current = self.sram.read8(addr)
276+
277+
if pixel in ((0xFF, 0, 0), (0, 0, 0)):
278+
current = current & ~(1 << (7 - y%8))
279+
else:
280+
current = current | (1 << (7 - y%8))
281+
282+
self.sram.write8(addr, current)

0 commit comments

Comments
 (0)