From 40fd8a8b85d9dcefc1a8b1f2448dc93af25b6e98 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Mon, 6 May 2019 12:16:44 -0400 Subject: [PATCH 1/5] Added ST7789 Display Support --- adafruit_rgb_display/rgb.py | 6 +- adafruit_rgb_display/st7789.py | 133 +++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 adafruit_rgb_display/st7789.py diff --git a/adafruit_rgb_display/rgb.py b/adafruit_rgb_display/rgb.py index 5616a4d..771d4ab 100644 --- a/adafruit_rgb_display/rgb.py +++ b/adafruit_rgb_display/rgb.py @@ -80,6 +80,8 @@ class Display: #pylint: disable-msg=no-member _COLUMN_SET = None _RAM_WRITE = None _RAM_READ = None + _X_START = 0 + _Y_START = 0 _INIT = () _ENCODE_PIXEL = ">H" _ENCODE_POS = ">HH" @@ -98,8 +100,8 @@ def init(self): #pylint: disable-msg=invalid-name,too-many-arguments def _block(self, x0, y0, x1, y1, data=None): """Read or write a block of data.""" - self.write(self._COLUMN_SET, self._encode_pos(x0, x1)) - self.write(self._PAGE_SET, self._encode_pos(y0, y1)) + self.write(self._COLUMN_SET, self._encode_pos(x0 + self._X_START, x1 + self._X_START)) + self.write(self._PAGE_SET, self._encode_pos(y0 + self._Y_START, y1 + self._Y_START)) if data is None: size = struct.calcsize(self._DECODE_PIXEL) return self.read(self._RAM_READ, diff --git a/adafruit_rgb_display/st7789.py b/adafruit_rgb_display/st7789.py new file mode 100644 index 0000000..cefe518 --- /dev/null +++ b/adafruit_rgb_display/st7789.py @@ -0,0 +1,133 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Melissa LeBlanc-Williams for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation 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 +# furnished 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 FOR 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. +""" +`adafruit_rgb_display.st7789` +==================================================== + +A simple driver for the ST7789-based displays. + +* Author(s): Melissa LeBlanc-Williams +""" + +try: + import struct +except ImportError: + import ustruct as struct +from micropython import const +from adafruit_rgb_display.rgb import DisplaySPI + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display.git" + +_NOP = const(0x00) +_SWRESET = const(0x01) +_RDDID = const(0x04) +_RDDST = const(0x09) + +_SLPIN = const(0x10) +_SLPOUT = const(0x11) +_PTLON = const(0x12) +_NORON = const(0x13) + +_INVOFF = const(0x20) +_INVON = const(0x21) +_DISPOFF = const(0x28) +_DISPON = const(0x29) +_CASET = const(0x2A) +_RASET = const(0x2B) +_RAMWR = const(0x2C) +_RAMRD = const(0x2E) + +_PTLAR = const(0x30) +_COLMOD = const(0x3A) +_MADCTL = const(0x36) + +_FRMCTR1 = const(0xB1) +_FRMCTR2 = const(0xB2) +_FRMCTR3 = const(0xB3) +_INVCTR = const(0xB4) +_DISSET5 = const(0xB6) + +_PWCTR1 = const(0xC0) +_PWCTR2 = const(0xC1) +_PWCTR3 = const(0xC2) +_PWCTR4 = const(0xC3) +_PWCTR5 = const(0xC4) +_VMCTR1 = const(0xC5) + +_RDID1 = const(0xDA) +_RDID2 = const(0xDB) +_RDID3 = const(0xDC) +_RDID4 = const(0xDD) + +_PWCTR6 = const(0xFC) + +_GMCTRP1 = const(0xE0) +_GMCTRN1 = const(0xE1) + + +class ST7789(DisplaySPI): + """ + A simple driver for the ST7789-based displays. + + >>> import busio + >>> import digitalio + >>> import board + >>> from adafruit_rgb_display import color565 + >>> import adafruit_rgb_display.st7789 as st7789 + >>> spi = busio.SPI(clock=board.SCK, MOSI=board.MOSI, MISO=board.MISO) + >>> display = st7789.ST7789(spi, cs=digitalio.DigitalInOut(board.GPIO0), + ... dc=digitalio.DigitalInOut(board.GPIO15), rst=digitalio.DigitalInOut(board.GPIO16)) + >>> display.fill(0x7521) + >>> display.pixel(64, 64, 0) + """ + _COLUMN_SET = _CASET + _PAGE_SET = _RASET + _RAM_WRITE = _RAMWR + _RAM_READ = _RAMRD + _Y_START = 80 + _INIT = ( + (_SWRESET, None), + (_SLPOUT, None), + (_COLMOD, b'\x55'), # 16bit color + (_MADCTL, b'\x08'), + ) + + #pylint: disable-msg=useless-super-delegation, too-many-arguments + def __init__(self, spi, dc, cs, rst=None, width=240, height=240, + baudrate=16000000, polarity=0, phase=0): + super().__init__(spi, dc, cs, rst, width, height, + baudrate=baudrate, polarity=polarity, phase=phase) + + def init(self): + super().init() + cols = struct.pack('>HH', 0, self.width) + rows = struct.pack('>HH', self._Y_START, self.height + self._Y_START) + for command, data in ( + (_CASET, cols), + (_RASET, rows), + (_INVON, None), + (_NORON, None), + (_DISPON, None), + (_MADCTL, b'\xc0'), #Set rotation to 0 and use RGB + ): + self.write(command, data) From f90bf2fe4a3e91bd46d2795e55f9d8a398ed303b Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Mon, 6 May 2019 12:21:43 -0400 Subject: [PATCH 2/5] Fixed broken RTD link --- docs/examples.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples.rst b/docs/examples.rst index b254c48..1624810 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -3,6 +3,6 @@ Simple test Ensure your device works with this simple test. -.. literalinclude:: ../examples/esp8266_tft_featherwing.py - :caption: examples/esp8266_tft_featherwing.py +.. literalinclude:: ../examples/rgbdisplay_ili9341test.py + :caption: examples/rgbdisplay_ili9341test.py :linenos: From 404f4e3eb42a20927b2fa292689f4dd41079f943 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Mon, 6 May 2019 13:37:15 -0400 Subject: [PATCH 3/5] Added simpletest --- docs/examples.rst | 4 +++ examples/rgbdisplay_simpletest.py | 46 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 examples/rgbdisplay_simpletest.py diff --git a/docs/examples.rst b/docs/examples.rst index 1624810..294de83 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -3,6 +3,10 @@ Simple test Ensure your device works with this simple test. +.. literalinclude:: ../examples/rgbdisplay_simpletest.py + :caption: examples/rgbdisplay_simpletest.py + :linenos: + .. literalinclude:: ../examples/rgbdisplay_ili9341test.py :caption: examples/rgbdisplay_ili9341test.py :linenos: diff --git a/examples/rgbdisplay_simpletest.py b/examples/rgbdisplay_simpletest.py new file mode 100644 index 0000000..3e232ad --- /dev/null +++ b/examples/rgbdisplay_simpletest.py @@ -0,0 +1,46 @@ +# Quick test of TFT FeatherWing (ST7789) with Feather M0 or M4 +# This will work even on a device running displayio +# Will fill the TFT black and put a red pixel in the center, wait 2 seconds, +# then fill the screen blue (with no pixel), wait 2 seconds, and repeat. +import time +import random +import digitalio +import board +import displayio + +from adafruit_rgb_display.rgb import color565 +import adafruit_rgb_display.st7789 as st7789 + +displayio.release_displays() + +# Configuratoin for CS and DC pins (these are FeatherWing defaults on M0/M4): +cs_pin = digitalio.DigitalInOut(board.D5) +dc_pin = digitalio.DigitalInOut(board.D6) +reset_pin = digitalio.DigitalInOut(board.D9) + +# Config for display baudrate (default max is 24mhz): +BAUDRATE = 24000000 + +# Setup SPI bus using hardware SPI: +spi = board.SPI() + +# Create the ST7789 display: +display = st7789.ST7789(spi, cs=cs_pin, dc=dc_pin, rst=reset_pin, baudrate=BAUDRATE) + +# Main loop: +while True: + # Fill the screen red, green, blue, then black: + for color in ((255, 0, 0), (0, 255, 0), (0, 0, 255)): + display.fill(color565(color)) + # Clear the display + display.fill(0) + # Draw a red pixel in the center. + display.pixel(display.width//2, display.height//2, color565(255, 0, 0)) + # Pause 2 seconds. + time.sleep(2) + # Clear the screen a random color + display.fill(color565(random.randint(0, 255), + random.randint(0, 255), + random.randint(0, 255))) + # Pause 2 seconds. + time.sleep(2) From 0b3466ee2ff4576b13a9a123de38188017305c6d Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Mon, 6 May 2019 14:22:08 -0400 Subject: [PATCH 4/5] Added HX8357 Display Support --- adafruit_rgb_display/hx8357.py | 106 ++++++++++++++++++++++++++++++ examples/rgbdisplay_hx8357test.py | 45 +++++++++++++ 2 files changed, 151 insertions(+) create mode 100755 adafruit_rgb_display/hx8357.py create mode 100644 examples/rgbdisplay_hx8357test.py diff --git a/adafruit_rgb_display/hx8357.py b/adafruit_rgb_display/hx8357.py new file mode 100755 index 0000000..3250983 --- /dev/null +++ b/adafruit_rgb_display/hx8357.py @@ -0,0 +1,106 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Melissa LeBlanc-Williams for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation 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 +# furnished 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 FOR 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. +""" +`adafruit_rgb_display.hx8357` +==================================================== + +A simple driver for the HX8357-based displays. + +* Author(s): Melissa LeBlanc-Williams +""" +from micropython import const +from adafruit_rgb_display.rgb import DisplaySPI + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display.git" + +_SWRESET = const(0x01) +_SLPOUT = const(0x11) +_NORON = const(0x13) +_INVOFF = const(0x20) +_INVON = const(0x21) +_DISPOFF = const(0x28) +_DISPON = const(0x29) +_CASET = const(0x2a) +_PASET = const(0x2b) +_RAMWR = const(0x2c) +_RAMRD = const(0x2e) +_TEON = const(0x35) +_MADCTL = const(0x36) +_COLMOD = const(0x3a) +_TEARLINE = const(0x44) +_SETOSC = const(0xb0) +_SETPWR1 = const(0xb1) +_SETRGB = const(0xb3) +_SETCYC = const(0xb4) +_SETCOM = const(0xb6) +_SETC = const(0xb9) +_SETSTBA = const(0xc0) +_SETPANEL = const(0xcc) +_SETGAMMA = const(0xe0) + +class HX8357(DisplaySPI): + """ + A simple driver for the HX8357-based displays. + + >>> import busio + >>> import digitalio + >>> import board + >>> from adafruit_rgb_display import color565 + >>> import adafruit_rgb_display.hx8357 as hx8357 + >>> spi = busio.SPI(clock=board.SCK, MOSI=board.MOSI, MISO=board.MISO) + >>> display = hx8357.HX8357(spi, cs=digitalio.DigitalInOut(board.GPIO0), + ... dc=digitalio.DigitalInOut(board.GPIO15)) + >>> display.fill(0x7521) + >>> display.pixel(64, 64, 0) + """ + _COLUMN_SET = _CASET + _PAGE_SET = _PASET + _RAM_WRITE = _RAMWR + _RAM_READ = _RAMRD + _INIT = ( + (_SWRESET, None), + (_SETC, b'\xFF\x83\x57'), + (_SETRGB, b'\x80\x00\x06\x06'), # 0x80 enables SDO pin (0x00 disables) + (_SETCOM, b'\x25'), # -1.52V + (_SETOSC, b'\x68'), # Normal mode 70Hz, Idle mode 55 Hz + (_SETPANEL, b'\x05'), # BGR, Gate direction swapped + (_SETPWR1, b'\x00\x15\x1C\x1C\x83\xAA'), # Not deep standby BT VSPR VSNR AP + (_SETSTBA, b'\x50\x50\x01\x3C\x1E\x08'), # OPON normal OPON idle STBA GEN + (_SETCYC, b'\x02\x40\x00\x2A\x2A\x0D\x78'), # NW 0x02 RTN DIV DUM DUM GDON GDOFF + (_SETGAMMA, b'\x02\x0A\x11\x1d\x23\x35\x41\x4b\x4b\x42\x3A\x27\x1B\x08\x09\x03\x02\x0A\x11\x1d\x23\x35\x41\x4b\x4b\x42\x3A\x27\x1B\x08\x09\x03\x00\x01'), + (_COLMOD, b'\x55'), # 16 bit + (_MADCTL, b'\xc0'), + (_TEON, b'\x00'), + (_TEARLINE, b'\x00\x02'), # TW off + (_SLPOUT, None), + (_MADCTL, b'\xa0'), + (_DISPON, None), + ) + _ENCODE_PIXEL = ">H" + _ENCODE_POS = ">HH" + + #pylint: disable-msg=useless-super-delegation, too-many-arguments + def __init__(self, spi, dc, cs, rst=None, width=480, height=320, + baudrate=16000000, polarity=0, phase=0): + super().__init__(spi, dc, cs, rst, width, height, + baudrate=baudrate, polarity=polarity, phase=phase) diff --git a/examples/rgbdisplay_hx8357test.py b/examples/rgbdisplay_hx8357test.py new file mode 100644 index 0000000..64629a7 --- /dev/null +++ b/examples/rgbdisplay_hx8357test.py @@ -0,0 +1,45 @@ +# Quick test of 3.5" TFT FeatherWing (HX8357) with Feather M0 or M4 +# This will work even on a device running displayio +# Will fill the TFT black and put a red pixel in the center, wait 2 seconds, +# then fill the screen blue (with no pixel), wait 2 seconds, and repeat. +import time +import random +import digitalio +import board +import displayio + +from adafruit_rgb_display.rgb import color565 +import adafruit_rgb_display.hx8357 as hx8357 + +displayio.release_displays() + +# Configuration for CS and DC pins (these are TFT FeatherWing defaults): +cs_pin = digitalio.DigitalInOut(board.D9) +dc_pin = digitalio.DigitalInOut(board.D10) + +# Config for display baudrate (default max is 24mhz): +BAUDRATE = 24000000 + +# Setup SPI bus using hardware SPI: +spi = board.SPI() + +# Create the HX8357 display: +display = hx8357.HX8357(spi, cs=cs_pin, dc=dc_pin, baudrate=BAUDRATE) + +# Main loop: +while True: + # Fill the screen red, green, blue, then black: + for color in ((255, 0, 0), (0, 255, 0), (0, 0, 255)): + display.fill(color565(color)) + # Clear the display + display.fill(0) + # Draw a red pixel in the center. + display.pixel(display.width//2, display.height//2, color565(255, 0, 0)) + # Pause 2 seconds. + time.sleep(2) + # Clear the screen a random color + display.fill(color565(random.randint(0, 255), + random.randint(0, 255), + random.randint(0, 255))) + # Pause 2 seconds. + time.sleep(2) From 3f53d3d41965c5767dbc80a0e568f4c80b2e0e83 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Mon, 6 May 2019 14:38:26 -0400 Subject: [PATCH 5/5] Linting --- adafruit_rgb_display/hx8357.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_rgb_display/hx8357.py b/adafruit_rgb_display/hx8357.py index 3250983..d835e2a 100755 --- a/adafruit_rgb_display/hx8357.py +++ b/adafruit_rgb_display/hx8357.py @@ -87,7 +87,8 @@ class HX8357(DisplaySPI): (_SETPWR1, b'\x00\x15\x1C\x1C\x83\xAA'), # Not deep standby BT VSPR VSNR AP (_SETSTBA, b'\x50\x50\x01\x3C\x1E\x08'), # OPON normal OPON idle STBA GEN (_SETCYC, b'\x02\x40\x00\x2A\x2A\x0D\x78'), # NW 0x02 RTN DIV DUM DUM GDON GDOFF - (_SETGAMMA, b'\x02\x0A\x11\x1d\x23\x35\x41\x4b\x4b\x42\x3A\x27\x1B\x08\x09\x03\x02\x0A\x11\x1d\x23\x35\x41\x4b\x4b\x42\x3A\x27\x1B\x08\x09\x03\x00\x01'), + (_SETGAMMA, b'\x02\x0A\x11\x1d\x23\x35\x41\x4b\x4b\x42\x3A\x27\x1B\x08\x09\x03\x02' \ + b'\x0A\x11\x1d\x23\x35\x41\x4b\x4b\x42\x3A\x27\x1B\x08\x09\x03\x00\x01'), (_COLMOD, b'\x55'), # 16 bit (_MADCTL, b'\xc0'), (_TEON, b'\x00'),