RPi Pico/MicroPython + ILI9341 SPI Display com toque, usando rdagger/micropython-ili9341

Tempo de leitura: 10 minutes

A tela usada neste exercício é uma cor de 65K de 2,4 polegadas usando o driver ili9341 com toque, 2.4inch_SPI_Module_ILI9341_SKU: MSP2402. Tenho outros exercícios usando a biblioteca jeffmer/micropython-ili9341. Este exercício usa outro lib rdagger/micropython-ili9341 é um monitor MicroPython ILI9341 e drivers de tela de toque XPT2046.

Conexão

Biblioteca

Visite rdagger/micropython-ili9341, copie ili9341.py, xglcd_font.py e fonts/Unispace12x24.c para o seu dispositivo Raspberry Pi Pico.

 

Para facilitar a atualização dos exemplos de lib, defino a conexão de hardware em código separado, mySetup.py. Salve-o no dispositivo Raspberry Pi Pico.

from ili9341 import Display
from machine import Pin, SPI

TFT_CLK_PIN = const(6)
TFT_MOSI_PIN = const(7)
TFT_MISO_PIN = const(4)

TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(15)

def createMyDisplay():
    #spi = SPI(0, baudrate=40000000, sck=Pin(TFT_CLK_PIN), mosi=Pin(TFT_MOSI_PIN))
    spiTFT = SPI(0, baudrate=51200000,
                 sck=Pin(TFT_CLK_PIN), mosi=Pin(TFT_MOSI_PIN))
    display = Display(spiTFT,
                      dc=Pin(TFT_DC_PIN), cs=Pin(TFT_CS_PIN), rst=Pin(TFT_RST_PIN))
    return display
        

Meu código de exercício, mPico_ili9341_test.py.

"""
Raspperry Pi Pico exercise display on ili9341 SPI Display
using rdagger/micropython-ili9341,
MicroPython ILI9341 Display and XPT2046 Touch Screen Drivers
https://github.com/rdagger/micropython-ili9341
"""
from machine import Pin, SPI
from sys import implementation
from os import uname
import utime

import ili9341
from xglcd_font import XglcdFont

import mySetup

print(implementation.name)
print(uname()[3])
print(uname()[4])

print(SPI(0))
print(SPI(1))

display = mySetup.createMyDisplay()

print('Loading fonts...')
print('Loading unispace')
unispace = XglcdFont('fonts/Unispace12x24.c', 12, 24)

display.draw_text(0, 0, ili9341.__name__, unispace,
                  ili9341.color565(255, 128, 0))
display.draw_text(0, 25, ili9341.implementation.name, unispace,
                  ili9341.color565(0, 0, 200))
display.draw_text(0, 50, str(ili9341.implementation.version), unispace,
                  ili9341.color565(0, 0, 200))

display.draw_text(0, 100, "https://github.com/", unispace,
                  ili9341.color565(200, 200, 200))
display.draw_text(0, 125, "rdagger/micropython-ili9341", unispace,
                  ili9341.color565(200, 200, 200))

display.draw_text(0, 175, "ABCDEFGHIJKLMNOPQRS", unispace,
                  ili9341.color565(200, 200, 200))
display.draw_text(0, 200, "TUVWXYZ", unispace,
                  ili9341.color565(200, 200, 200))
display.draw_text(0, 225, "abcdefghijklmnopqrs", unispace,
                  ili9341.color565(200, 200, 200))
display.draw_text(0, 250, "tuvwxyz", unispace,
                  ili9341.color565(200, 200, 200))
display.draw_text(0, 275, "01234567890", unispace,
                  ili9341.color565(200, 200, 200))
display.draw_text(0, 300, "~!@#$%^&*()_+`-={}[]", unispace,
                  ili9341.color565(200, 200, 200))
display.draw_text(0, 325, "\|;:'<>,.?/", unispace,
                  ili9341.color565(200, 200, 200))
    
for i in range(320):
    display.scroll(i)
    utime.sleep(0.02)
    
for i in range(320, 0, -1):
    display.scroll(i)
    utime.sleep(0.02)

utime.sleep(0.5)
# Display inversion on
display.write_cmd(display.INVON)
utime.sleep(2)
# Display inversion off
display.write_cmd(display.INVOFF)

while True:
    pass

print("- bye -")

Também modifico alguns dos exemplos da biblioteca.

demo_bouncing_boxes_.py

"""ILI9341 demo (bouncing boxes)."""
from machine import Pin, SPI
from random import random, seed
from ili9341 import Display, color565
from utime import sleep_us, ticks_cpu, ticks_us, ticks_diff
import mySetup

class Box(object):
    """Bouncing box."""

    def __init__(self, screen_width, screen_height, size, display, color):
        """Initialize box.

        Args:
            screen_width (int): Width of screen.
            screen_height (int): Width of height.
            size (int): Square side length.
            display (ILI9341): display object.
            color (int): RGB565 color value.
        """
        self.size = size
        self.w = screen_width
        self.h = screen_height
        self.display = display
        self.color = color
        # Generate non-zero random speeds between -5.0 and 5.0
        seed(ticks_cpu())
        r = random() * 10.0
        self.x_speed = 5.0 - r if r < 5.0 else r - 10.0
        r = random() * 10.0
        self.y_speed = 5.0 - r if r < 5.0 else r - 10.0

        self.x = self.w / 2.0
        self.y = self.h / 2.0
        self.prev_x = self.x
        self.prev_y = self.y

    def update_pos(self):
        """Update box position and speed."""
        x = self.x
        y = self.y
        size = self.size
        w = self.w
        h = self.h
        x_speed = abs(self.x_speed)
        y_speed = abs(self.y_speed)
        self.prev_x = x
        self.prev_y = y

        if x + size >= w - x_speed:
            self.x_speed = -x_speed
        elif x - size <= x_speed + 1:
            self.x_speed = x_speed

        if y + size >= h - y_speed:
            self.y_speed = -y_speed
        elif y - size <= y_speed + 1:
            self.y_speed = y_speed

        self.x = x + self.x_speed
        self.y = y + self.y_speed

    def draw(self):
        """Draw box."""
        x = int(self.x)
        y = int(self.y)
        size = self.size
        prev_x = int(self.prev_x)
        prev_y = int(self.prev_y)
        self.display.fill_hrect(prev_x - size,
                                prev_y - size,
                                size, size, 0)
        self.display.fill_hrect(x - size,
                                y - size,
                                size, size, self.color)


def test():
    """Bouncing box."""
    try:
        # Baud rate of 40000000 seems about the max
        #spi = SPI(1, baudrate=40000000, sck=Pin(14), mosi=Pin(13))
        #display = Display(spi, dc=Pin(4), cs=Pin(16), rst=Pin(17))
        display = mySetup.createMyDisplay()
        
        display.clear()

        colors = [color565(255, 0, 0),
                  color565(0, 255, 0),
                  color565(0, 0, 255),
                  color565(255, 255, 0),
                  color565(0, 255, 255),
                  color565(255, 0, 255)]
        sizes = [12, 11, 10, 9, 8, 7]
        boxes = [Box(239, 319, sizes[i], display,
                 colors[i]) for i in range(6)]

        while True:
            timer = ticks_us()
            for b in boxes:
                b.update_pos()
                b.draw()
            # Attempt to set framerate to 30 FPS
            timer_dif = 33333 - ticks_diff(ticks_us(), timer)
            if timer_dif > 0:
                sleep_us(timer_dif)

    except KeyboardInterrupt:
        display.cleanup()


test()

demo_colored_squares_.py

"""ILI9341 demo (colored squares)."""
from time import sleep
from ili9341 import Display
from machine import Pin, SPI
from sys import modules
import mySetup

RED = const(0XF800)  # (255, 0, 0)
GREEN = const(0X07E0)  # (0, 255, 0)
BLUE = const(0X001F)  # (0, 0, 255)
YELLOW = const(0XFFE0)  # (255, 255, 0)
FUCHSIA = const(0XF81F)  # (255, 0, 255)
AQUA = const(0X07FF)  # (0, 255, 255)
MAROON = const(0X8000)  # (128, 0, 0)
DARKGREEN = const(0X0400)  # (0, 128, 0)
NAVY = const(0X0010)  # (0, 0, 128)
TEAL = const(0X0410)  # (0, 128, 128)
PURPLE = const(0X8010)  # (128, 0, 128)
OLIVE = const(0X8400)  # (128, 128, 0)
ORANGE = const(0XFC00)  # (255, 128, 0)
DEEP_PINK = const(0XF810)  # (255, 0, 128)
CHARTREUSE = const(0X87E0)  # (128, 255, 0)
SPRING_GREEN = const(0X07F0)  # (0, 255, 128)
INDIGO = const(0X801F)  # (128, 0, 255)
DODGER_BLUE = const(0X041F)  # (0, 128, 255)
CYAN = const(0X87FF)  # (128, 255, 255)
PINK = const(0XFC1F)  # (255, 128, 255)
LIGHT_YELLOW = const(0XFFF0)  # (255, 255, 128)
LIGHT_CORAL = const(0XFC10)  # (255, 128, 128)
LIGHT_GREEN = const(0X87F0)  # (128, 255, 128)
LIGHT_SLATE_BLUE = const(0X841F)  # (128, 128, 255)
WHITE = const(0XFFF)  # (255, 255, 255)

colors = [RED,
          GREEN,
          BLUE,
          YELLOW,
          FUCHSIA,
          AQUA,
          MAROON,
          DARKGREEN,
          NAVY,
          TEAL,
          PURPLE,
          OLIVE,
          ORANGE,
          DEEP_PINK,
          CHARTREUSE,
          SPRING_GREEN,
          INDIGO,
          DODGER_BLUE,
          CYAN,
          PINK,
          LIGHT_YELLOW,
          LIGHT_CORAL,
          LIGHT_GREEN,
          LIGHT_SLATE_BLUE,
          WHITE ]

def test():
    """Test code."""
    """
    # Baud rate of 40000000 seems about the max
    spi = SPI(0, baudrate=40000000, sck=Pin(TFT_CLK_PIN), mosi=Pin(TFT_MOSI_PIN))
    display = Display(spi, dc=Pin(TFT_DC_PIN), cs=Pin(TFT_CS_PIN), rst=Pin(TFT_RST_PIN))
    """
    display = mySetup.createMyDisplay()

    """
    # Build color list from all upper case constants (lazy approach)
    colors = [getattr(modules[__name__], name) for name in dir(
        modules[__name__]) if name.isupper() and name is not 'SPI']
    """

    colors.sort()
    c = 0
    for x in range(0, 240, 48):
        for y in range(0, 320, 64):
            display.fill_rectangle(x, y, 47, 63, colors[c])
            c += 1
    sleep(9)
    display.cleanup()


test()

demo_color_palette_.py

"""ILI9341 demo (color palette)."""
from time import sleep
from ili9341 import Display, color565
from machine import Pin, SPI
import mySetup

def hsv_to_rgb(h, s, v):
    """
    Convert HSV to RGB (based on colorsys.py).

        Args:
            h (float): Hue 0 to 1.
            s (float): Saturation 0 to 1.
            v (float): Value 0 to 1 (Brightness).
    """
    if s == 0.0:
        return v, v, v
    i = int(h * 6.0)
    f = (h * 6.0) - i
    p = v * (1.0 - s)
    q = v * (1.0 - s * f)
    t = v * (1.0 - s * (1.0 - f))
    i = i % 6

    v = int(v * 255)
    t = int(t * 255)
    p = int(p * 255)
    q = int(q * 255)

    if i == 0:
        return v, t, p
    if i == 1:
        return q, v, p
    if i == 2:
        return p, v, t
    if i == 3:
        return p, q, v
    if i == 4:
        return t, p, v
    if i == 5:
        return v, p, q


def test():
    """Test code."""
    # Baud rate of 40000000 seems about the max
    #spi = SPI(1, baudrate=40000000, sck=Pin(14), mosi=Pin(13))
    #display = Display(spi, dc=Pin(4), cs=Pin(16), rst=Pin(17))
    display = mySetup.createMyDisplay()

    c = 0
    for x in range(0, 240, 20):
        for y in range(0, 320, 20):
            color = color565(*hsv_to_rgb(c / 192, 1, 1))
            display.fill_circle(x + 9, y + 9, 9, color)
            c += 1
    sleep(9)
    display.cleanup()


test()

demo_color_wheel_.py

"""ILI9341 demo (color wheel)."""
from time import sleep
from ili9341 import Display, color565
from machine import Pin, SPI
from math import cos, pi, sin
import mySetup

HALF_WIDTH = const(120)
HALF_HEIGHT = const(160)
CENTER_X = const(119)
CENTER_Y = const(159)
ANGLE_STEP_SIZE = 0.05  # Decrease step size for higher resolution
PI2 = pi * 2


def hsv_to_rgb(h, s, v):
    """
    Convert HSV to RGB (based on colorsys.py).

        Args:
            h (float): Hue 0 to 1.
            s (float): Saturation 0 to 1.
            v (float): Value 0 to 1 (Brightness).
    """
    if s == 0.0:
        return v, v, v
    i = int(h * 6.0)
    f = (h * 6.0) - i
    p = v * (1.0 - s)
    q = v * (1.0 - s * f)
    t = v * (1.0 - s * (1.0 - f))
    i = i % 6

    v = int(v * 255)
    t = int(t * 255)
    p = int(p * 255)
    q = int(q * 255)

    if i == 0:
        return v, t, p
    if i == 1:
        return q, v, p
    if i == 2:
        return p, v, t
    if i == 3:
        return p, q, v
    if i == 4:
        return t, p, v
    if i == 5:
        return v, p, q


def test():
    """Test code."""
    # Baud rate of 40000000 seems about the max
    #spi = SPI(1, baudrate=40000000, sck=Pin(14), mosi=Pin(13))
    #display = Display(spi, dc=Pin(4), cs=Pin(16), rst=Pin(17))
    display = mySetup.createMyDisplay()

    x, y = 0, 0
    angle = 0.0
    #  Loop all angles from 0 to 2 * PI radians
    while angle < PI2:
        # Calculate x, y from a vector with known length and angle
        x = int(CENTER_X * sin(angle) + HALF_WIDTH)
        y = int(CENTER_Y * cos(angle) + HALF_HEIGHT)
        color = color565(*hsv_to_rgb(angle / PI2, 1, 1))
        display.draw_line(x, y, CENTER_X, CENTER_Y, color)
        angle += ANGLE_STEP_SIZE

    sleep(5)

    for r in range(CENTER_X, 0, -1):
        color = color565(*hsv_to_rgb(r / HALF_WIDTH, 1, 1))
        display.fill_circle(CENTER_X, CENTER_Y, r, color)

    sleep(9)
    display.cleanup()


test()

demo_shapes_.py

"""ILI9341 demo (shapes)."""
from time import sleep
from ili9341 import Display, color565
from machine import Pin, SPI
import mySetup


def test():
    """Test code."""
    # Baud rate of 40000000 seems about the max
    #spi = SPI(1, baudrate=40000000, sck=Pin(14), mosi=Pin(13))
    #display = Display(spi, dc=Pin(4), cs=Pin(16), rst=Pin(17))
    display = mySetup.createMyDisplay()

    display.clear(color565(64, 0, 255))
    sleep(1)

    display.clear()

    display.draw_hline(10, 319, 229, color565(255, 0, 255))
    sleep(1)

    display.draw_vline(10, 0, 319, color565(0, 255, 255))
    sleep(1)

    display.fill_hrect(23, 50, 30, 75, color565(255, 255, 255))
    sleep(1)

    display.draw_hline(0, 0, 222, color565(255, 0, 0))
    sleep(1)

    display.draw_line(127, 0, 64, 127, color565(255, 255, 0))
    sleep(2)

    display.clear()

    coords = [[0, 63], [78, 80], [122, 92], [50, 50], [78, 15], [0, 63]]
    display.draw_lines(coords, color565(0, 255, 255))
    sleep(1)

    display.clear()
    display.fill_polygon(7, 120, 120, 100, color565(0, 255, 0))
    sleep(1)

    display.fill_rectangle(0, 0, 15, 227, color565(255, 0, 0))
    sleep(1)

    display.clear()

    display.fill_rectangle(0, 0, 163, 163, color565(128, 128, 255))
    sleep(1)

    display.draw_rectangle(0, 64, 163, 163, color565(255, 0, 255))
    sleep(1)

    display.fill_rectangle(64, 0, 163, 163, color565(128, 0, 255))
    sleep(1)

    display.draw_polygon(3, 120, 286, 30, color565(0, 64, 255), rotate=15)
    sleep(3)

    display.clear()

    display.fill_circle(132, 132, 70, color565(0, 255, 0))
    sleep(1)

    display.draw_circle(132, 96, 70, color565(0, 0, 255))
    sleep(1)

    display.fill_ellipse(96, 96, 30, 16, color565(255, 0, 0))
    sleep(1)

    display.draw_ellipse(96, 256, 16, 30, color565(255, 255, 0))

    sleep(5)
    display.cleanup()


test()

 

Detectar toque

Para detectar o toque, visite rdagger/micropython-ili9341, baixe xpt2046.py para Raspberry Pi Pico.

Salve mySetupX.py no Raspberry Pi Pico, com configuração para xpd2046. Conecte os pinos extras de acordo.

from ili9341 import Display
from machine import Pin, SPI
from xpt2046 import Touch

TFT_CLK_PIN = const(6)
TFT_MOSI_PIN = const(7)
TFT_MISO_PIN = const(4)

TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(15)

XPT_CLK_PIN = const(10)
XPT_MOSI_PIN = const(11)
XPT_MISO_PIN = const(8)

XPT_CS_PIN = const(12)
XPT_INT = const(0)

def createMyDisplay():
    spiTFT = SPI(0, baudrate=40000000, sck=Pin(TFT_CLK_PIN), mosi=Pin(TFT_MOSI_PIN))
    display = Display(spiTFT,
                      dc=Pin(TFT_DC_PIN), cs=Pin(TFT_CS_PIN), rst=Pin(TFT_RST_PIN))
    return display

def createXPT(touch_handler):
    spiXPT = SPI(1, baudrate=1000000,
                 sck=Pin(XPT_CLK_PIN), mosi=Pin(XPT_MOSI_PIN), miso=Pin(XPT_MISO_PIN))

    xpt = Touch(spiXPT, cs=Pin(XPT_CS_PIN), int_pin=Pin(XPT_INT),
                int_handler=touch_handler)

    return xpt

Execute xpt_cal_.py, toque nos cantos para encontrar o mín./Máx. De x/y. O min/max detectado de x/y será mostrado na tela. (Verifique o vídeo, y_max=2047 pode ser detectado incorretamente, mas muito perto. Aparece antes de ser tocado.)

xpt_cal_.py

from machine import Pin, SPI
from sys import implementation
from os import uname
import ili9341
from xglcd_font import XglcdFont
import mySetupX

print(implementation.name)
print(uname()[3])
print(uname()[4])

print(SPI(0))
print(SPI(1))

minX = maxX = minY = maxY = 500

def xpt_touch(x, y):
    global xptTouch
    global minX, maxX, minY, maxY
    
    touchXY = xptTouch.get_touch()
    rawX = xptTouch.send_command(xptTouch.GET_X)
    rawY = xptTouch.send_command(xptTouch.GET_Y)
    
    if rawX != 0:
        if rawX > maxX:
            maxX = rawX
        elif rawX < minX:
            minX = rawX
    if rawY != 0:    
        if rawY > maxY:
            maxY = rawY
        elif rawY < minY:
            minY = rawY
    
    display.fill_circle(x, y, 2, ili9341.color565(0, 255, 0))
    print(str(x) + ":" + str(y) + " / " + str(rawX) + ":" + str(rawY))
    
    if touchXY != None:
        touchX = touchXY[0]
        touchY = touchXY[1]
        display.fill_circle(touchX, touchY, 2, ili9341.color565(255, 0, 0))
        print(str(touchX) + ":" + str(touchY))
        
    xReading = "X: " + str(minX) + " - " + str(maxX) + "       "
    yReading = "Y: " + str(minY) + " - " + str(maxY) + "       "
        
    display.draw_text(0, 100, xReading, unispace,
                  ili9341.color565(255, 128, 0))
    display.draw_text(0, 125, yReading, unispace,
                  ili9341.color565(255, 128, 0))

display = mySetupX.createMyDisplay()
xptTouch = mySetupX.createXPT(xpt_touch)

print('Loading fonts...')
print('Loading unispace')
unispace = XglcdFont('fonts/Unispace12x24.c', 12, 24)

display.draw_text(0, 0, ili9341.__name__, unispace,
                  ili9341.color565(255, 128, 0))
display.draw_text(0, 25, ili9341.implementation.name, unispace,
                  ili9341.color565(0, 0, 200))
display.draw_text(0, 50, str(ili9341.implementation.version), unispace,
                  ili9341.color565(0, 0, 200))

while True:
    pass

print("- bye -")

Atualize x_min, x_max, y_min e y_max em mySetupX.py de acordo.

xpt = Touch(spiXPT, cs=Pin(XPT_CS_PIN), int_pin=Pin(XPT_INT),
            int_handler=touch_handler,
            x_min=64, x_max=1847, y_min=148, y_max=2047)

Execute meu código de exercício, xpt_moveII_2.4.py.

xpt_moveII_2.4.py

from machine import Pin, SPI, Timer
from sys import implementation
from os import uname
import ili9341
from xglcd_font import XglcdFont
import mySetupX

print(implementation.name)
print(uname()[3])
print(uname()[4])

print(SPI(0))
print(SPI(1))

led = Pin(25, Pin.OUT)

#=== variable share btween ISR and main loop ===
x_passedTo_ISR = 0
y_passwsTo_ISR = 0

EVT_NO = const(0)
EVT_PenDown = const(1)
EVT_PenUp   = const(2)
event = EVT_NO

TimerReached = False
#===============================================

def xpt_touch(x, y):
    global event, x_passedTo_ISR, y_passedTo_ISR
    event = EVT_PenDown
    x_passedTo_ISR = x
    y_passedTo_ISR = y

display = mySetupX.createMyDisplay()
xptTouch = mySetupX.createXPT(xpt_touch)

print('Loading fonts...')
print('Loading unispace')
unispace = XglcdFont('fonts/Unispace12x24.c', 12, 24)

display.clear()
display.draw_text(0, 0, ili9341.__name__, unispace,
                  ili9341.color565(255, 128, 0))
display.draw_text(0, 25, ili9341.implementation.name, unispace,
                  ili9341.color565(0, 0, 200))
display.draw_text(0, 50, str(ili9341.implementation.version), unispace,
                  ili9341.color565(0, 0, 200))

tim = Timer()
def TimerTick(timer):
    global TimerReached
    TimerReached = True

tim.init(freq=50, mode=Timer.PERIODIC, callback=TimerTick)

touching = False

lastX = lastY = 0

while True:
    curEvent = event
    event = EVT_NO
    if curEvent!= EVT_NO:
        if curEvent == EVT_PenDown:
            print("Pen Down")
            touching = True
            lastX = x_passedTo_ISR
            lastY = y_passedTo_ISR
    
            touchXY = xptTouch.get_touch()
            rawX = xptTouch.send_command(xptTouch.GET_X)
            rawY = xptTouch.send_command(xptTouch.GET_Y)
    
            display.clear()
            display.fill_circle(x_passedTo_ISR, y_passedTo_ISR,
                                8, ili9341.color565(0, 255, 0))
            print(str(x_passedTo_ISR) + ":" + str(y_passedTo_ISR) +
                  " / " + str(rawX) + ":" + str(rawY))
    
            if touchXY != None:
                touchX = touchXY[0]
                touchY = touchXY[1]
                display.fill_circle(touchX, touchY, 5, ili9341.color565(255, 0, 0))
                print(str(touchX) + ":" + str(touchY))
            
        elif curEvent == EVT_PenUp:
            print("Pen Up")
            pass
        else:
            print("unknown event!!!")
            
    if TimerReached:
        TimerReached = False
        
        if touching:
            led.toggle()
            buff = xptTouch.raw_touch()
            if buff is not None:
                x, y = xptTouch.normalize(*buff)
                lastX = x
                lastY = y
                display.fill_circle(x, y, 1, ili9341.color565(255, 255, 255))
                print("... " + str(x) + " : " + str(y))
            else:
                event = EVT_PenUp
                touching = False
                led.off()
                display.fill_circle(lastX, lastY, 5, ili9341.color565(0, 0, 255))

print("- bye -")

Testado em minha outra unidade de versão de 2,8 polegadas, 2,8 “TFT SPI 240*320. A posição X está na ordem inversa, então edite para a versão de 2,8 polegadas.

xpt_moveII_2.8.py

from machine import Pin, SPI, Timer
from sys import implementation
from os import uname
import ili9341
from xglcd_font import XglcdFont
import mySetupX

print(implementation.name)
print(uname()[3])
print(uname()[4])

print(SPI(0))
print(SPI(1))

led = Pin(25, Pin.OUT)

#=== variable share btween ISR and main loop ===
x_passedTo_ISR = 0
y_passwsTo_ISR = 0

EVT_NO = const(0)
EVT_PenDown = const(1)
EVT_PenUp   = const(2)
event = EVT_NO

TimerReached = False
#===============================================

def xpt_touch(x, y):
    global event, x_passedTo_ISR, y_passedTo_ISR
    event = EVT_PenDown
    x_passedTo_ISR = x
    y_passedTo_ISR = y

display = mySetupX.createMyDisplay()
xptTouch = mySetupX.createXPT(xpt_touch)

print('Loading fonts...')
print('Loading unispace')
unispace = XglcdFont('fonts/Unispace12x24.c', 12, 24)

display.clear()
display.draw_text(0, 0, ili9341.__name__, unispace,
                  ili9341.color565(255, 128, 0))
display.draw_text(0, 25, ili9341.implementation.name, unispace,
                  ili9341.color565(0, 0, 200))
display.draw_text(0, 50, str(ili9341.implementation.version), unispace,
                  ili9341.color565(0, 0, 200))

tim = Timer()
def TimerTick(timer):
    global TimerReached
    TimerReached = True

tim.init(freq=50, mode=Timer.PERIODIC, callback=TimerTick)

touching = False

lastX = lastY = 0

while True:
    curEvent = event
    event = EVT_NO
    if curEvent!= EVT_NO:
        if curEvent == EVT_PenDown:
            print("Pen Down")
            touching = True
            lastX = x_passedTo_ISR
            lastY = y_passedTo_ISR
    
            touchXY = xptTouch.get_touch()
            rawX = xptTouch.send_command(xptTouch.GET_X)
            rawY = xptTouch.send_command(xptTouch.GET_Y)
    
            display.clear()
            display.fill_circle(240-x_passedTo_ISR, y_passedTo_ISR,
                                8, ili9341.color565(0, 255, 0))
            print(str(x_passedTo_ISR) + ":" + str(y_passedTo_ISR) +
                  " / " + str(rawX) + ":" + str(rawY))
    
            if touchXY != None:
                touchX = touchXY[0]
                touchY = touchXY[1]
                display.fill_circle(240-touchX, touchY, 5, ili9341.color565(255, 0, 0))
                print(str(touchX) + ":" + str(touchY))
            
        elif curEvent == EVT_PenUp:
            print("Pen Up")
            pass
        else:
            print("unknown event!!!")
            
    if TimerReached:
        TimerReached = False
        
        if touching:
            led.toggle()
            buff = xptTouch.raw_touch()
            if buff is not None:
                x, y = xptTouch.normalize(*buff)
                lastX = x
                lastY = y
                display.fill_circle(240-x, y, 1, ili9341.color565(255, 255, 255))
                print("... " + str(x) + " : " + str(y))
            else:
                event = EVT_PenUp
                touching = False
                led.off()
                display.fill_circle(240-lastX, lastY, 5, ili9341.color565(0, 0, 255))

print("- bye -")

Relacionado:
~ Versão do CircuitPython: Raspberry Pi Pico/CircuitPython + ILI9341 SPI Display com toque