# SPDX-FileCopyrightText: 2019 Scott Shawcroft for Adafruit Industries # # SPDX-License-Identifier: MIT """ `adafruit_displayio_ssd1306` ================================================================================ DisplayIO driver for SSD1306 monochrome displays * Author(s): Scott Shawcroft Implementation Notes -------------------- **Hardware:** * `Monochrome 1.3" 128x64 OLED graphic display `_ * `Monochrome 128x32 I2C OLED graphic display `_ * `Monochrome 0.96" 128x64 OLED graphic display `_ * `Monochrome 128x32 SPI OLED graphic display `_ * `Adafruit FeatherWing OLED - 128x32 OLED `_ **Software and Dependencies:** * Adafruit CircuitPython (version 5+) firmware for the supported boards: https://github.com/adafruit/circuitpython/releases """ import displayio __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_SSD1306.git" # Sequence from page 19 here: https://cdn-shop.adafruit.com/datasheets/UG-2864HSWEG01+user+guide.pdf _INIT_SEQUENCE = ( b"\xAE\x00" # DISPLAY_OFF b"\x20\x01\x00" # Set memory addressing to horizontal mode. b"\x81\x01\xcf" # set contrast control b"\xA1\x00" # Column 127 is segment 0 b"\xA6\x00" # Normal display b"\xc8\x00" # Normal display b"\xA8\x01\x3f" # Mux ratio is 1/64 b"\xd5\x01\x80" # Set divide ratio b"\xd9\x01\xf1" # Set pre-charge period b"\xda\x01\x12" # Set com configuration b"\xdb\x01\x40" # Set vcom configuration b"\x8d\x01\x14" # Enable charge pump b"\xAF\x00" # DISPLAY_ON ) class SSD1306(displayio.Display): """ SSD1306 driver :param int width: The width of the display :param int height: The height of the display :param int rotation: The rotation of the display in degrees. Default is 0. Must be one of (0, 90, 180, 270) """ def __init__(self, bus, **kwargs): # Patch the init sequence for 32 pixel high displays. init_sequence = bytearray(_INIT_SEQUENCE) height = kwargs["height"] if "rotation" in kwargs and kwargs["rotation"] % 180 != 0: height = kwargs["width"] init_sequence[16] = height - 1 # patch mux ratio if kwargs["height"] == 32: init_sequence[25] = 0x02 # patch com configuration super().__init__( bus, init_sequence, **kwargs, color_depth=1, grayscale=True, pixels_in_byte_share_row=False, set_column_command=0x21, set_row_command=0x22, data_as_commands=True, brightness_command=0x81, single_byte_bounds=True, ) self._is_awake = True # Display starts in active state (_INIT_SEQUENCE) @property def is_awake(self): """ The power state of the display. (read-only) `True` if the display is active, `False` if in sleep mode. :type: bool """ return self._is_awake def sleep(self): """ Put display into sleep mode. Display uses < 10uA in sleep mode. Display remembers display data and operation mode active prior to sleeping. MP can access (update) the built-in display RAM. """ if self._is_awake: self.bus.send(0xAE, b"") # 0xAE = display off, sleep mode self._is_awake = False def wake(self): """ Wake display from sleep mode """ if not self._is_awake: self.bus.send(0xAF, b"") # 0xAF = display on self._is_awake = True