Merge pull request #68 from aceisace/v1.7.1

V1.7.1
This commit is contained in:
Ace 2020-01-19 00:41:01 +01:00 committed by GitHub
commit 96f99419a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2371 additions and 676 deletions

View File

@ -180,5 +180,5 @@ EOF
fi fi
echo -e "\e[1;36m"You can test if the programm works by running:"\e[0m" 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 fi

View 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 ###

View 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 ###

View 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 ###

View 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 ###

View 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 ###

View 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 ###

View 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 ###

View 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 ###

View 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
View File

@ -0,0 +1 @@
#nothing in here. What did you expect?

View File

@ -1,28 +1,22 @@
#!/usr/bin/python3 #!/usr/bin/python3
# -*- coding: utf-8 -*- # -*- 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 Copyright by aceisace
""" """
from __future__ import print_function from __future__ import print_function
from configuration import * from configuration import *
from settings import *
import arrow import arrow
from time import sleep from time import sleep
import gc 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""" """Perepare for execution of main programm"""
calibration_countdown = 'initial' calibration_countdown = 'initial'
skip_calibration = False
image_cleanup() image_cleanup()
"""Check time and calibrate display if time """ """Check time and calibrate display if time """
@ -36,8 +30,6 @@ while True:
'D MMM YYYY'), now.format('HH:mm'))) 'D MMM YYYY'), now.format('HH:mm')))
print('-----------Main programm started now----------') print('-----------Main programm started now----------')
"""------------------Calibration check----------------""" """------------------Calibration check----------------"""
if skip_calibration != True: if skip_calibration != True:
print('Calibration..', end = ' ') print('Calibration..', end = ' ')
@ -45,10 +37,10 @@ while True:
if calibration_countdown == 'initial': if calibration_countdown == 'initial':
print('required. Performing calibration now.') print('required. Performing calibration now.')
calibration_countdown = 0 calibration_countdown = 0
display.calibrate_display(3) calibrate_display(3)
else: else:
if calibration_countdown % (60 // int(update_interval)) == 0: if calibration_countdown % (60 // int(update_interval)) == 0:
display.calibrate_display(3) calibrate_display(3)
calibration_countdown = 0 calibration_countdown = 0
else: else:
print('not required. Continuing...') print('not required. Continuing...')
@ -56,43 +48,50 @@ while True:
print('Calibration skipped!. Please note that not calibrating e-paper', print('Calibration skipped!. Please note that not calibrating e-paper',
'displays causes ghosting') 'displays causes ghosting')
"""----------------Generating and assembling images------""" """----------------Generating and assembling images------"""
if top_section == 'Weather':
try: try:
weather.main() top_section_module = importlib.import_module(top_section)
weather_image = Image.open(image_path + 'weather.png') top_section_image = Image.open(image_path + top_section+'.png')
image.paste(weather_image, (0, 0)) image.paste(top_section_image, (0, 0))
except: except:
pass pass
if middle_section == 'Calendar':
try: try:
calendar.main() middle_section_module = importlib.import_module(middle_section)
calendar_image = Image.open(image_path + 'calendar.png') middle_section_image = Image.open(image_path + middle_section+'.png')
image.paste(calendar_image, (0, middle_section_offset)) image.paste(middle_section_image, (0, middle_section_offset))
except: except:
pass pass
if middle_section == 'Agenda':
try: try:
agenda.main() bottom_section_module = importlib.import_module(bottom_section)
agenda_image = Image.open(image_path + 'agenda.png') bottom_section_image = Image.open(image_path + bottom_section+'.png')
image.paste(agenda_image, (0, middle_section_offset)) image.paste(bottom_section_image, (0, bottom_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))
except: except:
pass pass
image.save(image_path + 'canvas.png') image.save(image_path + 'canvas.png')
"""---------Refreshing E-Paper with newly created image-----------""" """---------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-----------------""" """--------------Post processing after main loop-----------------"""
"""Collect some garbage to free up some resources""" """Collect some garbage to free up some resources"""
@ -106,12 +105,15 @@ while True:
"""Calculate duration until next display refresh""" """Calculate duration until next display refresh"""
for _ in range(1): for _ in range(1):
update_timings = [(60 - int(update_interval)*updates) for updates in 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] for _ in update_timings:
refresh_countdown = minutes[0]*60 + (60 - now.second) 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 del update_timings, minutes, image
sleep(refresh_countdown) sleep(refresh_countdown)

View File

@ -7,8 +7,6 @@ Copyright by aceisace
from __future__ import print_function from __future__ import print_function
from inkycal_icalendar import fetch_events from inkycal_icalendar import fetch_events
from configuration import* from configuration import*
from settings import *
import arrow
fontsize = 14 fontsize = 14
show_events = True show_events = True
@ -45,7 +43,8 @@ else:
line_pos = [(border_left, int(top_section_height + border_top + line * line_height)) line_pos = [(border_left, int(top_section_height + border_top + line * line_height))
for line in range(max_lines)] for line in range(max_lines)]
def main(): def generate_image():
if middle_section == 'inkycal_agenda' and internet_available() == True:
try: try:
clear_image('middle_section') clear_image('middle_section')
if not bottom_section: if not bottom_section:
@ -107,7 +106,7 @@ def main():
previous_date = agenda_events[events]['date'] previous_date = agenda_events[events]['date']
draw.line((date_col_start, line_pos[events][1], 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': elif agenda_events[events]['type'] == 'timed_event':
write_text(time_col_width, line_height, agenda_events[events]['time'], write_text(time_col_width, line_height, agenda_events[events]['time'],
@ -130,7 +129,7 @@ def main():
else: else:
agenda_image = image.crop((0,middle_section_offset,display_width, display_height)) 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') print('Done')
except Exception as e: except Exception as e:
@ -140,5 +139,7 @@ def main():
print('Reason: ',e) print('Reason: ',e)
pass pass
if __name__ == '__main__': def main():
main() generate_image()
main()

View File

@ -7,9 +7,6 @@ Copyright by aceisace
from __future__ import print_function from __future__ import print_function
import calendar import calendar
from configuration import * from configuration import *
from settings import *
import arrow
from PIL import Image, ImageDraw
print_events = False print_events = False
show_events = True 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)+ event_lines = [(border_left,(bottom_section_offset - events_height)+
int(events_height/max_event_lines*_)) for _ in range(max_event_lines)] 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: try:
clear_image('middle_section') clear_image('middle_section')
print('Calendar module: Generating image...', end = '') print('Calendar module: Generating image...', end = '')
@ -114,7 +112,7 @@ def main():
y_text = int((icon_height / 2) - (text_height / 1.7)) y_text = int((icon_height / 2) - (text_height / 1.7))
ImageDraw.Draw(icon).ellipse((x_circle-radius, y_circle-radius, ImageDraw.Draw(icon).ellipse((x_circle-radius, y_circle-radius,
x_circle+radius, y_circle+radius), fill= 'red' if 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', ImageDraw.Draw(icon).text((x_text, y_text), str(now.day), fill='white',
font=bold) font=bold)
image.paste(icon, current_day_pos, icon) image.paste(icon, current_day_pos, icon)
@ -149,7 +147,7 @@ def main():
int(grid[calendar_flat.index(days)][1] + icon_height*0.8))) int(grid[calendar_flat.index(days)][1] + icon_height*0.8)))
if event_icon == 'square': if event_icon == 'square':
square_size = int(icon_width *0.6) square_size = int(icon_width * 0.6)
center_x = int((icon_width - square_size) / 2) center_x = int((icon_width - square_size) / 2)
center_y = int((icon_height - square_size) / 2) center_y = int((icon_height - square_size) / 2)
for days in days_with_events: for days in days_with_events:
@ -198,7 +196,7 @@ def main():
events.end.format(style)), events.all_day) events.end.format(style)), events.all_day)
calendar_image = crop_image(image, 'middle_section') calendar_image = crop_image(image, 'middle_section')
calendar_image.save(image_path+'calendar.png') calendar_image.save(image_path+'inkycal_calendar.png')
print('Done') print('Done')
@ -209,6 +207,7 @@ def main():
print('Reason: ',e) print('Reason: ',e)
pass pass
def main():
generate_image()
if __name__ == '__main__': main()
main()

View File

@ -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)

View File

@ -44,8 +44,8 @@ def fetch_events():
if events.all_day and events.duration.days > 1: if events.all_day and events.duration.days > 1:
events.end = events.end.replace(days=-2) events.end = events.end.replace(days=-2)
else: else:
events.begin = events.begin.to(timezone)
events.end = events.end.to(timezone) events.end = events.end.to(timezone)
events.begin = events.begin.to(timezone)
try: try:
rule = re.search('RRULE:(.+?)\n', event_str).group(0)[:-2] rule = re.search('RRULE:(.+?)\n', event_str).group(0)[:-2]
if re.search('UNTIL=(.+?);', rule) and not re.search('UNTIL=(.+?)Z;', rule): 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) events.end = events.end.replace(days=-2)
if not events.all_day: if not events.all_day:
events.begin = events.begin.to(timezone)
events.end = events.end.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 """ 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.""" this one, copy the list or the contents to another one."""

View File

@ -7,7 +7,6 @@ Copyright by aceisace
from __future__ import print_function from __future__ import print_function
import feedparser import feedparser
from random import shuffle from random import shuffle
from settings import *
from configuration import * from configuration import *
fontsize = 14 fontsize = 14
@ -33,8 +32,8 @@ y_padding = int( (bottom_section_height % line_height) / 2 )
line_positions = [(border_left, bottom_section_offset + line_positions = [(border_left, bottom_section_offset +
border_top + y_padding + _*line_height ) for _ in range(max_lines)] border_top + y_padding + _*line_height ) for _ in range(max_lines)]
def main(): def generate_image():
if bottom_section == "RSS" and rss_feeds != [] and internet_available() == True: if bottom_section == "inkycal_rss" and rss_feeds != [] and internet_available() == True:
try: try:
clear_image('bottom_section') clear_image('bottom_section')
print('RSS module: Connectivity check passed. Generating image...', print('RSS module: Connectivity check passed. Generating image...',
@ -71,7 +70,7 @@ def main():
del filtered_feeds, parsed_feeds del filtered_feeds, parsed_feeds
rss_image = crop_image(image, 'bottom_section') rss_image = crop_image(image, 'bottom_section')
rss_image.save(image_path+'rss.png') rss_image.save(image_path+'inkycal_rss.png')
print('Done') print('Done')
except Exception as e: except Exception as e:
@ -81,5 +80,7 @@ def main():
print('Reason: ',e) print('Reason: ',e)
pass pass
if __name__ == '__main__': def main():
main() generate_image()
main()

View File

@ -10,10 +10,7 @@ Copyright by aceisace
""" """
from __future__ import print_function from __future__ import print_function
import pyowm import pyowm
from settings import *
from configuration import * from configuration import *
from PIL import Image, ImageDraw, ImageFont
import arrow
import math, decimal import math, decimal
dec = decimal.Decimal dec = decimal.Decimal
@ -130,7 +127,7 @@ def to_units(kelvin):
return conversion return conversion
def red_temp(negative_temperature): 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' colour = 'red'
else: else:
colour = 'black' colour = 'black'
@ -160,9 +157,9 @@ while font.getsize('hg')[1] <= (row_height * fill_height):
fontsize += 1 fontsize += 1
font = ImageFont.truetype(NotoSans+'.ttf', fontsize) font = ImageFont.truetype(NotoSans+'.ttf', fontsize)
def main(): def generate_image():
"""Connect to Openweathermap API and fetch weather data""" """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: try:
clear_image('top_section') clear_image('top_section')
print('Weather module: Connectivity check passed, Generating image...', 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((coloumn7, line_start_y, coloumn7, line_end_y), fill='black')
draw.line((0, top_section_height-border_top, top_section_width- draw.line((0, top_section_height-border_top, top_section_width-
border_left, top_section_height-border_top), 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 = crop_image(image, 'top_section')
weather_image.save(image_path+'weather.png') weather_image.save(image_path+'inkycal_weather.png')
print('Done') print('Done')
except Exception as e: except Exception as e:
@ -348,8 +345,10 @@ def main():
write_text(coloumn_width*6, row_height, message, humidity_icon_now_pos, write_text(coloumn_width*6, row_height, message, humidity_icon_now_pos,
font = font) font = font)
weather_image = crop_image(image, 'top_section') weather_image = crop_image(image, 'top_section')
weather_image.save(image_path+'weather.png') weather_image.save(image_path+'inkycal_weather.png')
pass pass
if __name__ == '__main__': def main():
main() generate_image()
main()

View File

@ -9,18 +9,27 @@ Copyright by aceisace
""" """
from PIL import Image, ImageDraw, ImageFont, ImageColor from PIL import Image, ImageDraw, ImageFont, ImageColor
import numpy import numpy
import arrow
from urllib.request import urlopen from urllib.request import urlopen
from settings import language from settings import *
from pytz import timezone from pytz import timezone
import os import os
from glob import glob from glob import glob
import importlib
"""Set the image background colour and text colour""" """Set the image background colour and text colour"""
background_colour = 'white' background_colour = 'white'
text_colour = 'black' text_colour = 'black'
"""Set the display height and width (in pixels)""" """Set some display parameters"""
display_height, display_width = 640, 384 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""" """Create 3 sections of the display, based on percentage"""
top_section_width = middle_section_width = bottom_section_width = display_width 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+'*'): for temp_files in glob(image_path+'*'):
os.remove(temp_files) os.remove(temp_files)
print('Done') 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()

View File

@ -43,6 +43,10 @@ body{
<div class="field"> <div class="field">
<label>How often should the display be refreshed?</label> <label>How often should the display be refreshed?</label>
<div class="ts checkboxes"> <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"> <div class="ts radio checkbox">
<input id="update_15_mins" type="radio" name="aa"> <input id="update_15_mins" type="radio" name="aa">
<label for="update_15_mins">every 15 minutes</label> <label for="update_15_mins">every 15 minutes</label>
@ -114,15 +118,39 @@ body{
</div> </div>
<div class="field"> <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 checkboxes">
<div class="ts radio checkbox"> <div class="ts radio checkbox">
<input id="colour" type="radio" name="dp" checked> <input id="epd_7_in_5_v2_colour" type="radio" name="dp" checked>
<label for="colour">Coloured (3 colours)</label> <label for="epd_7_in_5_v2_colour">7.5" v2 (800x400px) colour</label>
</div> </div>
<div class="ts radio checkbox"> <div class="ts radio checkbox">
<input id="black-and-white" type="radio" name="dp"> <input id="epd_7_in_5_v2" type="radio" name="dp">
<label for="black-and-white">Black and White</label> <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> </div>
</div> </div>
@ -305,7 +333,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
<br> <br>
<script> <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(){ function generate(){
var ical_urls = $("#ical_urls").val().trim(); 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"; var update_interval = "60";
if ($('#update_10_mins').is(':checked')){
update_interval = "10";
}
if ($('#update_15_mins').is(':checked')){ if ($('#update_15_mins').is(':checked')){
update_interval = "15"; 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"); calibration_hours = $("#calibration_hours").attr("placeholder");
} }
var display_colours = "black_and_white"; var model = "epd_7_in_5_v2_colour";
if ($('#colour').is(':checked')){ if ($('#epd_7_in_5_v2').is(':checked')){
display_colours = "colour"; 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"; var language = "en";
@ -417,30 +466,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
hours = "12"; hours = "12";
} }
var top_section = "Weather"; var top_section = "inkycal_weather";
if ($('#top_blank').is(':checked')){ if ($('#top_blank').is(':checked')){
top_section = ""; top_section = "";
} }
var middle_section = "Calendar"; var middle_section = "inkycal_calendar";
if ($('#Agenda').is(':checked')){ if ($('#Agenda').is(':checked')){
middle_section = "Agenda"; middle_section = "inkycal_agenda";
} }
if ($('#middle_blank').is(':checked')){ if ($('#middle_blank').is(':checked')){
middle_section = ""; middle_section = "";
} }
var bottom_section = "RSS"; var bottom_section = "inkycal_rss";
if ($('#Events').is(':checked')){
bottom_section = "Events";
}
if ($('#bottom_blank').is(':checked')){ if ($('#bottom_blank').is(':checked')){
bottom_section = ""; 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); //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, display_colours, 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){ 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,"location",e);
box = rk(box,"week_starts_on",f); box = rk(box,"week_starts_on",f);
box = rk(box,"calibration_hours",g); 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,"language",i);
box = rk(box,"units",j); box = rk(box,"units",j);
box = rk(box,"hours",k); box = rk(box,"hours",k);

View File

@ -1,13 +1,12 @@
ical_urls = ["https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics"] 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 rss_feeds = ["http://feeds.bbci.co.uk/news/world/rss.xml#"] # Use any RSS feed
update_interval = "60" # "15" # "30" # "60" update_interval = "60" # "15" # "30" # "60"
api_key = "" # Your openweathermap API-KEY -> "api-key" api_key = "" # Your openweathermap API-KEY -> "api-key"
location = "Stuttgart, DE" # "City name, Country code" location = "Stuttgart, DE" # "City name, Country code"
week_starts_on = "Monday" # "Monday" # "Sunday" week_starts_on = "Monday" # "Monday" # "Sunday"
calibration_hours = [0,12,18] # Do not change unless required calibration_hours = [0,12,18] # Do not change unlesss you know what you are doing
display_type = "colour" # "colour" # "black_and_white" model = "epd_7_in_5_v2_colour" # Choose the E-Paper model (see below)
language = "en" # "en" # "de" # "fr" # "jp" etc. language = "en" # "en" # "de" # "fr" # "jp" etc.
units = "metric" # "metric" # "imperial" units = "metric" # "metric" # "imperial"
hours = "24" # "24" # "12" hours = "24" # "24" # "12"
@ -26,3 +25,12 @@ bottom_section = "RSS" # "RSS"
# URLs should have this sign (") on both side -> "url1" # URLs should have this sign (") on both side -> "url1"
# If more than one URL is used, separate each one with a comma -> "url1", "url2" # 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