commit
96f99419a6
@ -180,5 +180,5 @@ EOF
|
||||
fi
|
||||
|
||||
echo -e "\e[1;36m"You can test if the programm works by running:"\e[0m"
|
||||
echo -e "\e[1;36m"python3 /home/"$USER"/Inky-Calendar/Calendar/inkycal.py"\e[0m"
|
||||
echo -e "\e[1;36m"python3 /home/"$USER"/Inky-Calendar/modules/inkycal.py"\e[0m"
|
||||
fi
|
||||
|
478
modules/drivers/epd_4_in_2.py
Normal file
478
modules/drivers/epd_4_in_2.py
Normal file
@ -0,0 +1,478 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd4in2.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
from PIL import Image
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 400
|
||||
EPD_HEIGHT = 300
|
||||
|
||||
GRAY1 = 0xff #white
|
||||
GRAY2 = 0xC0
|
||||
GRAY3 = 0x80 #gray
|
||||
GRAY4 = 0x00 #Blackest
|
||||
|
||||
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.GRAY1 = GRAY1 #white
|
||||
self.GRAY2 = GRAY2
|
||||
self.GRAY3 = GRAY3 #gray
|
||||
self.GRAY4 = GRAY4 #Blackest
|
||||
|
||||
lut_vcom0 = [
|
||||
0x00, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x00, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_ww = [
|
||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_bw = [
|
||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_wb = [
|
||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_bb = [
|
||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
|
||||
#******************************gray*********************************/
|
||||
#0~3 gray
|
||||
EPD_4IN2_4Gray_lut_vcom =[
|
||||
0x00 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
|
||||
0x60 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
|
||||
0x00 ,0x14 ,0x00 ,0x00 ,0x00 ,0x01,
|
||||
0x00 ,0x13 ,0x0A ,0x01 ,0x00 ,0x01,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
|
||||
]
|
||||
#R21
|
||||
EPD_4IN2_4Gray_lut_ww =[
|
||||
0x40 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
|
||||
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
|
||||
0x10 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
|
||||
0xA0 ,0x13 ,0x01 ,0x00 ,0x00 ,0x01,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
]
|
||||
#R22H r
|
||||
EPD_4IN2_4Gray_lut_bw =[
|
||||
0x40 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
|
||||
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
|
||||
0x00 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
|
||||
0x99 ,0x0C ,0x01 ,0x03 ,0x04 ,0x01,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
]
|
||||
#R23H w
|
||||
EPD_4IN2_4Gray_lut_wb =[
|
||||
0x40 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
|
||||
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
|
||||
0x00 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
|
||||
0x99 ,0x0B ,0x04 ,0x04 ,0x01 ,0x01,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
]
|
||||
#R24H b
|
||||
EPD_4IN2_4Gray_lut_bb =[
|
||||
0x80 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
|
||||
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
|
||||
0x20 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
|
||||
0x50 ,0x13 ,0x01 ,0x00 ,0x00 ,0x01,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
|
||||
]
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, 0)
|
||||
epdconfig.delay_ms(10)
|
||||
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 ReadBusy(self):
|
||||
self.send_command(0x71)
|
||||
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
|
||||
self.send_command(0x71)
|
||||
epdconfig.delay_ms(100)
|
||||
|
||||
def set_lut(self):
|
||||
self.send_command(0x20) # vcom
|
||||
for count in range(0, 44):
|
||||
self.send_data(self.lut_vcom0[count])
|
||||
|
||||
self.send_command(0x21) # ww --
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_ww[count])
|
||||
|
||||
self.send_command(0x22) # bw r
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_bw[count])
|
||||
|
||||
self.send_command(0x23) # wb w
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_bb[count])
|
||||
|
||||
self.send_command(0x24) # bb b
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_wb[count])
|
||||
|
||||
def Gray_SetLut(self):
|
||||
self.send_command(0x20) #vcom
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.EPD_4IN2_4Gray_lut_vcom[count])
|
||||
|
||||
self.send_command(0x21) #red not use
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.EPD_4IN2_4Gray_lut_ww[count])
|
||||
|
||||
self.send_command(0x22) #bw r
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.EPD_4IN2_4Gray_lut_bw[count])
|
||||
|
||||
self.send_command(0x23) #wb w
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.EPD_4IN2_4Gray_lut_wb[count])
|
||||
|
||||
self.send_command(0x24) #bb b
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.EPD_4IN2_4Gray_lut_bb[count])
|
||||
|
||||
self.send_command(0x25) #vcom
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.EPD_4IN2_4Gray_lut_ww[count])
|
||||
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
# EPD hardware init start
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01) # POWER SETTING
|
||||
self.send_data(0x03) # VDS_EN, VDG_EN
|
||||
self.send_data(0x00) # VCOM_HV, VGHL_LV[1], VGHL_LV[0]
|
||||
self.send_data(0x2b) # VDH
|
||||
self.send_data(0x2b) # VDL
|
||||
|
||||
self.send_command(0x06) # boost soft start
|
||||
self.send_data(0x17)
|
||||
self.send_data(0x17)
|
||||
self.send_data(0x17)
|
||||
|
||||
self.send_command(0x04) # POWER_ON
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x00) # panel setting
|
||||
self.send_data(0xbf) # KW-BF KWR-AF BWROTP 0f
|
||||
self.send_data(0x0d)
|
||||
|
||||
self.send_command(0x30) # PLL setting
|
||||
self.send_data(0x3c) # 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
|
||||
|
||||
self.send_command(0x61) # resolution setting
|
||||
self.send_data(0x01)
|
||||
self.send_data(0x90) # 128
|
||||
self.send_data(0x01)
|
||||
self.send_data(0x2c)
|
||||
|
||||
self.send_command(0x82) # vcom_DC setting
|
||||
self.send_data(0x28)
|
||||
|
||||
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
|
||||
self.send_data(0x97) # 97white border 77black border VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
|
||||
|
||||
self.set_lut()
|
||||
# EPD hardware init end
|
||||
return 0
|
||||
|
||||
def Init_4Gray(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
# EPD hardware init start
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01) #POWER SETTING
|
||||
self.send_data (0x03)
|
||||
self.send_data (0x00) #VGH=20V,VGL=-20V
|
||||
self.send_data (0x2b) #VDH=15V
|
||||
self.send_data (0x2b) #VDL=-15V
|
||||
self.send_data (0x13)
|
||||
|
||||
self.send_command(0x06) #booster soft start
|
||||
self.send_data (0x17) #A
|
||||
self.send_data (0x17) #B
|
||||
self.send_data (0x17) #C
|
||||
|
||||
self.send_command(0x04)
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x00) #panel setting
|
||||
self.send_data(0x3f) #KW-3f KWR-2F BWROTP 0f BWOTP 1f
|
||||
|
||||
self.send_command(0x30) #PLL setting
|
||||
self.send_data (0x3c) #100hz
|
||||
|
||||
self.send_command(0x61) #resolution setting
|
||||
self.send_data (0x01) #400
|
||||
self.send_data (0x90)
|
||||
self.send_data (0x01) #300
|
||||
self.send_data (0x2c)
|
||||
|
||||
self.send_command(0x82) #vcom_DC setting
|
||||
self.send_data (0x12)
|
||||
|
||||
self.send_command(0X50) #VCOM AND DATA INTERVAL SETTING
|
||||
self.send_data(0x97)
|
||||
|
||||
def getbuffer(self, image):
|
||||
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
|
||||
buf = [0xFF] * (int(self.width/8) * self.height)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
logging.debug("Horizontal")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
logging.debug("Vertical")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
|
||||
return buf
|
||||
|
||||
def getbuffer_4Gray(self, image):
|
||||
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
|
||||
buf = [0xFF] * (int(self.width / 4) * self.height)
|
||||
image_monocolor = image.convert('L')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
i=0
|
||||
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
logging.debug("Vertical")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if(pixels[x, y] == 0xC0):
|
||||
pixels[x, y] = 0x80
|
||||
elif (pixels[x, y] == 0x80):
|
||||
pixels[x, y] = 0x40
|
||||
i= i+1
|
||||
if(i%4 == 0):
|
||||
buf[int((x + (y * self.width))/4)] = ((pixels[x-3, y]&0xc0) | (pixels[x-2, y]&0xc0)>>2 | (pixels[x-1, y]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6)
|
||||
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
logging.debug("Horizontal")
|
||||
for x in range(imwidth):
|
||||
for y in range(imheight):
|
||||
newx = y
|
||||
newy = x
|
||||
if(pixels[x, y] == 0xC0):
|
||||
pixels[x, y] = 0x80
|
||||
elif (pixels[x, y] == 0x80):
|
||||
pixels[x, y] = 0x40
|
||||
i= i+1
|
||||
if(i%4 == 0):
|
||||
buf[int((newx + (newy * self.width))/4)] = ((pixels[x, y-3]&0xc0) | (pixels[x, y-2]&0xc0)>>2 | (pixels[x, y-1]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6)
|
||||
|
||||
return buf
|
||||
|
||||
def display(self, image):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0xFF)
|
||||
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(image[i])
|
||||
|
||||
self.send_command(0x12)
|
||||
self.ReadBusy()
|
||||
|
||||
def display_4Gray(self, image):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, EPD_WIDTH * EPD_HEIGHT / 8): # EPD_WIDTH * EPD_HEIGHT / 4
|
||||
temp3=0
|
||||
for j in range(0, 2):
|
||||
temp1 = image[i*2+j]
|
||||
for k in range(0, 2):
|
||||
temp2 = temp1&0xC0
|
||||
if(temp2 == 0xC0):
|
||||
temp3 |= 0x01#white
|
||||
elif(temp2 == 0x00):
|
||||
temp3 |= 0x00 #black
|
||||
elif(temp2 == 0x80):
|
||||
temp3 |= 0x01 #gray1
|
||||
else: #0x40
|
||||
temp3 |= 0x00 #gray2
|
||||
temp3 <<= 1
|
||||
|
||||
temp1 <<= 2
|
||||
temp2 = temp1&0xC0
|
||||
if(temp2 == 0xC0): #white
|
||||
temp3 |= 0x01
|
||||
elif(temp2 == 0x00): #black
|
||||
temp3 |= 0x00
|
||||
elif(temp2 == 0x80):
|
||||
temp3 |= 0x01 #gray1
|
||||
else : #0x40
|
||||
temp3 |= 0x00 #gray2
|
||||
if(j!=1 or k!=1):
|
||||
temp3 <<= 1
|
||||
temp1 <<= 2
|
||||
self.send_data(temp3)
|
||||
|
||||
self.send_command(0x13)
|
||||
|
||||
for i in range(0, EPD_WIDTH * EPD_HEIGHT / 8): #5808*4 46464
|
||||
temp3=0
|
||||
for j in range(0, 2):
|
||||
temp1 = image[i*2+j]
|
||||
for k in range(0, 2):
|
||||
temp2 = temp1&0xC0
|
||||
if(temp2 == 0xC0):
|
||||
temp3 |= 0x01#white
|
||||
elif(temp2 == 0x00):
|
||||
temp3 |= 0x00 #black
|
||||
elif(temp2 == 0x80):
|
||||
temp3 |= 0x00 #gray1
|
||||
else: #0x40
|
||||
temp3 |= 0x01 #gray2
|
||||
temp3 <<= 1
|
||||
|
||||
temp1 <<= 2
|
||||
temp2 = temp1&0xC0
|
||||
if(temp2 == 0xC0): #white
|
||||
temp3 |= 0x01
|
||||
elif(temp2 == 0x00): #black
|
||||
temp3 |= 0x00
|
||||
elif(temp2 == 0x80):
|
||||
temp3 |= 0x00 #gray1
|
||||
else: #0x40
|
||||
temp3 |= 0x01 #gray2
|
||||
if(j!=1 or k!=1):
|
||||
temp3 <<= 1
|
||||
temp1 <<= 2
|
||||
self.send_data(temp3)
|
||||
|
||||
self.Gray_SetLut()
|
||||
self.send_command(0x12)
|
||||
epdconfig.delay_ms(200)
|
||||
self.ReadBusy()
|
||||
# pass
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0xFF)
|
||||
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0xFF)
|
||||
|
||||
self.send_command(0x12)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0XA5)
|
||||
|
||||
epdconfig.module_exit()
|
||||
|
||||
### END OF FILE ###
|
||||
|
148
modules/drivers/epd_4_in_2_colour.py
Normal file
148
modules/drivers/epd_4_in_2_colour.py
Normal file
@ -0,0 +1,148 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd4in2bc.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 400
|
||||
EPD_HEIGHT = 300
|
||||
|
||||
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
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, 0)
|
||||
epdconfig.delay_ms(10)
|
||||
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 ReadBusy(self):
|
||||
logging.debug("e-Paper busy")
|
||||
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
|
||||
epdconfig.delay_ms(100)
|
||||
logging.debug("e-Paper busy release")
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x06) # BOOSTER_SOFT_START
|
||||
self.send_data (0x17)
|
||||
self.send_data (0x17)
|
||||
self.send_data (0x17) # 07 0f 17 1f 27 2F 37 2f
|
||||
|
||||
self.send_command(0x04) # POWER_ON
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x00) # PANEL_SETTING
|
||||
self.send_data(0x0F) # LUT from OTP
|
||||
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
|
||||
buf = [0xFF] * (int(self.width/8) * self.height)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
logging.debug("Horizontal")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
logging.debug("Vertical")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
|
||||
return buf
|
||||
|
||||
def display(self, imageblack, imagered):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(imageblack[i])
|
||||
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(imagered[i])
|
||||
|
||||
self.send_command(0x12)
|
||||
self.ReadBusy()
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0xFF)
|
||||
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0xFF)
|
||||
|
||||
self.send_command(0x12)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0xA5) # check code
|
||||
|
||||
epdconfig.module_exit()
|
||||
### END OF FILE ###
|
||||
|
200
modules/drivers/epd_5_in_83.py
Normal file
200
modules/drivers/epd_5_in_83.py
Normal file
@ -0,0 +1,200 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd5in83.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 600
|
||||
EPD_HEIGHT = 448
|
||||
|
||||
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
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, 0)
|
||||
epdconfig.delay_ms(10)
|
||||
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 ReadBusy(self):
|
||||
logging.debug("e-Paper busy")
|
||||
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
|
||||
epdconfig.delay_ms(100)
|
||||
logging.debug("e-Paper busy release")
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
# EPD hardware init start
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01) # POWER_SETTING
|
||||
self.send_data(0x37)
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x00) # PANEL_SETTING
|
||||
self.send_data(0xCF)
|
||||
self.send_data(0x08)
|
||||
|
||||
self.send_command(0x06) # BOOSTER_SOFT_START
|
||||
self.send_data(0xc7)
|
||||
self.send_data(0xcc)
|
||||
self.send_data(0x28)
|
||||
|
||||
self.send_command(0x04) # POWER_ON
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x30) # PLL_CONTROL
|
||||
self.send_data(0x3c)
|
||||
|
||||
self.send_command(0x41) # TEMPERATURE_CALIBRATION
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x50) # VCOM_AND_DATA_INTERVAL_SETTING
|
||||
self.send_data(0x77)
|
||||
|
||||
self.send_command(0x60) # TCON_SETTING
|
||||
self.send_data(0x22)
|
||||
|
||||
self.send_command(0x61) # TCON_RESOLUTION
|
||||
self.send_data(0x02) # source 600
|
||||
self.send_data(0x58)
|
||||
self.send_data(0x01) # gate 448
|
||||
self.send_data(0xC0)
|
||||
|
||||
self.send_command(0x82) # VCM_DC_SETTING
|
||||
self.send_data(0x1E) # decide by LUT file
|
||||
|
||||
self.send_command(0xe5) # FLASH MODE
|
||||
self.send_data(0x03)
|
||||
|
||||
# EPD hardware init end
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
buf = [0x00] * int(self.width * self.height / 4)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] < 64: # black
|
||||
buf[int((x + y * self.width) / 4)] &= ~(0xC0 >> (x % 4 * 2))
|
||||
elif pixels[x, y] < 192: # convert gray to red
|
||||
buf[int((x + y * self.width) / 4)] &= ~(0xC0 >> (x % 4 * 2))
|
||||
buf[int((x + y * self.width) / 4)] |= 0x40 >> (x % 4 * 2)
|
||||
else: # white
|
||||
buf[int((x + y * self.width) / 4)] |= 0xC0 >> (x % 4 * 2)
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] < 64: # black
|
||||
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
|
||||
elif pixels[x, y] < 192: # convert gray to red
|
||||
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
|
||||
buf[int((newx + newy*self.width) / 4)] |= 0x40 >> (y % 4 * 2)
|
||||
else: # white
|
||||
buf[int((newx + newy*self.width) / 4)] |= 0xC0 >> (y % 4 * 2)
|
||||
return buf
|
||||
|
||||
def display(self, image):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 4 * self.height)):
|
||||
temp1 = image[i]
|
||||
j = 0
|
||||
while (j < 4):
|
||||
if ((temp1 & 0xC0) == 0xC0):
|
||||
temp2 = 0x03
|
||||
elif ((temp1 & 0xC0) == 0x00):
|
||||
temp2 = 0x00
|
||||
else:
|
||||
temp2 = 0x04
|
||||
temp2 = (temp2 << 4) & 0xFF
|
||||
temp1 = (temp1 << 2) & 0xFF
|
||||
j += 1
|
||||
if((temp1 & 0xC0) == 0xC0):
|
||||
temp2 |= 0x03
|
||||
elif ((temp1 & 0xC0) == 0x00):
|
||||
temp2 |= 0x00
|
||||
else:
|
||||
temp2 |= 0x04
|
||||
temp1 = (temp1 << 2) & 0xFF
|
||||
self.send_data(temp2)
|
||||
j += 1
|
||||
|
||||
self.send_command(0x12)
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 4 * self.height)):
|
||||
for j in range(0, 4):
|
||||
self.send_data(0x33)
|
||||
self.send_command(0x12)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0XA5)
|
||||
|
||||
epdconfig.module_exit()
|
||||
|
||||
### END OF FILE ###
|
||||
|
200
modules/drivers/epd_5_in_83_colour.py
Normal file
200
modules/drivers/epd_5_in_83_colour.py
Normal file
@ -0,0 +1,200 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd5in83b.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 600
|
||||
EPD_HEIGHT = 448
|
||||
|
||||
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
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, 0)
|
||||
epdconfig.delay_ms(10)
|
||||
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 ReadBusy(self):
|
||||
logging.debug("e-Paper busy")
|
||||
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
|
||||
epdconfig.delay_ms(100)
|
||||
logging.debug("e-Paper busy release")
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01) # POWER_SETTING
|
||||
self.send_data(0x37)
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x00) # PANEL_SETTING
|
||||
self.send_data(0xCF)
|
||||
self.send_data(0x08)
|
||||
|
||||
self.send_command(0x30) # PLL_CONTROL
|
||||
self.send_data(0x3A) # PLL: 0-15:0x3C, 15+:0x3A
|
||||
self.send_command(0X82) # VCOM VOLTAGE SETTING
|
||||
self.send_data(0x28) # all temperature range
|
||||
|
||||
self.send_command(0x06) # boost
|
||||
self.send_data(0xc7)
|
||||
self.send_data(0xcc)
|
||||
self.send_data(0x15)
|
||||
|
||||
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
|
||||
self.send_data(0x77)
|
||||
|
||||
self.send_command(0X60) # TCON SETTING
|
||||
self.send_data(0x22)
|
||||
|
||||
self.send_command(0X65) # FLASH CONTROL
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x61) # tres
|
||||
self.send_data(0x02) # source 600
|
||||
self.send_data(0x58)
|
||||
self.send_data(0x01) # gate 448
|
||||
self.send_data(0xc0)
|
||||
|
||||
self.send_command(0xe5) # FLASH MODE
|
||||
self.send_data(0x03)
|
||||
self.send_data(0x03)
|
||||
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
|
||||
buf = [0xFF] * (int(self.width/8) * self.height)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
logging.debug("Horizontal")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
logging.debug("Vertical")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
|
||||
return buf
|
||||
|
||||
def display(self, imageblack, imagered):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 8 * self.height)):
|
||||
temp1 = imageblack[i]
|
||||
temp2 = imagered[i]
|
||||
j = 0
|
||||
while (j < 8):
|
||||
if ((temp2 & 0x80) == 0x00):
|
||||
temp3 = 0x04 #red
|
||||
elif ((temp1 & 0x80) == 0x00):
|
||||
temp3 = 0x00 #black
|
||||
else:
|
||||
temp3 = 0x03 #white
|
||||
|
||||
temp3 = (temp3 << 4) & 0xFF
|
||||
temp1 = (temp1 << 1) & 0xFF
|
||||
temp2 = (temp2 << 1) & 0xFF
|
||||
j += 1
|
||||
if((temp2 & 0x80) == 0x00):
|
||||
temp3 |= 0x04 #red
|
||||
elif ((temp1 & 0x80) == 0x00):
|
||||
temp3 |= 0x00 #black
|
||||
else:
|
||||
temp3 |= 0x03 #white
|
||||
temp1 = (temp1 << 1) & 0xFF
|
||||
temp2 = (temp2 << 1) & 0xFF
|
||||
self.send_data(temp3)
|
||||
j += 1
|
||||
|
||||
self.send_command(0x04) # POWER ON
|
||||
self.ReadBusy()
|
||||
self.send_command(0x12) # display refresh
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 8 * self.height)):
|
||||
self.send_data(0x33)
|
||||
self.send_data(0x33)
|
||||
self.send_data(0x33)
|
||||
self.send_data(0x33)
|
||||
|
||||
self.send_command(0x04) # POWER ON
|
||||
self.ReadBusy()
|
||||
self.send_command(0x12) # display refresh
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0xA5) # check code
|
||||
|
||||
epdconfig.module_exit()
|
||||
### END OF FILE ###
|
||||
|
202
modules/drivers/epd_7_in_5.py
Normal file
202
modules/drivers/epd_7_in_5.py
Normal file
@ -0,0 +1,202 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd7in5.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 640
|
||||
EPD_HEIGHT = 384
|
||||
|
||||
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
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, 0)
|
||||
epdconfig.delay_ms(10)
|
||||
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 ReadBusy(self):
|
||||
logging.debug("e-Paper busy")
|
||||
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
|
||||
epdconfig.delay_ms(100)
|
||||
logging.debug("e-Paper busy release")
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
# EPD hardware init start
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01) # POWER_SETTING
|
||||
self.send_data(0x37)
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x00) # PANEL_SETTING
|
||||
self.send_data(0xCF)
|
||||
self.send_data(0x08)
|
||||
|
||||
self.send_command(0x06) # BOOSTER_SOFT_START
|
||||
self.send_data(0xc7)
|
||||
self.send_data(0xcc)
|
||||
self.send_data(0x28)
|
||||
|
||||
self.send_command(0x04) # POWER_ON
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x30) # PLL_CONTROL
|
||||
self.send_data(0x3c)
|
||||
|
||||
self.send_command(0x41) # TEMPERATURE_CALIBRATION
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x50) # VCOM_AND_DATA_INTERVAL_SETTING
|
||||
self.send_data(0x77)
|
||||
|
||||
self.send_command(0x60) # TCON_SETTING
|
||||
self.send_data(0x22)
|
||||
|
||||
self.send_command(0x61) # TCON_RESOLUTION
|
||||
self.send_data(EPD_WIDTH >> 8) #source 640
|
||||
self.send_data(EPD_WIDTH & 0xff)
|
||||
self.send_data(EPD_HEIGHT >> 8) #gate 384
|
||||
self.send_data(EPD_HEIGHT & 0xff)
|
||||
|
||||
self.send_command(0x82) # VCM_DC_SETTING
|
||||
self.send_data(0x1E) # decide by LUT file
|
||||
|
||||
self.send_command(0xe5) # FLASH MODE
|
||||
self.send_data(0x03)
|
||||
|
||||
# EPD hardware init end
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
logging.debug("1234")
|
||||
buf = [0x00] * int(self.width * self.height / 4)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] < 64: # black
|
||||
buf[int((x + y * self.width) / 4)] &= ~(0xC0 >> (x % 4 * 2))
|
||||
elif pixels[x, y] < 192: # convert gray to red
|
||||
buf[int((x + y * self.width) / 4)] &= ~(0xC0 >> (x % 4 * 2))
|
||||
buf[int((x + y * self.width) / 4)] |= 0x40 >> (x % 4 * 2)
|
||||
else: # white
|
||||
buf[int((x + y * self.width) / 4)] |= 0xC0 >> (x % 4 * 2)
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] < 64: # black
|
||||
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
|
||||
elif pixels[x, y] < 192: # convert gray to red
|
||||
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
|
||||
buf[int((newx + newy*self.width) / 4)] |= 0x40 >> (y % 4 * 2)
|
||||
else: # white
|
||||
buf[int((newx + newy*self.width) / 4)] |= 0xC0 >> (y % 4 * 2)
|
||||
return buf
|
||||
|
||||
def display(self, image):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 4 * self.height)):
|
||||
temp1 = image[i]
|
||||
j = 0
|
||||
while (j < 4):
|
||||
if ((temp1 & 0xC0) == 0xC0):
|
||||
temp2 = 0x03
|
||||
elif ((temp1 & 0xC0) == 0x00):
|
||||
temp2 = 0x00
|
||||
else:
|
||||
temp2 = 0x04
|
||||
temp2 = (temp2 << 4) & 0xFF
|
||||
temp1 = (temp1 << 2) & 0xFF
|
||||
j += 1
|
||||
if((temp1 & 0xC0) == 0xC0):
|
||||
temp2 |= 0x03
|
||||
elif ((temp1 & 0xC0) == 0x00):
|
||||
temp2 |= 0x00
|
||||
else:
|
||||
temp2 |= 0x04
|
||||
temp1 = (temp1 << 2) & 0xFF
|
||||
self.send_data(temp2)
|
||||
j += 1
|
||||
|
||||
self.send_command(0x12)
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 4 * self.height)):
|
||||
for j in range(0, 4):
|
||||
self.send_data(0x33)
|
||||
|
||||
self.send_command(0x12)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0XA5)
|
||||
|
||||
epdconfig.module_exit()
|
||||
### END OF FILE ###
|
||||
|
201
modules/drivers/epd_7_in_5_colour.py
Normal file
201
modules/drivers/epd_7_in_5_colour.py
Normal file
@ -0,0 +1,201 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd7in5bc.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 640
|
||||
EPD_HEIGHT = 384
|
||||
|
||||
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
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, 0)
|
||||
epdconfig.delay_ms(10)
|
||||
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 ReadBusy(self):
|
||||
logging.debug("e-Paper busy")
|
||||
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
|
||||
epdconfig.delay_ms(100)
|
||||
logging.debug("e-Paper busy release")
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01) # POWER_SETTING
|
||||
self.send_data(0x37)
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x00) # PANEL_SETTING
|
||||
self.send_data(0xCF)
|
||||
self.send_data(0x08)
|
||||
|
||||
self.send_command(0x30) # PLL_CONTROL
|
||||
self.send_data(0x3A) # PLL: 0-15:0x3C, 15+:0x3A
|
||||
|
||||
self.send_command(0x82) # VCM_DC_SETTING
|
||||
self.send_data(0x28) #all temperature range
|
||||
|
||||
self.send_command(0x06) # BOOSTER_SOFT_START
|
||||
self.send_data(0xc7)
|
||||
self.send_data(0xcc)
|
||||
self.send_data(0x15)
|
||||
|
||||
self.send_command(0x50) # VCOM AND DATA INTERVAL SETTING
|
||||
self.send_data(0x77)
|
||||
|
||||
self.send_command(0x60) # TCON_SETTING
|
||||
self.send_data(0x22)
|
||||
|
||||
self.send_command(0x65) # FLASH CONTROL
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x61) # TCON_RESOLUTION
|
||||
self.send_data(self.width >> 8) # source 640
|
||||
self.send_data(self.width & 0xff)
|
||||
self.send_data(self.height >> 8) # gate 384
|
||||
self.send_data(self.height & 0xff)
|
||||
|
||||
self.send_command(0xe5) # FLASH MODE
|
||||
self.send_data(0x03)
|
||||
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
|
||||
buf = [0xFF] * (int(self.width/8) * self.height)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
logging.debug("Horizontal")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
logging.debug("Vertical")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
|
||||
return buf
|
||||
|
||||
def display(self, imageblack, imagered):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 8 * self.height)):
|
||||
temp1 = imageblack[i]
|
||||
temp2 = imagered[i]
|
||||
j = 0
|
||||
while (j < 8):
|
||||
if ((temp2 & 0x80) == 0x00):
|
||||
temp3 = 0x04 #red
|
||||
elif ((temp1 & 0x80) == 0x00):
|
||||
temp3 = 0x00 #black
|
||||
else:
|
||||
temp3 = 0x03 #white
|
||||
|
||||
temp3 = (temp3 << 4) & 0xFF
|
||||
temp1 = (temp1 << 1) & 0xFF
|
||||
temp2 = (temp2 << 1) & 0xFF
|
||||
j += 1
|
||||
if((temp2 & 0x80) == 0x00):
|
||||
temp3 |= 0x04 #red
|
||||
elif ((temp1 & 0x80) == 0x00):
|
||||
temp3 |= 0x00 #black
|
||||
else:
|
||||
temp3 |= 0x03 #white
|
||||
temp1 = (temp1 << 1) & 0xFF
|
||||
temp2 = (temp2 << 1) & 0xFF
|
||||
self.send_data(temp3)
|
||||
j += 1
|
||||
|
||||
self.send_command(0x04) # POWER ON
|
||||
self.ReadBusy()
|
||||
self.send_command(0x12) # display refresh
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width / 8 * self.height)):
|
||||
self.send_data(0x33)
|
||||
self.send_data(0x33)
|
||||
self.send_data(0x33)
|
||||
self.send_data(0x33)
|
||||
|
||||
self.send_command(0x04) # POWER ON
|
||||
self.ReadBusy()
|
||||
self.send_command(0x12) # display refresh
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0XA5)
|
||||
|
||||
epdconfig.module_exit()
|
||||
### END OF FILE ###
|
||||
|
170
modules/drivers/epd_7_in_5_v2.py
Normal file
170
modules/drivers/epd_7_in_5_v2.py
Normal file
@ -0,0 +1,170 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd7in5.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 800
|
||||
EPD_HEIGHT = 480
|
||||
|
||||
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
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
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 ReadBusy(self):
|
||||
logging.debug("e-Paper busy")
|
||||
self.send_command(0x71)
|
||||
busy = epdconfig.digital_read(self.busy_pin)
|
||||
while(busy == 0):
|
||||
self.send_command(0x71)
|
||||
busy = epdconfig.digital_read(self.busy_pin)
|
||||
epdconfig.delay_ms(200)
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
# EPD hardware init start
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01) #POWER SETTING
|
||||
self.send_data(0x07)
|
||||
self.send_data(0x07) #VGH=20V,VGL=-20V
|
||||
self.send_data(0x3f) #VDH=15V
|
||||
self.send_data(0x3f) #VDL=-15V
|
||||
|
||||
self.send_command(0x04) #POWER ON
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0X00) #PANNEL SETTING
|
||||
self.send_data(0x1F) #KW-3f KWR-2F BWROTP 0f BWOTP 1f
|
||||
|
||||
self.send_command(0x61) #tres
|
||||
self.send_data(0x03) #source 800
|
||||
self.send_data(0x20)
|
||||
self.send_data(0x01) #gate 480
|
||||
self.send_data(0xE0)
|
||||
|
||||
self.send_command(0X15)
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0X50) #VCOM AND DATA INTERVAL SETTING
|
||||
self.send_data(0x10)
|
||||
self.send_data(0x07)
|
||||
|
||||
self.send_command(0X60) #TCON SETTING
|
||||
self.send_data(0x22)
|
||||
|
||||
# EPD hardware init end
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
|
||||
buf = [0xFF] * (int(self.width/8) * self.height)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
logging.debug("Vertical")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
logging.debug("Horizontal")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
|
||||
return buf
|
||||
|
||||
def display(self, image):
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(~image[i]);
|
||||
|
||||
self.send_command(0x12)
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x12)
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0XA5)
|
||||
|
||||
epdconfig.module_exit()
|
||||
### END OF FILE ###
|
||||
|
173
modules/drivers/epd_7_in_5_v2_colour.py
Normal file
173
modules/drivers/epd_7_in_5_v2_colour.py
Normal file
@ -0,0 +1,173 @@
|
||||
# *****************************************************************************
|
||||
# * | File : epd7in5bc.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V4.0
|
||||
# * | Date : 2019-06-20
|
||||
# # | 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
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 800
|
||||
EPD_HEIGHT = 480
|
||||
|
||||
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
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, 1)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, 0)
|
||||
epdconfig.delay_ms(4)
|
||||
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 ReadBusy(self):
|
||||
logging.debug("e-Paper busy")
|
||||
self.send_command(0x71)
|
||||
busy = epdconfig.digital_read(self.busy_pin)
|
||||
while(busy == 0):
|
||||
self.send_command(0x71)
|
||||
busy = epdconfig.digital_read(self.busy_pin)
|
||||
epdconfig.delay_ms(200)
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
|
||||
self.reset()
|
||||
|
||||
self.send_command(0x01); #POWER SETTING
|
||||
self.send_data(0x07);
|
||||
self.send_data(0x07); #VGH=20V,VGL=-20V
|
||||
self.send_data(0x3f); #VDH=15V
|
||||
self.send_data(0x3f); #VDL=-15V
|
||||
|
||||
self.send_command(0x04); #POWER ON
|
||||
epdconfig.delay_ms(100);
|
||||
self.ReadBusy();
|
||||
|
||||
self.send_command(0X00); #PANNEL SETTING
|
||||
self.send_data(0x0F); #KW-3f KWR-2F BWROTP 0f BWOTP 1f
|
||||
|
||||
self.send_command(0x61); #tres
|
||||
self.send_data(0x03); #source 800
|
||||
self.send_data(0x20);
|
||||
self.send_data(0x01); #gate 480
|
||||
self.send_data(0xE0);
|
||||
|
||||
self.send_command(0X15);
|
||||
self.send_data(0x00);
|
||||
|
||||
self.send_command(0X50); #VCOM AND DATA INTERVAL SETTING
|
||||
self.send_data(0x11);
|
||||
self.send_data(0x07);
|
||||
|
||||
self.send_command(0X60); #TCON SETTING
|
||||
self.send_data(0x22);
|
||||
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
|
||||
buf = [0xFF] * (int(self.width/8) * self.height)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
logging.debug("Horizontal")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
logging.debug("Vertical")
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] == 0:
|
||||
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
|
||||
return buf
|
||||
|
||||
def display(self, imageblack, imagered):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(imageblack[i]);
|
||||
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(~imagered[i]);
|
||||
|
||||
self.send_command(0x12)
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def Clear(self):
|
||||
self.send_command(0x10)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0xff)
|
||||
|
||||
self.send_command(0x13)
|
||||
for i in range(0, int(self.width * self.height / 8)):
|
||||
self.send_data(0x00)
|
||||
|
||||
self.send_command(0x12)
|
||||
epdconfig.delay_ms(100)
|
||||
self.ReadBusy()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(0x02) # POWER_OFF
|
||||
self.ReadBusy()
|
||||
|
||||
self.send_command(0x07) # DEEP_SLEEP
|
||||
self.send_data(0XA5)
|
||||
|
||||
epdconfig.module_exit()
|
||||
### END OF FILE ###
|
||||
|
154
modules/drivers/epdconfig.py
Normal file
154
modules/drivers/epdconfig.py
Normal file
@ -0,0 +1,154 @@
|
||||
# /*****************************************************************************
|
||||
# * | File : epdconfig.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Hardware underlying interface
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V1.0
|
||||
# * | Date : 2019-06-21
|
||||
# * | Info :
|
||||
# ******************************************************************************
|
||||
# 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 os
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
class RaspberryPi:
|
||||
# Pin definition
|
||||
RST_PIN = 17
|
||||
DC_PIN = 25
|
||||
CS_PIN = 8
|
||||
BUSY_PIN = 24
|
||||
|
||||
def __init__(self):
|
||||
import spidev
|
||||
import RPi.GPIO
|
||||
|
||||
self.GPIO = RPi.GPIO
|
||||
|
||||
# SPI device, bus = 0, device = 0
|
||||
self.SPI = spidev.SpiDev(0, 0)
|
||||
|
||||
def digital_write(self, pin, value):
|
||||
self.GPIO.output(pin, value)
|
||||
|
||||
def digital_read(self, pin):
|
||||
return self.GPIO.input(pin)
|
||||
|
||||
def delay_ms(self, delaytime):
|
||||
time.sleep(delaytime / 1000.0)
|
||||
|
||||
def spi_writebyte(self, data):
|
||||
self.SPI.writebytes(data)
|
||||
|
||||
def module_init(self):
|
||||
self.GPIO.setmode(self.GPIO.BCM)
|
||||
self.GPIO.setwarnings(False)
|
||||
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
|
||||
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
||||
self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
|
||||
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
|
||||
self.SPI.max_speed_hz = 4000000
|
||||
self.SPI.mode = 0b00
|
||||
return 0
|
||||
|
||||
def module_exit(self):
|
||||
logging.debug("spi end")
|
||||
#self.SPI.close() #removed as it causes some problems
|
||||
|
||||
logging.debug("close 5V, Module enters 0 power consumption ...")
|
||||
self.GPIO.output(self.RST_PIN, 0)
|
||||
self.GPIO.output(self.DC_PIN, 0)
|
||||
|
||||
self.GPIO.cleanup()
|
||||
|
||||
|
||||
class JetsonNano:
|
||||
# Pin definition
|
||||
RST_PIN = 17
|
||||
DC_PIN = 25
|
||||
CS_PIN = 8
|
||||
BUSY_PIN = 24
|
||||
|
||||
def __init__(self):
|
||||
import ctypes
|
||||
find_dirs = [
|
||||
os.path.dirname(os.path.realpath(__file__)),
|
||||
'/usr/local/lib',
|
||||
'/usr/lib',
|
||||
]
|
||||
self.SPI = None
|
||||
for find_dir in find_dirs:
|
||||
so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')
|
||||
if os.path.exists(so_filename):
|
||||
self.SPI = ctypes.cdll.LoadLibrary(so_filename)
|
||||
break
|
||||
if self.SPI is None:
|
||||
raise RuntimeError('Cannot find sysfs_software_spi.so')
|
||||
|
||||
import Jetson.GPIO
|
||||
self.GPIO = Jetson.GPIO
|
||||
|
||||
def digital_write(self, pin, value):
|
||||
self.GPIO.output(pin, value)
|
||||
|
||||
def digital_read(self, pin):
|
||||
return self.GPIO.input(self.BUSY_PIN)
|
||||
|
||||
def delay_ms(self, delaytime):
|
||||
time.sleep(delaytime / 1000.0)
|
||||
|
||||
def spi_writebyte(self, data):
|
||||
self.SPI.SYSFS_software_spi_transfer(data[0])
|
||||
|
||||
def module_init(self):
|
||||
self.GPIO.setmode(self.GPIO.BCM)
|
||||
self.GPIO.setwarnings(False)
|
||||
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
|
||||
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
||||
self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
|
||||
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
|
||||
self.SPI.SYSFS_software_spi_begin()
|
||||
return 0
|
||||
|
||||
def module_exit(self):
|
||||
logging.debug("spi end")
|
||||
self.SPI.SYSFS_software_spi_end()
|
||||
|
||||
logging.debug("close 5V, Module enters 0 power consumption ...")
|
||||
self.GPIO.output(self.RST_PIN, 0)
|
||||
self.GPIO.output(self.DC_PIN, 0)
|
||||
|
||||
self.GPIO.cleanup()
|
||||
|
||||
|
||||
if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):
|
||||
implementation = RaspberryPi()
|
||||
else:
|
||||
implementation = JetsonNano()
|
||||
|
||||
for func in [x for x in dir(implementation) if not x.startswith('_')]:
|
||||
setattr(sys.modules[__name__], func, getattr(implementation, func))
|
||||
|
||||
|
||||
### END OF FILE ###
|
1
modules/drivers/init.py
Normal file
1
modules/drivers/init.py
Normal file
@ -0,0 +1 @@
|
||||
#nothing in here. What did you expect?
|
@ -1,28 +1,22 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Main script of Inky-Calendar software.
|
||||
v1.7.1
|
||||
|
||||
Main file of Inky-Calendar software. Creates dynamic images for each section,
|
||||
assembles them and sends it to the E-Paper
|
||||
|
||||
Copyright by aceisace
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from configuration import *
|
||||
from settings import *
|
||||
import arrow
|
||||
from time import sleep
|
||||
import gc
|
||||
import inkycal_drivers as drivers
|
||||
|
||||
import inkycal_rss as rss
|
||||
import inkycal_weather as weather
|
||||
import inkycal_calendar as calendar
|
||||
import inkycal_agenda as agenda
|
||||
|
||||
|
||||
display = drivers.EPD()
|
||||
skip_calibration = False
|
||||
|
||||
"""Perepare for execution of main programm"""
|
||||
calibration_countdown = 'initial'
|
||||
skip_calibration = False
|
||||
image_cleanup()
|
||||
|
||||
"""Check time and calibrate display if time """
|
||||
@ -36,8 +30,6 @@ while True:
|
||||
'D MMM YYYY'), now.format('HH:mm')))
|
||||
print('-----------Main programm started now----------')
|
||||
|
||||
|
||||
|
||||
"""------------------Calibration check----------------"""
|
||||
if skip_calibration != True:
|
||||
print('Calibration..', end = ' ')
|
||||
@ -45,10 +37,10 @@ while True:
|
||||
if calibration_countdown == 'initial':
|
||||
print('required. Performing calibration now.')
|
||||
calibration_countdown = 0
|
||||
display.calibrate_display(3)
|
||||
calibrate_display(3)
|
||||
else:
|
||||
if calibration_countdown % (60 // int(update_interval)) == 0:
|
||||
display.calibrate_display(3)
|
||||
calibrate_display(3)
|
||||
calibration_countdown = 0
|
||||
else:
|
||||
print('not required. Continuing...')
|
||||
@ -56,43 +48,50 @@ while True:
|
||||
print('Calibration skipped!. Please note that not calibrating e-paper',
|
||||
'displays causes ghosting')
|
||||
|
||||
|
||||
"""----------------Generating and assembling images------"""
|
||||
if top_section == 'Weather':
|
||||
try:
|
||||
weather.main()
|
||||
weather_image = Image.open(image_path + 'weather.png')
|
||||
image.paste(weather_image, (0, 0))
|
||||
top_section_module = importlib.import_module(top_section)
|
||||
top_section_image = Image.open(image_path + top_section+'.png')
|
||||
image.paste(top_section_image, (0, 0))
|
||||
except:
|
||||
pass
|
||||
|
||||
if middle_section == 'Calendar':
|
||||
try:
|
||||
calendar.main()
|
||||
calendar_image = Image.open(image_path + 'calendar.png')
|
||||
image.paste(calendar_image, (0, middle_section_offset))
|
||||
middle_section_module = importlib.import_module(middle_section)
|
||||
middle_section_image = Image.open(image_path + middle_section+'.png')
|
||||
image.paste(middle_section_image, (0, middle_section_offset))
|
||||
except:
|
||||
pass
|
||||
|
||||
if middle_section == 'Agenda':
|
||||
try:
|
||||
agenda.main()
|
||||
agenda_image = Image.open(image_path + 'agenda.png')
|
||||
image.paste(agenda_image, (0, middle_section_offset))
|
||||
except:
|
||||
pass
|
||||
|
||||
if bottom_section == 'RSS':
|
||||
try:
|
||||
rss.main()
|
||||
rss_image = Image.open(image_path + 'rss.png')
|
||||
image.paste(rss_image, (0, bottom_section_offset))
|
||||
bottom_section_module = importlib.import_module(bottom_section)
|
||||
bottom_section_image = Image.open(image_path + bottom_section+'.png')
|
||||
image.paste(bottom_section_image, (0, bottom_section_offset))
|
||||
except:
|
||||
pass
|
||||
|
||||
image.save(image_path + 'canvas.png')
|
||||
|
||||
"""---------Refreshing E-Paper with newly created image-----------"""
|
||||
display.show_image(image, reduce_colours= True)
|
||||
epaper = driver.EPD()
|
||||
print('Initialising E-Paper...', end = '')
|
||||
epaper.init()
|
||||
print('Done')
|
||||
|
||||
if three_colour_support == True:
|
||||
print('Sending image data and refreshing display...', end='')
|
||||
black_im, red_im = split_colours(image)
|
||||
epaper.display(epaper.getbuffer(black_im), epaper.getbuffer(red_im))
|
||||
print('Done')
|
||||
else:
|
||||
print('Sending image data and refreshing display...', end='')
|
||||
epaper.display(epaper.getbuffer(image.convert('1', dither=True)))
|
||||
print('Done')
|
||||
|
||||
print('Sending E-Paper to deep sleep...', end = '')
|
||||
epaper.sleep()
|
||||
print('Done')
|
||||
|
||||
"""--------------Post processing after main loop-----------------"""
|
||||
"""Collect some garbage to free up some resources"""
|
||||
@ -106,12 +105,15 @@ while True:
|
||||
"""Calculate duration until next display refresh"""
|
||||
for _ in range(1):
|
||||
update_timings = [(60 - int(update_interval)*updates) for updates in
|
||||
range(60//int(update_interval))]
|
||||
range(60//int(update_interval))][::-1]
|
||||
|
||||
minutes = [i - now.minute for i in update_timings if i >= now.minute]
|
||||
refresh_countdown = minutes[0]*60 + (60 - now.second)
|
||||
for _ in update_timings:
|
||||
if now.minute <= _:
|
||||
minutes = _ - now.minute
|
||||
break
|
||||
|
||||
print('{0} Minutes left until next refresh'.format(minutes[0]))
|
||||
refresh_countdown = minutes*60 + (60 - now.second)
|
||||
print('{0} Minutes left until next refresh'.format(minutes))
|
||||
|
||||
del update_timings, minutes, image
|
||||
sleep(refresh_countdown)
|
||||
|
@ -7,8 +7,6 @@ Copyright by aceisace
|
||||
from __future__ import print_function
|
||||
from inkycal_icalendar import fetch_events
|
||||
from configuration import*
|
||||
from settings import *
|
||||
import arrow
|
||||
|
||||
fontsize = 14
|
||||
show_events = True
|
||||
@ -45,7 +43,8 @@ else:
|
||||
line_pos = [(border_left, int(top_section_height + border_top + line * line_height))
|
||||
for line in range(max_lines)]
|
||||
|
||||
def main():
|
||||
def generate_image():
|
||||
if middle_section == 'inkycal_agenda' and internet_available() == True:
|
||||
try:
|
||||
clear_image('middle_section')
|
||||
if not bottom_section:
|
||||
@ -107,7 +106,7 @@ def main():
|
||||
|
||||
previous_date = agenda_events[events]['date']
|
||||
draw.line((date_col_start, line_pos[events][1],
|
||||
line_width,line_pos[events][1]), fill = 'red' if display_type == 'colour' else 'black')
|
||||
line_width,line_pos[events][1]), fill = 'red' if three_colour_support == True' else 'black')
|
||||
|
||||
elif agenda_events[events]['type'] == 'timed_event':
|
||||
write_text(time_col_width, line_height, agenda_events[events]['time'],
|
||||
@ -130,7 +129,7 @@ def main():
|
||||
else:
|
||||
agenda_image = image.crop((0,middle_section_offset,display_width, display_height))
|
||||
|
||||
agenda_image.save(image_path+'agenda.png')
|
||||
agenda_image.save(image_path+'inkycal_agenda.png')
|
||||
print('Done')
|
||||
|
||||
except Exception as e:
|
||||
@ -140,5 +139,7 @@ def main():
|
||||
print('Reason: ',e)
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
def main():
|
||||
generate_image()
|
||||
|
||||
main()
|
||||
|
@ -7,9 +7,6 @@ Copyright by aceisace
|
||||
from __future__ import print_function
|
||||
import calendar
|
||||
from configuration import *
|
||||
from settings import *
|
||||
import arrow
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
print_events = False
|
||||
show_events = True
|
||||
@ -68,7 +65,8 @@ max_event_lines = (events_height - border_top) // (font.getsize('hg')[1]
|
||||
event_lines = [(border_left,(bottom_section_offset - events_height)+
|
||||
int(events_height/max_event_lines*_)) for _ in range(max_event_lines)]
|
||||
|
||||
def main():
|
||||
def generate_image():
|
||||
if middle_section == "inkycal_calendar" and internet_available() == True:
|
||||
try:
|
||||
clear_image('middle_section')
|
||||
print('Calendar module: Generating image...', end = '')
|
||||
@ -114,7 +112,7 @@ def main():
|
||||
y_text = int((icon_height / 2) - (text_height / 1.7))
|
||||
ImageDraw.Draw(icon).ellipse((x_circle-radius, y_circle-radius,
|
||||
x_circle+radius, y_circle+radius), fill= 'red' if
|
||||
display_type == 'colour' else 'black', outline=None)
|
||||
three_colour_support == True else 'black', outline=None)
|
||||
ImageDraw.Draw(icon).text((x_text, y_text), str(now.day), fill='white',
|
||||
font=bold)
|
||||
image.paste(icon, current_day_pos, icon)
|
||||
@ -198,7 +196,7 @@ def main():
|
||||
events.end.format(style)), events.all_day)
|
||||
|
||||
calendar_image = crop_image(image, 'middle_section')
|
||||
calendar_image.save(image_path+'calendar.png')
|
||||
calendar_image.save(image_path+'inkycal_calendar.png')
|
||||
|
||||
print('Done')
|
||||
|
||||
@ -209,6 +207,7 @@ def main():
|
||||
print('Reason: ',e)
|
||||
pass
|
||||
|
||||
def main():
|
||||
generate_image()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -1,344 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Drivers file for Inky-Calendar software.
|
||||
Handles E-Paper display related tasks
|
||||
"""
|
||||
|
||||
from PIL import Image
|
||||
import RPi.GPIO as GPIO
|
||||
from settings import display_type
|
||||
import numpy
|
||||
import spidev
|
||||
import RPi.GPIO as GPIO
|
||||
from time import sleep
|
||||
|
||||
RST_PIN = 17
|
||||
DC_PIN = 25
|
||||
CS_PIN = 8
|
||||
BUSY_PIN = 24
|
||||
|
||||
EPD_WIDTH = 640
|
||||
EPD_HEIGHT = 384
|
||||
|
||||
SPI = spidev.SpiDev(0, 0)
|
||||
|
||||
def epd_digital_write(pin, value):
|
||||
GPIO.output(pin, value)
|
||||
|
||||
def epd_digital_read(pin):
|
||||
return GPIO.input(BUSY_PIN)
|
||||
|
||||
def epd_delay_ms(delaytime):
|
||||
sleep(delaytime / 1000.0)
|
||||
|
||||
def spi_transfer(data):
|
||||
SPI.writebytes(data)
|
||||
|
||||
def epd_init():
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setwarnings(False)
|
||||
GPIO.setup(RST_PIN, GPIO.OUT)
|
||||
GPIO.setup(DC_PIN, GPIO.OUT)
|
||||
GPIO.setup(CS_PIN, GPIO.OUT)
|
||||
GPIO.setup(BUSY_PIN, GPIO.IN)
|
||||
SPI.max_speed_hz = 4000000
|
||||
SPI.mode = 0b00
|
||||
return 0;
|
||||
|
||||
# EPD7IN5 commands
|
||||
PANEL_SETTING = 0x00
|
||||
POWER_SETTING = 0x01
|
||||
POWER_OFF = 0x02
|
||||
POWER_OFF_SEQUENCE_SETTING = 0x03
|
||||
POWER_ON = 0x04
|
||||
POWER_ON_MEASURE = 0x05
|
||||
BOOSTER_SOFT_START = 0x06
|
||||
DEEP_SLEEP = 0x07
|
||||
DATA_START_TRANSMISSION_1 = 0x10
|
||||
DATA_STOP = 0x11
|
||||
DISPLAY_REFRESH = 0x12
|
||||
IMAGE_PROCESS = 0x13
|
||||
LUT_FOR_VCOM = 0x20
|
||||
LUT_BLUE = 0x21
|
||||
LUT_WHITE = 0x22
|
||||
LUT_GRAY_1 = 0x23
|
||||
LUT_GRAY_2 = 0x24
|
||||
LUT_RED_0 = 0x25
|
||||
LUT_RED_1 = 0x26
|
||||
LUT_RED_2 = 0x27
|
||||
LUT_RED_3 = 0x28
|
||||
LUT_XON = 0x29
|
||||
PLL_CONTROL = 0x30
|
||||
TEMPERATURE_SENSOR_COMMAND = 0x40
|
||||
TEMPERATURE_CALIBRATION = 0x41
|
||||
TEMPERATURE_SENSOR_WRITE = 0x42
|
||||
TEMPERATURE_SENSOR_READ = 0x43
|
||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50
|
||||
LOW_POWER_DETECTION = 0x51
|
||||
TCON_SETTING = 0x60
|
||||
TCON_RESOLUTION = 0x61
|
||||
SPI_FLASH_CONTROL = 0x65
|
||||
REVISION = 0x70
|
||||
GET_STATUS = 0x71
|
||||
AUTO_MEASUREMENT_VCOM = 0x80
|
||||
READ_VCOM_VALUE = 0x81
|
||||
VCM_DC_SETTING = 0x82
|
||||
|
||||
class EPD:
|
||||
def __init__(self):
|
||||
self.reset_pin = RST_PIN
|
||||
self.dc_pin = DC_PIN
|
||||
self.busy_pin = BUSY_PIN
|
||||
self.width = EPD_WIDTH
|
||||
self.height = EPD_HEIGHT
|
||||
|
||||
def digital_write(self, pin, value):
|
||||
epd_digital_write(pin, value)
|
||||
|
||||
def digital_read(self, pin):
|
||||
return epd_digital_read(pin)
|
||||
|
||||
def delay_ms(self, delaytime):
|
||||
epd_delay_ms(delaytime)
|
||||
|
||||
def send_command(self, command):
|
||||
self.digital_write(self.dc_pin, GPIO.LOW)
|
||||
spi_transfer([command])
|
||||
|
||||
def send_data(self, data):
|
||||
self.digital_write(self.dc_pin, GPIO.HIGH)
|
||||
spi_transfer([data])
|
||||
|
||||
def init(self):
|
||||
if (epd_init() != 0):
|
||||
return -1
|
||||
self.reset()
|
||||
self.send_command(POWER_SETTING)
|
||||
self.send_data(0x37)
|
||||
self.send_data(0x00)
|
||||
self.send_command(PANEL_SETTING)
|
||||
self.send_data(0xCF)
|
||||
self.send_data(0x08)
|
||||
self.send_command(BOOSTER_SOFT_START)
|
||||
self.send_data(0xc7)
|
||||
self.send_data(0xcc)
|
||||
self.send_data(0x28)
|
||||
self.send_command(POWER_ON)
|
||||
self.wait_until_idle()
|
||||
self.send_command(PLL_CONTROL)
|
||||
self.send_data(0x3c)
|
||||
self.send_command(TEMPERATURE_CALIBRATION)
|
||||
self.send_data(0x00)
|
||||
self.send_command(VCOM_AND_DATA_INTERVAL_SETTING)
|
||||
self.send_data(0x77)
|
||||
self.send_command(TCON_SETTING)
|
||||
self.send_data(0x22)
|
||||
self.send_command(TCON_RESOLUTION)
|
||||
self.send_data(0x02) #source 640
|
||||
self.send_data(0x80)
|
||||
self.send_data(0x01) #gate 384
|
||||
self.send_data(0x80)
|
||||
self.send_command(VCM_DC_SETTING)
|
||||
self.send_data(0x1E) #decide by LUT file
|
||||
self.send_command(0xe5) #FLASH MODE
|
||||
self.send_data(0x03)
|
||||
|
||||
def wait_until_idle(self):
|
||||
while(self.digital_read(self.busy_pin) == 0): # 0: busy, 1: idle
|
||||
self.delay_ms(100)
|
||||
|
||||
def reset(self):
|
||||
self.digital_write(self.reset_pin, GPIO.LOW) # module reset
|
||||
self.delay_ms(200)
|
||||
self.digital_write(self.reset_pin, GPIO.HIGH)
|
||||
self.delay_ms(200)
|
||||
|
||||
def calibrate_display(self, no_of_cycles):
|
||||
"""Function for Calibration"""
|
||||
|
||||
if display_type == 'colour':
|
||||
packets = int(self.width / 2 * self.height)
|
||||
if display_type == 'black_and_white':
|
||||
packets = int(self.width / 4 * self.height)
|
||||
|
||||
white, red, black = 0x33, 0x04, 0x00
|
||||
|
||||
self.init()
|
||||
print('----------Started calibration of E-Paper display----------')
|
||||
for _ in range(no_of_cycles):
|
||||
self.send_command(DATA_START_TRANSMISSION_1)
|
||||
print('Calibrating black...')
|
||||
[self.send_data(black) for i in range(packets)]
|
||||
self.send_command(DISPLAY_REFRESH)
|
||||
self.wait_until_idle()
|
||||
|
||||
if display_type == 'colour':
|
||||
print('Calibrating red...')
|
||||
self.send_command(DATA_START_TRANSMISSION_1)
|
||||
[self.send_data(red) for i in range(packets)]
|
||||
self.send_command(DISPLAY_REFRESH)
|
||||
self.wait_until_idle()
|
||||
|
||||
print('Calibrating white...')
|
||||
self.send_command(DATA_START_TRANSMISSION_1)
|
||||
[self.send_data(white) for i in range(packets)]
|
||||
self.send_command(DISPLAY_REFRESH)
|
||||
self.wait_until_idle()
|
||||
|
||||
print('Cycle {0} of {1} complete'.format(_+1, no_of_cycles))
|
||||
|
||||
print('-----------Calibration complete----------')
|
||||
self.sleep()
|
||||
|
||||
def reduce_colours(self, image):
|
||||
buffer = numpy.array(image)
|
||||
r,g,b = buffer[:,:,0], buffer[:,:,1], buffer[:,:,2]
|
||||
|
||||
if display_type == "colour":
|
||||
buffer[numpy.logical_and(r <= 180, r == g)] = [0,0,0] #black
|
||||
buffer[numpy.logical_and(r >= 150, g >= 150)] = [255,255,255] #white
|
||||
buffer[numpy.logical_and(r >= 150, g <= 90)] = [255,0,0] #red
|
||||
|
||||
image = Image.fromarray(buffer)
|
||||
return image
|
||||
|
||||
def clear(self, colour='white'):
|
||||
if display_type == 'colour':
|
||||
packets = int(self.width / 2 * self.height)
|
||||
if display_type == 'black_and_white':
|
||||
packets = int(self.width / 4 * self.height)
|
||||
|
||||
if colour == 'white': data = 0x33
|
||||
if colour == 'red': data = 0x04
|
||||
if colour == 'black': data = 0x00
|
||||
|
||||
self.init()
|
||||
self.send_command(DATA_START_TRANSMISSION_1)
|
||||
[self.send_data(data) for _ in range(packets)]
|
||||
self.send_command(DISPLAY_REFRESH)
|
||||
print('waiting until E-Paper is not busy')
|
||||
self.delay_ms(100)
|
||||
self.wait_until_idle()
|
||||
print('E-Paper free')
|
||||
self.sleep()
|
||||
|
||||
def get_frame_buffer(self, image):
|
||||
imwidth, imheight = image.size
|
||||
if imwidth == self.height and imheight == self.width:
|
||||
image = image.rotate(270, expand = True)
|
||||
print('Rotated image by 270 degrees...', end= '')
|
||||
elif imwidth != self.width or imheight != self.height:
|
||||
raise ValueError('Image must be same dimensions as display \
|
||||
({0}x{1}).' .format(self.width, self.height))
|
||||
else:
|
||||
print('Image size OK')
|
||||
imwidth, imheight = image.size
|
||||
|
||||
if display_type == 'colour':
|
||||
buf = [0x00] * int(self.width * self.height / 4)
|
||||
image_grayscale = image.convert('L')
|
||||
pixels = image_grayscale.load()
|
||||
|
||||
for y in range(self.height):
|
||||
for x in range(self.width):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0: # black
|
||||
buf[int((x + y * self.width) / 4)] &= ~(0xC0 >> (x % 4 * 2))
|
||||
elif pixels[x, y] == 76: # convert gray to red
|
||||
buf[int((x + y * self.width) / 4)] &= ~(0xC0 >> (x % 4 * 2))
|
||||
buf[int((x + y * self.width) / 4)] |= 0x40 >> (x % 4 * 2)
|
||||
else: # white
|
||||
buf[int((x + y * self.width) / 4)] |= 0xC0 >> (x % 4 * 2)
|
||||
|
||||
if display_type == 'black_and_white':
|
||||
buf = [0x00] * int(self.width * self.height / 8)
|
||||
image_monocolor = image.convert('1', dither = True)
|
||||
|
||||
pixels = image_monocolor.load()
|
||||
for y in range(self.height):
|
||||
for x in range(self.width):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] != 0:
|
||||
buf[int((x + y * self.width) / 8)] |= 0x80 >> (x % 8)
|
||||
|
||||
return buf
|
||||
|
||||
def display_frame(self, frame_buffer):
|
||||
self.send_command(DATA_START_TRANSMISSION_1)
|
||||
if display_type == 'colour':
|
||||
for i in range(0, int(self.width / 4 * self.height)):
|
||||
temp1 = frame_buffer[i]
|
||||
j = 0
|
||||
while (j < 4):
|
||||
if ((temp1 & 0xC0) == 0xC0):
|
||||
temp2 = 0x03 #white
|
||||
elif ((temp1 & 0xC0) == 0x00):
|
||||
temp2 = 0x00 #black
|
||||
else:
|
||||
temp2 = 0x04 #red
|
||||
temp2 = (temp2 << 4) & 0xFF
|
||||
temp1 = (temp1 << 2) & 0xFF
|
||||
j += 1
|
||||
if((temp1 & 0xC0) == 0xC0):
|
||||
temp2 |= 0x03 #white
|
||||
elif ((temp1 & 0xC0) == 0x00):
|
||||
temp2 |= 0x00 #black
|
||||
else:
|
||||
temp2 |= 0x04 #red
|
||||
temp1 = (temp1 << 2) & 0xFF
|
||||
self.send_data(temp2)
|
||||
j += 1
|
||||
|
||||
if display_type == 'black_and_white':
|
||||
for i in range(0, 30720):
|
||||
temp1 = frame_buffer[i]
|
||||
j = 0
|
||||
while (j < 8):
|
||||
if(temp1 & 0x80):
|
||||
temp2 = 0x03 #white
|
||||
else:
|
||||
temp2 = 0x00 #black
|
||||
temp2 = (temp2 << 4) & 0xFF
|
||||
temp1 = (temp1 << 1) & 0xFF
|
||||
j += 1
|
||||
if(temp1 & 0x80):
|
||||
temp2 |= 0x03 #white
|
||||
else:
|
||||
temp2 |= 0x00 #black
|
||||
temp1 = (temp1 << 1) & 0xFF
|
||||
self.send_data(temp2)
|
||||
j += 1
|
||||
|
||||
self.send_command(DISPLAY_REFRESH)
|
||||
self.delay_ms(100)
|
||||
self.wait_until_idle()
|
||||
|
||||
def show_image(self, image, reduce_colours = True):
|
||||
print('Initialising E-Paper Display...', end='')
|
||||
self.init()
|
||||
sleep(5)
|
||||
print('Done')
|
||||
|
||||
if reduce_colours == True:
|
||||
print('Optimising Image for E-Paper displays...', end = '')
|
||||
image = self.reduce_colours(image)
|
||||
print('Done')
|
||||
else:
|
||||
print('No colour optimisation done on image')
|
||||
|
||||
print('Creating image buffer and sending it to E-Paper display...', end='')
|
||||
data = self.get_frame_buffer(image)
|
||||
print('Done')
|
||||
print('Refreshing display...', end = '')
|
||||
self.display_frame(data)
|
||||
print('Done')
|
||||
print('Sending E-Paper to deep sleep mode...',end='')
|
||||
self.sleep()
|
||||
print('Done')
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(POWER_OFF)
|
||||
self.wait_until_idle()
|
||||
self.send_command(DEEP_SLEEP)
|
||||
self.send_data(0xa5)
|
@ -44,8 +44,8 @@ def fetch_events():
|
||||
if events.all_day and events.duration.days > 1:
|
||||
events.end = events.end.replace(days=-2)
|
||||
else:
|
||||
events.begin = events.begin.to(timezone)
|
||||
events.end = events.end.to(timezone)
|
||||
events.begin = events.begin.to(timezone)
|
||||
try:
|
||||
rule = re.search('RRULE:(.+?)\n', event_str).group(0)[:-2]
|
||||
if re.search('UNTIL=(.+?);', rule) and not re.search('UNTIL=(.+?)Z;', rule):
|
||||
@ -76,8 +76,8 @@ def fetch_events():
|
||||
events.end = events.end.replace(days=-2)
|
||||
|
||||
if not events.all_day:
|
||||
events.begin = events.begin.to(timezone)
|
||||
events.end = events.end.to(timezone)
|
||||
events.begin = events.begin.to(timezone)
|
||||
|
||||
""" The list upcoming_events should not be modified. If you need the data from
|
||||
this one, copy the list or the contents to another one."""
|
||||
|
@ -7,7 +7,6 @@ Copyright by aceisace
|
||||
from __future__ import print_function
|
||||
import feedparser
|
||||
from random import shuffle
|
||||
from settings import *
|
||||
from configuration import *
|
||||
|
||||
fontsize = 14
|
||||
@ -33,8 +32,8 @@ y_padding = int( (bottom_section_height % line_height) / 2 )
|
||||
line_positions = [(border_left, bottom_section_offset +
|
||||
border_top + y_padding + _*line_height ) for _ in range(max_lines)]
|
||||
|
||||
def main():
|
||||
if bottom_section == "RSS" and rss_feeds != [] and internet_available() == True:
|
||||
def generate_image():
|
||||
if bottom_section == "inkycal_rss" and rss_feeds != [] and internet_available() == True:
|
||||
try:
|
||||
clear_image('bottom_section')
|
||||
print('RSS module: Connectivity check passed. Generating image...',
|
||||
@ -71,7 +70,7 @@ def main():
|
||||
del filtered_feeds, parsed_feeds
|
||||
|
||||
rss_image = crop_image(image, 'bottom_section')
|
||||
rss_image.save(image_path+'rss.png')
|
||||
rss_image.save(image_path+'inkycal_rss.png')
|
||||
print('Done')
|
||||
|
||||
except Exception as e:
|
||||
@ -81,5 +80,7 @@ def main():
|
||||
print('Reason: ',e)
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
def main():
|
||||
generate_image()
|
||||
|
||||
main()
|
||||
|
@ -10,10 +10,7 @@ Copyright by aceisace
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import pyowm
|
||||
from settings import *
|
||||
from configuration import *
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import arrow
|
||||
import math, decimal
|
||||
dec = decimal.Decimal
|
||||
|
||||
@ -130,7 +127,7 @@ def to_units(kelvin):
|
||||
return conversion
|
||||
|
||||
def red_temp(negative_temperature):
|
||||
if display_type == 'colour' and negative_temperature[0] == '-' and units == 'metric':
|
||||
if three_colour_support == True and negative_temperature[0] == '-' and units == 'metric':
|
||||
colour = 'red'
|
||||
else:
|
||||
colour = 'black'
|
||||
@ -160,9 +157,9 @@ while font.getsize('hg')[1] <= (row_height * fill_height):
|
||||
fontsize += 1
|
||||
font = ImageFont.truetype(NotoSans+'.ttf', fontsize)
|
||||
|
||||
def main():
|
||||
def generate_image():
|
||||
"""Connect to Openweathermap API and fetch weather data"""
|
||||
if top_section == "Weather" and api_key != "" and owm.is_API_online() is True:
|
||||
if top_section == "inkycal_weather" and api_key != "" and owm.is_API_online() is True:
|
||||
try:
|
||||
clear_image('top_section')
|
||||
print('Weather module: Connectivity check passed, Generating image...',
|
||||
@ -331,10 +328,10 @@ def main():
|
||||
draw.line((coloumn7, line_start_y, coloumn7, line_end_y), fill='black')
|
||||
draw.line((0, top_section_height-border_top, top_section_width-
|
||||
border_left, top_section_height-border_top),
|
||||
fill='red' if display_type == 'colour' else 'black' , width=3)
|
||||
fill='red' if three_colour_support == 'True' else 'black' , width=3)
|
||||
|
||||
weather_image = crop_image(image, 'top_section')
|
||||
weather_image.save(image_path+'weather.png')
|
||||
weather_image.save(image_path+'inkycal_weather.png')
|
||||
print('Done')
|
||||
|
||||
except Exception as e:
|
||||
@ -348,8 +345,10 @@ def main():
|
||||
write_text(coloumn_width*6, row_height, message, humidity_icon_now_pos,
|
||||
font = font)
|
||||
weather_image = crop_image(image, 'top_section')
|
||||
weather_image.save(image_path+'weather.png')
|
||||
weather_image.save(image_path+'inkycal_weather.png')
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
def main():
|
||||
generate_image()
|
||||
|
||||
main()
|
||||
|
@ -9,18 +9,27 @@ Copyright by aceisace
|
||||
"""
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageColor
|
||||
import numpy
|
||||
import arrow
|
||||
from urllib.request import urlopen
|
||||
from settings import language
|
||||
from settings import *
|
||||
from pytz import timezone
|
||||
import os
|
||||
from glob import glob
|
||||
import importlib
|
||||
|
||||
"""Set the image background colour and text colour"""
|
||||
background_colour = 'white'
|
||||
text_colour = 'black'
|
||||
|
||||
"""Set the display height and width (in pixels)"""
|
||||
display_height, display_width = 640, 384
|
||||
"""Set some display parameters"""
|
||||
driver = importlib.import_module('drivers.'+model)
|
||||
display_height, display_width = driver.EPD_WIDTH, driver.EPD_HEIGHT
|
||||
|
||||
"""Check if the display supports 3 colours"""
|
||||
if 'colour' in model:
|
||||
three_colour_support = True
|
||||
else:
|
||||
three_colour_support = False
|
||||
|
||||
"""Create 3 sections of the display, based on percentage"""
|
||||
top_section_width = middle_section_width = bottom_section_width = display_width
|
||||
@ -189,3 +198,50 @@ def image_cleanup():
|
||||
for temp_files in glob(image_path+'*'):
|
||||
os.remove(temp_files)
|
||||
print('Done')
|
||||
|
||||
def split_colours(image):
|
||||
if three_colour_support == True:
|
||||
"""Split image into two, one for red pixels, the other for black pixels"""
|
||||
buffer = numpy.array(image.convert('RGB'))
|
||||
red, green = buffer[:, :, 0], buffer[:, :, 1]
|
||||
buffer_red, buffer_black = numpy.array(image), numpy.array(image)
|
||||
|
||||
buffer_red[numpy.logical_and(red >= 200, green <= 90)] = [0,0,0] #red->black
|
||||
red1 = buffer_red[:,:,0]
|
||||
buffer_red[red1 != 0] = [255,255,255] #white
|
||||
red_im = Image.fromarray(buffer_red).convert('1',dither=True).rotate(270,expand=True)
|
||||
|
||||
buffer_black[numpy.logical_and(red <= 180, red == green)] = [0,0,0] #black
|
||||
red2 = buffer_black[:,:,0]
|
||||
buffer_black[red2 != 0] = [255,255,255] # white
|
||||
black_im = Image.fromarray(buffer_black).convert('1', dither=True).rotate(270,expand=True)
|
||||
return black_im, red_im
|
||||
|
||||
def calibrate_display(no_of_cycles):
|
||||
"""How many times should each colour be calibrated? Default is 3"""
|
||||
epaper = driver.EPD()
|
||||
epaper.init()
|
||||
|
||||
white = Image.new('1', (display_width, display_height), 'white')
|
||||
black = Image.new('1', (display_width, display_height), 'black')
|
||||
|
||||
print('----------Started calibration of E-Paper display----------')
|
||||
if 'colour' in model:
|
||||
for _ in range(no_of_cycles):
|
||||
print('Calibrating black...')
|
||||
epaper.display(epaper.getbuffer(black), epaper.getbuffer(white))
|
||||
print('Calibrating red/yellow...')
|
||||
epaper.display(epaper.getbuffer(white), epaper.getbuffer(black))
|
||||
print('Calibrating white...')
|
||||
epaper.display(epaper.getbuffer(white), epaper.getbuffer(white))
|
||||
print('Cycle {0} of {1} complete'.format(_+1, no_of_cycles))
|
||||
else:
|
||||
for _ in range(no_of_cycles):
|
||||
print('Calibrating black...')
|
||||
epaper.display(epaper.getbuffer(black))
|
||||
print('Calibrating white...')
|
||||
epaper.display(epaper.getbuffer(white)),
|
||||
print('Cycle {0} of {1} complete'.format(_+1, no_of_cycles))
|
||||
|
||||
print('-----------Calibration complete----------')
|
||||
epaper.sleep()
|
||||
|
@ -43,6 +43,10 @@ body{
|
||||
<div class="field">
|
||||
<label>How often should the display be refreshed?</label>
|
||||
<div class="ts checkboxes">
|
||||
<div class="ts radio checkbox">
|
||||
<input id="update_10_mins" type="radio" name="aa">
|
||||
<label for="update_10_mins">every 10 minutes. Not recommended for 3-colour E-Papers.</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="update_15_mins" type="radio" name="aa">
|
||||
<label for="update_15_mins">every 15 minutes</label>
|
||||
@ -114,15 +118,39 @@ body{
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label>Which Colours does your E-Paper Display support?</label>
|
||||
<label>Which E-Paper model are you using?</label>
|
||||
<div class="ts checkboxes">
|
||||
<div class="ts radio checkbox">
|
||||
<input id="colour" type="radio" name="dp" checked>
|
||||
<label for="colour">Coloured (3 colours)</label>
|
||||
<input id="epd_7_in_5_v2_colour" type="radio" name="dp" checked>
|
||||
<label for="epd_7_in_5_v2_colour">7.5" v2 (800x400px) colour</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="black-and-white" type="radio" name="dp">
|
||||
<label for="black-and-white">Black and White</label>
|
||||
<input id="epd_7_in_5_v2" type="radio" name="dp">
|
||||
<label for="epd_7_in_5_v2">7.5" v2 (800x400px) black-white</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="epd_7_in_5_colour" type="radio" name="dp">
|
||||
<label for="epd_7_in_5_colour">7.5" v1 (600x384px) colour</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="epd_7_in_5" type="radio" name="dp">
|
||||
<label for="epd_7_in_5">7.5" v1 (600x384px) black-white</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="epd_5_in_83_colour" type="radio" name="dp">
|
||||
<label for="epd_5_in_83_colour">5.83" colour</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="epd_5_in_83" type="radio" name="dp">
|
||||
<label for="epd_5_in_83">5.83" black-white</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="epd_4_in_2_colour" type="radio" name="dp">
|
||||
<label for="epd_4_in_2_colour">4.2" colour</label>
|
||||
</div>
|
||||
<div class="ts radio checkbox">
|
||||
<input id="epd_4_in_2" type="radio" name="dp">
|
||||
<label for="epd_4_in_2">4.2" black-white</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -305,7 +333,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
<br>
|
||||
|
||||
<script>
|
||||
var template = 'ical_urls = [{ical_urls}]\nrss_feeds = [{rss_urls}]\nupdate_interval = "{update_interval}"\napi_key = "{api_key}"\nlocation = "{location}"\nweek_starts_on = "{week_starts_on}"\ncalibration_hours = [{calibration_hours}]\ndisplay_type = "{display_colours}"\nlanguage = "{language}"\nunits = "{units}"\nhours = "{hours}"\ntop_section = "{top_section}"\nmiddle_section = "{middle_section}"\nbottom_section = "{bottom_section}"';
|
||||
var template = 'ical_urls = [{ical_urls}]\nrss_feeds = [{rss_urls}]\nupdate_interval = "{update_interval}"\napi_key = "{api_key}"\nlocation = "{location}"\nweek_starts_on = "{week_starts_on}"\ncalibration_hours = [{calibration_hours}]\nmodel = "{model}"\nlanguage = "{language}"\nunits = "{units}"\nhours = "{hours}"\ntop_section = "{top_section}"\nmiddle_section = "{middle_section}"\nbottom_section = "{bottom_section}"';
|
||||
|
||||
function generate(){
|
||||
var ical_urls = $("#ical_urls").val().trim();
|
||||
@ -319,6 +347,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
}
|
||||
|
||||
var update_interval = "60";
|
||||
if ($('#update_10_mins').is(':checked')){
|
||||
update_interval = "10";
|
||||
}
|
||||
if ($('#update_15_mins').is(':checked')){
|
||||
update_interval = "15";
|
||||
}
|
||||
@ -352,9 +383,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
calibration_hours = $("#calibration_hours").attr("placeholder");
|
||||
}
|
||||
|
||||
var display_colours = "black_and_white";
|
||||
if ($('#colour').is(':checked')){
|
||||
display_colours = "colour";
|
||||
var model = "epd_7_in_5_v2_colour";
|
||||
if ($('#epd_7_in_5_v2').is(':checked')){
|
||||
model = "epd_7_in_5_v2";
|
||||
}
|
||||
if ($('#epd_7_in_5_colour').is(':checked')){
|
||||
model = "epd_7_in_5_colour";
|
||||
}
|
||||
if ($('#epd_7_in_5').is(':checked')){
|
||||
model = "epd_7_in_5";
|
||||
}
|
||||
if ($('#epd_5_in_83_colour').is(':checked')){
|
||||
model = "epd_5_in_83_colour";
|
||||
}
|
||||
if ($('#epd_5_in_83').is(':checked')){
|
||||
model = "epd_5_in_83";
|
||||
}
|
||||
if ($('#epd_4_in_2_colour').is(':checked')){
|
||||
model = "epd_4_in_2_colour";
|
||||
}
|
||||
if ($('#epd_4_in_2').is(':checked')){
|
||||
model = "epd_4_in_2";
|
||||
}
|
||||
|
||||
var language = "en";
|
||||
@ -417,30 +466,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
hours = "12";
|
||||
}
|
||||
|
||||
var top_section = "Weather";
|
||||
var top_section = "inkycal_weather";
|
||||
if ($('#top_blank').is(':checked')){
|
||||
top_section = "";
|
||||
}
|
||||
|
||||
var middle_section = "Calendar";
|
||||
var middle_section = "inkycal_calendar";
|
||||
if ($('#Agenda').is(':checked')){
|
||||
middle_section = "Agenda";
|
||||
middle_section = "inkycal_agenda";
|
||||
}
|
||||
if ($('#middle_blank').is(':checked')){
|
||||
middle_section = "";
|
||||
}
|
||||
|
||||
var bottom_section = "RSS";
|
||||
if ($('#Events').is(':checked')){
|
||||
bottom_section = "Events";
|
||||
}
|
||||
var bottom_section = "inkycal_rss";
|
||||
if ($('#bottom_blank').is(':checked')){
|
||||
bottom_section = "";
|
||||
}
|
||||
|
||||
|
||||
//console.log(ical_urls, rss_urls, update_interval, api_key, location, week_starts_on, calibration_hours, display_type, language, units, hours, top_section, middle_section, bottom_section);
|
||||
createPythonSetting(ical_urls, rss_urls, update_interval, api_key, location, week_starts_on, calibration_hours, display_colours, language, units, hours, top_section, middle_section, bottom_section);
|
||||
//console.log(ical_urls, rss_urls, update_interval, api_key, location, week_starts_on, calibration_hours, model, language, units, hours, top_section, middle_section, bottom_section);
|
||||
createPythonSetting(ical_urls, rss_urls, update_interval, api_key, location, week_starts_on, calibration_hours, model, language, units, hours, top_section, middle_section, bottom_section);
|
||||
}
|
||||
|
||||
function rk(content,key,value){
|
||||
@ -457,7 +503,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
box = rk(box,"location",e);
|
||||
box = rk(box,"week_starts_on",f);
|
||||
box = rk(box,"calibration_hours",g);
|
||||
box = rk(box,"display_colours",h);
|
||||
box = rk(box,"model",h);
|
||||
box = rk(box,"language",i);
|
||||
box = rk(box,"units",j);
|
||||
box = rk(box,"hours",k);
|
||||
|
@ -1,13 +1,12 @@
|
||||
ical_urls = ["https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics"]
|
||||
rss_feeds = ["http://feeds.bbci.co.uk/news/world/rss.xml#"] # Use any RSS feed
|
||||
|
||||
|
||||
update_interval = "60" # "15" # "30" # "60"
|
||||
api_key = "" # Your openweathermap API-KEY -> "api-key"
|
||||
location = "Stuttgart, DE" # "City name, Country code"
|
||||
week_starts_on = "Monday" # "Monday" # "Sunday"
|
||||
calibration_hours = [0,12,18] # Do not change unless required
|
||||
display_type = "colour" # "colour" # "black_and_white"
|
||||
calibration_hours = [0,12,18] # Do not change unlesss you know what you are doing
|
||||
model = "epd_7_in_5_v2_colour" # Choose the E-Paper model (see below)
|
||||
language = "en" # "en" # "de" # "fr" # "jp" etc.
|
||||
units = "metric" # "metric" # "imperial"
|
||||
hours = "24" # "24" # "12"
|
||||
@ -26,3 +25,12 @@ bottom_section = "RSS" # "RSS"
|
||||
# URLs should have this sign (") on both side -> "url1"
|
||||
# If more than one URL is used, separate each one with a comma -> "url1", "url2"
|
||||
|
||||
"""Supported E-Paper models"""
|
||||
# epd_7_in_5_v2_colour # 7.5" high-res black-white-red/yellow
|
||||
# epd_7_in_5_v2 # 7.5" high-res black-white
|
||||
# epd_7_in_5_colour # 7.5" black-white-red/yellow
|
||||
# epd_7_in_5 # 7.5" black-white
|
||||
# epd_5_in_83_colour # 5.83" black-white-red/yellow
|
||||
# epd_5_in_83 # 5.83" black-white
|
||||
# epd_4_in_2_colour # 4.2" black-white-red/yellow
|
||||
# epd_4_in_2 # 4.2" black-white
|
||||
|
Loading…
Reference in New Issue
Block a user