From c84dc45f7b594d4f4fd5695ec5243a417842884c Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Thu, 11 Mar 2021 17:05:25 -0800 Subject: [PATCH 1/2] Added SSD1680 Driver --- adafruit_epd/ssd1680.py | 183 +++++++++++++++++++++++++++++++++++ examples/epd_bitmap.py | 2 + examples/epd_blinka.py | 2 + examples/epd_pillow_demo.py | 2 + examples/epd_pillow_image.py | 2 + examples/epd_simpletest.py | 2 + 6 files changed, 193 insertions(+) create mode 100644 adafruit_epd/ssd1680.py diff --git a/adafruit_epd/ssd1680.py b/adafruit_epd/ssd1680.py new file mode 100644 index 0000000..b408b6b --- /dev/null +++ b/adafruit_epd/ssd1680.py @@ -0,0 +1,183 @@ +# SPDX-FileCopyrightText: 2018 Dean Miller for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +`adafruit_epd.ssd1680` - Adafruit SSD1680 - ePaper display driver +==================================================================================== +CircuitPython driver for Adafruit SSD1680 display breakouts +* Author(s): Melissa LeBlanc-Williams +""" + +import time +from micropython import const +import adafruit_framebuf +from adafruit_epd.epd import Adafruit_EPD + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git" + +_SSD1680_DRIVER_CONTROL = const(0x01) +_SSD1680_GATE_VOLTAGE = const(0x03) +_SSD1680_SOURCE_VOLTAGE = const(0x04) +_SSD1680_INIT_SETTING = const(0x08) +_SSD1680_INIT_WRITE_REG = const(0x09) +_SSD1680_INIT_READ_REG = const(0x0A) +_SSD1680_BOOSTER_SOFT_START = const(0x0C) +_SSD1680_DEEP_SLEEP = const(0x10) +_SSD1680_DATA_MODE = const(0x11) +_SSD1680_SW_RESET = const(0x12) +_SSD1680_HV_DETECT = const(0x14) +_SSD1680_VCI_DETECT = const(0x15) +_SSD1680_TEMP_CONTROL = const(0x18) +_SSD1680_TEMP_WRITE = const(0x1A) +_SSD1680_TEMP_READ = const(0x1B) +_SSD1680_EXTTEMP_WRITE = const(0x1C) +_SSD1680_MASTER_ACTIVATE = const(0x20) +_SSD1680_DISP_CTRL1 = const(0x21) +_SSD1680_DISP_CTRL2 = const(0x22) +_SSD1680_WRITE_BWRAM = const(0x24) +_SSD1680_WRITE_REDRAM = const(0x26) +_SSD1680_READ_RAM = const(0x27) +_SSD1680_VCOM_SENSE = const(0x28) +_SSD1680_VCOM_DURATION = const(0x29) +_SSD1680_WRITE_VCOM_OTP = const(0x2A) +_SSD1680_WRITE_VCOM_CTRL = const(0x2B) +_SSD1680_WRITE_VCOM_REG = const(0x2C) +_SSD1680_READ_OTP = const(0x2D) +_SSD1680_READ_USERID = const(0x2E) +_SSD1680_READ_STATUS = const(0x2F) +_SSD1680_WRITE_WS_OTP = const(0x30) +_SSD1680_LOAD_WS_OTP = const(0x31) +_SSD1680_WRITE_LUT = const(0x32) +_SSD1680_CRC_CALC = const(0x34) +_SSD1680_CRC_READ = const(0x35) +_SSD1680_PROG_OTP = const(0x36) +_SSD1680_WRITE_DISPLAY_OPT = const(0x37) +_SSD1680_WRITE_USERID = const(0x38) +_SSD1680_OTP_PROGMODE = const(0x39) +_SSD1680_WRITE_BORDER = const(0x3C) +_SSD1680_END_OPTION = const(0x3F) +_SSD1680_SET_RAMXPOS = const(0x44) +_SSD1680_SET_RAMYPOS = const(0x45) +_SSD1680_AUTOWRITE_RED = const(0x46) +_SSD1680_AUTOWRITE_BW = const(0x47) +_SSD1680_SET_RAMXCOUNT = const(0x4E) +_SSD1680_SET_RAMYCOUNT = const(0x4F) +_SSD1680_NOP = const(0xFF) + + +class Adafruit_SSD1680(Adafruit_EPD): + """driver class for Adafruit SSD1680 ePaper display breakouts""" + + # pylint: disable=too-many-arguments + def __init__( + self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin + ): + super().__init__( + width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin + ) + + if width % 8 != 0: + width += 8 - width % 8 + + self._buffer1_size = int(width * height / 8) + self._buffer2_size = self._buffer1_size + + if sramcs_pin: + self._buffer1 = self.sram.get_view(0) + self._buffer2 = self.sram.get_view(self._buffer1_size) + else: + self._buffer1 = bytearray(self._buffer1_size) + self._buffer2 = bytearray(self._buffer2_size) + + self._framebuf1 = adafruit_framebuf.FrameBuffer( + self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB + ) + self._framebuf2 = adafruit_framebuf.FrameBuffer( + self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB + ) + self.set_black_buffer(0, True) + self.set_color_buffer(1, False) + # pylint: enable=too-many-arguments + + def begin(self, reset=True): + """Begin communication with the display and set basic settings""" + if reset: + self.hardware_reset() + self.power_down() + + def busy_wait(self): + """Wait for display to be done with current task, either by polling the + busy pin, or pausing""" + if self._busy: + while self._busy.value: + time.sleep(0.01) + else: + time.sleep(0.5) + + def power_up(self): + """Power up the display in preparation for writing RAM and updating""" + self.hardware_reset() + self.busy_wait() + self.command(_SSD1680_SW_RESET) + self.busy_wait() + # driver output control + self.command( + _SSD1680_DRIVER_CONTROL, + bytearray([self._height - 1, (self._height - 1) >> 8, 0x00]), + ) + # data entry mode + self.command(_SSD1680_DATA_MODE, bytearray([0x03])) + + # Set voltages + self.command(_SSD1680_WRITE_VCOM_REG, bytearray([0x36])) + self.command(_SSD1680_GATE_VOLTAGE, bytearray([0x17])) + self.command(_SSD1680_SOURCE_VOLTAGE, bytearray([0x41, 0x00, 0x32])) + + # Set ram X start/end postion + self.command(_SSD1680_SET_RAMXPOS, bytearray([0x00, 0x0F])) + # Set ram Y start/end postion + self.command( + _SSD1680_SET_RAMYPOS, + bytearray([0, 0, self._height - 1, (self._height - 1) >> 8]), + ) + # Set border waveform + self.command(_SSD1680_WRITE_BORDER, bytearray([0x05])) + + # Set ram X count + self.command(_SSD1680_SET_RAMXCOUNT, bytearray([0x01])) + # Set ram Y count + self.command(_SSD1680_SET_RAMYCOUNT, bytearray([self._height - 1, 0])) + self.busy_wait() + + def power_down(self): + """Power down the display - required when not actively displaying!""" + self.command(_SSD1680_DEEP_SLEEP, bytearray([0x01])) + time.sleep(0.1) + + def update(self): + """Update the display from internal memory""" + self.command(_SSD1680_DISP_CTRL2, bytearray([0xF4])) + self.command(_SSD1680_MASTER_ACTIVATE) + self.busy_wait() + if not self._busy: + time.sleep(3) # wait 3 seconds + + def write_ram(self, index): + """Send the one byte command for starting the RAM write process. Returns + the byte read at the same time over SPI. index is the RAM buffer, can be + 0 or 1 for tri-color displays.""" + if index == 0: + return self.command(_SSD1680_WRITE_BWRAM, end=False) + if index == 1: + return self.command(_SSD1680_WRITE_REDRAM, end=False) + raise RuntimeError("RAM index must be 0 or 1") + + def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use + """Set the RAM address location, not used on this chipset but required by + the superclass""" + # Set RAM X address counter + self.command(_SSD1680_SET_RAMXCOUNT, bytearray([x + 1])) + # Set RAM Y address counter + self.command(_SSD1680_SET_RAMYCOUNT, bytearray([y, y >> 8])) diff --git a/examples/epd_bitmap.py b/examples/epd_bitmap.py index 23a027e..1daa25a 100644 --- a/examples/epd_bitmap.py +++ b/examples/epd_bitmap.py @@ -10,6 +10,7 @@ from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-impo from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import +from adafruit_epd.ssd1680 import Adafruit_SSD1680 # pylint: disable=unused-import from adafruit_epd.ssd1681 import Adafruit_SSD1681 # pylint: disable=unused-import @@ -25,6 +26,7 @@ busy = digitalio.DigitalInOut(board.D12) # can be None to not use this pin print("Creating display") # display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display # display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display +# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display # display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display # display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display # display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display diff --git a/examples/epd_blinka.py b/examples/epd_blinka.py index 2ea4f46..275871a 100644 --- a/examples/epd_blinka.py +++ b/examples/epd_blinka.py @@ -15,6 +15,7 @@ from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import from adafruit_epd.ssd1675b import Adafruit_SSD1675B # pylint: disable=unused-import +from adafruit_epd.ssd1680 import Adafruit_SSD1680 # pylint: disable=unused-import from adafruit_epd.ssd1681 import Adafruit_SSD1681 # pylint: disable=unused-import # create the spi device and pins we will need @@ -32,6 +33,7 @@ busy = digitalio.DigitalInOut(board.D7) # can be None to not use this pin # give them all to our driver print("Creating display") # display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display +# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display # display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display # display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display # display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display diff --git a/examples/epd_pillow_demo.py b/examples/epd_pillow_demo.py index 0509cf5..50cc615 100644 --- a/examples/epd_pillow_demo.py +++ b/examples/epd_pillow_demo.py @@ -15,6 +15,7 @@ from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-impo from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import +from adafruit_epd.ssd1680 import Adafruit_SSD1680 # pylint: disable=unused-import from adafruit_epd.ssd1681 import Adafruit_SSD1681 # pylint: disable=unused-import # First define some color constants @@ -40,6 +41,7 @@ busy = digitalio.DigitalInOut(board.D17) # give them all to our driver # display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display # display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display +# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display # display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display # display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display # display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display diff --git a/examples/epd_pillow_image.py b/examples/epd_pillow_image.py index 6c0e24a..3ba2fb3 100644 --- a/examples/epd_pillow_image.py +++ b/examples/epd_pillow_image.py @@ -17,6 +17,7 @@ from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-impo from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import +from adafruit_epd.ssd1680 import Adafruit_SSD1680 # pylint: disable=unused-import from adafruit_epd.ssd1681 import Adafruit_SSD1681 # pylint: disable=unused-import @@ -31,6 +32,7 @@ busy = digitalio.DigitalInOut(board.D17) # give them all to our driver # display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display # display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display +# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display # display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display # display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display # display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display diff --git a/examples/epd_simpletest.py b/examples/epd_simpletest.py index 62d6e93..7f469a7 100644 --- a/examples/epd_simpletest.py +++ b/examples/epd_simpletest.py @@ -10,6 +10,7 @@ from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-impo from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import +from adafruit_epd.ssd1680 import Adafruit_SSD1680 # pylint: disable=unused-import from adafruit_epd.ssd1681 import Adafruit_SSD1681 # pylint: disable=unused-import # create the spi device and pins we will need @@ -24,6 +25,7 @@ busy = digitalio.DigitalInOut(board.D5) # can be None to not use this pin print("Creating display") # display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display # display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display +# display = Adafruit_SSD1680(122, 250, # 2.13" HD Tri-color display # display = Adafruit_SSD1681(200, 200, # 1.54" HD Tri-color display # display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display # display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display From ec379ba7ae36cc2f30429d1bdd9d1d13f2ba033b Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Thu, 11 Mar 2021 17:09:55 -0800 Subject: [PATCH 2/2] Ran pre-commit again because it didn't work the first time --- adafruit_epd/ssd1680.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_epd/ssd1680.py b/adafruit_epd/ssd1680.py index b408b6b..fd632fb 100644 --- a/adafruit_epd/ssd1680.py +++ b/adafruit_epd/ssd1680.py @@ -134,7 +134,7 @@ class Adafruit_SSD1680(Adafruit_EPD): self.command(_SSD1680_WRITE_VCOM_REG, bytearray([0x36])) self.command(_SSD1680_GATE_VOLTAGE, bytearray([0x17])) self.command(_SSD1680_SOURCE_VOLTAGE, bytearray([0x41, 0x00, 0x32])) - + # Set ram X start/end postion self.command(_SSD1680_SET_RAMXPOS, bytearray([0x00, 0x0F])) # Set ram Y start/end postion @@ -144,7 +144,7 @@ class Adafruit_SSD1680(Adafruit_EPD): ) # Set border waveform self.command(_SSD1680_WRITE_BORDER, bytearray([0x05])) - + # Set ram X count self.command(_SSD1680_SET_RAMXCOUNT, bytearray([0x01])) # Set ram Y count