CircuitPython on Pico 2 + Touch LCD, act as a HID mouse.

Refer to the cpy_pico2_st7796_BusDisplay_FT6336.py exercise in last post "Use ST7796 SPI LCD on CircuitPython/Raspberry Pi Pico 2, by instancing BusDisplay object using custom init_sequence", It simple read touch reported by adafruit_focaltouch and display a cursor on screen, no any actual function. In this exercise I will add a simple handler to detect touch action such as touch-down, touch-up, and touch-move, and finally report to PC as HID mouse function.


Connection, refer to last post "Use ST7796 SPI LCD on CircuitPython/Raspberry Pi Pico 2, by instancing BusDisplay object using custom init_sequence".

To install libraries for following exercise using circup:

circup install adafruit_display_text adafruit_focaltouch adafruit_hid adafruit_button

Exercise Code:

cpy_pico2_st7796_BusDisplay_FT6336_handler.py

Before we report HID mouse function, we have to detect touch action touch-down, touch-up, and touch-move. In this code, a simple handler is added to detect such events.

And it's found that the code current_touched = ft.touched is actually a function call to _read() in adafruit_focaltouch.py. If irq_pin is not None and no touch, it will stay in a while-loop until touched and irq_pin changed to low, and the result is cannot detect touch-up. So I remove irq_pin.

cpy_pico2_st7796_BusDisplay_FT6336_handler.py
"""
Raspberry Pi Pico 2/CircuitPython 9
to display on Waveshare 3.5" 320x480 ST7796 SPI IPS
Handle touch-down, touch-up snd touch move of FT6336U.

For connection and setup, check the previous exercise
"Use ST7796 SPI LCD on CircuitPython/Raspberry Pi Pico 2, by instancing BusDisplay object using custom init_sequence."
(https://coxxect.blogspot.com/2025/02/use-st7796-spi-lcd-on.html)

Follow the cpy_pico2_st7796_BusDisplay_FT6336.py in previous exercise,
implement a simple handle to detect touch-down, touch-up and touch-move event.
Such that I can draw something on screen, then report as HID mouse action in next exercise.

Libraries need to install:
adafruit_display_text
adafruit_focaltouch

install with circup:
circup install adafruit_display_text adafruit_focaltouch
"""

import os, sys
import board
import busio
import displayio
import terminalio
from adafruit_display_text import label
import time

import busdisplay

from digitalio import DigitalInOut, Direction
import adafruit_focaltouch
import bitmaptools

led = DigitalInOut(board.LED)
led.direction = Direction.OUTPUT

spi_miso = board.GP0
spi_sck  = board.GP2
spi_mosi = board.GP3
disp_res  = board.GP6
disp_dc   = board.GP5
disp_cs   = board.GP1
disp_blk  = board.GP7

#Connection to FT6336U
TOUCH_SDA = board.GP8
TOUCH_SCL = board.GP9
TOUCH_INT = board.GP10
TOUCH_RST = board.GP11

DISPLAY_width = 320
DISPLAY_height = 480

ST7796_INIT_SEQUENCE = (
    b"\x01\x80\x96"  # _SWRESET and Delay 150ms

    b"\x11\x80\x78"  # SLPOUT
    b"\x36\x01\x48"  # b"\x36\x01\x08"  # MADCTL
    b"\x3A\x01\x05"  #COLMOD
    b"\xF0\x01\xC3"  # CSCON enable command 2 part I
    b"\xF0\x01\x96"  # CSCON enable command 2 part II
    b"\xB4\x01\x01"  # DIC (Display Inversion Control) - 1 dot inversion
    b"\xB7\x01\xC6"  # EM (Entry mode Set)
    b"\xC0\x02\x80\x45"  # PWR1(Power Control 1)
    b"\xC1\x01\x13"  # PWR2(Power Control 2)
    b"\xC2\x01\xA7"  # PWR3(Power Control 3
    b"\xC5\x01\x0A"  # VCMPCTL (VCOM Control)
    b"\xE8\x08\x40\x8A\x00\x00\x29\x19\xA5\x33" # DOCA (Display Output Ctrl Adjust)
    b"\xE0\x0E\xD0\x08\x0F\x06\x06\x33\x30\x33\x47\x17\x13\x13\x2B\x31" # PGC (Positive Gamma Control)
    b"\xE1\x0E\xD0\x0A\x11\x0B\x09\x07\x2F\x33\x47\x38\x15\x16\x2C\x32" # NGC (Negative Gamma Control)
    b"\xF0\x01\x3C"     # CSCON disable command 2 part I
    b"\xF0\x81\x69\x78" # CSCON disable command 2 part II, then delay 120ms
    b"\x21\x00" # INVON (Display Inversion On)
    b"\x29\x00" # DISPON (Display On)
)

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

touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT

touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.5)

disp_spi = busio.SPI(clock=spi_sck, MOSI=spi_mosi, MISO=spi_miso)

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

# rot_setting is used to better manager display width/height, touch x/y adjust
# for rotation setting.
# elements in rot_setting[] set according to rotation, set in rot_set
# rotation: pass to BusDisplay
# width : pass to 
# height: pass to BusDisplay
# exchange x/y in touch
# inverse x in touch
# inverse y in touch
rot_setting = [[0, DISPLAY_width, DISPLAY_height, False, False, False],
               [90, DISPLAY_height, DISPLAY_width, True, False, True],
               [180, DISPLAY_width, DISPLAY_height, False, True, True],
               [270, DISPLAY_height, DISPLAY_width, True, True, False]]

# rot_set set rotation
# 0 - 0
# 1 - 90
# 2 - 180
# 3 - 279
rot_set = 1

print("--- rot_setting ---")
print("rot_set\t\t", rot_set)
print("rotation:\t", rot_setting[rot_set][0])
print("width:\t\t",  rot_setting[rot_set][1])
print("height:\t\t", rot_setting[rot_set][2])
print("exchange xy:\t", rot_setting[rot_set][3])
print("reverse x:\t",   rot_setting[rot_set][4])
print("reverse x:\t",   rot_setting[rot_set][5])


display = busdisplay.BusDisplay(display_bus,
                                ST7796_INIT_SEQUENCE,
                                width=rot_setting[rot_set][1],
                                height=rot_setting[rot_set][2],
                                backlight_pin=disp_blk,
                                rotation=rot_setting[rot_set][0])

touch_i2c = busio.I2C(TOUCH_SCL, TOUCH_SDA)
# if irq_pin is not None, and no touch, the code will stay in while loop in reading touched!
#ft = adafruit_focaltouch.Adafruit_FocalTouch(touch_i2c, debug=False, irq_pin=touch_irq)
ft = adafruit_focaltouch.Adafruit_FocalTouch(touch_i2c, debug=False)

sys_info_text = sys.implementation[0] + " " + os.uname()[3] +\
                "\nrun on " + os.uname()[4] +\
                "\nusing " + busdisplay.BusDisplay.__name__ +\
                "\n" + adafruit_focaltouch.__name__ + " " + adafruit_focaltouch.__version__
print("=======================================")
print(sys_info_text)
print("=======================================")
print()
# Make the display context
bgGroup = displayio.Group()
display.root_group = bgGroup

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

# place a label on screen center
text_area = label.Label(terminalio.FONT, text="coXXect.blogspot.com", scale=2, color=0xFFFFFF)
text_area_width = text_area.bounding_box[2]*text_area.scale
text_area_height = text_area.bounding_box[3]*text_area.scale
text_area.x = int((display.width - text_area_width)/2)
text_area.y = int((display.height - text_area_height)/2)
bgGroup.append(text_area)

last_touched = False
last_touch_pt = [0, 0]

def getTouchPt(touches):
    if rot_setting[rot_set][3]:
        x = touches[0]['y'] # exchange x/y
        y = touches[0]['x']
    else:
        x = touches[0]['x'] # keep no exchange
        y = touches[0]['y']
    
    if rot_setting[rot_set][4]:
        x = display.width - x # reverse x
    if rot_setting[rot_set][5]:
        y = display.height - y # reverse y
        
    return x, y
    
while True:
    # onboard LED is used to monitor before/after reading FT6336U touch data
    led.value = True
    current_touched = ft.touched
    current_touches = ft.touches
    led.value = False
    if current_touched:
        #sometimes ft.touches is [], empty!
        #so I check len to prevent IndexError: index out of range
        if len(current_touches)>0:
            if last_touched:  # touched->touched, touch-move
                x, y = getTouchPt(current_touches)
                bitmaptools.draw_line(bg_bitmap,
                                      last_touch_pt[0], last_touch_pt[1],
                                      x, y,
                                      1)
                last_touch_pt = x, y
                
            else:
                # untouched->touched, touch-down
                last_touched = True
                print("Touch DOWN")
                last_touch_pt = getTouchPt(current_touches)
                bitmaptools.draw_circle(bg_bitmap,
                                        last_touch_pt[0], last_touch_pt[1],
                                        10,
                                        1)
                
    elif not current_touched and last_touched:
        # touched->untouched, touch-up
        last_touched = False
        print("Touch UP")
        bg_bitmap.fill(0)
    
    time.sleep(0.05)


cpy_pico2_st7796_BusDisplay_FT6336_mouse.py, report mouse.move().
"""
Raspberry Pi Pico 2/CircuitPython 9
to display on Waveshare 3.5" 320x480 ST7796 SPI IPS
Report mouse.move(), using usb_hid and adafruit_hid.mouse.

Libraries need to install:
adafruit_display_text
adafruit_focaltouch
adafruit_hid

install with circup:
circup install adafruit_display_text adafruit_focaltouch adafruit_hid
"""

import os, sys
import board
import busio
import displayio
import terminalio
from adafruit_display_text import label
import time

import busdisplay

from digitalio import DigitalInOut, Direction
import adafruit_focaltouch
import bitmaptools

import usb_hid
from adafruit_hid.mouse import Mouse

led = DigitalInOut(board.LED)
led.direction = Direction.OUTPUT

spi_miso = board.GP0
spi_sck  = board.GP2
spi_mosi = board.GP3
disp_res  = board.GP6
disp_dc   = board.GP5
disp_cs   = board.GP1
disp_blk  = board.GP7

#Connection to FT6336U
TOUCH_SDA = board.GP8
TOUCH_SCL = board.GP9
TOUCH_INT = board.GP10
TOUCH_RST = board.GP11

DISPLAY_width = 320
DISPLAY_height = 480

ST7796_INIT_SEQUENCE = (
    b"\x01\x80\x96"  # _SWRESET and Delay 150ms

    b"\x11\x80\x78"  # SLPOUT
    b"\x36\x01\x48"  # b"\x36\x01\x08"  # MADCTL
    b"\x3A\x01\x05"  #COLMOD
    b"\xF0\x01\xC3"  # CSCON enable command 2 part I
    b"\xF0\x01\x96"  # CSCON enable command 2 part II
    b"\xB4\x01\x01"  # DIC (Display Inversion Control) - 1 dot inversion
    b"\xB7\x01\xC6"  # EM (Entry mode Set)
    b"\xC0\x02\x80\x45"  # PWR1(Power Control 1)
    b"\xC1\x01\x13"  # PWR2(Power Control 2)
    b"\xC2\x01\xA7"  # PWR3(Power Control 3
    b"\xC5\x01\x0A"  # VCMPCTL (VCOM Control)
    b"\xE8\x08\x40\x8A\x00\x00\x29\x19\xA5\x33" # DOCA (Display Output Ctrl Adjust)
    b"\xE0\x0E\xD0\x08\x0F\x06\x06\x33\x30\x33\x47\x17\x13\x13\x2B\x31" # PGC (Positive Gamma Control)
    b"\xE1\x0E\xD0\x0A\x11\x0B\x09\x07\x2F\x33\x47\x38\x15\x16\x2C\x32" # NGC (Negative Gamma Control)
    b"\xF0\x01\x3C"     # CSCON disable command 2 part I
    b"\xF0\x81\x69\x78" # CSCON disable command 2 part II, then delay 120ms
    b"\x21\x00" # INVON (Display Inversion On)
    b"\x29\x00" # DISPON (Display On)
)

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

touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT

touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.5)

disp_spi = busio.SPI(clock=spi_sck, MOSI=spi_mosi, MISO=spi_miso)

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

# rot_setting is used to better manager display width/height, touch x/y adjust
# for rotation setting.
# elements in rot_setting[] set according to rotation, set in rot_set
# rotation: pass to BusDisplay
# width : pass to 
# height: pass to BusDisplay
# exchange x/y in touch
# inverse x in touch
# inverse y in touch
rot_setting = [[0, DISPLAY_width, DISPLAY_height, False, False, False],
               [90, DISPLAY_height, DISPLAY_width, True, False, True],
               [180, DISPLAY_width, DISPLAY_height, False, True, True],
               [270, DISPLAY_height, DISPLAY_width, True, True, False]]

# rot_set set rotation
# 0 - 0
# 1 - 90
# 2 - 180
# 3 - 279
rot_set = 1

print("--- rot_setting ---")
print("rot_set\t\t", rot_set)
print("rotation:\t", rot_setting[rot_set][0])
print("width:\t\t",  rot_setting[rot_set][1])
print("height:\t\t", rot_setting[rot_set][2])
print("exchange xy:\t", rot_setting[rot_set][3])
print("reverse x:\t",   rot_setting[rot_set][4])
print("reverse x:\t",   rot_setting[rot_set][5])


display = busdisplay.BusDisplay(display_bus,
                                ST7796_INIT_SEQUENCE,
                                width=rot_setting[rot_set][1],
                                height=rot_setting[rot_set][2],
                                backlight_pin=disp_blk,
                                rotation=rot_setting[rot_set][0])

touch_i2c = busio.I2C(TOUCH_SCL, TOUCH_SDA)
ft = adafruit_focaltouch.Adafruit_FocalTouch(touch_i2c, debug=False)

sys_info_text = sys.implementation[0] + " " + os.uname()[3] +\
                "\nrun on " + os.uname()[4] +\
                "\nusing " + busdisplay.BusDisplay.__name__ +\
                "\n" + adafruit_focaltouch.__name__ + " " + adafruit_focaltouch.__version__
print("=======================================")
print(sys_info_text)
print("=======================================")
print()
# Make the display context
bgGroup = displayio.Group()
display.root_group = bgGroup

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

# place a label on screen center
text_area = label.Label(terminalio.FONT, text="coXXect.blogspot.com", scale=2, color=0xFFFFFF)
text_area_width = text_area.bounding_box[2]*text_area.scale
text_area_height = text_area.bounding_box[3]*text_area.scale
text_area.x = int((display.width - text_area_width)/2)
text_area.y = int((display.height - text_area_height)/2)
bgGroup.append(text_area)

last_touched = False
last_touch_pt = [0, 0]

def getTouchPt(touches):
    if rot_setting[rot_set][3]:
        x = touches[0]['y'] # exchange x/y
        y = touches[0]['x']
    else:
        x = touches[0]['x'] # keep no exchange
        y = touches[0]['y']
    
    if rot_setting[rot_set][4]:
        x = display.width - x # reverse x
    if rot_setting[rot_set][5]:
        y = display.height - y # reverse y
        
    return x, y
    
mouse = Mouse(usb_hid.devices)

while True:
    led.value = True
    current_touched = ft.touched
    current_touches = ft.touches
    led.value = False
    if current_touched:
        #sometimes ft.touches is [], empty!
        #so I check len to prevent IndexError: index out of range
        if len(current_touches)>0:
            if last_touched:  # touched->touched, touch-move
                x, y = getTouchPt(current_touches)
                mouse.move(x=x-last_touch_pt[0], y=y-last_touch_pt[1])
                bitmaptools.draw_line(bg_bitmap,
                                      last_touch_pt[0], last_touch_pt[1],
                                      x, y,
                                      1)
                last_touch_pt = x, y
                
            else:
                # untouched->touched, touch-down
                last_touched = True
                last_touch_pt = getTouchPt(current_touches)
                bitmaptools.draw_circle(bg_bitmap,
                                        last_touch_pt[0], last_touch_pt[1],
                                        10,
                                        1)
                
    elif not current_touched and last_touched:
        # touched->untouched, touch-up
        last_touched = False
        bg_bitmap.fill(0)
    
    time.sleep(0.05)


cpy_pico2_st7796_BusDisplay_FT6336_mouse_buttons.py, two buttons added to report mouse.click().
"""
Raspberry Pi Pico 2/CircuitPython 9
to display on Waveshare 3.5" 320x480 ST7796 SPI IPS
Added LEFT and RIGHT button.
Single click only, no double click, no press-and-hold.

Libraries need to install:
adafruit_display_text
adafruit_focaltouch
adafruit_hid
adafruit_button

install with circup:
circup install adafruit_display_text adafruit_focaltouch adafruit_hid adafruit_button
"""

import os, sys
import board
import busio
import displayio
import terminalio
from adafruit_display_text import label
import time

import busdisplay

from digitalio import DigitalInOut, Direction
import adafruit_focaltouch
import bitmaptools

import usb_hid
from adafruit_hid.mouse import Mouse

from adafruit_button import Button

led = DigitalInOut(board.LED)
led.direction = Direction.OUTPUT

spi_miso = board.GP0
spi_sck  = board.GP2
spi_mosi = board.GP3
disp_res  = board.GP6
disp_dc   = board.GP5
disp_cs   = board.GP1
disp_blk  = board.GP7

#Connection to FT6336U
TOUCH_SDA = board.GP8
TOUCH_SCL = board.GP9
TOUCH_INT = board.GP10
TOUCH_RST = board.GP11

DISPLAY_width = 320
DISPLAY_height = 480

ST7796_INIT_SEQUENCE = (
    b"\x01\x80\x96"  # _SWRESET and Delay 150ms

    b"\x11\x80\x78"  # SLPOUT
    b"\x36\x01\x48"  # b"\x36\x01\x08"  # MADCTL
    b"\x3A\x01\x05"  #COLMOD
    b"\xF0\x01\xC3"  # CSCON enable command 2 part I
    b"\xF0\x01\x96"  # CSCON enable command 2 part II
    b"\xB4\x01\x01"  # DIC (Display Inversion Control) - 1 dot inversion
    b"\xB7\x01\xC6"  # EM (Entry mode Set)
    b"\xC0\x02\x80\x45"  # PWR1(Power Control 1)
    b"\xC1\x01\x13"  # PWR2(Power Control 2)
    b"\xC2\x01\xA7"  # PWR3(Power Control 3
    b"\xC5\x01\x0A"  # VCMPCTL (VCOM Control)
    b"\xE8\x08\x40\x8A\x00\x00\x29\x19\xA5\x33" # DOCA (Display Output Ctrl Adjust)
    b"\xE0\x0E\xD0\x08\x0F\x06\x06\x33\x30\x33\x47\x17\x13\x13\x2B\x31" # PGC (Positive Gamma Control)
    b"\xE1\x0E\xD0\x0A\x11\x0B\x09\x07\x2F\x33\x47\x38\x15\x16\x2C\x32" # NGC (Negative Gamma Control)
    b"\xF0\x01\x3C"     # CSCON disable command 2 part I
    b"\xF0\x81\x69\x78" # CSCON disable command 2 part II, then delay 120ms
    b"\x21\x00" # INVON (Display Inversion On)
    b"\x29\x00" # DISPON (Display On)
)

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

touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT

touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.5)

disp_spi = busio.SPI(clock=spi_sck, MOSI=spi_mosi, MISO=spi_miso)

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

# rot_setting is used to better manager display width/height, touch x/y adjust
# for rotation setting.
# elements in rot_setting[] set according to rotation, set in rot_set
# rotation: pass to BusDisplay
# width : pass to 
# height: pass to BusDisplay
# exchange x/y in touch
# inverse x in touch
# inverse y in touch
rot_setting = [[0, DISPLAY_width, DISPLAY_height, False, False, False],
               [90, DISPLAY_height, DISPLAY_width, True, False, True],
               [180, DISPLAY_width, DISPLAY_height, False, True, True],
               [270, DISPLAY_height, DISPLAY_width, True, True, False]]

# rot_set set rotation
# 0 - 0
# 1 - 90
# 2 - 180
# 3 - 279
rot_set = 1

print("--- rot_setting ---")
print("rot_set\t\t", rot_set)
print("rotation:\t", rot_setting[rot_set][0])
print("width:\t\t",  rot_setting[rot_set][1])
print("height:\t\t", rot_setting[rot_set][2])
print("exchange xy:\t", rot_setting[rot_set][3])
print("reverse x:\t",   rot_setting[rot_set][4])
print("reverse x:\t",   rot_setting[rot_set][5])


display = busdisplay.BusDisplay(display_bus,
                                ST7796_INIT_SEQUENCE,
                                width=rot_setting[rot_set][1],
                                height=rot_setting[rot_set][2],
                                backlight_pin=disp_blk,
                                rotation=rot_setting[rot_set][0])

touch_i2c = busio.I2C(TOUCH_SCL, TOUCH_SDA)
ft = adafruit_focaltouch.Adafruit_FocalTouch(touch_i2c, debug=False)

sys_info_text = sys.implementation[0] + " " + os.uname()[3] +\
                "\nrun on " + os.uname()[4] +\
                "\nusing " + busdisplay.BusDisplay.__name__ +\
                "\n" + adafruit_focaltouch.__name__ + " " + adafruit_focaltouch.__version__
print("=======================================")
print(sys_info_text)
print("=======================================")
print()
# Make the display context
bgGroup = displayio.Group()
display.root_group = bgGroup

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

# place a label on screen center
text_area = label.Label(terminalio.FONT, text="coXXect.blogspot.com", scale=2, color=0xFFFFFF)
text_area_width = text_area.bounding_box[2]*text_area.scale
text_area_height = text_area.bounding_box[3]*text_area.scale
text_area.x = int((display.width - text_area_width)/2)
text_area.y = int((display.height - text_area_height)/2)
bgGroup.append(text_area)

#Place two buttons
BUTTON_WIDTH = display.width//4
BUTTON_HEIGHT = 50
BUTTON_TOP = display.height-100

BUT_FILL_SELECTED = 0x505050
BUT_FILL_UNSELECTED = 0x202020

button_left = Button(
    x=display.width//8,
    y=BUTTON_TOP,
    width=BUTTON_WIDTH,
    height=BUTTON_HEIGHT,
    label="LEFT",
    label_font=terminalio.FONT,
    label_color=0xFFFF00,
    fill_color=BUT_FILL_UNSELECTED,
    outline_color=0x767676,
    selected_fill=0x1A1A1A,
    selected_outline=0x2E2E2E,
    selected_label=0x525252,
    style = Button.SHADOWRECT,
)

button_right = Button(
    x=display.width*7//8-BUTTON_WIDTH,
    y=BUTTON_TOP,
    width=BUTTON_WIDTH,
    height=BUTTON_HEIGHT,
    label="RIGHT",
    label_font=terminalio.FONT,
    label_color=0xFFFF00,
    fill_color=BUT_FILL_UNSELECTED,
    outline_color=0x767676,
    selected_fill=0x1A1A1A,
    selected_outline=0x2E2E2E,
    selected_label=0x525252,
    style = Button.SHADOWRECT,
)

bgGroup.append(button_left)
bgGroup.append(button_right)

last_touched = False
last_touch_pt = [0, 0]
button_pressing = True #False

def getTouchPt(touches):
    if rot_setting[rot_set][3]:
        x = touches[0]['y'] # exchange x/y
        y = touches[0]['x']
    else:
        x = touches[0]['x'] # keep no exchange
        y = touches[0]['y']

    if rot_setting[rot_set][4]:
        x = display.width - x # reverse x
    if rot_setting[rot_set][5]:
        y = display.height - y # reverse y
        
    return x, y
    
mouse = Mouse(usb_hid.devices)

while True:
    led.value = True
    current_touched = ft.touched
    current_touches = ft.touches
    led.value = False
    if current_touched:
        #sometimes ft.touches is [], empty!
        #so I check len to prevent IndexError: index out of range
        if len(current_touches)>0:
            if last_touched:  # touched->touched, moving
                if not button_pressing:
                    x, y = getTouchPt(current_touches)
                    mouse.move(x-last_touch_pt[0], y-last_touch_pt[1])
                    bitmaptools.draw_line(bg_bitmap,
                                          last_touch_pt[0], last_touch_pt[1],
                                          x, y,
                                          1)
                    last_touch_pt = x, y

            else:
                # untouched->touched, touch down
                last_touched = True
                last_touch_pt = getTouchPt(current_touches)
                if button_left.contains(last_touch_pt):
                    mouse.click(Mouse.LEFT_BUTTON)
                    button_left.fill_color = BUT_FILL_SELECTED
                    button_pressing = True
                elif button_right.contains(last_touch_pt):
                    mouse.click(Mouse.RIGHT_BUTTON)
                    button_right.fill_color = BUT_FILL_SELECTED
                    button_pressing = True
                else:
                    bitmaptools.draw_circle(bg_bitmap,
                                        last_touch_pt[0], last_touch_pt[1],
                                        10,
                                        1)
                
    elif not current_touched and last_touched:
        # touch up
        last_touched = False
        bg_bitmap.fill(0)
        button_pressing = False
        button_left.fill_color = BUT_FILL_UNSELECTED
        button_right.fill_color = BUT_FILL_UNSELECTED
    
    time.sleep(0.05)



Comments

Popular posts from this blog

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

Drive 320x240 ILI9341 SPI TFT using ESP32-S3 (NodeMCU ESP-S3-12K-Kit) using TFT_eSPI library, in Arduino Framework.