1.28" 240x240 Round Display with GC9A01 SPI, on Raspberry Pi Pico 2 W/CircuitPython 10.0.3.
Exercises run on
Raspberry Pi Pico 2 W/CircuitPython 10.0.3, to display on
1.28 inch IPS Module: GC9A01+CST816S 240*240(Round) 4W-SPI.
Connection:
Code:
cpy_rpPicoW_gc9a01_color.py, basic color test.
cpy_rpPicoW_gc9a01_circle_scene.py, draw something circles.
cpy_rpPicoW_gc9a01_heart.py, display beating heart.
More adafruit_turtle examples:
cpy_rpPicoW_gc9a01_turtle_heart.py
cpy_rpPicoW_gc9a01_turtle_examples.py
Related:
~ Install and using CircUp (CircuitPython library updater) to install CircuitPython libraries.
Next:
~ Downloading Bitmap via WiFi with CircuitPython, Saving to Local File System, and Displaying on LCD using OnDiskBitmap.
~ Pico 2 W/CircuitPython 10.0.3 Display bmp images in SD, using displayio.OnDiskBitmap()/adafruit_imageload.load().
~ Raspberry Pi Pico 2 W/CircuitPython 10.0.3: Load animated GIFs from MicroSD, display them on a 240*240 GC9A01 LCD using gifio.OnDiskGif.
Connection:
Raspberry Pi Pico 2 W
Run |
GP22| ------- LCD_BLK ------------+
GND | |
GP21| ------- LCD_DC ---------+ |
GP20| ------- LCD_RES-------+ | |
GP19| MOSI - SPI_SDA ----+ | | |
GP18| SCK - SPI_SCL --+ | | | |
GND | | | | | |
GP17| SS - LCD_CS ---|-|-|-|-+ |
GP16| MISO - no use | | | | | |
--------+ | | | | | |
| | | | | |
| | | | | | GC9A01
| | | | | |
| | | | | +---- BLK
| | | | +------ CS
| | | +-------- DC
| | +---------- RES
| +------------ SDA
+-------------- SCL
3V3 --- VCC
GND --- GND
Code:
cpy_rpPicoW_gc9a01_color.py, basic color test.
"""
Raspberry Pi Pico 2 W/CircuitPython 10.0.3
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Basic Color Test
details:
https://coxxect.blogspot.com/2026/01/128-240x240-round-display-with-gc9a01.html
Library needed:
- adafruit_gc9a01a.mpy
- adafruit_display_text folder
"""
import os, sys
import board
import time
import displayio
import busio
import terminalio
import adafruit_gc9a01a
from fourwire import FourWire
from adafruit_display_text import label
displayio.release_displays()
tft_blk = board.GP22
tft_cs = board.GP17
tft_dc = board.GP21
tft_res = board.GP20
tft_sda = board.GP19
tft_scl = board.GP18
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=tft_scl, MOSI=tft_sda)
display_bus = FourWire(spi_bus=disp_spi,
command=tft_dc,
chip_select=tft_cs,
reset=tft_res)
display = adafruit_gc9a01a.GC9A01A(display_bus, width=240, height=240, backlight_pin=tft_blk)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
adafruit_gc9a01a.__name__ + " " + adafruit_gc9a01a.__version__
print("=======================================")
print(info)
print("=======================================")
print()
# Make the display context
bgGroup = displayio.Group()
#display.show(bgGroup)
display.root_group = bgGroup
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_area = label.Label(terminalio.FONT, text=info, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
time.sleep(3)
text_group.scale = 2
time.sleep(2)
text_group.scale = 3
time.sleep(2)
while True:
for i in colorSet:
color_palette[0] = i[0]
text_area.text = i[1]
text_area.color = i[0] ^ 0xFFFFFF
time.sleep(3)
cpy_rpPicoW_gc9a01_circle_scene.py, draw something circles.
"""
Raspberry Pi Pico 2 W/CircuitPython 10.0.3
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Draw something (concentric circles, rainbow wheel, spiral illusion),
also show how to switch between scenes (bgGroup and group), by calling show_scene().
details:
https://coxxect.blogspot.com/2026/01/128-240x240-round-display-with-gc9a01.html
Library needed:
- adafruit_gc9a01a.mpy
- adafruit_display_text folder
"""
import os, sys
import board
import time
import displayio
import busio
import terminalio
import adafruit_gc9a01a
from fourwire import FourWire
from adafruit_display_text import label
import math
displayio.release_displays()
tft_blk = board.GP22
tft_cs = board.GP17
tft_dc = board.GP21
tft_res = board.GP20
tft_sda = board.GP19
tft_scl = board.GP18
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=tft_scl, MOSI=tft_sda)
display_bus = FourWire(spi_bus=disp_spi,
command=tft_dc,
chip_select=tft_cs,
reset=tft_res)
display = adafruit_gc9a01a.GC9A01A(display_bus, width=240, height=240, backlight_pin=tft_blk)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
adafruit_gc9a01a.__name__ + " " + adafruit_gc9a01a.__version__
print("=======================================")
print(info)
print("=======================================")
print()
# Group to display Title
bgGroup = displayio.Group()
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_area = label.Label(terminalio.FONT, text=info, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
# Group to display Bitmap
bitmap = displayio.Bitmap(240, 240, 256)
palette = displayio.Palette(256)
tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette)
group = displayio.Group()
group.append(tile_grid)
# Used to switch whole root_group, between bgGroup and group
def show_scene(scene_group):
display.root_group = scene_group
show_scene(bgGroup)
time.sleep(2)
show_scene(group)
# clear palette all to black
def clear_palette():
for i in range(0, 256):
palette[i] = (0, 0, 0)
def fill_palette_red():
palette[0] = (0, 0, 0)
for i in range(1, 256):
palette[i] = (i, 255-i, 255-i)
def fill_palette_green():
palette[0] = (0, 0, 0)
for i in range(1, 256):
palette[i] = (255-i, i, 255-i)
def fill_palette_blue():
palette[0] = (0, 0, 0)
for i in range(1, 256):
palette[i] = (255-i, 255-i, 255)
def fill_palette_white():
palette[0] = (0, 0, 0)
for i in range(1, 256):
palette[i] = (i, i, i)
def fill_palette_black():
palette[0] = (0, 0, 0)
for i in range(1, 256):
palette[i] = (255-i, 255-i, 255-i)
def change_palette():
fill_palette_red()
time.sleep(2)
fill_palette_green()
time.sleep(2)
fill_palette_blue()
time.sleep(2)
fill_palette_white()
time.sleep(2)
fill_palette_black()
time.sleep(2)
def draw_concentric_circles():
text_group.scale = 1
text_area.text = "concentric\ncircles"
show_scene(bgGroup)
time.sleep(2)
show_scene(group)
clear_palette()
bitmap.fill(0)
for r in range(10, 120, 5):
color = (r*2) % 255
for angle in range(0, 360, 1):
angle_radians = math.radians(angle)
x = int(120 + r * (math.cos(angle_radians)))
y = int(120 + r * (math.sin(angle_radians)))
if 0 <= x < 240 and 0 <= y < 240:
bitmap[x, y] = color
change_palette()
def draw_rainbow_wheel():
text_group.scale = 2
text_area.text = "rainbow\nwheel"
show_scene(bgGroup)
time.sleep(2)
show_scene(group)
clear_palette()
bitmap.fill(0)
for angle in range(0, 360, 5):
# Because palette[0]=Black, so map 0~359(angle) to 1~255(color)
color = 1 + int(angle * 254 / 359)
for r in range(20, 120):
x = int(120 + r * math.cos(math.radians(angle)))
y = int(120 + r * math.sin(math.radians(angle)))
if 0 <= x < 240 and 0 <= y < 240:
bitmap[x, y] = color
change_palette()
def draw_spiral_illusion():
text_group.scale = 3
text_area.text = "spiral\nillusion"
show_scene(bgGroup)
time.sleep(2)
show_scene(group)
clear_palette()
bitmap.fill(0)
palette[0] = 0x000000 # Black
palette[1] = 0xFFFFFF # White
for s in range(4, 9, 1):
do_spiral_illusion(step=s)
time.sleep(2)
def do_spiral_illusion(step=5):
bitmap.fill(0)
for angle in range(0, 360, step):
for r in range(20, 120, step):
x = int(120 + r * math.cos(math.radians(angle)))
y = int(120 + r * math.sin(math.radians(angle)))
if 0 <= x < 240 and 0 <= y < 240:
bitmap[x, y] = ((r//step + angle//step) % 2)
while True:
draw_concentric_circles()
draw_rainbow_wheel()
draw_spiral_illusion()
cpy_rpPicoW_gc9a01_heart.py, display beating heart.
"""
Raspberry Pi Pico 2 W/CircuitPython 10.0.3
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Draw beating heart, switch between two bitmaps to prevent flicker problem.
details:
https://coxxect.blogspot.com/2026/01/128-240x240-round-display-with-gc9a01.html
Library needed:
- adafruit_gc9a01a.mpy
- adafruit_display_text folder
"""
import os, sys
import board
import time
import displayio
import busio
import terminalio
import adafruit_gc9a01a
from fourwire import FourWire
from adafruit_display_text import label
import math
displayio.release_displays()
tft_blk = board.GP22
tft_cs = board.GP17
tft_dc = board.GP21
tft_res = board.GP20
tft_sda = board.GP19
tft_scl = board.GP18
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=tft_scl, MOSI=tft_sda)
display_bus = FourWire(spi_bus=disp_spi,
command=tft_dc,
chip_select=tft_cs,
reset=tft_res)
display = adafruit_gc9a01a.GC9A01A(display_bus, width=240, height=240, backlight_pin=tft_blk)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
adafruit_gc9a01a.__name__ + " " + adafruit_gc9a01a.__version__
print("=======================================")
print(info)
print("=======================================")
print()
# Group to display Title
bgGroup = displayio.Group()
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_area = label.Label(terminalio.FONT, text=info, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
# Group to display Bitmap
# two bitmaps, same palette
bitmap_a = displayio.Bitmap(240, 240, 2)
bitmap_b = displayio.Bitmap(240, 240, 2)
palette = displayio.Palette(2)
palette[0] = 0x000000 # Black
palette[1] = 0xFF0000 # Red
tile_grid = displayio.TileGrid(bitmap_a, pixel_shader=palette)
group = displayio.Group()
group.append(tile_grid)
# Used to switch whole root_group, between bgGroup and group
def show_scene(scene_group):
display.root_group = scene_group
show_scene(bgGroup)
time.sleep(2)
show_scene(group)
WIDTH = display.width
HEIGHT = display.height
CENTER_X = WIDTH//2
CENTER_Y = HEIGHT//2
# parameter to calculate scale
heart_size = 5
beating_amplitude = 1
beating_speed = 2
def to_draw_heart():
use_a = True
while True:
scale = heart_size + beating_amplitude*math.sin(time.monotonic()*beating_speed)
if use_a:
draw_heart(bitmap_a, scale)
tile_grid.bitmap = bitmap_a
else:
draw_heart(bitmap_b, scale)
tile_grid.bitmap = bitmap_b
use_a = not use_a
time.sleep(0.05)
# helper to draw heart into a bitmap
def draw_heart(bitmap, scale):
bitmap.fill(0)
for t in range(0, 360, 2):
rad = math.radians(t)
x = int(CENTER_X + scale * 16 * math.sin(rad)**3)
y = int(CENTER_Y - scale * (13*math.cos(rad)
- 5*math.cos(2*rad)
- 2*math.cos(3*rad)
- math.cos(4*rad)))
if 0 <= x < WIDTH and 0 <= y < HEIGHT:
bitmap[x, y] = 1
while True:
text_group.scale = 3
text_area.text = "Beating\nheart"
show_scene(bgGroup)
time.sleep(2)
show_scene(group)
to_draw_heart()
More adafruit_turtle examples:
cpy_rpPicoW_gc9a01_turtle_heart.py
"""
Raspberry Pi Pico 2 W/CircuitPython 10.0.3
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
Draw a heart using adafruit_turtle
details:
https://coxxect.blogspot.com/2026/01/128-240x240-round-display-with-gc9a01.html
Library needed:
- adafruit_gc9a01a.mpy
- adafruit_turtle.mpy
- adafruit_display_text folder
To install lib using circup:
circup install adafruit_gc9a01a adafruit_turtle adafruit_display_text
"""
import os, sys
import board
import time
import displayio
import busio
import terminalio
import adafruit_gc9a01a
from fourwire import FourWire
import adafruit_turtle
from adafruit_display_text import label
import math
displayio.release_displays()
tft_blk = board.GP22
tft_cs = board.GP17
tft_dc = board.GP21
tft_res = board.GP20
tft_sda = board.GP19
tft_scl = board.GP18
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=tft_scl, MOSI=tft_sda)
display_bus = FourWire(spi_bus=disp_spi,
command=tft_dc,
chip_select=tft_cs,
reset=tft_res)
display = adafruit_gc9a01a.GC9A01A(display_bus, width=240, height=240, backlight_pin=tft_blk)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
adafruit_gc9a01a.__name__ + " " + adafruit_gc9a01a.__version__ + "\n" + \
adafruit_turtle.__name__ + " " + adafruit_turtle.__version__
print("=======================================")
print(info)
print("=======================================")
print()
# Make the display context
bgGroup = displayio.Group()
#display.show(bgGroup)
display.root_group = bgGroup
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_area = label.Label(terminalio.FONT, text=info, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
time.sleep(3)
# Draw using adafruit_turtle
t = adafruit_turtle.turtle(display)
# Set the pen color to RED
t.pencolor(adafruit_turtle.Color.RED)
t.pensize(2)
def draw_heart():
side_length = 100 # length of the side line, the first and last forward
arc_step = 0.87 # Arc step size (180 degree)
t.penup()
t.goto(0, -70) # move to the bottom of the heart (screen center is 0, 0)
t.pendown()
t.left(135) # The bottom angle is set to 90 degrees. (180-135=45, 45*2=90)
t.forward(side_length)
# left half circle (180 degree)
for _ in range(180):
t.right(1)
t.forward(arc_step)
t.left(90) # Mid-turn
# right half circle (180 degree)
for _ in range(180):
t.right(1)
t.forward(arc_step)
t.forward(side_length)
draw_heart()
while True:
pass
cpy_rpPicoW_gc9a01_turtle_examples.py
"""
Raspberry Pi Pico 2 W/CircuitPython 10.0.3
with 1.28" 240x240 Round GC9A01 SPI IPS LCD
More adafruit_turtle examples
details:
https://coxxect.blogspot.com/2026/01/128-240x240-round-display-with-gc9a01.html
Library needed:
- adafruit_gc9a01a.mpy
- adafruit_turtle.mpy
- adafruit_display_text folder
To install lib using circup:
circup install adafruit_gc9a01a adafruit_turtle adafruit_display_text
ref:
https://learn.adafruit.com/circuitpython-turtle-graphics/example-scripts
"""
import os, sys
import board
import time
import displayio
import busio
import terminalio
import adafruit_gc9a01a
from fourwire import FourWire
import adafruit_turtle
from adafruit_display_text import label
import math
displayio.release_displays()
tft_blk = board.GP22
tft_cs = board.GP17
tft_dc = board.GP21
tft_res = board.GP20
tft_sda = board.GP19
tft_scl = board.GP18
# Release any resources currently in use for the displays
displayio.release_displays()
disp_spi = busio.SPI(clock=tft_scl, MOSI=tft_sda)
display_bus = FourWire(spi_bus=disp_spi,
command=tft_dc,
chip_select=tft_cs,
reset=tft_res)
display = adafruit_gc9a01a.GC9A01A(display_bus, width=240, height=240, backlight_pin=tft_blk)
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
adafruit_gc9a01a.__name__ + " " + adafruit_gc9a01a.__version__ + "\n" + \
adafruit_turtle.__name__ + " " + adafruit_turtle.__version__
print("=======================================")
print(info)
print("=======================================")
print()
# Make the display context
bgGroup = displayio.Group()
#display.show(bgGroup)
display.root_group = bgGroup
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_area = label.Label(terminalio.FONT, text=info, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
time.sleep(1)
# Draw using adafruit_turtle
turtle = adafruit_turtle.turtle(display)
def clear_all():
turtle.penup()
turtle.clear() # Clear the screen, the position and heading of the turtle is unaffected.
turtle.home() # Move the turtle to its initial position and heading.
def star():
starsize = min(display.width, display.height) * 0.9 # 90% of screensize
print("star")
turtle.pencolor(adafruit_turtle.Color.WHITE)
turtle.penup()
#turtle.goto(-starsize/2, 0)
turtle.goto(0, -starsize/2)
turtle.pendown()
start = turtle.pos()
while True:
turtle.forward(starsize)
turtle.left(170)
if abs(turtle.pos() - start) < 1:
break
def rainbow_benzene():
benzsize = min(display.width, display.height) * 0.5
print("rainbow benzene")
colors = (adafruit_turtle.Color.RED,
adafruit_turtle.Color.ORANGE,
adafruit_turtle.Color.YELLOW,
adafruit_turtle.Color.GREEN,
adafruit_turtle.Color.BLUE,
adafruit_turtle.Color.PURPLE)
turtle.pendown()
start = turtle.pos()
for x in range(benzsize):
turtle.pencolor(colors[x%6])
turtle.forward(x)
turtle.left(59)
def two_color():
print("two-color")
turtle.pendown()
colors = [adafruit_turtle.Color.ORANGE, adafruit_turtle.Color.PURPLE]
for x in range(150):
turtle.pencolor(colors[x % 2])
turtle.forward(x)
turtle.left(91)
def line_circle():
print("Line Circle")
turtle.pencolor(adafruit_turtle.Color.YELLOW)
turtle.pendown()
for _ in range(21):
for _ in range(6):
turtle.forward(50)
turtle.right(61)
turtle.right(11.1111)
def hilbert2(step, rule, angle, depth, t):
if depth > 0:
a = lambda: hilbert2(step, "a", angle, depth - 1, t)
b = lambda: hilbert2(step, "b", angle, depth - 1, t)
left = lambda: t.left(angle)
right = lambda: t.right(angle)
forward = lambda: t.forward(step)
if rule == "a":
left(); b(); forward(); right(); a(); forward(); a(); right(); forward(); b(); left()
if rule == "b":
right(); a(); forward(); left(); b(); forward(); b(); left(); forward(); a(); right()
while True:
clear_all()
star()
time.sleep(2)
clear_all()
rainbow_benzene()
time.sleep(2)
clear_all()
two_color()
time.sleep(2)
clear_all()
line_circle()
time.sleep(2)
clear_all()
turtle.penup()
turtle.goto(80, -80)
turtle.pendown()
print("hilbert2")
hilbert2(5, "a", 90, 5, turtle)
time.sleep(2)
Related:
~ Install and using CircUp (CircuitPython library updater) to install CircuitPython libraries.
Next:
~ Downloading Bitmap via WiFi with CircuitPython, Saving to Local File System, and Displaying on LCD using OnDiskBitmap.
~ Pico 2 W/CircuitPython 10.0.3 Display bmp images in SD, using displayio.OnDiskBitmap()/adafruit_imageload.load().
~ Raspberry Pi Pico 2 W/CircuitPython 10.0.3: Load animated GIFs from MicroSD, display them on a 240*240 GC9A01 LCD using gifio.OnDiskGif.
Comments
Post a Comment