From c93b2039606e54d0297e8ef4386267c6fd0824d3 Mon Sep 17 00:00:00 2001 From: Fabian Pammer Date: Thu, 6 Aug 2020 17:14:06 +0200 Subject: [PATCH 1/3] Add support for new Waveshare 5.65 inch 7 color e-paper display (based on waveshare python example) --- drivers/drivers_color.py | 148 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/drivers/drivers_color.py b/drivers/drivers_color.py index 270fbda..7d2b4d6 100644 --- a/drivers/drivers_color.py +++ b/drivers/drivers_color.py @@ -224,6 +224,154 @@ 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) + image_rgb = image.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). From dffc5acc07ad946f0b558b020d5e3133c0d87ca7 Mon Sep 17 00:00:00 2001 From: Fabian Pammer Date: Sun, 9 Aug 2020 13:35:30 +0200 Subject: [PATCH 2/3] Add new driver to driver list --- papertty.py | 1 + 1 file changed, 1 insertion(+) diff --git a/papertty.py b/papertty.py index b6baad9..1f2235d 100755 --- a/papertty.py +++ b/papertty.py @@ -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, From 35d4898a1041ed78f3d087917e59379f706048b5 Mon Sep 17 00:00:00 2001 From: Fabian Pammer Date: Sun, 9 Aug 2020 18:27:38 +0200 Subject: [PATCH 3/3] Add image quantization to the (limited) palette of the e-paper module --- drivers/drivers_color.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/drivers_color.py b/drivers/drivers_color.py index 7d2b4d6..e3f8a58 100644 --- a/drivers/drivers_color.py +++ b/drivers/drivers_color.py @@ -15,6 +15,7 @@ # along with this program. If not, see . from drivers.drivers_full import WaveshareFull +from PIL import Image class WaveshareColor(WaveshareFull): @@ -313,7 +314,13 @@ def init(self, **kwargs): def get_frame_buffer(self, image, reverse=False): buf = [0x00] * int(self.width * self.height / 2) - image_rgb = image.convert('RGB') + + # 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: