From 651f91a9a29ba2e969fb4049a864af87b0f53e02 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Fri, 8 Sep 2023 20:26:44 +0200 Subject: [PATCH] Revert "feat: Add in support for Waveshare 2.13inb V4 e-ink display" This reverts commit 52305fa0a6adbbc98a612810032892d746a56d47. --- pwnagotchi/ui/display.py | 3 - pwnagotchi/ui/hw/__init__.py | 13 +- .../libs/waveshare/v213inb_v4/epd2in13b_V4.py | 204 ---------------- .../hw/libs/waveshare/v213inb_v4/epdconfig.py | 227 ------------------ pwnagotchi/ui/hw/waveshare213inb_v4.py | 71 ------ pwnagotchi/utils.py | 3 - 6 files changed, 8 insertions(+), 513 deletions(-) delete mode 100644 pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epd2in13b_V4.py delete mode 100644 pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epdconfig.py delete mode 100644 pwnagotchi/ui/hw/waveshare213inb_v4.py diff --git a/pwnagotchi/ui/display.py b/pwnagotchi/ui/display.py index cd626de6..c072c9a4 100644 --- a/pwnagotchi/ui/display.py +++ b/pwnagotchi/ui/display.py @@ -69,9 +69,6 @@ class Display(View): def is_waveshare213bc(self): return self._implementation.name == 'waveshare213bc' - - def is_waveshare213inb_v4(self): - return self._implementation.name == 'waveshare213inb_v4' def is_spotpear24inch(self): return self._implementation.name == 'spotpear24inch' diff --git a/pwnagotchi/ui/hw/__init__.py b/pwnagotchi/ui/hw/__init__.py index 17516da7..c09450d5 100644 --- a/pwnagotchi/ui/hw/__init__.py +++ b/pwnagotchi/ui/hw/__init__.py @@ -13,9 +13,9 @@ from pwnagotchi.ui.hw.waveshare144lcd import Waveshare144lcd from pwnagotchi.ui.hw.waveshare154inch import Waveshare154inch from pwnagotchi.ui.hw.waveshare213d import Waveshare213d from pwnagotchi.ui.hw.waveshare213bc import Waveshare213bc -from pwnagotchi.ui.hw.waveshare35lcd import Waveshare35lcd from pwnagotchi.ui.hw.spotpear24inch import Spotpear24inch - +from pwnagotchi.ui.hw.displayhatmini import DisplayHatMini +from pwnagotchi.ui.hw.waveshare35lcd import Waveshare35lcd def display_for(config): # config has been normalized already in utils.load_config @@ -64,8 +64,11 @@ def display_for(config): elif config['ui']['display']['type'] == 'waveshare213bc': return Waveshare213bc(config) - elif config['ui']['display']['type'] == 'waveshare35lcd': - return Waveshare35lcd(config) - elif config['ui']['display']['type'] == 'spotpear24inch': return Spotpear24inch(config) + + elif config['ui']['display']['type'] == 'displayhatmini': + return DisplayHatMini(config) + + elif config['ui']['display']['type'] == 'waveshare35lcd': + return Waveshare35lcd(config) \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epd2in13b_V4.py b/pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epd2in13b_V4.py deleted file mode 100644 index 3c87471b..00000000 --- a/pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epd2in13b_V4.py +++ /dev/null @@ -1,204 +0,0 @@ -# ***************************************************************************** -# * | File : epd2in13b_V4.py -# * | Author : Waveshare team -# * | Function : Electronic paper driver -# * | Info : -# *---------------- -# * | This version: V1.0 -# * | Date : 2022-04-21 -# # | 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 - - # hardware reset - 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) - - # send 1 byte command - 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) - - # send 1 byte 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) - - # judge e-Paper whether is busy - def busy(self): - logger.debug("e-Paper busy") - while (epdconfig.digital_read(self.busy_pin) != 0): - epdconfig.delay_ms(10) - logger.debug("e-Paper busy release") - - # set the display window - def set_windows(self, xstart, ystart, xend, yend): - self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION - self.send_data((xstart >> 3) & 0xff) - self.send_data((xend >> 3) & 0xff) - - self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION - self.send_data(ystart & 0xff) - self.send_data((ystart >> 8) & 0xff) - self.send_data(yend & 0xff) - self.send_data((yend >> 8) & 0xff) - - # set the display cursor(origin) - def set_cursor(self, xstart, ystart): - self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER - self.send_data(xstart & 0xff) - - self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER - self.send_data(ystart & 0xff) - self.send_data((ystart >> 8) & 0xff) - - # initialize - def init(self): - if (epdconfig.module_init() != 0): - return -1 - - self.reset() - - self.busy() - self.send_command(0x12) # SWRESET - self.busy() - - 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.set_windows(0, 0, self.width - 1, self.height - 1) - self.set_cursor(0, 0) - - self.send_command(0x3C) # BorderWavefrom - self.send_data(0x05) - - self.send_command(0x18) # Read built-in temperature sensor - self.send_data(0x80) - - self.send_command(0x21) # Display update control - self.send_data(0x80) - self.send_data(0x80) - - self.busy() - - return 0 - - # turn on display - def ondisplay(self): - self.send_command(0x20) - self.busy() - - # image converted to bytearray - 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 - - # display image - def display(self, imageblack, imagered): - self.send_command(0x24) - self.send_data2(imageblack) - - self.send_command(0x26) - self.send_data2(imagered) - - self.ondisplay() - - # display white image - def clear(self): - if self.width % 8 == 0: - linewidth = int(self.width/8) - else: - linewidth = int(self.width/8) + 1 - - buf = [0xff] * (int(linewidth * self.height)) - - self.send_command(0x24) - self.send_data2(buf) - - self.send_command(0x26) - self.send_data2(buf) - - self.ondisplay() - - # Compatible with older version functions - def Clear(self): - self.clear() - - # sleep - def sleep(self): - self.send_command(0x10) # DEEP_SLEEP - self.send_data(0x01) # check code - - epdconfig.delay_ms(2000) - epdconfig.module_exit() -### END OF FILE ### diff --git a/pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epdconfig.py b/pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epdconfig.py deleted file mode 100644 index 2c1cd1da..00000000 --- a/pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epdconfig.py +++ /dev/null @@ -1,227 +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 - - 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.BUSY_PIN, self.GPIO.IN) - - # 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.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN]) - - -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 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.BUSY_PIN, self.GPIO.IN) - 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.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN]) - - -class SunriseX3: - # Pin definition - RST_PIN = 17 - DC_PIN = 25 - CS_PIN = 8 - BUSY_PIN = 24 - 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.BUSY_PIN, self.GPIO.IN) - - # 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.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_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 ### \ No newline at end of file diff --git a/pwnagotchi/ui/hw/waveshare213inb_v4.py b/pwnagotchi/ui/hw/waveshare213inb_v4.py deleted file mode 100644 index dfddb7f6..00000000 --- a/pwnagotchi/ui/hw/waveshare213inb_v4.py +++ /dev/null @@ -1,71 +0,0 @@ -import logging - -import pwnagotchi.ui.fonts as fonts -from pwnagotchi.ui.hw.base import DisplayImpl -from PIL import Image - -class Waveshare213bV4(DisplayImpl): - def __init__(self, config): - super(Waveshare213bV4, self).__init__(config, 'waveshare213inb_v4') - self._display = None - - def layout(self): - if self.config['color'] == 'black': - fonts.setup(10, 9, 10, 35, 25, 9) - self._layout['width'] = 250 - self._layout['height'] = 122 - self._layout['face'] = (0, 40) - self._layout['name'] = (5, 20) - self._layout['channel'] = (0, 0) - self._layout['aps'] = (28, 0) - self._layout['uptime'] = (185, 0) - self._layout['line1'] = [0, 14, 250, 14] - self._layout['line2'] = [0, 108, 250, 108] - self._layout['friend_face'] = (0, 92) - self._layout['friend_name'] = (40, 94) - self._layout['shakes'] = (0, 109) - self._layout['mode'] = (225, 109) - self._layout['status'] = { - 'pos': (125, 20), - 'font': fonts.status_font(fonts.Medium), - 'max': 20 - } - else: - fonts.setup(10, 8, 10, 25, 25, 9) - self._layout['width'] = 212 - self._layout['height'] = 104 - self._layout['face'] = (0, 26) - self._layout['name'] = (5, 15) - self._layout['channel'] = (0, 0) - self._layout['aps'] = (28, 0) - self._layout['status'] = (91, 15) - self._layout['uptime'] = (147, 0) - self._layout['line1'] = [0, 12, 212, 12] - self._layout['line2'] = [0, 92, 212, 92] - self._layout['friend_face'] = (0, 76) - self._layout['friend_name'] = (40, 78) - self._layout['shakes'] = (0, 93) - self._layout['mode'] = (187, 93) - self._layout['status'] = { - 'pos': (125, 20), - 'font': fonts.status_font(fonts.Medium), - 'max': 14 - } - return self._layout - - def initialize(self): - logging.info("initializing waveshare 2.13inb v4 display") - from pwnagotchi.ui.hw.libs.waveshare.v213inb_v4.epd2in13b_V4 import EPD - self._display = EPD() - self._display.init() - self._display.Clear() - - def render(self, canvasBlack = None, canvasRed = None): - buffer = self._display.getbuffer - image = Image.new('1', (self._layout['height'], self._layout['width'])) - imageBlack = image if canvasBlack is None else canvasBlack - imageRed = image if canvasRed is None else canvasRed - self._display.display(buffer(imageBlack), buffer(imageRed)) - - def clear(self): - self._display.Clear() \ No newline at end of file diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index d03e5796..66e6cc27 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -277,9 +277,6 @@ def load_config(args): elif config['ui']['display']['type'] in ('ws_213bc', 'ws213bc', 'waveshare_213bc', 'waveshare213bc'): config['ui']['display']['type'] = 'waveshare213bc' - - elif config['ui']['display']['type'] in ('ws_213bv4', 'ws213bv4', 'waveshare_213bv4', 'waveshare213inb_v4'): - config['ui']['display']['type'] = 'waveshare213inb_v4' elif config['ui']['display']['type'] in ('spotpear24inch'): config['ui']['display']['type'] = 'spotpear24inch'