From 838cf40522831a9b6d0bc8da78d2cb7a232748e1 Mon Sep 17 00:00:00 2001 From: peterhinch Date: Tue, 6 Dec 2022 17:51:54 +0000 Subject: [PATCH] Use framebuf.ellipse, migrate create_color to CWriter. --- color_setup.py | 45 +++++++++++++++++++++----------------------- gui/core/colors.py | 11 ++--------- gui/core/nanogui.py | 46 +++++++-------------------------------------- gui/core/writer.py | 14 +++++++++++++- 4 files changed, 43 insertions(+), 73 deletions(-) diff --git a/color_setup.py b/color_setup.py index a950d22..5a47ea8 100644 --- a/color_setup.py +++ b/color_setup.py @@ -4,40 +4,37 @@ # Copyright (c) 2020 Peter Hinch # As written, supports: -# Adafruit 1.5" 128*128 OLED display: https://www.adafruit.com/product/1431 -# Adafruit 1.27" 128*96 display https://www.adafruit.com/product/1673 +# ili9341 240x320 displays on Pi Pico # Edit the driver import for other displays. # 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). -# Pyb SSD -# 3v3 Vin (10) -# Gnd Gnd (11) -# Y1 DC (3 DC) -# Y2 CS (5 OC OLEDCS) -# Y3 Rst (4 R RESET) -# Y6 CLK (2 CL SCK) -# Y8 DATA (1 SI MOSI) +# WIRING +# Pico Display +# GPIO Pin +# 3v3 36 Vin +# IO6 9 CLK Hardware SPI0 +# IO7 10 DATA (AKA SI MOSI) +# IO8 11 DC +# IO9 12 Rst +# Gnd 13 Gnd +# IO10 14 CS -import machine +from machine import Pin, SPI import gc # *** Choose your color display driver here *** -# Driver supporting non-STM platforms -# from drivers.ssd1351.ssd1351_generic import SSD1351 as SSD +# ili9341 specific driver +from drivers.ili93xx.ili9341 import ILI9341 as SSD -# STM specific driver -from drivers.ssd1351.ssd1351 import SSD1351 as SSD +pdc = Pin(8, Pin.OUT, value=0) # Arbitrary pins +prst = Pin(9, Pin.OUT, value=1) +pcs = Pin(10, Pin.OUT, value=1) -height = 96 # 1.27 inch 96*128 (rows*cols) display -# height = 128 # 1.5 inch 128*128 display - -pdc = machine.Pin('Y1', machine.Pin.OUT_PP, value=0) -pcs = machine.Pin('Y2', machine.Pin.OUT_PP, value=1) -prst = machine.Pin('Y3', machine.Pin.OUT_PP, value=1) -spi = machine.SPI(2) +# Kept as ssd to maintain compatability gc.collect() # Precaution before instantiating framebuf -ssd = SSD(spi, pcs, pdc, prst, height) # Create a display instance +# See DRIVERS.md re overclocking the SPI bus +spi = SPI(0, sck=Pin(6), mosi=Pin(7), miso=Pin(4), baudrate=30_000_000) +ssd = SSD(spi, dc=pdc, cs=pcs, rst=prst) diff --git a/gui/core/colors.py b/gui/core/colors.py index a6c3699..ad8d262 100644 --- a/gui/core/colors.py +++ b/gui/core/colors.py @@ -4,18 +4,11 @@ # Copyright (c) 2020 Peter Hinch from color_setup import SSD +from gui.core.writer import CWriter # Code can be portable between 4-bit and other drivers by calling create_color def create_color(idx, r, g, b): - c = SSD.rgb(r, g, b) - if not hasattr(SSD, 'lut'): - return c - if not 0 <= idx <= 15: - raise ValueError('Color nos must be 0..15') - x = idx << 1 - SSD.lut[x] = c & 0xff - SSD.lut[x + 1] = c >> 8 - return idx + return CWriter.create_color(SSD, idx, r, g, b) if hasattr(SSD, 'lut'): # Colors defined by LUT BLACK = create_color(0, 0, 0, 0) diff --git a/gui/core/nanogui.py b/gui/core/nanogui.py index 6a46270..a74d300 100644 --- a/gui/core/nanogui.py +++ b/gui/core/nanogui.py @@ -14,48 +14,16 @@ from gui.core.writer import Writer import framebuf import gc -def _circle(dev, x0, y0, r, color): # Single pixel circle - x = -r - y = 0 - err = 2 -2*r - while x <= 0: - dev.pixel(x0 -x, y0 +y, color) - dev.pixel(x0 +x, y0 +y, color) - dev.pixel(x0 +x, y0 -y, color) - dev.pixel(x0 -x, y0 -y, color) - e2 = err - if (e2 <= y): - y += 1 - err += y*2 +1 - if (-x == y and e2 <= x): - e2 = 0 - if (e2 > x): - x += 1 - err += x*2 +1 -def circle(dev, x0, y0, r, color, width =1): # Draw circle - x0, y0, r = int(x0), int(y0), int(r) - for r in range(r, r -width, -1): - _circle(dev, x0, y0, r, color) +def circle(dev, x0, y0, r, color, _=1): # Draw circle + x, y, r = int(x0), int(y0), int(r) + dev.ellipse(x, y, r, r, color) + def fillcircle(dev, x0, y0, r, color): # Draw filled circle - x0, y0, r = int(x0), int(y0), int(r) - x = -r - y = 0 - err = 2 -2*r - while x <= 0: - dev.line(x0 -x, y0 -y, x0 -x, y0 +y, color) - dev.line(x0 +x, y0 -y, x0 +x, y0 +y, color) - e2 = err - if (e2 <= y): - y +=1 - err += y*2 +1 - if (-x == y and e2 <= x): - e2 = 0 - if (e2 > x): - x += 1 - err += x*2 +1 - + x, y, r = int(x0), int(y0), int(r) + dev.ellipse(x, y, r, r, color, True) + # If a (framebuf based) device is passed to refresh, the screen is cleared. # None causes pending widgets to be drawn and the result to be copied to hardware. # The pend mechanism enables a displayable object to postpone its renedering diff --git a/gui/core/writer.py b/gui/core/writer.py index 0414211..48f5e14 100644 --- a/gui/core/writer.py +++ b/gui/core/writer.py @@ -1,6 +1,7 @@ # writer.py Implements the Writer class. # Handles colour, word wrap and tab stops +# V0.5.1 Dec 2022 Support 4-bit color display drivers. # V0.5.0 Sep 2021 Color now requires firmware >= 1.17. # V0.4.3 Aug 2021 Support for fast blit to color displays (PR7682). # V0.4.0 Jan 2021 Improved handling of word wrap and line clip. Upside-down @@ -25,7 +26,7 @@ from uctypes import bytearray_at, addressof from sys import implementation import os -__version__ = (0, 5, 0) +__version__ = (0, 5, 1) fast_mode = True # Does nothing. Kept to avoid breaking code. @@ -255,6 +256,17 @@ class Writer(): # Writer for colour displays. class CWriter(Writer): + @staticmethod + def create_color(ssd, idx, r, g, b): + c = ssd.rgb(r, g, b) + if not hasattr(ssd, 'lut'): + return c + if not 0 <= idx <= 15: + raise ValueError('Color nos must be 0..15') + x = idx << 1 + ssd.lut[x] = c & 0xff + ssd.lut[x + 1] = c >> 8 + return idx def __init__(self, device, font, fgcolor=None, bgcolor=None, verbose=True): if not hasattr(device, 'palette'):