Skip to content

Commit

Permalink
Merge pull request #63 from fpammer/driver-5in65f
Browse files Browse the repository at this point in the history
Add support for new Waveshare 5.65 inch 7 color e-paper display
  • Loading branch information
joukos committed Aug 10, 2020
2 parents 5ffe395 + 35d4898 commit 30f18c3
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 0 deletions.
155 changes: 155 additions & 0 deletions drivers/drivers_color.py
Expand Up @@ -15,6 +15,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from drivers.drivers_full import WaveshareFull
from PIL import Image


class WaveshareColor(WaveshareFull):
Expand Down Expand Up @@ -224,6 +225,160 @@ def sleep(self):
self.send_data(0xa5)


class EPD5in65f(WaveshareColor):
"""Waveshare 5.65" - 7 colors"""

LUT_BLACK = 0x000000 # 0000 BGR
LUT_WHITE = 0xffffff # 0001
LUT_GREEN = 0x00ff00 # 0010
LUT_BLUE = 0xff0000 # 0011
LUT_RED = 0x0000ff # 0100
LUT_YELLOW = 0x00ffff # 0101
LUT_ORANGE = 0x0080ff # 0110
POWER_SAVING = 0xE3
TCON_RESOLUTION = 0x61
TEMPERATURE_CALIBRATION = 0x41

def __init__(self):
super().__init__(name='5.65" F', width=600, height=448)

def reset(self):
self.digital_write(self.RST_PIN, 1)
self.delay_ms(600)
self.digital_write(self.RST_PIN, 0)
self.delay_ms(2)
self.digital_write(self.RST_PIN, 1)
self.delay_ms(200)

def send_command(self, command):
self.digital_write(self.DC_PIN, 0)
self.digital_write(self.CS_PIN, 0)
self.spi_transfer([command])
self.digital_write(self.CS_PIN, 1)

def send_data(self, data):
self.digital_write(self.DC_PIN, 1)
self.digital_write(self.CS_PIN, 0)
self.spi_transfer([data])
self.digital_write(self.CS_PIN, 1)

def wait_until_busy(self):
while self.digital_read(self.BUSY_PIN) == 0: # 0: idle, 1: busy
self.delay_ms(100)

def wait_until_idle(self):
while self.digital_read(self.BUSY_PIN) == 1: # 0: idle, 1: busy
self.delay_ms(100)

def init(self, **kwargs):
if self.epd_init() != 0:
return -1

# EPD hardware init start
self.reset()

self.wait_until_busy()
self.send_command(self.PANEL_SETTING)
self.send_data(0xEF)
self.send_data(0x08)
self.send_command(self.POWER_SETTING)
self.send_data(0x37)
self.send_data(0x00)
self.send_data(0x23)
self.send_data(0x23)
self.send_command(self.POWER_OFF_SEQUENCE_SETTING)
self.send_data(0x00)
self.send_command(self.BOOSTER_SOFT_START)
self.send_data(0xC7)
self.send_data(0xC7)
self.send_data(0x1D)
self.send_command(self.PLL_CONTROL)
self.send_data(0x3C)
self.send_command(self.TEMPERATURE_SENSOR_COMMAND)
self.send_data(0x00)
self.send_command(self.VCOM_AND_DATA_INTERVAL_SETTING)
self.send_data(0x37)
self.send_command(self.TCON_SETTING)
self.send_data(0x22)
self.send_command(self.TCON_RESOLUTION)
self.send_data(0x02)
self.send_data(0x58)
self.send_data(0x01)
self.send_data(0xC0)
self.send_command(self.POWER_SAVING)
self.send_data(0xAA)

self.delay_ms(100)
self.send_command(0x50)
self.send_data(0x37)

def get_frame_buffer(self, image, reverse=False):
buf = [0x00] * int(self.width * self.height / 2)

# quantize image with palette of possible colors
image_palette = Image.new('P', (1, 1))
image_palette.putpalette(([0, 0, 0, 255, 255, 255, 0, 255, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 255, 128, 0]
+ [0, 0, 0]) * 32) # multiply by 32 to pad palette to reach required length of 768
image_rgb = image.quantize(palette=image_palette).convert('RGB')

imwidth, imheight = image_rgb.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))

pixels = image_rgb.load()

for y in range(self.height):
for x in range(self.width):
pos = int((x + y * self.width) / 2)
color = 0

if pixels[x, y][0] == 0 and pixels[x, y][1] == 0 and pixels[x, y][2] == 0:
color = 0
elif pixels[x, y][0] == 255 and pixels[x, y][1] == 255 and pixels[x, y][2] == 255:
color = 1
elif pixels[x, y][0] == 0 and pixels[x, y][1] == 255 and pixels[x, y][2] == 0:
color = 2
elif pixels[x, y][0] == 0 and pixels[x, y][1] == 0 and pixels[x, y][2] == 255:
color = 3
elif pixels[x, y][0] == 255 and pixels[x, y][1] == 0 and pixels[x, y][2] == 0:
color = 4
elif pixels[x, y][0] == 255 and pixels[x, y][1] == 255 and pixels[x, y][2] == 0:
color = 5
elif pixels[x, y][0] == 255 and pixels[x, y][1] == 128 and pixels[x, y][2] == 0:
color = 6

data_t = buf[pos] & (~(0xF0 >> ((x % 2) * 4)))
buf[pos] = data_t | ((color << 4) >> ((x % 2) * 4))

return buf

def display_frame(self, frame_buffer, *args):
self.send_command(self.TCON_RESOLUTION)
self.send_data(0x02)
self.send_data(0x58)
self.send_data(0x01)
self.send_data(0xC0)
self.send_command(self.DATA_START_TRANSMISSION_1)
for i in range(0, int(self.height)):
for j in range(0, int(self.width / 2)):
self.send_data((frame_buffer[j + (int(self.width / 2) * i)]))
self.send_command(self.POWER_ON)
self.wait_until_busy()
self.send_command(self.DISPLAY_REFRESH)
self.wait_until_busy()
self.send_command(self.POWER_OFF)
self.wait_until_idle()
self.delay_ms(500)

def sleep(self):
self.delay_ms(500)
self.send_command(self.DEEP_SLEEP)
self.send_data(0XA5)
self.digital_write(self.RST_PIN, 0)


# This is a 'monochrome' display but surprisingly, the only difference to EPD7in5b is
# setting a different resolution in init() (after TCON_RESOLUTION command),
# thus, it is here and a subclass of EPD7in5b (for now).
Expand Down
1 change: 1 addition & 0 deletions papertty.py
Expand Up @@ -411,6 +411,7 @@ def get_drivers():

drivers_color.EPD4in2b, drivers_color.EPD7in5b,
drivers_color.EPD5in83, drivers_color.EPD5in83b,
drivers_color.EPD5in65f,

drivers_colordraw.EPD1in54b, drivers_colordraw.EPD1in54c,
drivers_colordraw.EPD2in13b, drivers_colordraw.EPD2in7b,
Expand Down

0 comments on commit 30f18c3

Please sign in to comment.