Now that framebuf has routines for triangles and ellipses we no longer need these very large routines in our code. Waveshare recently showed how to enlarge the size of the build-in font. I’ve combined both these space saving improvements in the following code.
# GC9A01 driver with compact GFX & Text routines
# Tony Goodhew 24 Sept 2024
# Driver and text code from Waveshare
# Uses framebuf routines
# This method is easy to adapt to other LCD screens with Waveshare drivers
from machine import Pin,I2C,SPI,PWM
import framebuf
import time
import math
import array
import random
DC = 8
CS = 9
SCK = 10
MOSI = 11
RST = 12
BL = 25
Vbat_Pin = 29
width = 240
height = 240
class LCD_1inch28(framebuf.FrameBuffer): # Waveshare RP2040 1.28" IPS LCD Board Driver - Round Display
def __init__(self):
self.width = 240
self.height = 240
self.cs = Pin(CS,Pin.OUT)
self.rst = Pin(RST,Pin.OUT)
self.cs(1)
self.spi = SPI(1,100_000_000,polarity=0, phase=0,sck=Pin(SCK),mosi=Pin(MOSI),miso=None)
self.dc = Pin(DC,Pin.OUT)
self.dc(1)
self.buffer = bytearray(self.height * self.width * 2)
super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
self.init_display()
self.red = 0x07E0
self.green = 0x001f
self.blue = 0xf800
self.white = 0xffff
self.fill(self.white)
self.show()
self.pwm = PWM(Pin(BL))
self.pwm.freq(5000)
def write_cmd(self, cmd):
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)
def write_data(self, buf):
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(bytearray([buf]))
self.cs(1)
def set_bl_pwm(self,duty):
self.pwm.duty_u16(duty)#max 65535
def init_display(self):
"""Initialize display"""
self.rst(1)
time.sleep(0.01)
self.rst(0)
time.sleep(0.01)
self.rst(1)
time.sleep(0.05)
self.write_cmd(0xEF)
self.write_cmd(0xEB)
self.write_data(0x14)
self.write_cmd(0xFE)
self.write_cmd(0xEF)
self.write_cmd(0xEB)
self.write_data(0x14)
self.write_cmd(0x84)
self.write_data(0x40)
self.write_cmd(0x85)
self.write_data(0xFF)
self.write_cmd(0x86)
self.write_data(0xFF)
self.write_cmd(0x87)
self.write_data(0xFF)
self.write_cmd(0x88)
self.write_data(0x0A)
self.write_cmd(0x89)
self.write_data(0x21)
self.write_cmd(0x8A)
self.write_data(0x00)
self.write_cmd(0x8B)
self.write_data(0x80)
self.write_cmd(0x8C)
self.write_data(0x01)
self.write_cmd(0x8D)
self.write_data(0x01)
self.write_cmd(0x8E)
self.write_data(0xFF)
self.write_cmd(0x8F)
self.write_data(0xFF)
self.write_cmd(0xB6)
self.write_data(0x00)
self.write_data(0x20)
self.write_cmd(0x36)
self.write_data(0x98)
self.write_cmd(0x3A)
self.write_data(0x05)
self.write_cmd(0x90)
self.write_data(0x08)
self.write_data(0x08)
self.write_data(0x08)
self.write_data(0x08)
self.write_cmd(0xBD)
self.write_data(0x06)
self.write_cmd(0xBC)
self.write_data(0x00)
self.write_cmd(0xFF)
self.write_data(0x60)
self.write_data(0x01)
self.write_data(0x04)
self.write_cmd(0xC3)
self.write_data(0x13)
self.write_cmd(0xC4)
self.write_data(0x13)
self.write_cmd(0xC9)
self.write_data(0x22)
self.write_cmd(0xBE)
self.write_data(0x11)
self.write_cmd(0xE1)
self.write_data(0x10)
self.write_data(0x0E)
self.write_cmd(0xDF)
self.write_data(0x21)
self.write_data(0x0c)
self.write_data(0x02)
self.write_cmd(0xF0)
self.write_data(0x45)
self.write_data(0x09)
self.write_data(0x08)
self.write_data(0x08)
self.write_data(0x26)
self.write_data(0x2A)
self.write_cmd(0xF1)
self.write_data(0x43)
self.write_data(0x70)
self.write_data(0x72)
self.write_data(0x36)
self.write_data(0x37)
self.write_data(0x6F)
self.write_cmd(0xF2)
self.write_data(0x45)
self.write_data(0x09)
self.write_data(0x08)
self.write_data(0x08)
self.write_data(0x26)
self.write_data(0x2A)
self.write_cmd(0xF3)
self.write_data(0x43)
self.write_data(0x70)
self.write_data(0x72)
self.write_data(0x36)
self.write_data(0x37)
self.write_data(0x6F)
self.write_cmd(0xED)
self.write_data(0x1B)
self.write_data(0x0B)
self.write_cmd(0xAE)
self.write_data(0x77)
self.write_cmd(0xCD)
self.write_data(0x63)
self.write_cmd(0x70)
self.write_data(0x07)
self.write_data(0x07)
self.write_data(0x04)
self.write_data(0x0E)
self.write_data(0x0F)
self.write_data(0x09)
self.write_data(0x07)
self.write_data(0x08)
self.write_data(0x03)
self.write_cmd(0xE8)
self.write_data(0x34)
self.write_cmd(0x62)
self.write_data(0x18)
self.write_data(0x0D)
self.write_data(0x71)
self.write_data(0xED)
self.write_data(0x70)
self.write_data(0x70)
self.write_data(0x18)
self.write_data(0x0F)
self.write_data(0x71)
self.write_data(0xEF)
self.write_data(0x70)
self.write_data(0x70)
self.write_cmd(0x63)
self.write_data(0x18)
self.write_data(0x11)
self.write_data(0x71)
self.write_data(0xF1)
self.write_data(0x70)
self.write_data(0x70)
self.write_data(0x18)
self.write_data(0x13)
self.write_data(0x71)
self.write_data(0xF3)
self.write_data(0x70)
self.write_data(0x70)
self.write_cmd(0x64)
self.write_data(0x28)
self.write_data(0x29)
self.write_data(0xF1)
self.write_data(0x01)
self.write_data(0xF1)
self.write_data(0x00)
self.write_data(0x07)
self.write_cmd(0x66)
self.write_data(0x3C)
self.write_data(0x00)
self.write_data(0xCD)
self.write_data(0x67)
self.write_data(0x45)
self.write_data(0x45)
self.write_data(0x10)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0x00)
self.write_cmd(0x67)
self.write_data(0x00)
self.write_data(0x3C)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0x01)
self.write_data(0x54)
self.write_data(0x10)
self.write_data(0x32)
self.write_data(0x98)
self.write_cmd(0x74)
self.write_data(0x10)
self.write_data(0x85)
self.write_data(0x80)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0x4E)
self.write_data(0x00)
self.write_cmd(0x98)
self.write_data(0x3e)
self.write_data(0x07)
self.write_cmd(0x35)
self.write_cmd(0x21)
self.write_cmd(0x11)
time.sleep(0.12)
self.write_cmd(0x29)
time.sleep(0.02)
self.write_cmd(0x21)
self.write_cmd(0x11)
self.write_cmd(0x29)
def show(self):
self.write_cmd(0x2A)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0xef)
self.write_cmd(0x2B)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0x00)
self.write_data(0xEF)
self.write_cmd(0x2C)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(self.buffer)
self.cs(1)
def colour(R,G,B): # Convert RGB888 to RGB565
return (((G&0b00011100)<<3) +((B&0b11111000)>>3)<<8) + (R&0b11111000)+((G&0b11100000)>>5)
LCD = LCD_1inch28() #=============== Initialise the display ===================
LCD.set_bl_pwm(65535) # Brightness
# =========== GFX Routines ============
def clear(c):
LCD.fill(c)
def circle(x,y,r,c):
LCD.ellipse(x,y,r,r,c,1)
def ring(x,y,r,c):
LCD.ellipse(x,y,r,r,c,0)
def write_text(text,x,y,size,color): # Thanks to Waveshare 1.47 incj LCD Module Docs.
''' Method to write Text on OLED/lcd Displays
with a variable font size
Args:
text: the string of chars to be displayed
x: x co-ordinate of starting position
y: y co-ordinate of starting position
size: font size of text
color: color of text to be displayed
'''
background = LCD.pixel(x,y)
info = []
# Creating reference characters to read their values
LCD.text(text,x,y,color) # Uses code in Framebuf
for i in range(x,x+(8*len(text))):
for j in range(y,y+8):
# Fetching amd saving details of pixels, such as
# x co-ordinate, y co-ordinate, and color of the pixel
px_color = LCD.pixel(i,j)
info.append((i,j,px_color)) if px_color == color else None
# Clearing the reference characters from the screen
LCD.text(text,x,y,0)
# Writing the custom-sized font characters on screen
for px_info in info:
LCD.fill_rect(size*px_info[0] - (size-1)*x , size*px_info[1] - (size-1)*y, size, size, px_info[2])
def centre_text(text,y,size,color): # Additional routine from Tony Goodhew
x = int((width - len(text)*size*8)/2)
write_text(text,x,y,size,color)
def triangle(x1,y1,x2,y2,x3,y3,c): # Draw outline triangle
q = array.array('h',(x1,y1,x2,y2,x3,y3))
LCD.poly(x1,y1,q,c,0)
def tri_filled(x1,y1,x2,y2,x3,y3,c): # Draw filled triangle
q = array.array('h',(x1,y1,x2,y2,x3,y3))
LCD.poly(x1,y1,q,c,1)
def circle(x,y,r,c):
LCD.ellipse(x,y,r,r,c,1)
# =========== End of support routines ===========
# ==== Board now setup ========== MAIN BELOW====================
clear(0) # Clear the screen
xc = 120 # Coordinates of centre
yc = 120
centre_text("GC9A01",90,3,colour(0,255,255))
centre_text("GFX",120,3,colour(255,255,0))
centre_text("Tony Goodhew",150,2,colour(200,200,200))
LCD.show()
time.sleep(1.7)
clear(0)
x1 =10
x2 = 100
x3 = 200
y1 = 50
y2 = 150
y3 = 20
c = colour(255,0,0)
tri_filled(x1,y1,x2,y2,x3,y3,c)
LCD.show()
time.sleep(1)
triangle(x1,y1,x2,y2,x3,y3,colour(0,255,0))
LCD.show()
time.sleep(1)
for r in range(120,5,-5):
c = colour(random.randint(0,255),random.randint(0,255),random.randint(0,255))
circle(xc,yc,r,c)
LCD.show()
time.sleep(0.15)
# Character size demo
LCD.fill(0)
for size in range(1,13,1):
centre_text(str(size),80-size*2,size,colour(255,255,0))
# centre_text("Text Size" ,140,4,colour(0,0,255))
LCD.show()
time.sleep(0.8)
if size == 1: time.sleep(0.6)
LCD.fill(0)
LCD.show()
LCD.fill(0)
size = 5
centre_text("BYE",100-size*2,size,colour(255,0,255))
centre_text("Tony Goodhew",150,2,colour(200,200,200))
LCD.show()
time.sleep(3)
clear(0)
LCD.show()
You can see it working on the small round screen here:
You now have much more room for your own graphics code. It is all done in Micropython so can be added to or edited down by anyone.
I hope this helps.