From 97b86d0e5feab9fa756f11fb9255fda3ac914f49 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Wed, 24 Mar 2021 12:11:23 +0000 Subject: [PATCH] ssd7789.py bugs fixed. --- DRIVERS.md | 9 +++--- color_setup/ssd7789.py | 40 +++++++++++++++++++++++++ drivers/st7789/st7789_4bit.py | 56 +++++++++++++++++++++++++---------- 3 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 color_setup/ssd7789.py diff --git a/DRIVERS.md b/DRIVERS.md index c91c093..456396e 100644 --- a/DRIVERS.md +++ b/DRIVERS.md @@ -377,7 +377,7 @@ The response may be of interest. ## 3.3 Drivers for ST7789 **UNDER DEVELOPMENT** -Works on Adafruit display in landscape mode. Anything else is dubious. +Initial testing on Adafruit display looks good. These displays tend to be physically small with a high pixel density. The chip supports up to 240x320 displays. The Adafruit units tested are 240x240. To keep @@ -443,12 +443,11 @@ gc.collect() # Precaution before instantiating framebuf spi = SPI(1, 30_000_000, sck=Pin(10), mosi=Pin(11), miso=Pin(8)) ssd = SSD(spi, dc=pdc, cs=pcs, rst=prst, disp_mode=PORTRAIT | REFLECT) ``` -On Adafruit displays, valid combinations are: +On Adafruit displays, combinations that don't produce mirror images are: 1. No arg: landscape mode. 2. `USD | REFLECT` Upside down landscape mode (rotate 180°). - 3. `PORTRAIT | REFLECT` Portrait mode (rotate 90°). - 4. `PORTRAIT | USD | REFLECT` Upside down portrait (rotate 270°). - **DOES NOT YET WORK** + 3. `PORTRAIT | REFLECT` Portrait mode (rotate 90° CCW). + 4. `PORTRAIT | USD` Upside down portrait (rotate 90° CW). ###### [Contents](./DRIVERS.md#contents) diff --git a/color_setup/ssd7789.py b/color_setup/ssd7789.py new file mode 100644 index 0000000..824c489 --- /dev/null +++ b/color_setup/ssd7789.py @@ -0,0 +1,40 @@ +# color_setup.py Customise for your hardware config + +# Released under the MIT License (MIT). See LICENSE. +# Copyright (c) 2021 Peter Hinch + +# As written, supports: +# Adafruit 1.3" and 1.54" 240x240 Wide Angle TFT LCD Display with MicroSD - ST7789 +# https://www.adafruit.com/product/4313 +# https://www.adafruit.com/product/3787 + +# Demo of initialisation procedure designed to minimise risk of memory fail +# when instantiating the frame buffer. The aim is to do this as early as +# possible before importing other modules. + +# WIRING (Adafruit pin nos and names). +# Pico SSD +# VBUS Vin +# Gnd Gnd +# 13 D/C +# 14 TCS +# 15 RST +# 10 SCK +# 11 SI MOSI + +# No connect: Lite, CCS, SO (MISO) +from machine import Pin, SPI +import gc + +# *** Choose your color display driver here *** + +from drivers.st7789.st7789_4bit import ST7789 as SSD, PORTRAIT, USD + +pdc = Pin(13, Pin.OUT, value=0) # Arbitrary pins +pcs = Pin(14, Pin.OUT, value=1) +prst = Pin(15, Pin.OUT, value=1) + +gc.collect() # Precaution before instantiating framebuf +spi = SPI(1, 60_000_000, sck=Pin(10), mosi=Pin(11), miso=Pin(8)) +ssd = SSD(spi, dc=pdc, cs=pcs, rst=prst) #, disp_mode=PORTRAIT | USD) + diff --git a/drivers/st7789/st7789_4bit.py b/drivers/st7789/st7789_4bit.py index 6c540b9..49c1eb5 100644 --- a/drivers/st7789/st7789_4bit.py +++ b/drivers/st7789/st7789_4bit.py @@ -62,7 +62,8 @@ class ST7789(framebuf.FrameBuffer): return ((b & 0xf8) << 5 | (g & 0x1c) << 11 | (g & 0xe0) >> 5 | (r & 0xf8)) ^ 0xffff # rst and cs are active low, SPI is mode 0 - def __init__(self, spi, cs, dc, rst, height=240, width=240, disp_mode=PORTRAIT | REFLECT, init_spi=False): + # TEST height=140, width=200, disp_mode=PORTRAIT|REFLECT + def __init__(self, spi, cs, dc, rst, height=240, width=240, disp_mode=0, init_spi=False): self._spi = spi # Clock cycle time for write 16ns 62.5MHz max (read is 150ns) self._rst = rst # Pins self._dc = dc @@ -123,28 +124,51 @@ class ST7789(framebuf.FrameBuffer): cmd(b'\x20') # INVOFF Adafruit turn inversion on. This driver fixes .rgb cmd(b'\x13') # NORON Normal display mode - # Adafruit skip setting CA and RA but using it may help portability - # CASET column address. start=0, end=width - if (disp_mode & USD) and (disp_mode & PORTRAIT): - wcd(b'\x2b', int.to_bytes(240 - self.width, 2, 'big') + int.to_bytes(239, 2, 'big')) - else: - wcd(b'\x2a', int.to_bytes(self.width - 1, 4, 'big')) - # RASET row addr. start=0, end=height - if (disp_mode & USD) and not (disp_mode & PORTRAIT): - wcd(b'\x2b', int.to_bytes(320 - self.height, 2, 'big') + int.to_bytes(319, 2, 'big')) - else: - wcd(b'\x2b', int.to_bytes(self.height - 1, 4, 'big')) - + # Adafruit skip setting CA and RA. We do it to enable rotation and + # reflection. Also hopefully to help portability. Set display window + # depending on mode, .height and .width. + self.set_window(disp_mode) # d7..d5 of MADCTL determine rotation/orientation datasheet P124, P231 # d7 = MY page addr order # d6 = MX col addr order # d5 = MV row/col exchange wcd(b'\x36', int.to_bytes(disp_mode, 1, 'little')) cmd(b'\x29') # DISPON - #sleep_ms(500) # Adafruit. Seems unnecessary. No mention in datasheet. + + # Define the mapping between RAM and the display + # May need modifying for non-Adafruit hardware which may use a different + # mapping between chip RAM and LCD. Datasheet section 8.12 p124. + def set_window(self, mode): + rht = 320 + rwd = 240 # RAM ht and width + wht = self.height + wwd = self.width # Window dimensions + # Determine x and y start and end. Defaults for LANDSCAPE and PORTRAIT + ys = 0 # y start + ye = wht - 1 # y end + xs = 0 + xe = wwd - 1 + if mode & PORTRAIT: + if mode & REFLECT: + ys = rwd - wht + ye = rwd - 1 + if mode & USD: + xs = rht - wwd + xe = rht - 1 + else: # LANDSCAPE + if mode & REFLECT: + xs = rwd - wht + xe = rwd - 1 + if mode & USD: + ys = rht - wwd + ye = rht - 1 + # Col address set + self._wcd(b'\x2a', int.to_bytes(xs, 2, 'big') + int.to_bytes(xe, 2, 'big')) + # Row address set + self._wcd(b'\x2b', int.to_bytes(ys, 2, 'big') + int.to_bytes(ye, 2, 'big')) def show(self): # Blocks for 83ms @60MHz SPI - ts = ticks_us() +# ts = ticks_us() clut = ST7789.lut wd = self.width // 2 end = self.height * wd @@ -160,4 +184,4 @@ class ST7789(framebuf.FrameBuffer): _lcopy(lb, buf[start :], clut, wd) # Copy and map colors self._spi.write(lb) self._cs(1) - print(ticks_diff(ticks_us(), ts)) +# print(ticks_diff(ticks_us(), ts))