#!/usr/bin/python # -*- coding:utf-8 -*- # ***************************************************************************** # * | File : epd5in65f.py # * | Author : Waveshare team # * | Function : Electronic paper driver # * | Info : # *---------------- # * | This version: V1.0 # * | Date : 2020-03-02 # # | Info : python demo # ----------------------------------------------------------------------------- # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documnetation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # import logging from . import epdconfig import PIL from PIL import Image import io # Display resolution EPD_WIDTH = 600 EPD_HEIGHT = 448 logger = logging.getLogger(__name__) class EPD: def __init__(self): self.reset_pin = epdconfig.RST_PIN self.dc_pin = epdconfig.DC_PIN self.busy_pin = epdconfig.BUSY_PIN self.cs_pin = epdconfig.CS_PIN self.width = EPD_WIDTH self.height = EPD_HEIGHT self.BLACK = 0x000000 # 0000 BGR self.WHITE = 0xffffff # 0001 self.GREEN = 0x00ff00 # 0010 self.BLUE = 0xff0000 # 0011 self.RED = 0x0000ff # 0100 self.YELLOW = 0x00ffff # 0101 self.ORANGE = 0x0080ff # 0110 # Hardware reset def reset(self): epdconfig.digital_write(self.reset_pin, 1) epdconfig.delay_ms(600) epdconfig.digital_write(self.reset_pin, 0) epdconfig.delay_ms(2) epdconfig.digital_write(self.reset_pin, 1) epdconfig.delay_ms(200) def send_command(self, command): epdconfig.digital_write(self.dc_pin, 0) epdconfig.digital_write(self.cs_pin, 0) epdconfig.spi_writebyte([command]) epdconfig.digital_write(self.cs_pin, 1) def send_data(self, data): epdconfig.digital_write(self.dc_pin, 1) epdconfig.digital_write(self.cs_pin, 0) epdconfig.spi_writebyte([data]) epdconfig.digital_write(self.cs_pin, 1) def send_data_bulk(self, data): epdconfig.digital_write(self.dc_pin, 1) epdconfig.digital_write(self.cs_pin, 0) epdconfig.spi_writebyte2(data) epdconfig.digital_write(self.cs_pin, 1) def ReadBusyHigh(self): logger.debug("e-Paper busy") while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy epdconfig.delay_ms(100) logger.debug("e-Paper busy release") def ReadBusyLow(self): logger.debug("e-Paper busy") while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy epdconfig.delay_ms(100) logger.debug("e-Paper busy release") def init(self): if (epdconfig.module_init() != 0): return -1 # EPD hardware init start self.reset() self.ReadBusyHigh() self.send_command(0x00) self.send_data(0xEF) self.send_data(0x08) self.send_command(0x01) self.send_data(0x37) self.send_data(0x00) self.send_data(0x23) self.send_data(0x23) self.send_command(0x03) self.send_data(0x00) self.send_command(0x06) self.send_data(0xC7) self.send_data(0xC7) self.send_data(0x1D) self.send_command(0x30) self.send_data(0x3c) self.send_command(0x41) self.send_data(0x00) self.send_command(0x50) self.send_data(0x37) self.send_command(0x60) self.send_data(0x22) self.send_command(0x61) self.send_data(0x02) self.send_data(0x58) self.send_data(0x01) self.send_data(0xC0) self.send_command(0xE3) self.send_data(0xAA) epdconfig.delay_ms(100) self.send_command(0x50) self.send_data(0x37) # EPD hardware init end return 0 def getbuffer(self, image): # Create a pallette with the 7 colors supported by the panel pal_image = Image.new("P", (1,1)) pal_image.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)*249) # Check if we need to rotate the image imwidth, imheight = image.size if(imwidth == self.width and imheight == self.height): image_temp = image elif(imwidth == self.height and imheight == self.width): image_temp = image.rotate(90, expand=True) else: logger.warning("Invalid image dimensions: %d x %d, expected %d x %d" % (imwidth, imheight, self.width, self.height)) # Convert the soruce image to the 7 colors, dithering if needed image_7color = image_temp.convert("RGB").quantize(palette=pal_image) buf_7color = bytearray(image_7color.tobytes('raw')) # PIL does not support 4 bit color, so pack the 4 bits of color # into a single byte to transfer to the panel buf = [0x00] * int(self.width * self.height / 2) idx = 0 for i in range(0, len(buf_7color), 2): buf[idx] = (buf_7color[i] << 4) + buf_7color[i+1] idx += 1 return buf def display(self,image): self.send_command(0x61) #Set Resolution setting self.send_data(0x02) self.send_data(0x58) self.send_data(0x01) self.send_data(0xC0) self.send_command(0x10) self.send_data_bulk(image) self.send_command(0x04) #0x04 self.ReadBusyHigh() self.send_command(0x12) #0x12 self.ReadBusyHigh() self.send_command(0x02) #0x02 self.ReadBusyLow() epdconfig.delay_ms(500) def Clear(self): self.send_command(0x61) #Set Resolution setting self.send_data(0x02) self.send_data(0x58) self.send_data(0x01) self.send_data(0xC0) self.send_command(0x10) # Set all pixels to white buf = [0x11] * int(self.width * self.height / 2) self.send_data_bulk(buf) self.send_command(0x04) #0x04 self.ReadBusyHigh() self.send_command(0x12) #0x12 self.ReadBusyHigh() self.send_command(0x02) #0x02 self.ReadBusyLow() epdconfig.delay_ms(500) def sleep(self): epdconfig.delay_ms(500) self.send_command(0x07) # DEEP_SLEEP self.send_data(0XA5) epdconfig.digital_write(self.reset_pin, 0) epdconfig.delay_ms(2000) epdconfig.module_exit()