diff --git a/pwnagotchi/ui/hw/i2coled.py b/pwnagotchi/ui/hw/i2coled.py index 61a675dd..1c55035e 100644 --- a/pwnagotchi/ui/hw/i2coled.py +++ b/pwnagotchi/ui/hw/i2coled.py @@ -3,20 +3,33 @@ # https://github.com/adafruit/Adafruit_Python_SSD1306 # SMBus parts coming from BLavery's lib_oled96 repo: # https://github.com/BLavery/lib_oled96 +# I2C address, width and height import from config.toml made by NurseJackass import logging import pwnagotchi.ui.fonts as fonts from pwnagotchi.ui.hw.base import DisplayImpl +# +# Default is 128x64 display on i2c address 0x3C +# +# Configure i2c address and dimensions in config.toml: +# +# ui.display.type = "i2coled" +# ui.display.i2c_addr = 0x3C +# ui.display.width = 128 +# ui.display.height = 64 +# + class I2COled(DisplayImpl): def __init__(self, config): + self._config = config['ui']['display'] super(I2COled, self).__init__(config, 'i2coled') def layout(self): fonts.setup(8, 8, 8, 10, 10, 8) - self._layout['width'] = 128 - self._layout['height'] = 64 + self._layout['width'] = self._config['width'] if 'width' in self._config else 128 + self._layout['height'] = self._config['height'] if 'height' in self._config else 64 self._layout['face'] = (0, 30) self._layout['name'] = (0, 10) self._layout['channel'] = (72, 10) @@ -36,10 +49,14 @@ class I2COled(DisplayImpl): return self._layout def initialize(self): - logging.info("initializing 128x64 I2C Oled Display on address 0x3C") - logging.info("To change resolution or address check pwnagotchi/ui/hw/libs/i2coled/epd.py") + 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 %dx%d I2C Oled Display on address 0x%X" % (width, height, i2caddr)) + from pwnagotchi.ui.hw.libs.i2coled.epd import EPD - self._display = EPD() + self._display = EPD(address=i2caddr, width=width, height=height) self._display.Init() self._display.Clear() diff --git a/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py b/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py index e5c02ecd..815f53cf 100644 --- a/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py +++ b/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py @@ -100,13 +100,19 @@ class SSD1306Base(object): """Send command byte to display.""" # I2C write. assert(len(cmd) <= 31) - self.bus.write_i2c_block_data(self.addr, self.cmd_mode, list(cmd)) + try: + self.bus.write_i2c_block_data(self.addr, self.cmd_mode, list(cmd)) + except Exception as e: + logging.exception(e) def data(self, data): """Send byte of data to display.""" # I2C write. - for i in range(0, len(data), 31): - self.bus.write_i2c_block_data(self.addr, self.data_mode, list(data[i:i+31])) + try: + for i in range(0, len(data), 31): + self.bus.write_i2c_block_data(self.addr, self.data_mode, list(data[i:i+31])) + except Exception as e: + logging.exception(e) def begin(self, vccstate=SSD1306_SWITCHCAPVCC): """Initialize display.""" @@ -116,7 +122,7 @@ class SSD1306Base(object): self._initialize() # Turn on the display. self.command(SSD1306_DISPLAYON) - + def ShowImage(self): """ The image on the "canvas" is flushed through to the hardware display. @@ -128,10 +134,12 @@ class SSD1306Base(object): self.command(SSD1306_PAGEADDR) self.command(0) # Page start address. (0 = reset) self.command(self._pages-1) # Page end address. - - for i in range(0, len(self._buffer), 16): - self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) - + try: + for i in range(0, len(self._buffer), 16): + self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) + except Exception as e: + logging.exception(e) + def getbuffer(self, image): """Set buffer to value of Python Imaging Library image. The image should be in 1 bit mode and a size equal to the display size. @@ -229,7 +237,7 @@ class SSD1306_128_64(SSD1306Base): class SSD1306_128_32(SSD1306Base): def __init__(self, width, height, address=None, bus=None): # Call base class constructor. - super(SSD1306_128_64, self).__init__(128, 64, address, bus) + super(SSD1306_128_32, self).__init__(128, 32, address, bus) def _initialize(self): # 128x32 pixel specific initialization. diff --git a/pwnagotchi/ui/hw/libs/i2coled/epd.py b/pwnagotchi/ui/hw/libs/i2coled/epd.py index 898aee36..c35ee8c9 100644 --- a/pwnagotchi/ui/hw/libs/i2coled/epd.py +++ b/pwnagotchi/ui/hw/libs/i2coled/epd.py @@ -8,20 +8,27 @@ EPD_HEIGHT = 64 # disp = SSD1306.SSD1306_128_32(128, 32, address=0x3C) # 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 -disp = SSD1306.SSD1306_128_64(128, 64, address=0x3C) class EPD(object): - def __init__(self): - self.width = EPD_WIDTH - self.height = EPD_HEIGHT + def __init__(self, address=0x3D, width=EPD_WIDTH, height=EPD_HEIGHT): + self.width = width + self.height = height + + # choose subclass based on dimensions + if height == 32: + self.disp = SSD1306.SSD1306_128_32(width, height, address) + elif height == 16: + self.disp = SSD1306.SSD1306_96_16(width, height, address) + else: + self.disp = SSD1306.SSD1306_128_64(width, height, address) def Init(self): - disp.begin() + self.disp.begin() def Clear(self): - disp.clear() + self.disp.clear() def display(self, image): - disp.getbuffer(image) - disp.ShowImage() \ No newline at end of file + self.disp.getbuffer(image) + self.disp.ShowImage() \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py index 4ca97dad..c529c48f 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py @@ -106,7 +106,7 @@ class SSD1306Base(object): self._initialize() # Turn on the display. self.command(SSD1306_DISPLAYON) - + def ShowImage(self): """ The image on the "canvas" is flushed through to the hardware display. @@ -118,10 +118,10 @@ class SSD1306Base(object): self.command(SSD1306_PAGEADDR) self.command(0) # Page start address. (0 = reset) self.command(self._pages-1) # Page end address. - + for i in range(0, len(self._buffer), 16): self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) - + def getbuffer(self, image): """Set buffer to value of Python Imaging Library image. The image should be in 1 bit mode and a size equal to the display size. diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py index f8894b98..b0f0763d 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py @@ -95,11 +95,8 @@ class ST7789(object): offset_left=0, offset_top=0): """Create an instance of the display using SPI communication. - Must provide the GPIO pin number for the D/C pin and the SPI driver. - Can optionally provide the GPIO pin number for the reset pin as the rst parameter. - :param port: SPI port number :param cs: SPI chip-select number (0 or 1 for BCM :param backlight: Pin for controlling backlight @@ -109,7 +106,6 @@ class ST7789(object): :param rotation: Rotation of display connected to ST7789 :param invert: Invert display :param spi_speed_hz: SPI speed (in Hz) - """ if rotation not in [0, 90, 180, 270]: raise ValueError("Invalid rotation {}".format(rotation)) @@ -287,9 +283,7 @@ class ST7789(object): def begin(self): """Set up the display - Deprecated. Included in __init__. - """ pass @@ -326,9 +320,7 @@ class ST7789(object): def display(self, image): """Write the provided image to the hardware. - :param image: Should be RGB format and the same dimensions as the display hardware. - """ # Set address bounds to entire display. self.set_window()