diff --git a/pwnagotchi/ui/hw/argonpod.py b/pwnagotchi/ui/hw/argonpod.py index 1749df34..cb416b57 100644 --- a/pwnagotchi/ui/hw/argonpod.py +++ b/pwnagotchi/ui/hw/argonpod.py @@ -1,12 +1,12 @@ # board GPIO: -# Key1: -# Key2: -# Key3: -# Key4: -# +# Key1: GPIO 16 +# Key2: GPIO 20 +# Key3: GPIO 21 +# Key4: GPIO 26 +# IR: GPIO 23 # Touch chipset: # HW info: https://argon40.com/products/pod-display-2-8inch -# HW datasheet: +# HW MANUAL: https://cdn.shopify.com/s/files/1/0556/1660/2177/files/ARGON_POD_MANUAL.pdf?v=1668390711%0A import logging @@ -44,6 +44,9 @@ class ArgonPod(DisplayImpl): def initialize(self): logging.info("Initializing Argon Pod display") + logging.info("Available pins for GPIO Buttons: 16, 20, 21, 26") + logging.info("IR available on GPIO 23") + logging.info("Backlight pin available on GPIO 18") from pwnagotchi.ui.hw.libs.argon.argonpod.ILI9341 import ILI9341 self._display = ILI9341(0, 0, 22, 18) diff --git a/pwnagotchi/ui/hw/displayhatmini.py b/pwnagotchi/ui/hw/displayhatmini.py index 55cb86ef..ba9cbb8a 100644 --- a/pwnagotchi/ui/hw/displayhatmini.py +++ b/pwnagotchi/ui/hw/displayhatmini.py @@ -1,9 +1,7 @@ import logging - import pwnagotchi.ui.fonts as fonts from pwnagotchi.ui.hw.base import DisplayImpl - class DisplayHatMini(DisplayImpl): def __init__(self, config): super(DisplayHatMini, self).__init__(config, 'displayhatmini') @@ -29,11 +27,14 @@ class DisplayHatMini(DisplayImpl): 'font': fonts.status_font(fonts.Medium), 'max': 20 } - return self._layout def initialize(self): - logging.info("initializing Display Hat Mini") + logging.info("Initializing Display Hat Mini") + logging.info("Available pins for GPIO Buttons A/B/X/Y: 5, 6, 16, 24") + logging.info("Available pins for RGB Led: 17, 27, 22") + logging.info("Backlight pin available on GPIO 13") + logging.info("I2C bus available on stemma QT and Breakout Garden headers") from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789 self._display = ST7789(0,1,9,13) diff --git a/pwnagotchi/ui/hw/gfxhat.py b/pwnagotchi/ui/hw/gfxhat.py index ced3d5ea..51160402 100644 --- a/pwnagotchi/ui/hw/gfxhat.py +++ b/pwnagotchi/ui/hw/gfxhat.py @@ -8,7 +8,7 @@ # ui.display.blcolor = "olive" # # Contrast should be between 30-50, default is 40 -# Backlight are predefined in the epd.py +# Backlight are predefined in the lcd.py # Available backlight colors: # white, grey, maroon, red, purple, fuchsia, green, # lime, olive, yellow, navy, blue, teal, aqua @@ -48,10 +48,16 @@ class GfxHat(DisplayImpl): def initialize(self): contrast = self._config['contrast'] if 'contrast' in self._config else 40 blcolor = self._config['blcolor'] if 'blcolor' in self._config else 'OLIVE' - logging.info("initializing Pimoroni GfxHat") - logging.info("initializing Pimoroni GfxHat - Contrast: %d Backlight color: %s" % (contrast, blcolor)) - from pwnagotchi.ui.hw.libs.pimoroni.gfxhat.epd import EPD - self._display = EPD(contrast=contrast) + logging.info("Initializing Pimoroni GfxHat - Contrast: %d Backlight color: %s" % (contrast, blcolor)) + logging.info("Available config options: ui.display.contrast and ui.display.color") + logging.info("Contrast should be between 30-50, default is 40") + logging.info("Backlight are predefined in the lcd.py") + logging.info("Available backlight colors:") + logging.info("white, grey, maroon, red, purple, fuchsia, green,") + logging.info("lime, olive, yellow, navy, blue, teal, aqua") + logging.info("Touch control work in progress (6 touch buttons with short and long press and LED feedback)") + from pwnagotchi.ui.hw.libs.pimoroni.gfxhat.lcd import LCD + self._display = LCD(contrast=contrast) self._display.Init(color_name=blcolor) self._display.Clear() diff --git a/pwnagotchi/ui/hw/i2coled.py b/pwnagotchi/ui/hw/i2coled.py index 0f58e4bb..402c3657 100644 --- a/pwnagotchi/ui/hw/i2coled.py +++ b/pwnagotchi/ui/hw/i2coled.py @@ -52,11 +52,11 @@ class I2COled(DisplayImpl): i2caddr = self._config['i2c_addr'] if 'i2c_addr' in self._config else 0x3C width = self._config['width'] if 'width' in self._config else 128 height = self._config['height'] if 'height' in self._config else 64 + logging.info("Initializing SSD1306 based %dx%d I2C Oled Display on address 0x%X" % (width, height, i2caddr)) + logging.info("Available config options: ui.display.width, ui.display.height and ui.display.i2caddr") - logging.info("initializing %dx%d I2C Oled Display on address 0x%X" % (width, height, i2caddr)) - - from pwnagotchi.ui.hw.libs.i2coled.epd import EPD - self._display = EPD(address=i2caddr, width=width, height=height) + from pwnagotchi.ui.hw.libs.i2coled.oled import OLED + self._display = OLED(address=i2caddr, width=width, height=height) self._display.Init() self._display.Clear() diff --git a/pwnagotchi/ui/hw/libs/i2coled/epd.py b/pwnagotchi/ui/hw/libs/i2coled/oled.py similarity index 95% rename from pwnagotchi/ui/hw/libs/i2coled/epd.py rename to pwnagotchi/ui/hw/libs/i2coled/oled.py index 12023664..347afb4d 100644 --- a/pwnagotchi/ui/hw/libs/i2coled/epd.py +++ b/pwnagotchi/ui/hw/libs/i2coled/oled.py @@ -9,7 +9,7 @@ EPD_HEIGHT = 64 # disp = SSD1306.SSD1306_96_16(96, 16, address=0x3C) # If you change for different resolution, you have to modify the layout in pwnagotchi/ui/hw/i2coled.py -class EPD(object): +class OLED(object): def __init__(self, address=0x3C, width=EPD_WIDTH, height=EPD_HEIGHT): self.width = width diff --git a/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/backlight.py b/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/backlight.py index 98ccc885..59a15f1f 100644 --- a/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/backlight.py +++ b/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/backlight.py @@ -9,7 +9,7 @@ LED_MAP = [2, 1, 0, 5, 4, 3] def setup(): """Set up the backlight on GFX HAT.""" global _sn3218 - import sn3218 as _sn3218 + from . import sn3218 as _sn3218 _sn3218.enable() _sn3218.enable_leds(0b111111111111111111) diff --git a/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/epd.py b/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/epd.py deleted file mode 100644 index 48768e0f..00000000 --- a/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/epd.py +++ /dev/null @@ -1,55 +0,0 @@ -from . import st7567 -from . import backlight -CONTRAST = 40 - -# Define RGB colors -WHITE = (255, 255, 255) -GREY = (255, 255, 255) -MAROON = (128, 0, 0) -RED = (255, 0, 0) -PURPLE = (128, 0, 128) -FUCHSIA = (255, 0, 255) -GREEN = (0, 128, 0) -LIME = (0, 255, 0) -OLIVE = (128, 128, 0) -YELLOW = (255, 255, 0) -NAVY = (0, 0, 128) -BLUE = (0, 0, 255) -TEAL = (0, 128, 128) -AQUA = (0, 255, 255) - -# Map color names to RGB values -color_map = { - 'WHITE': WHITE, - 'GREY' : GREY, - 'MAROON': MAROON, - 'RED': RED, - 'PURPLE': PURPLE, - 'FUCHSIA': FUCHSIA, - 'GREEN' : GREEN, - 'LIME' : LIME, - 'OLIVE' : OLIVE, - 'YELLOW' : YELLOW, - 'NAVY' : NAVY, - 'BLUE' : BLUE, - 'TEAL' : TEAL, - 'AQUA' : AQUA -} - -class EPD(object): - - def __init__(self, contrast=CONTRAST, blcolor=('OLIVE')): - self.disp = st7567.ST7567() - self.disp.contrast(contrast) - - def Init(self, color_name): - self.disp.setup() - blcolor = color_map.get(color_name.upper(), OLIVE) # Default to olive if color not found - backlight.set_all(*blcolor) - backlight.show() - - def Clear(self): - self.disp.clear() - - def Display(self, image): - self.disp.show(image) \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/lcd.py b/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/lcd.py index 9ba0e4aa..b6644d25 100644 --- a/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/lcd.py +++ b/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/lcd.py @@ -1,57 +1,55 @@ -"""Library for the GFX HAT ST7567 SPI LCD.""" -from .st7567 import ST7567 +from . import st7567 +from . import backlight +CONTRAST = 40 -st7567 = ST7567() +# Define RGB colors +WHITE = (255, 255, 255) +GREY = (255, 255, 255) +MAROON = (128, 0, 0) +RED = (255, 0, 0) +PURPLE = (128, 0, 128) +FUCHSIA = (255, 0, 255) +GREEN = (0, 128, 0) +LIME = (0, 255, 0) +OLIVE = (128, 128, 0) +YELLOW = (255, 255, 0) +NAVY = (0, 0, 128) +BLUE = (0, 0, 255) +TEAL = (0, 128, 128) +AQUA = (0, 255, 255) -dimensions = st7567.dimensions +# Map color names to RGB values +color_map = { + 'WHITE': WHITE, + 'GREY' : GREY, + 'MAROON': MAROON, + 'RED': RED, + 'PURPLE': PURPLE, + 'FUCHSIA': FUCHSIA, + 'GREEN' : GREEN, + 'LIME' : LIME, + 'OLIVE' : OLIVE, + 'YELLOW' : YELLOW, + 'NAVY' : NAVY, + 'BLUE' : BLUE, + 'TEAL' : TEAL, + 'AQUA' : AQUA +} +class LCD(object): -def clear(): - """Clear GFX HAT's display buffer.""" - st7567.clear() + def __init__(self, contrast=CONTRAST, blcolor=('OLIVE')): + self.disp = st7567.ST7567() + self.disp.contrast(contrast) + def Init(self, color_name): + self.disp.setup() + blcolor = color_map.get(color_name.upper(), OLIVE) # Default to olive if color not found + backlight.set_all(*blcolor) + backlight.show() -def set_pixel(x, y, value): - """Set a single pixel in GTX HAT's display buffer. + def Clear(self): + self.disp.clear() - :param x: X position (from 0 to 127) - :param y: Y position (from 0 to 63) - :param value: pixel state 1 = On, 0 = Off - - """ - st7567.set_pixel(x, y, value) - - -def show(): - """Update GFX HAT with the current buffer contents.""" - st7567.show() - - -def contrast(value): - """Change GFX HAT LCD contrast.""" - st7567.contrast(value) - - -def rotation(r=0): - """Set the display rotation. - - :param r: Specify the rotation in degrees: 0, or 180 - - """ - if r == 0: - st7567.rotated = False - - elif r == 180: - st7567.rotated = True - - else: - raise ValueError('Rotation must be 0 or 180 degrees') - - -def get_rotation(): - """Get the display rotation value. - - Returns an integer, either 0, or 180 - - """ - return 180 if st7567.rotated else 0 + def Display(self, image): + self.disp.show(image) \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/sn3218.py b/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/sn3218.py new file mode 100644 index 00000000..5ea24d29 --- /dev/null +++ b/pwnagotchi/ui/hw/libs/pimoroni/gfxhat/sn3218.py @@ -0,0 +1,214 @@ +import sys +import warnings + +__version__ = '1.2.7' + +I2C_ADDRESS = 0x54 +CMD_ENABLE_OUTPUT = 0x00 +CMD_SET_PWM_VALUES = 0x01 +CMD_ENABLE_LEDS = 0x13 +CMD_UPDATE = 0x16 +CMD_RESET = 0x17 + +if sys.version_info < (3, ): + SMBUS = "python-smbus" +else: + SMBUS = "python3-smbus" + +# Helper function to avoid exception chaining output in python3. +# use exec to shield newer syntax from older python +if sys.version_info < (3, 3): + def _raise_from_none(exc): + raise exc +else: + exec("def _raise_from_none(exc): raise exc from None") + +try: + from smbus import SMBus +except ImportError: + err_string = "This library requires {smbus}\nInstall with: sudo apt install {smbus}".format(smbus=SMBUS) + import_error = ImportError(err_string) + _raise_from_none(import_error) + +def i2c_bus_id(): + """ + Returns the i2c bus ID. + """ + with open('/proc/cpuinfo') as cpuinfo: + revision = [l[12:-1] for l in cpuinfo if l[:8] == "Revision"][0] + # https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md + return 1 if int(revision, 16) >= 4 else 0 + + +def enable(): + """ + Enables output. + """ + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_ENABLE_OUTPUT, [0x01]) + + +def disable(): + """ + Disables output. + """ + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_ENABLE_OUTPUT, [0x00]) + + +def reset(): + """ + Resets all internal registers. + """ + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_RESET, [0xFF]) + + +def enable_leds(enable_mask): + """ + Enables or disables each LED channel. The first 18 bit values are + used to determine the state of each channel (1=on, 0=off) if fewer + than 18 bits are provided the remaining channels are turned off. + + Args: + enable_mask (int): up to 18 bits of data + Raises: + TypeError: if enable_mask is not an integer. + """ + if not isinstance(enable_mask, int): + raise TypeError("enable_mask must be an integer") + + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_ENABLE_LEDS, + [enable_mask & 0x3F, (enable_mask >> 6) & 0x3F, (enable_mask >> 12) & 0X3F]) + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_UPDATE, [0xFF]) + + +def channel_gamma(channel, gamma_table): + """ + Overrides the gamma table for a single channel. + + Args: + channel (int): channel number + gamma_table (list): list of 256 gamma correction values + Raises: + TypeError: if channel is not an integer. + ValueError: if channel is not in the range 0..17. + TypeError: if gamma_table is not a list. + """ + global channel_gamma_table + + if not isinstance(channel, int): + raise TypeError("channel must be an integer") + + if channel not in range(18): + raise ValueError("channel be an integer in the range 0..17") + + if not isinstance(gamma_table, list) or len(gamma_table) != 256: + raise TypeError("gamma_table must be a list of 256 integers") + + channel_gamma_table[channel] = gamma_table + + +def output(values): + """ + Outputs a new set of values to the driver. + + Args: + values (list): channel number + Raises: + TypeError: if values is not a list of 18 integers. + """ + if not isinstance(values, list) or len(values) != 18: + raise TypeError("values must be a list of 18 integers") + + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_SET_PWM_VALUES, [channel_gamma_table[i][values[i]] for i in range(18)]) + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_UPDATE, [0xFF]) + + +def output_raw(values): + """ + Outputs a new set of values to the driver. + Similar to output(), but does not use channel_gamma_table. + + Args: + values (list): channel number + Raises: + TypeError: if values is not a list of 18 integers. + """ + # SMBus.write_i2c_block_data does the type check, so we don't have to + if len(values) != 18: + raise TypeError("values must be a list of 18 integers") + + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_SET_PWM_VALUES, values) + i2c.write_i2c_block_data(I2C_ADDRESS, CMD_UPDATE, [0xFF]) + + +try: + i2c = SMBus(i2c_bus_id()) +except IOError as e: + warntxt=""" +###### ###### ###### ###### ###### ###### ###### ###### +i2c initialization failed - is i2c enabled on this system? +See https://github.com/pimoroni/sn3218/wiki/missing-i2c +###### ###### ###### ###### ###### ###### ###### ###### +""" + warnings.warn(warntxt) + raise(e) + +# generate a good default gamma table +default_gamma_table = [int(pow(255, float(i - 1) / 255)) for i in range(256)] +channel_gamma_table = [default_gamma_table] * 18 + +enable_leds(0b111111111111111111) + +def test_cycles(): + print("sn3218 test cycles") + + import time + import math + + # enable output + enable() + enable_leds(0b111111111111111111) + + print(">> test enable mask (on/off)") + enable_mask = 0b000000000000000000 + output([0x10] * 18) + for i in range(10): + enable_mask = ~enable_mask + enable_leds(enable_mask) + time.sleep(0.15) + + print(">> test enable mask (odd/even)") + enable_mask = 0b101010101010101010 + output([0x10] * 18) + for i in range(10): + enable_mask = ~enable_mask + enable_leds(enable_mask) + time.sleep(0.15) + + print(">> test enable mask (rotate)") + enable_mask = 0b100000100000100000 + output([0x10] * 18) + for i in range(10): + enable_mask = ((enable_mask & 0x01) << 18) | enable_mask >> 1 + enable_leds(enable_mask) + time.sleep(0.15) + + print(">> test gamma gradient") + enable_mask = 0b111111111111111111 + enable_leds(enable_mask) + for i in range(256): + output([((j * (256//18)) + (i * (256//18))) % 256 for j in range(18)]) + time.sleep(0.01) + + print(">> test gamma fade") + enable_mask = 0b111111111111111111 + enable_leds(enable_mask) + for i in range(512): + output([int((math.sin(float(i)/64.0) + 1.0) * 128.0)]*18) + time.sleep(0.01) + + # turn everything off and disable output + output([0 for i in range(18)]) + disable() + +if __name__ == "__main__": + test_cycles() \ No newline at end of file diff --git a/pwnagotchi/ui/hw/minipitft.py b/pwnagotchi/ui/hw/minipitft.py index 02efff78..9f859f1d 100644 --- a/pwnagotchi/ui/hw/minipitft.py +++ b/pwnagotchi/ui/hw/minipitft.py @@ -1,6 +1,6 @@ # board GPIO: -# A: GPIO22 -# B: GPIO23 +# A: GPIO23 +# B: GPIO24 # # HW datasheet: https://learn.adafruit.com/adafruit-1-3-color-tft-bonnet-for-raspberry-pi/overview @@ -38,7 +38,10 @@ class MiniPitft(DisplayImpl): return self._layout def initialize(self): - logging.info("initializing Adafruit Mini Pi Tft 240x240") + logging.info("Initializing Adafruit Mini Pi Tft 240x240") + logging.info("Available pins for GPIO Buttons: 23, 24") + logging.info("Backlight pin available on GPIO 22") + logging.info("I2C bus available on stemma QT header") from pwnagotchi.ui.hw.libs.adafruit.minipitft.ST7789 import ST7789 self._display = ST7789(0,0,25,22) diff --git a/pwnagotchi/ui/hw/minipitft2.py b/pwnagotchi/ui/hw/minipitft2.py index d8905d05..bf9a5c71 100644 --- a/pwnagotchi/ui/hw/minipitft2.py +++ b/pwnagotchi/ui/hw/minipitft2.py @@ -1,6 +1,6 @@ # board GPIO: -# A: GPIO22 -# B: GPIO23 +# A: GPIO23 +# B: GPIO24 # # HW datasheet: https://learn.adafruit.com/adafruit-1-3-color-tft-bonnet-for-raspberry-pi/overview @@ -39,6 +39,9 @@ class MiniPitft2(DisplayImpl): def initialize(self): logging.info("initializing Adafruit Mini Pi Tft 135x240") + logging.info("Available pins for GPIO Buttons: 23, 24") + logging.info("Backlight pin available on GPIO 22") + logging.info("I2C bus available on stemma QT header") from pwnagotchi.ui.hw.libs.adafruit.minipitft2.ST7789 import ST7789 self._display = ST7789(0,0,25,22) diff --git a/pwnagotchi/ui/hw/pirateaudio.py b/pwnagotchi/ui/hw/pirateaudio.py index e55a6226..5a570b7e 100644 --- a/pwnagotchi/ui/hw/pirateaudio.py +++ b/pwnagotchi/ui/hw/pirateaudio.py @@ -45,6 +45,10 @@ class PirateAudio(DisplayImpl): def initialize(self): logging.info("Initializing PirateAudio - display only") + logging.info("Available pins for GPIO Buttons A/B/X/Y: 5, 6, 16, 20 or 24") + logging.info("refer to the pimoroni site or pinout.xyz") + logging.info("Backlight pin available on GPIO 13") + logging.info("I2S for the DAC available on pins: 18, 19 and 21") from pwnagotchi.ui.hw.libs.pimoroni.pirateaudio.ST7789 import ST7789 self._display = ST7789(0,1,9,13) diff --git a/pwnagotchi/ui/hw/pitft.py b/pwnagotchi/ui/hw/pitft.py index dbf6c358..4334af5c 100644 --- a/pwnagotchi/ui/hw/pitft.py +++ b/pwnagotchi/ui/hw/pitft.py @@ -50,6 +50,9 @@ class Pitft(DisplayImpl): def initialize(self): logging.info("Initializing adafruit pitft 320x240 screen") + logging.info("Available pins for GPIO Buttons on the 3,2inch: 17, 22, 23, 27") + logging.info("Available pins for GPIO Buttons on the 2,8inch: 26, 13, 12, 6, 5") + logging.info("Backlight pin available on GPIO 18") from pwnagotchi.ui.hw.libs.adafruit.pitft.ILI9341 import ILI9341 self._display = ILI9341(0, 0, 25, 18) diff --git a/pwnagotchi/ui/hw/tftbonnet.py b/pwnagotchi/ui/hw/tftbonnet.py index 5b014b92..fc742910 100644 --- a/pwnagotchi/ui/hw/tftbonnet.py +++ b/pwnagotchi/ui/hw/tftbonnet.py @@ -44,6 +44,9 @@ class TftBonnet(DisplayImpl): def initialize(self): logging.info("initializing Adafruit Tft Bonnet") + logging.info("Available pins for GPIO Buttons Up/Down/Left/Right/Center/A/B: 17, 22, 27, 23, 4, 5, 6") + logging.info("Backlight pin available on GPIO 26") + logging.info("I2C bus available on stemma QT header") from pwnagotchi.ui.hw.libs.adafruit.tftbonnet.ST7789 import ST7789 self._display = ST7789(0,0,25,26) diff --git a/pwnagotchi/ui/hw/waveshareoledlcd.py b/pwnagotchi/ui/hw/waveshareoledlcd.py index 19e58b31..60e82e69 100644 --- a/pwnagotchi/ui/hw/waveshareoledlcd.py +++ b/pwnagotchi/ui/hw/waveshareoledlcd.py @@ -49,6 +49,7 @@ class Waveshareoledlcd(DisplayImpl): def initialize(self): logging.info("initializing Waveshare OLED/LCD hat") + logging.info("Available pins for GPIO Buttons K1/K2/K3/K4: 4, 17, 23, 24") from pwnagotchi.ui.hw.libs.waveshare.oled.oledlcd.ST7789 import ST7789 self._display = ST7789(0,0,22,18) diff --git a/pwnagotchi/ui/hw/waveshareoledlcdvert.py b/pwnagotchi/ui/hw/waveshareoledlcdvert.py index ee817a26..2e86983b 100644 --- a/pwnagotchi/ui/hw/waveshareoledlcdvert.py +++ b/pwnagotchi/ui/hw/waveshareoledlcdvert.py @@ -49,6 +49,7 @@ class Waveshareoledlcdvert(DisplayImpl): def initialize(self): logging.info("initializing Waveshare OLED/LCD hat vertical mode") + logging.info("Available pins for GPIO Buttons K1/K2/K3/K4: 4, 17, 23, 24") from pwnagotchi.ui.hw.libs.waveshare.oled.oledlcd.ST7789vert import ST7789 self._display = ST7789(0,0,22,18)