Use ST7796 SPI LCD on CircuitPython/Raspberry Pi Pico 2, by instancing BusDisplay object using custom init_sequence.

Currently, it's no ST7796 driver for CircuitPython. So I create ST7796 display by instancing object of busdisplay.BusDisplay with custom init_sequence(ST7796_INIT_SEQUENCE). Tested on WaveShare "3.5 inch 320×480 Capacitive Touch LCD", embedded with ST7796S driver chip and FT6336U capacitive touch control chip, with Raspberry Pi Pico 2 running CircuitPython 9.2.4.

For the init_sequence, I reference the MicroPython demo of Working with Raspberry Pi Pico in WaveShare wiki, with a little bit modification. Exactly  ONE bit: (D6 MX/Column Address Order) on MADCTL (36h), to flip left/right. (refer ST7796S Datasheet)

In following exercises, various various function of the ST7796 display module was tested, include:
- Display area, color test. (cpy_pico2_st7796_BusDisplay.py)
- Touch function of FT6336U capacitive touch drive.(cpy_pico2_st7796_BusDisplay_FT6336.py).
- display bmp image (from CIRCUITPY device/SD) using adafruit_imageload. (cpy_pico2_st7796_BusDisplay_sd_imageload.py)
- and the final exercise, cpy_pico2_st7796_BusDisplay_sd_imageload_touch.py, test all three part ST7796 LCD, FT6336U capacitive touch driver and SD Card reader (cpy_pico2_st7796_BusDisplay_sd_imageload_touch.py)


Connection:


		Connection:

			Waveshare 	Raspberry Pi
			320×480		Pico 2
			ST7796 SPI	
			w/ FT6336U
			-------------------------
			VCC 		3.3V
			3V3		No Connection
			GND 		GND
			MISO 		GP0
			MOSI 		GP3
			SCLK 		GP2
			SD_CS		GP4
			LCD_CS 		GP1
			LCD_DC 		GP5
			LCD_RST 	GP6
			LCD_BL 		GP7
			TP_SDA 		GP8
			TP_SCL 		GP9
			TP_INT 		GP10
			TP_RST		GP11
			

Libraries:

To install all lib using circup:
circup install adafruit_display_text adafruit_focaltouch adafruit_cursorcontrol adafruit_imageload
About circup, read "Install and using CircUp (CircuitPython library updater) to install CircuitPython libraries".

Test images:

All test images shown in the video were generated using MicroSoft "Image Creator in Bing", not real. Converted to 240x240 RGB888 bmp using py_cv_batch_resize_RGB888.py in "Resize jpg and convert to bmp in RGB888 and RGB565 mode, using Python/GIMP", save to "images" folder in MicroSD and CIRCUITPY device.

Exercises code:

cpy_pico2_st7796_BusDisplay.py
"""
Raspberry Pi Pico 2/CircuitPython 9
to display on Waveshare 3.5" 320x480 ST7796 SPI IPS
Hello World with color test.

Currently, it's no ST7796 driver for CircuitPython.
So I create ST7796 display by creating an instance of busdisplay.BusDisplay
with custom init_sequence(ST7796_INIT_SEQUENCE).

Libraries need to install:
adafruit_display_text

install with circup:
circup install adafruit_display_text
"""

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

import busdisplay

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

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()

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

display_bus = displayio.FourWire(spi_bus=disp_spi,
                                 command=disp_dc,
                                 chip_select=disp_cs,
                                 reset=disp_res)
"""
display = busdisplay.BusDisplay(display_bus,
                                ST7796_INIT_SEQUENCE,
                                width=DISPLAY_width,
                                height=DISPLAY_height,
                                backlight_pin=disp_blk,
                                rotation=0)
"""
display = busdisplay.BusDisplay(display_bus,
                                ST7796_INIT_SEQUENCE,
                                width=DISPLAY_height,
                                height=DISPLAY_width,
                                backlight_pin=disp_blk,
                                rotation=90)


sys_info_text = sys.implementation[0] + " " + os.uname()[3] +\
                "\nrun on " + os.uname()[4] +\
                "\nusing " + busdisplay.BusDisplay.__name__
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, 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)

color_bitmap = displayio.Bitmap(display.width-2, display.height-2, 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=1, y=1)
bgGroup.append(color_sprite)

color_text_group = displayio.Group(scale=3, x=20, y=120)
color_text_area = label.Label(terminalio.FONT, text="", color=0xFFFFFF)
color_text_group.append(color_text_area)
bgGroup.append(color_text_group)

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

# Color Test
time.sleep(0.5)
for i in colorSet:
    time.sleep(2)
    color_palette[0] = i[0]
    color_text_area.text = i[1]
    color_text_area.color = i[0] ^ 0xFFFFFF

time.sleep(2)
bgGroup.remove(color_text_group)

# scrolling text
# ref:
# https://learn.adafruit.com/rgb-led-matrices-matrix-panels-with-circuitpython/example-simple-two-line-text-scroller
def scroll(line):
    line.x = line.x - 1
    line_width = line.bounding_box[2]
    if line.x < -line_width:
        line.x = display.width
        
def reverse_scroll(line):
    line.x = line.x + 1
    line_width = line.bounding_box[2]
    if line.x >= display.width:
        line.x = -line_width

# Scrolling text

sys_info_group = displayio.Group(scale=3, x=0, y=20)
sys_info_area = label.Label(terminalio.FONT, text=sys_info_text, color=0xFFFFFF)
sys_info_group.append(sys_info_area)
bgGroup.append(sys_info_group)

info1_group = displayio.Group(scale=2, x=0, y=220)
info1_text = "coXXect.blogspot.com"
info1_area = label.Label(terminalio.FONT, text=info1_text, color=0xFFFF00)
info1_group.append(info1_area)
bgGroup.append(info1_group)

#scroll_end = time.monotonic() + 30  # Scroll text for 15 second
#while time.monotonic() < scroll_end:
while True:
    scroll(sys_info_area)
    reverse_scroll(info1_area)
    display.refresh(minimum_frames_per_second=0)


cpy_pico2_st7796_BusDisplay_FT6336.py
"""
Raspberry Pi Pico 2/CircuitPython 9
to display on Waveshare 3.5" 320x480 ST7796 SPI IPS
Touch test, with curcor displayed.

To set rotation, screen width/height, and touch x/y have to be adjusted accordingly.
So I implement rot_setting[] and rot_set to handle them.
To set rotation, set rot_set instead.

Libraries need to install:
adafruit_display_text
adafruit_focaltouch
adafruit_cursorcontrol

install with circup:
circup install adafruit_display_text adafruit_focaltouch adafruit_cursorcontrol
"""

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 adafruit_cursorcontrol.cursorcontrol

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 = 0

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, irq_pin=touch_irq)

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__ +\
                "\n" + adafruit_cursorcontrol.cursorcontrol.__name__ + " " + adafruit_cursorcontrol.cursorcontrol.__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, 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)

color_bitmap = displayio.Bitmap(display.width-2, display.height-2, 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=1, y=1)
bgGroup.append(color_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)

# Draw labels to display touch x/y
x_group = displayio.Group(scale=2, x=10, y=20)
x_text = "---"
x_area = label.Label(terminalio.FONT, text=x_text, color=0xFFFFFF)
x_group.append(x_area)
bgGroup.append(x_group)
y_group = displayio.Group(scale=2, x=10, y=40)
y_text = "---"
y_area = label.Label(terminalio.FONT, text=y_text, color=0xFFFFFF)
y_group.append(y_area)
bgGroup.append(y_group)

# initialize the mouse cursor object
# place over all others

mouse_cursor = adafruit_cursorcontrol.cursorcontrol.Cursor(
    display, display_group=bgGroup)
mouse_cursor.x = int(display.width/2)
mouse_cursor.y = int(display.height/2)

while True:
    # if the screen is being touched print the touches
    if ft.touched:
        touches = ft.touches
        
        #sometimes ft.touches is [], empty!
        #so I check len to prevent IndexError: index out of range
        if len(touches)>0:
            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

            mouse_cursor.x = x
            mouse_cursor.y = y
            x_area.text = str(x)
            y_area.text = str(y)

    else:
        print('no touch')

    time.sleep(.3)


cpy_pico2_st7796_BusDisplay_sd_imageload.py
"""
Raspberry Pi Pico 2/CircuitPython 9
to display on Waveshare 3.5" 320x480 ST7796 SPI IPS
Display bmp images (from sd/device 'images' folder) using adafruit_imageload.
Auto switch images.

Libraries need to install:
adafruit_imageload

install with circup:
circup install adafruit_imageload
"""

import os, sys
import board
import busio
import displayio
import terminalio
import time

import busdisplay
import sdcardio
import storage
import adafruit_imageload

import gc

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

sd_cs = board.GP4

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()

share_spi = busio.SPI(clock=spi_sck, MOSI=spi_mosi, MISO=spi_miso)
"""
Try to increase the speed of spi
Found that it limit to: share_spi.frequency: 37500000
and no significant improvement overall.
"""
share_spi.try_lock()
share_spi.configure(baudrate=40000000)
share_spi.unlock()

print("share_spi.frequency:", share_spi.frequency)

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 = 1

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

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])

# init SD Card
sd = sdcardio.SDCard(spi=share_spi,
                     cs=sd_cs)
vfs = storage.VfsFat(sd)
storage.mount(vfs, '/sd')
#images_folder = '/sd/images/'  # load images from sd card, 'images' folder
images_folder = '/images/'     # load images from CircuitPython device, 'images' folder
files = os.listdir(images_folder)
bmp_files = [file for file in files if file.endswith('.bmp')]
bmp_file_list = sorted(bmp_files)

for f in bmp_file_list:
    print(images_folder + f)

sys_info_text = sys.implementation[0] + " " + os.uname()[3] +\
                "\nrun on " + os.uname()[4] +\
                "\nusing " + busdisplay.BusDisplay.__name__
print("=======================================")
print(sys_info_text)
print("=======================================")
print()

# Create a dummy bitmap
dummy_bitmap = displayio.Bitmap(240, 240, 1)
dummy_palette = displayio.Palette(1)
dummy_palette[0] = 0x000000
bmpTileGrid = displayio.TileGrid(dummy_bitmap, pixel_shader=dummy_palette)
bmpTileGrid.x = (display.width-240)//2
bmpTileGrid.y = (display.height-240)//2

group = displayio.Group()
group.append(bmpTileGrid)
display.root_group = group

# remark: my Python code converting RGB565
#         not work for adafruit_imageload.
def update_images(path_to_bmp):
    gc.collect()
    
    # using adafruit_imageload
    image, palette = adafruit_imageload.load(
        path_to_bmp, bitmap=displayio.Bitmap, palette=displayio.Palette)
    
    bmpTileGrid.bitmap = image
    bmpTileGrid.pixel_shader = palette
    #display.refresh()  # for display.auto_refresh = False

counter = 1
while True:
    print("======== Loop Start " + str(counter) + " ========")
    
    tick_ms_start = time.monotonic()
    for f in bmp_file_list:
        update_images(images_folder+f)
    tick_ms_end = time.monotonic()
    
    print("--- Loop End ---")
    
    print("Time for one loop:",
          tick_ms_end-tick_ms_start,
          "s")
    
    counter = counter+1
    
while True:
    pass


cpy_pico2_st7796_BusDisplay_sd_imageload_touch.py
"""
Raspberry Pi Pico 2/CircuitPython 9
to display on Waveshare 3.5" 320x480 ST7796 SPI IPS
Display bmp images (from sd/device 'images' folder) using adafruit_imageload.
Touch to switch images.
- Touch on left 1/3 to switch to previous image.
- Touch on right 1/3 to switch to next image.

This exercise test all three parts of Waveshare 3.5" 320x480 ST7796 SPI IPS:
screen, touch and sd card reader.

Libraries need to install:
adafruit_display_text
adafruit_imageload
adafruit_focaltouch

install with circup:
circup install adafruit_display_text adafruit_imageload adafruit_focaltouch
"""

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

import busdisplay
import sdcardio
import storage
import adafruit_imageload

from digitalio import DigitalInOut, Direction
import adafruit_focaltouch

import gc

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

sd_cs = board.GP4

#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)

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

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 = 1

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

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, irq_pin=touch_irq)

# init SD Card
sd = sdcardio.SDCard(spi=share_spi,
                     cs=sd_cs)
vfs = storage.VfsFat(sd)
storage.mount(vfs, '/sd')
#images_folder = '/sd/images/'  # load images from sd card, 'images' folder
images_folder = '/images/'     # load images from CircuitPython device, 'images' folder

files = os.listdir(images_folder)
bmp_files = [file for file in files if file.endswith('.bmp')]
bmp_file_list = sorted(bmp_files)

for f in bmp_file_list:
    print(images_folder + f)

sys_info_text = sys.implementation[0] + " " + os.uname()[3] +\
                "\nrun on " + os.uname()[4] +\
                "\nusing " + busdisplay.BusDisplay.__name__
print("=======================================")
print(sys_info_text)
print("=======================================")
print()

group = displayio.Group()

# Create a dummy bitmap
dummy_bitmap = displayio.Bitmap(240, 240, 1)
dummy_palette = displayio.Palette(1)
dummy_palette[0] = 0x000000
bmpTileGrid = displayio.TileGrid(dummy_bitmap, pixel_shader=dummy_palette)
bmpTileGrid.x = (display.width-240)//2
bmpTileGrid.y = (display.height-240)//2
group.append(bmpTileGrid)

# place a label on screen center
text_area = label.Label(terminalio.FONT, text="", color=0xFFFFFF)
text_area.x = 10
text_area.y = 10
group.append(text_area)

display.root_group = group

# remark: my Python code converting RGB565
#         not work for adafruit_imageload.
def update_images(path_to_bmp):
    gc.collect()
    
    # using adafruit_imageload
    image, palette = adafruit_imageload.load(
        path_to_bmp, bitmap=displayio.Bitmap, palette=displayio.Palette)
    
    bmpTileGrid.bitmap = image
    bmpTileGrid.pixel_shader = palette
    #display.refresh()  # for display.auto_refresh = False

image_index = 0

def wait_touch():
    left_max = display.width//3
    right_min = (display.width*2)//3
    while True:
        # if the screen is being touched print the touches
        if ft.touched:
            touches = ft.touches
            #sometimes ft.touches is [], empty!
            #so I check len to prevent IndexError: index out of range
            if len(touches)>0:
                if rot_setting[rot_set][3]:
                    x = touches[0]['y']
                    y = touches[0]['x']
                else:
                    x = touches[0]['x']
                    y = touches[0]['y']
                
                if rot_setting[rot_set][4]:
                    x = display.width - x

                if rot_setting[rot_set][5]:
                    y = display.height - y

                if x < left_max:
                    return -1
                elif x > right_min:
                    return 1

        else:
            print('no touch')

        time.sleep(.3)

while True:
    image_full_path = images_folder+bmp_file_list[image_index]
    text_area.text = image_full_path
    text_area.scale=1
    update_images(image_full_path)
    text_area.scale=2

    image_index = image_index+wait_touch()
    if image_index==len(bmp_file_list):
        image_index=0
    if image_index==-1:
        image_index=len(bmp_file_list)-1



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