Seeed Studio XIAO ESP32S3 Sense/CircuitPython display on 1.28" 240x240 GC9A01 Round IPS LCD

This exercise run on Seeed Studio XIAO ESP32S3 Sense running CircuitPython 9.2.1, to display on 1.28" 240x240 GC9A01 Round IPS LCD. Also exercises to run Turtle graphics on CircuitPython.

Libraries (or modules) gc9a01, adafruit_display_text and adafruit_turtle are needed. In old approach, you can download them from CircuitPython Libraries and copy to CircuitPython device manually. In this video, the libraries were installed using another approach CircUp. To install CircUp, read my previous post "Install and using CircUp (CircuitPython library updater) to install CircuitPython libraries".

If you use old approach to download manually, notice that gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...), not Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).



Connection:

Exercise Code:

cpy_XS3_gc9a01_color.py, simple demo exercise with color test.
"""
Color test on
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD

Library needed:
- gc9a01.mpy
- adafruit_display_text folder

Notice that gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...),
not Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).
"""
import os, sys
import board
import time
import displayio
import busio
import terminalio
import gc9a01
from adafruit_display_text import label

displayio.release_displays()

disp_sck  = board.D8
disp_mosi = board.D10
disp_res  = board.D0
disp_dc   = board.D1
disp_cs   = board.D2
disp_blk  = board.D3

# Release any resources currently in use for the displays
displayio.release_displays()

disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)

display_bus = displayio.FourWire(spi_bus=disp_spi,
                                 command=disp_dc,
                                 chip_select=disp_cs,
                                 reset=disp_res)

display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)

#=======================================
info = os.uname()[4] + "\n" + \
       sys.implementation[0] + " " + os.uname()[3] + "\n" + \
       gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()

# Make the display context
bgGroup = displayio.Group()

#display.show(bgGroup)
display.root_group = bgGroup

bg_bitmap = displayio.Bitmap(display.width, display.height, 1)  # with one color
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF  # White
bg_sprite = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette, x=0, y=0)
bgGroup.append(bg_sprite)

colorSet = ((0xFF0000, "RED"),
            (0x00FF00, "GREEN"),
            (0x0000FF, "BLUE"),
            (0xFFFFFF, "WHITE"),
            (0x000000, "BLACK"))

color_bitmap = displayio.Bitmap(display.width, display.height, 1)  # with one color
color_palette = displayio.Palette(1)
color_palette[0] = 0x000000  # BLACK
color_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
bgGroup.append(color_sprite)

# Draw label
text_group = displayio.Group(scale=1, x=20, y=120)
text = "Hello\n" + os.uname()[4]
text_area = label.Label(terminalio.FONT, text=text, color=0xFFFFFF)
text_group.append(text_area)  # Subgroup for text scaling
bgGroup.append(text_group)

time.sleep(2)
text_group.scale = 2
time.sleep(2)
text_group.scale = 3

while True:
    for i in colorSet:
        time.sleep(2)
        color_palette[0] = i[0]
        text_area.text = i[1]
        text_area.color = i[0] ^ 0xFFFFFF


cpy_XS3_gc9a01_turtle.py, Python Turtle graphics run on CircuitPython.
"""
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD

Python Turtle graphics run on CircuitPython - squares

Library needed:
- gc9a01.mpy
- adafruit_turtle.mpy

Notice that gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...),
not Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).
"""
import os, sys
import board
import time
import displayio
import busio
import gc9a01
from adafruit_turtle import Color, turtle

displayio.release_displays()

disp_sck  = board.D8
disp_mosi = board.D10
disp_res  = board.D0
disp_dc   = board.D1
disp_cs   = board.D2
disp_blk  = board.D3

# Release any resources currently in use for the displays
displayio.release_displays()

disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)

display_bus = displayio.FourWire(spi_bus=disp_spi,
                                 command=disp_dc,
                                 chip_select=disp_cs,
                                 reset=disp_res)

display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
turtle = turtle(display)
#=======================================
info = os.uname()[4] + "\n" + \
       sys.implementation[0] + " " + os.uname()[3] + "\n" + \
       gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()

def drawSquare(t,size,angle):
    t.left(angle)
    halfsize = size * .5
    t.pu()
    t.setpos(0,0)
    t.backward(halfsize)
    t.left(90)
    t.backward(halfsize)
    t.right(90)
    t.pd()

    for i in range(0,4):
        t.fd(size)
        t.left(90)

def drawSquarePattern(t):
    t.pencolor(Color.WHITE)
    drawSquare(t,240,0)
    for i in range(0,20):
        size = 240 * pow(1/1.2,i+1)
        drawSquare(t,size,12.5)

drawSquarePattern(turtle)

print("~ bye ~")


cpy_XS3_gc9a01_turtle_circles.py, another exercise using Turtle graphics on CircuitPython to draw circle.
"""
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD

Python Turtle graphics run on CircuitPython - circles

Library needed:
- gc9a01.mpy
- adafruit_turtle.mpy

Notice that gc9a01.mpy is in Community Bundle (circuitpython-community-bundle-...),
not Adafruit Circuit Bundle (adafruit-circuitpython-bundle-...).
"""
import os, sys
import board
import time
import displayio
import busio
import gc9a01
from adafruit_turtle import Color, turtle

displayio.release_displays()

disp_sck  = board.D8
disp_mosi = board.D10
disp_res  = board.D0
disp_dc   = board.D1
disp_cs   = board.D2
disp_blk  = board.D3

# Release any resources currently in use for the displays
displayio.release_displays()

disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)

display_bus = displayio.FourWire(spi_bus=disp_spi,
                                 command=disp_dc,
                                 chip_select=disp_cs,
                                 reset=disp_res)

display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
turtle = turtle(display)
#=======================================
info = os.uname()[4] + "\n" + \
       sys.implementation[0] + " " + os.uname()[3] + "\n" + \
       gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()

def drawSimplestCircles(t):
    t.clear()
    t.pencolor(Color.WHITE)
    t.pendown()
    r = 50
    t.circle(r)
    t.penup()
    
def drawCircles(t):
    t.clear()
    t.pencolor(Color.YELLOW)
    
    for i in range(10):
        r = i * (120/10)
        t.pendown()
        t.circle(r)
        t.penup()
        t.sety(-r)

def drawBigCircles(t):
    t.clear()
    t.pencolor(Color.RED)
    t.pendown()
    
    for i in range(10):
        r = i * (120/10)
        t.circle(r)
        
    t.penup()
    
drawSimplestCircles(turtle)
time.sleep(2)

drawCircles(turtle)
time.sleep(2)

drawBigCircles(turtle)
print("~ bye ~")


Another adafruit_turtle example to draw a heart


cpy_XS3_gc9a01_turtle_heart.py
"""
Seeed Studio XIAO ESP32S3 Sense/CircuitPython 9.2.1
with 1.28" 240x240 Round GC9A01 SPI IPS LCD

Python Turtle graphics run on CircuitPython - heart
(with help from Microsoft Copilot)

Library needed:
- gc9a01.mpy
- adafruit_turtle.mpy

To install libraries using CircUp:
> circup install gc9a01, adafruit_turtle

To install and and using CircUp to install CircuitPython libraries.
https://coxxect.blogspot.com/2024/12/install-and-using-circup-circuitpython.html

"""
import os, sys
import board
import time
import displayio
import busio
import gc9a01
from adafruit_turtle import Color, turtle

displayio.release_displays()

disp_sck  = board.D8
disp_mosi = board.D10
disp_res  = board.D0
disp_dc   = board.D1
disp_cs   = board.D2
disp_blk  = board.D3

# Release any resources currently in use for the displays
displayio.release_displays()

disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)

display_bus = displayio.FourWire(spi_bus=disp_spi,
                                 command=disp_dc,
                                 chip_select=disp_cs,
                                 reset=disp_res)

display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)
turtle = turtle(display)
#=======================================
info = os.uname()[4] + "\n" + \
       sys.implementation[0] + " " + os.uname()[3] + "\n" + \
       gc9a01.__name__ + " " + gc9a01.__version__
print("=======================================")
print(info)
print("=======================================")
print()
        
def draw_heart(t):
    t.pencolor(Color.RED)
    t.pensize(5)
    t.pd()

    t.left(140)
    t.forward(56)
    for _ in range(200):
        t.right(1)
        t.forward(0.5)
    t.left(120)
    for _ in range(200):
        t.right(1)
        t.forward(0.5)
    t.forward(56)

    t.hideturtle()

draw_heart(turtle)

print("~ bye ~")



Camera Frame at Round Display


Actually, this code copied from Seeed Studio XIAO ESP32S3 Getting Started Guide, with little bit modification.

"""
Camera Frame at Round Display
https://wiki.seeedstudio.com/xiao_esp32s3_project_circuitpython/#getting-started-1

Library modules needed:
- gc9a01
- adafruit_ticks

To install Library modules using circup:
> circup install gc9a01, adafruit_ticks

To install circup on Windows, read:
https://coxxect.blogspot.com/2024/12/install-and-using-circup-circuitpython.html
"""

import board
import busio
import displayio
import espcamera
import adafruit_ticks
import gc9a01
import struct

# Connection follow my previous exercise:
# https://coxxect.blogspot.com/2024/12/seeed-studio-xiao-esp32s3.html
disp_sck  = board.D8
disp_mosi = board.D10
disp_res  = board.D0
disp_dc   = board.D1
disp_cs   = board.D2
disp_blk  = board.D3

# Release any resources currently in use for the displays
# Otherwise will raise "ValueError: D8 in use" when re-try in Thonny
displayio.release_displays()

disp_spi = busio.SPI(clock=disp_sck, MOSI=disp_mosi)
display_bus = displayio.FourWire(spi_bus=disp_spi,
                                 command=disp_dc,
                                 chip_select=disp_cs,
                                 reset=disp_res)
display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=disp_blk)

# will raise of following error if without connection. Just comment it.
# RuntimeError: No pull up found on SDA or SCL; check your wiring
#i2c = busio.I2C(board.SCL, board.SDA)

cam_i2c = busio.I2C(board.CAM_SCL, board.CAM_SDA)

# Appears that this example does not use Displayio at all
# print frame directly on display_bus to be faster
# so, rotation setting not works...

main = displayio.Group()
display.root_group = main

# Camera Init
cam = espcamera.Camera(
    data_pins=board.CAM_DATA,
    external_clock_pin=board.CAM_XCLK,
    pixel_clock_pin=board.CAM_PCLK,
    vsync_pin=board.CAM_VSYNC,
    href_pin=board.CAM_HREF,
    pixel_format=espcamera.PixelFormat.RGB565,
    frame_size=espcamera.FrameSize.R240X240,
    i2c=cam_i2c,
    external_clock_frequency=20_000_000,
    framebuffer_count=2,
    grab_mode=espcamera.GrabMode.WHEN_EMPTY)

# Sending init bytes to display_bus
display_bus.send(36, struct.pack(">hh", 0, 239))
display_bus.send(42, struct.pack(">hh", 0, 239))
display_bus.send(43, struct.pack(">hh", 0, 80+239))
display.auto_refresh = False

t0 = adafruit_ticks.ticks_ms()

while True:
    frame = cam.take(1)                                                         
    if isinstance(frame, displayio.Bitmap):                                     
        display_bus.send(44, frame)                                             
        t1 = adafruit_ticks.ticks_ms()                                          
        fps = 1000 / adafruit_ticks.ticks_diff(t1, t0)
        print(f"{fps:3.1f}fps")  # typically runs at about 25fps
        t0 = t1

next:
Display bmp with XIAO ESP32S3 Sense/CircuitPython on GC9A01 Round LCD using OnDiskBitmap, adafruit_imageload and adafruit_slideshow
download bmp via WiFi and display using OnDiskBitmap, running on ESP32S3/CircuitPython 9


Comments

Popular posts from this blog

480x320 TFT/ILI9488 SPI wih EP32C3 (arduino-esp32) using Arduino_GFX Library

my dev.tools - FNIRSI 2C23T 3-in-1 Dual Channel Oscilloscope/Multimeter/Signal Generator