Multiple changes

Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
This commit is contained in:
jayofelony
2024-03-20 22:25:36 +01:00
parent bf9a0a96c1
commit 51625e61f9
20 changed files with 78 additions and 2423 deletions

View File

@ -100,7 +100,6 @@ class Client(object):
await asyncio.sleep(sleep_time) await asyncio.sleep(sleep_time)
continue continue
except OSError: except OSError:
sleep_time = min_sleep + max_sleep * random.random()
logging.warning('connection to the bettercap endpoint failed...') logging.warning('connection to the bettercap endpoint failed...')
pwnagotchi.restart("AUTO") pwnagotchi.restart("AUTO")

View File

@ -4,6 +4,8 @@ import subprocess
import time import time
import random import random
from io import TextIOWrapper from io import TextIOWrapper
import os
import platform
import pwnagotchi import pwnagotchi
from pwnagotchi import plugins from pwnagotchi import plugins
@ -32,6 +34,8 @@ class FixServices(plugins.Plugin):
self.pattern2 = re.compile(r'wifi error while hopping to channel') self.pattern2 = re.compile(r'wifi error while hopping to channel')
self.pattern3 = re.compile(r'Firmware has halted or crashed') self.pattern3 = re.compile(r'Firmware has halted or crashed')
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon') self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
self.pattern5 = re.compile(r'fatal error: concurrent map iteration and map write')
self.pattern6 = re.compile(r'panic: runtime error')
self.isReloadingMon = False self.isReloadingMon = False
self.connection = None self.connection = None
self.LASTTRY = 0 self.LASTTRY = 0
@ -113,41 +117,43 @@ class FixServices(plugins.Plugin):
logging.debug("[Fix_Services]**** checking") logging.debug("[Fix_Services]**** checking")
# Look for pattern 1 # Look for pattern 1
if len(self.pattern.findall(last_lines)) >= 3: if platform.machine().startswith('arm'):
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) if len(self.pattern.findall(last_lines)) >= 3:
if hasattr(agent, 'view'): logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
display = agent.view() if hasattr(agent, 'view'):
display.set('status', 'Blind-Bug detected. Restarting.') display = agent.view()
display.update(force=True) display.set('status', 'Blind-Bug detected. Restarting.')
logging.debug('[Fix_Services] Blind-Bug detected. Restarting.') display.update(force=True)
try: logging.debug('[Fix_Services] Blind-Bug detected. Restarting.')
self._tryTurningItOffAndOnAgain(agent) try:
except Exception as err: self._tryTurningItOffAndOnAgain(agent)
logging.warning("[Fix_Services] TTOAOA: %s" % repr(err)) except Exception as err:
logging.warning("[Fix_Services] TTOAOA: %s" % repr(err))
# Look for pattern 2 # Look for pattern 2
elif len(self.pattern2.findall(other_last_lines)) >= 5: elif len(self.pattern2.findall(other_last_lines)) >= 5:
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) if platform.machine().startswith('arm'):
if hasattr(agent, 'view'): logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
display = agent.view() if hasattr(agent, 'view'):
display.set('status', 'Wifi channel stuck. Restarting recon.') display = agent.view()
display.update(force=True) display.set('status', 'Wifi channel stuck. Restarting recon.')
logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.') display.update(force=True)
logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.')
try: try:
result = agent.run("wifi.recon off; wifi.recon on") result = agent.run("wifi.recon off; wifi.recon on")
if result["success"]: if result["success"]:
logging.debug("[Fix_Services] wifi.recon flip: success!") logging.debug("[Fix_Services] wifi.recon flip: success!")
if display: if display:
display.update(force=True, new_data={"status": "Wifi recon flipped!", display.update(force=True, new_data={"status": "Wifi recon flipped!",
"face": faces.COOL}) "face": faces.COOL})
else:
print("Wifi recon flipped\nthat was easy!")
else: else:
print("Wifi recon flipped\nthat was easy!") logging.warning("[Fix_Services] wifi.recon flip: FAILED: %s" % repr(result))
else:
logging.warning("[Fix_Services] wifi.recon flip: FAILED: %s" % repr(result))
except Exception as err: except Exception as err:
logging.error("[Fix_Services wifi.recon flip] %s" % repr(err)) logging.error("[Fix_Services wifi.recon flip] %s" % repr(err))
# Look for pattern 3 # Look for pattern 3
elif len(self.pattern3.findall(other_last_lines)) >= 1: elif len(self.pattern3.findall(other_last_lines)) >= 1:
@ -177,6 +183,25 @@ class FixServices(plugins.Plugin):
except Exception as err: except Exception as err:
logging.error("[Fix_Services monstart]: %s" % repr(err)) logging.error("[Fix_Services monstart]: %s" % repr(err))
# Look for pattern 5
elif len(self.pattern5.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
# Look for pattern 6
elif len(self.pattern6.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
else: else:
print("logs look good") print("logs look good")

View File

View File

@ -34,7 +34,7 @@ class DisplayHatMini(DisplayImpl):
def initialize(self): def initialize(self):
logging.info("initializing Display Hat Mini") logging.info("initializing Display Hat Mini")
from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789 from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789
self._display = ST7789(0,1,9,13) self._display = ST7789(0, 1, 9, 13)
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) self._display.display(canvas)

View File

@ -90,8 +90,8 @@ ST7789_PWCTR6 = 0xFC
class ST7789(object): class ST7789(object):
"""Representation of an ST7789 TFT LCD.""" """Representation of an ST7789 TFT LCD."""
def __init__(self, port, cs, dc, backlight, rst=None, width=320, def __init__(self, port, cs, dc, backlight=None, rst=None, width=240,
height=240, rotation=0, invert=True, spi_speed_hz=60 * 1000 * 1000, height=240, rotation=90, invert=True, spi_speed_hz=4000000,
offset_left=0, offset_left=0,
offset_top=0): offset_top=0):
"""Create an instance of the display using SPI communication. """Create an instance of the display using SPI communication.

View File

@ -1,224 +0,0 @@
# *****************************************************************************
# * | File : epd2in13.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 documentation 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
# furnished 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 = 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
lut_full_update = [
0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00
]
lut_partial_update = [
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]
# Hardware reset
def reset(self):
epdconfig.digital_write(self.cs_pin, 0)
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)
epdconfig.digital_write(self.cs_pin, 1)
def send_command(self, command):
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
def send_data(self, data):
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.digital_write(self.dc_pin, 1)
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) # DISPLAY_UPDATE_CONTROL_2
self.send_data(0xC4)
self.send_command(0x20) # MASTER_ACTIVATION
self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE
logging.debug("e-Paper busy")
self.ReadBusy()
logging.debug("e-Paper busy release")
def init(self, lut):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x01) # DRIVER_OUTPUT_CONTROL
self.send_data((EPD_HEIGHT - 1) & 0xFF)
self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF)
self.send_data(0x00) # GD = 0 SM = 0 TB = 0
self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL
self.send_data(0xD7)
self.send_data(0xD6)
self.send_data(0x9D)
self.send_command(0x2C) # WRITE_VCOM_REGISTER
self.send_data(0xA8) # VCOM 7C
self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD
self.send_data(0x1A) # 4 dummy lines per gate
self.send_command(0x3B) # SET_GATE_TIME
self.send_data(0x08) # 2us per line
self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL
self.send_data(0x03)
self.send_command(0X11) # DATA_ENTRY_MODE_SETTING
self.send_data(0x03) # X increment; Y increment
# WRITE_LUT_REGISTER
self.send_command(0x32)
for count in range(30):
self.send_data(lut[count])
return 0
##
# @brief: specify the memory area for data R/W
##
def SetWindows(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
self.send_data((x_start >> 3) & 0xFF)
self.send_data((x_end >> 3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
##
# @brief: specify the start point for data R/W
##
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x >> 3) & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
self.ReadBusy()
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):
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):
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.SetWindows(0, 0, self.width, self.height);
for j in range(0, self.height):
self.SetCursor(0, j);
self.send_command(0x24);
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
self.SetWindows(0, 0, self.width, self.height);
for j in range(0, self.height):
self.SetCursor(0, j);
self.send_command(0x24);
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 ###

View File

@ -1,164 +0,0 @@
# *****************************************************************************
# * | File : epd2in13bc.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 documentation 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
# furnished 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.
#
from . import epdconfig
import RPi.GPIO as GPIO
# import numpy as np
# Display resolution
EPD_WIDTH = 104
EPD_HEIGHT = 212
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, GPIO.HIGH)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, GPIO.LOW) # module reset
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, GPIO.HIGH)
epdconfig.delay_ms(200)
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, GPIO.LOW)
epdconfig.digital_write(self.cs_pin, GPIO.LOW)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, GPIO.HIGH)
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, GPIO.HIGH)
epdconfig.digital_write(self.cs_pin, GPIO.LOW)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, GPIO.HIGH)
def ReadBusy(self):
epdconfig.delay_ms(20)
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
epdconfig.delay_ms(100)
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x06) # BOOSTER_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(0x8F)
self.send_command(0x50) # VCOM_AND_DATA_INTERVAL_SETTING
self.send_data(0xF0)
self.send_command(0x61) # RESOLUTION_SETTING
self.send_data(self.width & 0xff)
self.send_data(self.height >> 8)
self.send_data(self.height & 0xff)
return 0
def getbuffer(self, image):
buf = [0xFF] * (int(self.width/8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
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] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
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] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def displayBlack(self, imageblack):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imageblack[i])
self.send_command(0x92)
self.send_command(0x12) # REFRESH
self.ReadBusy()
def display(self, imageblack, imagecolor):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imageblack[i])
self.send_command(0x92)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imagecolor[i])
self.send_command(0x92)
self.send_command(0x12) # REFRESH
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(0x92)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0xFF)
self.send_command(0x92)
self.send_command(0x12) # REFRESH
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

@ -1,359 +0,0 @@
# *****************************************************************************
# * | File : epd2in13d.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.
#
# =============================================================================
# THIS FILE HAS BEEN MODIFIED FROM ORIGINAL, IT HAS BEEN MODIFIED TO RUN THE
# THREE COLOR WAVESHARE 2.13IN DISPLAY AT A MUCH, MUCH FASTER RATE THAN NORMAL
# AND IT COULD DAMAGE YOUR DISPLAY. THERE IS NO WARRANTY INCLUDED AND YOU USE
# THIS CODE AT YOUR OWN RISK. WE ARE NOT RESPONSIBLE FOR ANYTHING THAT HAPPENS
# INCLUDING BUT NOT LIMITED TO: DESTRUCTION OF YOUR DISPLAY, PI, HOUSE, CAR,
# SPACE-TIME-CONTINUUM, OR IF THE CODE KILLS YOUR CAT. IF YOU AREN'T WILLING TO
# TAKE THESE RISKS, PLEASE DO NOT USE THIS CODE.
# =============================================================================
import logging
from . import epdconfig
from PIL import Image
import RPi.GPIO as GPIO
# Display resolution
EPD_WIDTH = 104
EPD_HEIGHT = 212
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
lut_vcomDC = [
0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
0x60, 0x28, 0x28, 0x00, 0x00, 0x01,
0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
0x00, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]
lut_ww = [
0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
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, 0x0F, 0x0F, 0x00, 0x00, 0x03,
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, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_bb = [
0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x00,
0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_vcom1 = [
0xA0, 0x10, 0x10, 0x00, 0x00, 0x02,
0x00, 0x10, 0x10, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]
lut_ww1 = [
0x50, 0x01, 0x01, 0x00, 0x00, 0x01,
0xA0, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_bw1 = [
0x50, 0x01, 0x01, 0x00, 0x00, 0x01,
0xA0, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_wb1 = [
0xA0, 0x01, 0x01, 0x00, 0x00, 0x01,
0x50, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_bb1 = [
0xA0, 0x01, 0x01, 0x00, 0x00, 0x01,
0x50, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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):
logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
self.send_command(0x71)
epdconfig.delay_ms(100)
logging.debug("e-Paper busy release")
def TurnOnDisplay(self):
self.send_command(0x12)
epdconfig.delay_ms(10)
self.ReadBusy()
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)
self.send_data(0x00)
self.send_data(0x2b)
self.send_data(0x2b)
self.send_data(0x03)
self.send_command(0x06) # boost 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(0xbf) # LUT from OTP,128x296
self.send_data(0x0d) # VCOM to 0V fast
self.send_command(0x30) # PLL setting
self.send_data(0x21) # 3a 100HZ 29 150Hz 39 200HZ 31 171HZ
self.send_command(0x61) # resolution setting
self.send_data(self.width)
self.send_data((self.height >> 8) & 0xff)
self.send_data(self.height& 0xff)
self.send_command(0x82) # vcom_DC setting
self.send_data(0x28)
return 0
def SetFullReg(self):
self.send_command(0x82)
self.send_data(0x00)
self.send_command(0X50)
self.send_data(0x97)
# self.send_command(0x00) # panel setting
# self.send_data(0x9f) # LUT from OTP,128x296
def SetPartReg(self):
# self.send_command(0x00) # panel setting
# self.send_data(0xbf) # LUT from OTP,128x296
self.send_command(0x82)
self.send_data(0x03)
self.send_command(0X50)
self.send_data(0x47)
self.send_command(0x20) # vcom
for count in range(0, 44):
self.send_data(self.lut_vcom1[count])
self.send_command(0x21) # ww --
for count in range(0, 42):
self.send_data(self.lut_ww1[count])
self.send_command(0x22) # bw r
for count in range(0, 42):
self.send_data(self.lut_bw1[count])
self.send_command(0x23) # wb w
for count in range(0, 42):
self.send_data(self.lut_wb1[count])
self.send_command(0x24) # bb b
for count in range(0, 42):
self.send_data(self.lut_bb1[count])
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):
if (Image == None):
return
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00)
epdconfig.delay_ms(10)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(image[i])
epdconfig.delay_ms(10)
self.SetFullReg()
self.TurnOnDisplay()
def DisplayPartial(self, image):
if (Image == None):
return
self.SetPartReg()
self.send_command(0x91)
self.send_command(0x90)
self.send_data(0)
self.send_data(self.width - 1)
self.send_data(0)
self.send_data(0)
self.send_data(int(self.height / 256))
self.send_data(self.height % 256 - 1)
self.send_data(0x28)
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(image[i])
epdconfig.delay_ms(10)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(~image[i])
epdconfig.delay_ms(10)
self.TurnOnDisplay()
def Clear(self):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00)
epdconfig.delay_ms(10)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00)
epdconfig.delay_ms(10)
self.SetFullReg()
self.TurnOnDisplay()
def sleep(self):
self.send_command(0X50)
self.send_data(0xf7)
self.send_command(0X02) # power off
self.send_command(0X07) # deep sleep
self.send_data(0xA5)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,154 +0,0 @@
# /*****************************************************************************
# * | 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 documentation 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
# furnished 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(self.BUSY_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()
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 ###

View File

@ -1,338 +0,0 @@
# //*****************************************************************************
# * | File : epd2in13.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V3.0
# * | Date : 2018-11-01
# * | Info : python2 demo
# * 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
# * 2.Change:
# display_frame -> TurnOnDisplay
# set_memory_area -> SetWindow
# set_memory_pointer -> SetCursor
# * 3.How to use
# epd = epd2in13.EPD()
# epd.init(epd.lut_full_update)
# image = Image.new('1', (epd2in13.EPD_WIDTH, epd2in13.EPD_HEIGHT), 255)
# ...
# drawing ......
# ...
# epd.display(getbuffer(image))
# ******************************************************************************//
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation 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
# furnished 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 time
import spidev
import RPi.GPIO as GPIO
from PIL import Image
# 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;
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
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
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):
digital_write(self.reset_pin, GPIO.HIGH)
delay_ms(200)
digital_write(self.reset_pin, GPIO.LOW) # module reset
delay_ms(200)
digital_write(self.reset_pin, GPIO.HIGH)
delay_ms(200)
def send_command(self, command):
digital_write(self.dc_pin, GPIO.LOW)
spi_writebyte([command])
def send_data(self, data):
digital_write(self.dc_pin, GPIO.HIGH)
spi_writebyte([data])
def wait_until_idle(self):
while (digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
delay_ms(100)
def TurnOnDisplay(self):
self.send_command(0x22)
self.send_data(0xC7)
self.send_command(0x20)
self.wait_until_idle()
def init(self, update):
if (module_init() != 0):
return -1
# EPD hardware init start
self.reset()
if (update == self.FULL_UPDATE):
self.wait_until_idle()
self.send_command(0x12) # soft reset
self.wait_until_idle()
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.wait_until_idle()
else:
self.send_command(0x2C) # VCOM Voltage
self.send_data(0x26)
self.wait_until_idle()
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.wait_until_idle()
self.send_command(0x3C) # BorderWavefrom
self.send_data(0x01)
return 0
def getbuffer(self, image):
if self.width % 8 == 0:
linewidth = self.width // 8
else:
linewidth = 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):
# print("Vertical")
for y in range(imheight):
for x in range(imwidth):
if pixels[x, y] == 0:
x = imwidth - x
buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8))
elif (imwidth == self.height and imheight == self.width):
# print("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[newx // 8 + newy * linewidth] &= ~(0x80 >> (y % 8))
return buf
def display(self, image):
if self.width % 8 == 0:
linewidth = self.width // 8
else:
linewidth = 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 = self.width // 8
else:
linewidth = 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 = self.width // 8
else:
linewidth = self.width // 8 + 1
# print(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(0x22) # POWER OFF
self.send_data(0xC3)
self.send_command(0x20)
self.send_command(0x10) # enter deep sleep
self.send_data(0x01)
delay_ms(100)
### END OF FILE ###

View File

@ -1,397 +0,0 @@
# *****************************************************************************
# * | File : epd2in13_V3.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.1
# * | Date : 2021-10-30
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import logging
from . import epdconfig
import numpy as np
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
lut_partial_update= [
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x14,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
0x22,0x17,0x41,0x00,0x32,0x36,
]
lut_full_update = [
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0xF,0x0,0x0,0x0,0x0,0x0,0x0,
0xF,0x0,0x0,0xF,0x0,0x0,0x2,
0xF,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
0x22,0x17,0x41,0x0,0x32,0x36,
]
'''
function :Hardware reset
parameter:
'''
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
'''
function :send command
parameter:
command : Command register
'''
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)
'''
function :send data
parameter:
data : Write data
'''
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)
'''
function :Wait until the busy_pin goes LOW
parameter:
'''
def ReadBusy(self):
logger.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10)
logger.debug("e-Paper busy release")
'''
function : Turn On Display
parameter:
'''
def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xC7)
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Part
parameter:
'''
def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control
self.send_data(0x0f) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Set lut
parameter:
lut : lut data
'''
def Lut(self, lut):
self.send_command(0x32)
for i in range(0, 153):
self.send_data(lut[i])
self.ReadBusy()
'''
function : Send lut data and configuration
parameter:
lut : lut data
'''
def SetLut(self, lut):
self.Lut(lut)
self.send_command(0x3f)
self.send_data(lut[153])
self.send_command(0x03) # gate voltage
self.send_data(lut[154])
self.send_command(0x04) # source voltage
self.send_data(lut[155]) # VSH
self.send_data(lut[156]) # VSH2
self.send_data(lut[157]) # VSL
self.send_command(0x2c) # VCOM
self.send_data(lut[158])
'''
function : Setting the display window
parameter:
xstart : X-axis starting position
ystart : Y-axis starting position
xend : End position of X-axis
yend : End position of Y-axis
'''
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF)
self.send_data((x_end>>3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
'''
function : Set Cursor
parameter:
x : X-axis starting position
y : Y-axis starting position
'''
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
'''
function : Initialize the e-Paper register
parameter:
'''
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.ReadBusy()
self.send_command(0x12) #SWRESET
self.ReadBusy()
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(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x3c)
self.send_data(0x05)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.send_command(0x18)
self.send_data(0x80)
self.ReadBusy()
self.SetLut(self.lut_full_update)
return 0
'''
function : Display images
parameter:
image : Image data
'''
def getbuffer(self, image):
img = image
imwidth, imheight = img.size
if(imwidth == self.width and imheight == self.height):
img = img.convert('1')
elif(imwidth == self.height and imheight == self.width):
# image has correct dimensions, but needs to be rotated
img = img.rotate(90, expand=True).convert('1')
else:
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
# return a blank buffer
return [0x00] * (int(self.width/8) * self.height)
buf = bytearray(img.tobytes('raw'))
return buf
'''
function : Sends the image buffer in RAM to e-Paper and displays
parameter:
image : Image data
'''
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()
'''
function : Sends the image buffer in RAM to e-Paper and partial refresh
parameter:
image : Image data
'''
def displayPartial(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.SetLut(self.lut_partial_update)
self.send_command(0x37)
self.send_data(0x00)
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_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x80)
self.send_command(0x22)
self.send_data(0xC0)
self.send_command(0x20)
self.ReadBusy()
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplayPart()
'''
function : Refresh a base image
parameter:
image : Image data
'''
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()
'''
function : Clear screen
parameter:
'''
def Clear(self, color):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
# logger.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()
'''
function : Enter sleep mode
parameter:
'''
def sleep(self):
self.send_command(0x10) #enter deep sleep
self.send_data(0x01)
epdconfig.delay_ms(2000)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,154 +0,0 @@
# /*****************************************************************************
# * | 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()
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 ###

View File

@ -1,350 +0,0 @@
# *****************************************************************************
# * | File : epd2in13_V4.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2023-06-25
# # | 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 = 122
EPD_HEIGHT = 250
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
'''
function :Hardware reset
parameter:
'''
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
'''
function :send command
parameter:
command : Command register
'''
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)
'''
function :send data
parameter:
data : Write data
'''
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)
# send a lot of data
def send_data2(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte2(data)
epdconfig.digital_write(self.cs_pin, 1)
'''
function :Wait until the busy_pin goes LOW
parameter:
'''
def ReadBusy(self):
logger.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10)
logger.debug("e-Paper busy release")
'''
function : Turn On Display
parameter:
'''
def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xf7)
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Fast
parameter:
'''
def TurnOnDisplay_Fast(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xC7) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Part
parameter:
'''
def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xff) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Setting the display window
parameter:
xstart : X-axis starting position
ystart : Y-axis starting position
xend : End position of X-axis
yend : End position of Y-axis
'''
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF)
self.send_data((x_end>>3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
'''
function : Set Cursor
parameter:
x : X-axis starting position
y : Y-axis starting position
'''
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
'''
function : Initialize the e-Paper register
parameter:
'''
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.ReadBusy()
self.send_command(0x12) #SWRESET
self.ReadBusy()
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(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x3c)
self.send_data(0x05)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.send_command(0x18)
self.send_data(0x80)
self.ReadBusy()
return 0
'''
function : Initialize the e-Paper fast register
parameter:
'''
def init_fast(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x12) #SWRESET
self.ReadBusy()
self.send_command(0x18) # Read built-in temperature sensor
self.send_command(0x80)
self.send_command(0x11) # data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x22) # Load temperature value
self.send_data(0xB1)
self.send_command(0x20)
self.ReadBusy()
self.send_command(0x1A) # Write to temperature register
self.send_data(0x64)
self.send_data(0x00)
self.send_command(0x22) # Load temperature value
self.send_data(0x91)
self.send_command(0x20)
self.ReadBusy()
return 0
'''
function : Display images
parameter:
image : Image data
'''
def getbuffer(self, image):
img = image
imwidth, imheight = img.size
if(imwidth == self.width and imheight == self.height):
img = img.convert('1')
elif(imwidth == self.height and imheight == self.width):
# image has correct dimensions, but needs to be rotated
img = img.rotate(90, expand=True).convert('1')
else:
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
# return a blank buffer
return [0x00] * (int(self.width/8) * self.height)
buf = bytearray(img.tobytes('raw'))
return buf
'''
function : Sends the image buffer in RAM to e-Paper and displays
parameter:
image : Image data
'''
def display(self, image):
self.send_command(0x24)
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Sends the image buffer in RAM to e-Paper and fast displays
parameter:
image : Image data
'''
def display_fast(self, image):
self.send_command(0x24)
self.send_data2(image)
self.TurnOnDisplay_Fast()
'''
function : Sends the image buffer in RAM to e-Paper and partial refresh
parameter:
image : Image data
'''
def displayPartial(self, image):
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.send_command(0x3C) # BorderWavefrom
self.send_data(0x80)
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(0x03)
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
self.send_data2(image)
self.TurnOnDisplayPart()
'''
function : Refresh a base image
parameter:
image : Image data
'''
def displayPartBaseImage(self, image):
self.send_command(0x24)
self.send_data2(image)
self.send_command(0x26)
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Clear screen
parameter:
'''
def Clear(self, color=0xFF):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
# logger.debug(linewidth)
self.send_command(0x24)
self.send_data2([color] * int(self.height * linewidth))
self.TurnOnDisplay()
'''
function : Enter sleep mode
parameter:
'''
def sleep(self):
self.send_command(0x10) #enter deep sleep
self.send_data(0x01)
epdconfig.delay_ms(2000)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,243 +0,0 @@
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.2
# * | Date : 2022-10-29
# * | 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
logger = logging.getLogger(__name__)
class RaspberryPi:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
def __init__(self):
import spidev
import RPi.GPIO
self.GPIO = RPi.GPIO
self.SPI = spidev.SpiDev()
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 spi_writebyte2(self, data):
self.SPI.writebytes2(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.PWR_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.GPIO.output(self.PWR_PIN, 1)
# SPI device, bus = 0, device = 0
self.SPI.open(0, 0)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.close()
logger.debug("close 5V, Module enters 0 power consumption ...")
self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0)
self.GPIO.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN, self.PWR_PIN])
class JetsonNano:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
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 spi_writebyte2(self, data):
for i in range(len(data)):
self.SPI.SYSFS_software_spi_transfer(data[i])
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.PWR_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.GPIO.output(self.PWR_PIN, 1)
self.SPI.SYSFS_software_spi_begin()
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.SYSFS_software_spi_end()
logger.debug("close 5V, Module enters 0 power consumption ...")
self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0)
self.GPIO.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN, self.PWR_PIN])
class SunriseX3:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
Flag = 0
def __init__(self):
import spidev
import Hobot.GPIO
self.GPIO = Hobot.GPIO
self.SPI = spidev.SpiDev()
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 spi_writebyte2(self, data):
# for i in range(len(data)):
# self.SPI.writebytes([data[i]])
self.SPI.xfer3(data)
def module_init(self):
if self.Flag == 0:
self.Flag = 1
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.PWR_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.GPIO.output(self.PWR_PIN, 1)
# SPI device, bus = 0, device = 0
self.SPI.open(2, 0)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
else:
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.close()
logger.debug("close 5V, Module enters 0 power consumption ...")
self.Flag = 0
self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0)
self.GPIO.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN], self.PWR_PIN)
if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):
implementation = RaspberryPi()
elif os.path.exists('/sys/bus/platform/drivers/gpio-x3'):
implementation = SunriseX3()
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 ###

View File

@ -42,6 +42,5 @@ class Waveshare3in52(DisplayImpl):
self._display.display(buf) self._display.display(buf)
self._display.refresh() self._display.refresh()
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -304,16 +304,16 @@ def load_config(args):
elif config['ui']['display']['type'] in ('waveshare1in64g', 'ws1in64g', 'ws164g', 'waveshare_164g', 'waveshare_1in64g'): elif config['ui']['display']['type'] in ('waveshare1in64g', 'ws1in64g', 'ws164g', 'waveshare_164g', 'waveshare_1in64g'):
config['ui']['display']['type'] = 'waveshare1in64g' config['ui']['display']['type'] = 'waveshare1in64g'
elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1'): elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1', 'waveshare2in13'):
config['ui']['display']['type'] = 'waveshare_1' config['ui']['display']['type'] = 'waveshare_1'
elif config['ui']['display']['type'] in ('ws_2', 'ws2', 'waveshare_2', 'waveshare2'): elif config['ui']['display']['type'] in ('ws_2', 'ws2', 'waveshare_2', 'waveshare2', 'waveshare2in13v2'):
config['ui']['display']['type'] = 'waveshare_2' config['ui']['display']['type'] = 'waveshare_2'
elif config['ui']['display']['type'] in ('ws_3', 'ws3', 'waveshare_3', 'waveshare3'): elif config['ui']['display']['type'] in ('ws_3', 'ws3', 'waveshare_3', 'waveshare3', 'waveshare2in13v3'):
config['ui']['display']['type'] = 'waveshare_3' config['ui']['display']['type'] = 'waveshare_3'
elif config['ui']['display']['type'] in ('ws_4', 'ws4', 'waveshare_4', 'waveshare4'): elif config['ui']['display']['type'] in ('ws_4', 'ws4', 'waveshare_4', 'waveshare4', 'waveshare2in13v4'):
config['ui']['display']['type'] = 'waveshare_4' config['ui']['display']['type'] = 'waveshare_4'
elif config['ui']['display']['type'] in ('waveshare2in13b_v3', 'waveshare2in13b_v3', 'ws213bv3', 'waveshare_213bv3', 'waveshare213inb_v3'): elif config['ui']['display']['type'] in ('waveshare2in13b_v3', 'waveshare2in13b_v3', 'ws213bv3', 'waveshare_213bv3', 'waveshare213inb_v3'):

View File

@ -9,11 +9,13 @@ dependencies = [
"Pillow", "Pillow",
"PyYAML", "PyYAML",
"RPi.GPIO", "RPi.GPIO",
"dbus-python",
"file-read-backwards", "file-read-backwards",
"flask", "flask",
"flask-cors", "flask-cors",
"flask-wtf", "flask-wtf",
"gast", "gast",
"gpiozero",
"gym", "gym",
"inky", "inky",
"pycryptodome", "pycryptodome",
@ -30,7 +32,7 @@ dependencies = [
"torch", "torch",
"torchvision", "torchvision",
"tweepy", "tweepy",
"websockets" "websockets",
] ]
requires-python = ">=3.9" requires-python = ">=3.9"
authors = [ authors = [

View File

@ -9,6 +9,7 @@ import re
import shutil import shutil
import warnings import warnings
import platform import platform
import apt
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -31,6 +32,18 @@ def install_file(source_filename, dest_filename):
def install_system_files(): def install_system_files():
f = open("apt_packages.txt", "r")
cache = apt.cache.Cache()
cache.update()
cache.open()
for x in f:
pkg = cache[x]
if pkg.is_installed:
continue
else:
pkg.mark_install()
f.close()
setup_path = os.path.dirname(__file__) setup_path = os.path.dirname(__file__)
if platform.machine().startswith('arm'): if platform.machine().startswith('arm'):
data_path = os.path.join(setup_path, "builder/data/32bit") data_path = os.path.join(setup_path, "builder/data/32bit")