Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big refactor to match arduino logic separation #9

Merged
merged 30 commits into from
Mar 31, 2019
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
bdda668
get rid of clear_display/clear_buffer and replace with just fill()
ladyada Jan 1, 2019
9c51956
charge arg order/kwarg, make busy/reset optional
ladyada Jan 1, 2019
fb19eea
fix bitmap example, tested!
ladyada Jan 1, 2019
c4002d0
new format
ladyada Jan 6, 2019
346a9d4
use mem buffer if no SRAM pin
ladyada Jan 6, 2019
f7c3501
begin framebuffification
ladyada Jan 6, 2019
4f9b90c
add const underscores and rotation
ladyada Jan 6, 2019
0728206
fix none-8-bit boundary sizes
ladyada Jan 6, 2019
cf49a1d
ahh, orientation is always with inkdots at bottom
ladyada Jan 6, 2019
642cb0d
width/height change with rotation
ladyada Jan 6, 2019
2c20e84
fix incorrect init order
ladyada Mar 5, 2019
7fd35d0
big refactor but now works with ram or sram
ladyada Mar 31, 2019
b32893c
fix width and height
ladyada Mar 31, 2019
fe0cb4d
linty!@
ladyada Mar 31, 2019
ad5b467
fix pylint spi.write complaint
ladyada Mar 31, 2019
d908c69
lint examples
ladyada Mar 31, 2019
cf64f48
so close!
ladyada Mar 31, 2019
42de3be
lintylint
ladyada Mar 31, 2019
e695787
add 2.7" tricolor and single byte transfer support for weird chips
ladyada Mar 31, 2019
9010050
linting
ladyada Mar 31, 2019
0921380
add line for 2.7" and also more complete framebuf test
ladyada Mar 31, 2019
11c3179
allow rearranging of buffers (for flex displays)
ladyada Mar 31, 2019
d37b643
matchy up 2.7" to new buffer assignment
ladyada Mar 31, 2019
eb8fe05
add tri-color 4.2"
ladyada Mar 31, 2019
f8081ff
add more displays
ladyada Mar 31, 2019
59827d6
woops forgot to unset
ladyada Mar 31, 2019
b04d3e7
lint
ladyada Mar 31, 2019
f10cbbd
linted example
ladyada Mar 31, 2019
0e53954
upcoming shield
ladyada Mar 31, 2019
09f16e0
lint example
ladyada Mar 31, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
351 changes: 271 additions & 80 deletions adafruit_epd/epd.py

Large diffs are not rendered by default.

295 changes: 106 additions & 189 deletions adafruit_epd/il0373.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,205 +28,122 @@

import time
from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.mcp_sram import Adafruit_MCP_SRAM

IL0373_PANEL_SETTING = const(0x00)
IL0373_POWER_SETTING = const(0x01)
IL0373_POWER_OFF = const(0x02)
IL0373_POWER_OFF_SEQUENCE = const(0x03)
IL0373_POWER_ON = const(0x04)
IL0373_POWER_ON_MEASURE = const(0x05)
IL0373_BOOSTER_SOFT_START = const(0x06)
IL0373_DEEP_SLEEP = const(0x07)
IL0373_DTM1 = const(0x10)
IL0373_DATA_STOP = const(0x11)
IL0373_DISPLAY_REFRESH = const(0x12)
IL0373_DTM2 = const(0x13)
IL0373_PDTM1 = const(0x14)
IL0373_PDTM2 = const(0x15)
IL0373_PDRF = const(0x16)
IL0373_LUT1 = const(0x20)
IL0373_LUTWW = const(0x21)
IL0373_LUTBW = const(0x22)
IL0373_LUTWB = const(0x23)
IL0373_LUTBB = const(0x24)
IL0373_PLL = const(0x30)
IL0373_CDI = const(0x50)
IL0373_RESOLUTION = const(0x61)
IL0373_VCM_DC_SETTING = const(0x82)
_IL0373_PANEL_SETTING = const(0x00)
_IL0373_POWER_SETTING = const(0x01)
_IL0373_POWER_OFF = const(0x02)
_IL0373_POWER_OFF_SEQUENCE = const(0x03)
_IL0373_POWER_ON = const(0x04)
_IL0373_POWER_ON_MEASURE = const(0x05)
_IL0373_BOOSTER_SOFT_START = const(0x06)
_IL0373_DEEP_SLEEP = const(0x07)
_IL0373_DTM1 = const(0x10)
_IL0373_DATA_STOP = const(0x11)
_IL0373_DISPLAY_REFRESH = const(0x12)
_IL0373_DTM2 = const(0x13)
_IL0373_PDTM1 = const(0x14)
_IL0373_PDTM2 = const(0x15)
_IL0373_PDRF = const(0x16)
_IL0373_LUT1 = const(0x20)
_IL0373_LUTWW = const(0x21)
_IL0373_LUTBW = const(0x22)
_IL0373_LUTWB = const(0x23)
_IL0373_LUTBB = const(0x24)
_IL0373_PLL = const(0x30)
_IL0373_CDI = const(0x50)
_IL0373_RESOLUTION = const(0x61)
_IL0373_VCM_DC_SETTING = const(0x82)

class Adafruit_IL0373(Adafruit_EPD):
"""driver class for Adafruit IL0373 ePaper display breakouts"""
# pylint: disable=too-many-arguments
def __init__(self, width, height, rst_pin, dc_pin, busy_pin, srcs_pin, cs_pin, spi):
super(Adafruit_IL0373, self).__init__(width, height, rst_pin, dc_pin, busy_pin,
srcs_pin, cs_pin, spi)

self.bw_bufsize = int(width * height / 8)
self.red_bufsize = int(width * height / 8)

self.begin()
def __init__(self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin):
super(Adafruit_IL0373, self).__init__(width, height, spi, cs_pin, dc_pin,
sramcs_pin, rst_pin, busy_pin)

self._buffer1_size = int(width * height / 8)
self._buffer2_size = int(width * height / 8)

if sramcs_pin:
self._buffer1 = self.sram.get_view(0)
self._buffer2 = self.sram.get_view(self._buffer1_size)
else:
self._buffer1 = bytearray((width * height) // 8)
self._buffer2 = bytearray((width * height) // 8)
# since we have *two* framebuffers - one for red and one for black
# we dont subclass but manage manually
self._framebuf1 = adafruit_framebuf.FrameBuffer(self._buffer1, width, height,
buf_format=adafruit_framebuf.MHMSB)
self._framebuf2 = adafruit_framebuf.FrameBuffer(self._buffer2, width, height,
buf_format=adafruit_framebuf.MHMSB)
self.set_black_buffer(0, True)
self.set_color_buffer(1, True)
# pylint: enable=too-many-arguments

def begin(self, reset=True):
"""Begin communication with the display and set basic settings"""
super(Adafruit_IL0373, self).begin(reset)

while self._busy.value is False:
pass

self.command(IL0373_POWER_SETTING, bytearray([0x03, 0x00, 0x2b, 0x2b, 0x09]))
self.command(IL0373_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))

def update(self):
"""update the display"""
self.command(IL0373_DISPLAY_REFRESH)

while self._busy.value is False:
pass

self.command(IL0373_CDI, bytearray([0x17]))
self.command(IL0373_VCM_DC_SETTING, bytearray([0x00]))
self.command(IL0373_POWER_OFF)
time.sleep(2)
if reset:
self.hardware_reset()
self.power_down()

def busy_wait(self):
"""Wait for display to be done with current task, either by polling the
busy pin, or pausing"""
if self._busy:
while not self._busy.value:
pass
else:
time.sleep(0.5)

def power_up(self):
"""power up the display"""
self.command(IL0373_POWER_ON)

while self._busy.value is False:
pass

time.sleep(.2)

self.command(IL0373_PANEL_SETTING, bytearray([0xCF]))
self.command(IL0373_CDI, bytearray([0x37]))
self.command(IL0373_PLL, bytearray([0x29]))
_b1 = self.height & 0xFF
_b2 = (self.height >> 8) & 0xFF
_b3 = self.width & 0xFF
_b4 = (self.width >> 8) & 0xFF
self.command(IL0373_RESOLUTION, bytearray([_b1, _b2, _b3, _b4]))
self.command(IL0373_VCM_DC_SETTING, bytearray([0x0A]))


def display(self):
"""show the contents of the display buffer"""
self.power_up()

while not self.spi_device.try_lock():
pass
self.sram.cs_pin.value = False
#send read command
self.spi_device.write(bytearray([Adafruit_MCP_SRAM.SRAM_READ]))
#send start address
self.spi_device.write(bytearray([0x00, 0x00]))
self.spi_device.unlock()

#first data byte from SRAM will be transfered in at the
#same time as the EPD command is transferred out
cmd = self.command(IL0373_DTM1, end=False)

while not self.spi_device.try_lock():
pass
self._dc.value = True
xfer = bytearray([cmd])
outbuf = bytearray(1)
for _ in range(self.bw_bufsize):
outbuf[0] = xfer[0]
self.spi_device.write_readinto(outbuf, xfer)
self._cs.value = True
self.sram.cs_pin.value = True

time.sleep(.002)
"""Power up the display in preparation for writing RAM and updating"""
self.hardware_reset()
self.busy_wait()

self.command(_IL0373_POWER_SETTING, bytearray([0x03, 0x00, 0x2b, 0x2b, 0x09]))
self.command(_IL0373_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
self.command(_IL0373_POWER_ON)

self.busy_wait()
time.sleep(0.2)

self.command(_IL0373_PANEL_SETTING, bytearray([0xCF]))
self.command(_IL0373_CDI, bytearray([0x37]))
self.command(_IL0373_PLL, bytearray([0x29]))
_b1 = self._width & 0xFF
_b2 = (self._height >> 8) & 0xFF
_b3 = self._height & 0xFF
self.command(_IL0373_RESOLUTION, bytearray([_b1, _b2, _b3]))
self.command(_IL0373_VCM_DC_SETTING, bytearray([0x0A]))
time.sleep(0.05)

def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_IL0373_CDI, bytearray([0x17]))
self.command(_IL0373_VCM_DC_SETTING, bytearray([0x00]))
self.command(_IL0373_POWER_OFF)

self.sram.cs_pin.value = False
#send read command
self.spi_device.write(bytearray([Adafruit_MCP_SRAM.SRAM_READ]))
#send start address
self.spi_device.write(bytearray([(self.bw_bufsize >> 8), (self.bw_bufsize & 0xFF)]))
self.spi_device.unlock()

#first data byte from SRAM will be transfered in at the
#same time as the EPD command is transferred out
cmd = self.command(IL0373_DTM2, end=False)

while not self.spi_device.try_lock():
pass
self._dc.value = True
xfer = bytearray([cmd])
outbuf = bytearray(1)
for _ in range(self.bw_bufsize):
outbuf[0] = xfer[0]
self.spi_device.write_readinto(outbuf, xfer)
self._cs.value = True
self.sram.cs_pin.value = True
self.spi_device.unlock()

self.update()

def image(self, image):
"""Set buffer to value of Python Imaging Library image. The image should
be in RGB mode and a size equal to the display size.
"""
if image.mode != 'RGB':
raise ValueError('Image must be in mode RGB.')
imwidth, imheight = image.size
if imwidth != self.width or imheight != self.height:
raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
.format(self.width, self.height))
# Grab all the pixels from the image, faster than getpixel.
pix = image.load()

for y in iter(range(image.size[1])):
for x in iter(range(image.size[0])):
if x == 0:
x = 1
pixel = pix[x, y]

addr = int(((self.width - x) * self.height + y)/8)

if pixel == (0xFF, 0, 0):
addr = addr + self.bw_bufsize
current = self.sram.read8(addr)

if pixel in ((0xFF, 0, 0), (0, 0, 0)):
current = current & ~(1 << (7 - y%8))
else:
current = current | (1 << (7 - y%8))

self.sram.write8(addr, current)

def draw_pixel(self, x, y, color):
"""draw a single pixel in the display buffer"""
if (x < 0) or (x >= self.width) or (y < 0) or (y >= self.height):
return

if x == 0:
x = 1

addr = ((self.width - x) * self.height + y) // 8
if color == Adafruit_EPD.RED:
addr = addr + self.bw_bufsize
current = self.sram.read8(addr)

if color == Adafruit_EPD.WHITE:
current = current | (1 << (7 - y%8))
elif color in (Adafruit_EPD.RED, Adafruit_EPD.BLACK):
current = current & ~(1 << (7 - y%8))
elif color == Adafruit_EPD.INVERSE:
current = current ^ (1 << (7 - y%8))

self.sram.write8(addr, current)
return

def clear_buffer(self):
"""clear the display buffer"""
self.sram.erase(0x00, self.bw_bufsize, 0xFF)
self.sram.erase(self.bw_bufsize, self.red_bufsize, 0xFF)

def clear_display(self):
"""clear the entire display"""
self.clear_buffer()
self.display()
def update(self):
"""Update the display from internal memory"""
self.command(_IL0373_DISPLAY_REFRESH)
time.sleep(0.1)
self.busy_wait()
if not self._busy:
time.sleep(15) # wait 15 seconds

def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_IL0373_DTM1, end=False)
if index == 1:
return self.command(_IL0373_DTM2, end=False)
raise RuntimeError("RAM index must be 0 or 1")

def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
"""Set the RAM address location, not used on this chipset but required by
the superclass"""
return # on this chip it does nothing
Loading