aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLars Kroenner2019-12-28 15:39:01 +0100
committerLars Kroenner2019-12-28 15:39:01 +0100
commit5af19a2df10ba7f240991c771740201de654b8e5 (patch)
tree97c5f3d73948387b5399218d3a065a3c2f208c80
parentbc3358a8456180f79fff6db964aee213a43d7eb2 (diff)
parent7ab78f003c0b9374ec3067ce10dc6111bcc25e06 (diff)
Mega awesome merge of LarsVomMars :)
-rw-r--r--epaper/epd2in13.py313
-rw-r--r--epaper/epdconfig.py73
-rw-r--r--epaper/main.py39
3 files changed, 425 insertions, 0 deletions
diff --git a/epaper/epd2in13.py b/epaper/epd2in13.py
new file mode 100644
index 0000000..9d1359a
--- /dev/null
+++ b/epaper/epd2in13.py
@@ -0,0 +1,313 @@
+# *****************************************************************************
+# * | File : epd2in13_V2.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
+import epdconfig
+import numpy as np
+
+# Display resolution
+EPD_WIDTH = 122
+EPD_HEIGHT = 250
+
+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
+
+ FULL_UPDATE = 0
+ PART_UPDATE = 1
+ lut_full_update= [
+ 0x80,0x60,0x40,0x00,0x00,0x00,0x00, #LUT0: BB: VS 0 ~7
+ 0x10,0x60,0x20,0x00,0x00,0x00,0x00, #LUT1: BW: VS 0 ~7
+ 0x80,0x60,0x40,0x00,0x00,0x00,0x00, #LUT2: WB: VS 0 ~7
+ 0x10,0x60,0x20,0x00,0x00,0x00,0x00, #LUT3: WW: VS 0 ~7
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT4: VCOM: VS 0 ~7
+
+ 0x03,0x03,0x00,0x00,0x02, # TP0 A~D RP0
+ 0x09,0x09,0x00,0x00,0x02, # TP1 A~D RP1
+ 0x03,0x03,0x00,0x00,0x02, # TP2 A~D RP2
+ 0x00,0x00,0x00,0x00,0x00, # TP3 A~D RP3
+ 0x00,0x00,0x00,0x00,0x00, # TP4 A~D RP4
+ 0x00,0x00,0x00,0x00,0x00, # TP5 A~D RP5
+ 0x00,0x00,0x00,0x00,0x00, # TP6 A~D RP6
+
+ 0x15,0x41,0xA8,0x32,0x30,0x0A,
+ ]
+
+ lut_partial_update = [ #20 bytes
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT0: BB: VS 0 ~7
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x00, #LUT1: BW: VS 0 ~7
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00, #LUT2: WB: VS 0 ~7
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT3: WW: VS 0 ~7
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT4: VCOM: VS 0 ~7
+
+ 0x0A,0x00,0x00,0x00,0x00, # TP0 A~D RP0
+ 0x00,0x00,0x00,0x00,0x00, # TP1 A~D RP1
+ 0x00,0x00,0x00,0x00,0x00, # TP2 A~D RP2
+ 0x00,0x00,0x00,0x00,0x00, # TP3 A~D RP3
+ 0x00,0x00,0x00,0x00,0x00, # TP4 A~D RP4
+ 0x00,0x00,0x00,0x00,0x00, # TP5 A~D RP5
+ 0x00,0x00,0x00,0x00,0x00, # TP6 A~D RP6
+
+ 0x15,0x41,0xA8,0x32,0x30,0x0A,
+ ]
+
+ # 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):
+ while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
+ epdconfig.delay_ms(100)
+
+ def TurnOnDisplay(self):
+ self.send_command(0x22)
+ self.send_data(0xC7)
+ self.send_command(0x20)
+ self.ReadBusy()
+
+ def TurnOnDisplayPart(self):
+ self.send_command(0x22)
+ self.send_data(0x0c)
+ self.send_command(0x20)
+ self.ReadBusy()
+
+ def init(self, update):
+ if (epdconfig.module_init() != 0):
+ return -1
+ # EPD hardware init start
+ self.reset()
+ if(update == self.FULL_UPDATE):
+ self.ReadBusy()
+ self.send_command(0x12) # soft reset
+ self.ReadBusy()
+
+ self.send_command(0x74) #set analog block control
+ self.send_data(0x54)
+ self.send_command(0x7E) #set digital block control
+ self.send_data(0x3B)
+
+ self.send_command(0x01) #Driver output control
+ self.send_data(0xF9)
+ self.send_data(0x00)
+ self.send_data(0x00)
+
+ self.send_command(0x11) #data entry mode
+ self.send_data(0x01)
+
+ self.send_command(0x44) #set Ram-X address start/end position
+ self.send_data(0x00)
+ self.send_data(0x0F) #0x0C-->(15+1)*8=128
+
+ self.send_command(0x45) #set Ram-Y address start/end position
+ self.send_data(0xF9) #0xF9-->(249+1)=250
+ self.send_data(0x00)
+ self.send_data(0x00)
+ self.send_data(0x00)
+
+ self.send_command(0x3C) #BorderWavefrom
+ self.send_data(0x03)
+
+ self.send_command(0x2C) #VCOM Voltage
+ self.send_data(0x55) #
+
+ self.send_command(0x03)
+ self.send_data(self.lut_full_update[70])
+
+ self.send_command(0x04) #
+ self.send_data(self.lut_full_update[71])
+ self.send_data(self.lut_full_update[72])
+ self.send_data(self.lut_full_update[73])
+
+ self.send_command(0x3A) #Dummy Line
+ self.send_data(self.lut_full_update[74])
+ self.send_command(0x3B) #Gate time
+ self.send_data(self.lut_full_update[75])
+
+ self.send_command(0x32)
+ for count in range(70):
+ self.send_data(self.lut_full_update[count])
+
+ self.send_command(0x4E) # set RAM x address count to 0
+ self.send_data(0x00)
+ self.send_command(0x4F) # set RAM y address count to 0X127
+ self.send_data(0xF9)
+ self.send_data(0x00)
+ self.ReadBusy()
+ else:
+ self.send_command(0x2C) #VCOM Voltage
+ self.send_data(0x26)
+
+ self.ReadBusy()
+
+ self.send_command(0x32)
+ for count in range(70):
+ self.send_data(self.lut_partial_update[count])
+
+ self.send_command(0x37)
+ self.send_data(0x00)
+ self.send_data(0x00)
+ self.send_data(0x00)
+ self.send_data(0x00)
+ self.send_data(0x40)
+ self.send_data(0x00)
+ self.send_data(0x00)
+
+ self.send_command(0x22)
+ self.send_data(0xC0)
+ self.send_command(0x20)
+ self.ReadBusy()
+
+ self.send_command(0x3C) #BorderWavefrom
+ self.send_data(0x01)
+ return 0
+
+ def getbuffer(self, image):
+ if self.width%8 == 0:
+ linewidth = int(self.width/8)
+ else:
+ linewidth = int(self.width/8) + 1
+
+ buf = [0xFF] * (linewidth * self.height)
+ image_monocolor = image.convert('1')
+ imwidth, imheight = image_monocolor.size
+ pixels = image_monocolor.load()
+
+ if(imwidth == self.width and imheight == self.height):
+ logging.debug("Vertical")
+ for y in range(imheight):
+ for x in range(imwidth):
+ if pixels[x, y] == 0:
+ x = imwidth - x
+ buf[int(x / 8) + y * linewidth] &= ~(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:
+ newy = imwidth - newy - 1
+ buf[int(newx / 8) + newy*linewidth] &= ~(0x80 >> (y % 8))
+ return buf
+
+
+ def display(self, image):
+ if self.width%8 == 0:
+ linewidth = int(self.width/8)
+ else:
+ linewidth = int(self.width/8) + 1
+
+ self.send_command(0x24)
+ for j in range(0, self.height):
+ for i in range(0, linewidth):
+ self.send_data(image[i + j * linewidth])
+ self.TurnOnDisplay()
+
+ def displayPartial(self, image):
+ if self.width%8 == 0:
+ linewidth = int(self.width/8)
+ else:
+ linewidth = int(self.width/8) + 1
+
+ self.send_command(0x24)
+ for j in range(0, self.height):
+ for i in range(0, linewidth):
+ self.send_data(image[i + j * linewidth])
+
+
+ # self.send_command(0x26)
+ # for j in range(0, self.height):
+ # for i in range(0, linewidth):
+ # self.send_data(~image[i + j * linewidth])
+ self.TurnOnDisplayPart()
+
+ def displayPartBaseImage(self, image):
+ if self.width%8 == 0:
+ linewidth = int(self.width/8)
+ else:
+ linewidth = int(self.width/8) + 1
+
+ self.send_command(0x24)
+ for j in range(0, self.height):
+ for i in range(0, linewidth):
+ self.send_data(image[i + j * linewidth])
+
+
+ self.send_command(0x26)
+ for j in range(0, self.height):
+ for i in range(0, linewidth):
+ self.send_data(image[i + j * linewidth])
+ self.TurnOnDisplay()
+
+ def Clear(self, color):
+ if self.width%8 == 0:
+ linewidth = int(self.width/8)
+ else:
+ linewidth = int(self.width/8) + 1
+ # logging.debug(linewidth)
+
+ self.send_command(0x24)
+ for j in range(0, self.height):
+ for i in range(0, linewidth):
+ self.send_data(color)
+ self.TurnOnDisplay()
+
+ def sleep(self):
+ self.send_command(0x10) #enter deep sleep
+ self.send_data(0x01)
+ epdconfig.delay_ms(100)
+
+ epdconfig.module_exit()
+
+### END OF FILE ###
+
+
diff --git a/epaper/epdconfig.py b/epaper/epdconfig.py
new file mode 100644
index 0000000..78ff647
--- /dev/null
+++ b/epaper/epdconfig.py
@@ -0,0 +1,73 @@
+# /*****************************************************************************
+# * | File : EPD_1in54.py
+# * | Author : Waveshare team
+# * | Function : Hardware underlying interface
+# * | Info :
+# *----------------
+# * | This version: V2.0
+# * | Date : 2018-11-01
+# * | Info :
+# * 1.Remove:
+# digital_write(self, pin, value)
+# digital_read(self, pin)
+# delay_ms(self, delaytime)
+# set_lut(self, lut)
+# self.lut = self.lut_full_update
+# ******************************************************************************/
+# 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 spidev
+import RPi.GPIO as GPIO
+import time
+
+# Pin definition
+RST_PIN = 17
+DC_PIN = 25
+CS_PIN = 8
+BUSY_PIN = 24
+
+# SPI device, bus = 0, device = 0
+SPI = spidev.SpiDev(0, 0)
+
+def digital_write(pin, value):
+ GPIO.output(pin, value)
+
+def digital_read(pin):
+ return GPIO.input(BUSY_PIN)
+
+def delay_ms(delaytime):
+ time.sleep(delaytime / 1000.0)
+
+def spi_writebyte(data):
+ SPI.writebytes(data)
+
+def module_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 = 2000000
+ SPI.mode = 0b00
+ return 0;
+
+### END OF FILE ###
diff --git a/epaper/main.py b/epaper/main.py
new file mode 100644
index 0000000..6e97544
--- /dev/null
+++ b/epaper/main.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+# -*- coding:utf-8 -*-
+
+import epd2in13
+import time
+import requests
+from datetime import date
+from datetime import datetime
+from PIL import Image,ImageDraw,ImageFont
+
+font_size = 14
+
+epd = epd2in13.EPD()
+epd.init(epd.FULL_UPDATE)
+epd.Clear(0xFF)
+
+image = Image.new('1', (epd2in13.EPD_HEIGHT, epd2in13.EPD_WIDTH), 255) # 255: clear the frame
+draw = ImageDraw.Draw(image)
+font = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', font_size)
+
+resp = requests.get('http://data.c3voc.de/36C3/everything.schedule.json')
+days = resp.json()['schedule']['conference']['days']
+conferences = []
+for day in days:
+ for room in day['rooms']:
+ for conference in day['rooms'][room]:
+ conf_date = time.mktime(datetime.strptime(conference['date'], '%Y-%m-%dT%H:%M:%S%z').timetuple())
+ if conf_date - time.time() > 2 * 60 * 60:
+ conferences.append(conference)
+
+sorted_list = sorted(conferences, key = lambda i: i['date'])
+
+for i in range(1, 6):
+ draw.text((0, font_size * i + 2), conferences[i - 1]['title'], font=font, fill=0)
+epd.display(epd.getbuffer(image))
+
+# time.sleep(10)
+# epd.Clear(0xFF)
+epd.sleep()