Need to run two Pico Display Packs

Currently I have one 1.54" SPI Color Square LCD (240x240) Breakout: and a Pico Display Pack 2.0: running on a Pico. Large solderless bread board setup. I was running two of the 1.54 color LCD’s but need more room for text etc. It looks like the Display Pack doesn’t support the cs=(17), bl=(20) option? Likely because its intended to plug directly into the Pico, or be on an omnibus etc.
Wondering if there is a way to do it? A code option I’m not aware of?

To get around the 256 Kbyte memory limit I
write to the buffer
update display 1
clear the buffer, but don’t update the display
write to the buffer for display 2
update display 2
clear the buffer, but don’t update the display
wash rinse and repeat.

import picodisplay2 as display2
from breakout_colourlcd240x240 import BreakoutColourLCD240x240

display_buffer = bytearray(320 * 240 * 2)  # 2-bytes per pixel (RGB565)
display1 = BreakoutColourLCD240x240(display_buffer, cs=(22), bl=(21))
#display2 = BreakoutColourLCD240x240(display_buffer, cs=(17), bl=(20))
display2.init(display_buffer)

Tried to cheat and use,

display_buffer = bytearray(320 * 240 * 2)  # 2-bytes per pixel (RGB565)
display1 = BreakoutColourLCD240x240(display_buffer, cs=(22), bl=(21))
display2 = BreakoutColourLCD240x240(display_buffer, cs=(17), bl=(20))

It works but its rotated 270 degrees. Which just won’t work for me. Likely because the ribbon cable is on the bottom on the 240 x 240, but on the right on the 320 x 240. Almost worked?

@hel @gadgetoid

Actually the rotation isn’t a big deal, might actually be better in portrait mode. More testing has shown its only using 240x240, the bottom 1/4 of the screen is unusable.
Phil Howard has done up a unifying driver that works on the Display Pack, supports landscape or portrait mode, and supports alternate pin selection. In theory I can setup two displays each on a different chip select and different backlight pin. I can’t get it to run two displays at once though.
Pico Display Pack V2 x 2? · Issue #299 · pimoroni/pimoroni-pico (github.com)
Unified display drivers · Issue #309 · pimoroni/pimoroni-pico (github.com)

This works using the current official driver.

import time

from breakout_colourlcd240x240 import BreakoutColourLCD240x240

display_buffer = bytearray(240 * 240 * 2)  # 2-bytes per pixel (RGB565)
display1 = BreakoutColourLCD240x240(display_buffer, cs=(17), bl=(20))
display2 = BreakoutColourLCD240x240(display_buffer, cs=(22), bl=(21))



display1.set_backlight(1.0)
display2.set_backlight(1.0)

print(display1)
print(display2)

while True:
    display1.set_pen(0, 0, 255)
    display1.clear()
    display1.update()
    display1.set_pen(0, 0, 0)  # Set pen to black
    display1.text("display 1", 10, 10, 240, 5)  
    display1.update()
    display1.clear()
    
    display2.set_pen(0, 255, 0)
    display2.clear()
    display2.update()
    display2.set_pen(0, 0, 0)  # Set pen to black
    display2.text("display 2", 10, 10, 240, 5)  
    display2.update()
    display2.clear()
    
    time.sleep(2)
    
    display1.set_pen(0, 255, 0)
    display1.clear()
    display1.update()
    display1.set_pen(0, 0, 0)  # Set pen to black
    display1.text("display 1 slot 0", 10, 10, 240, 5)  
    display1.update()
    display1.clear()
    
    display2.set_pen(0, 255, 255)
    display2.clear()
    display2.update()
    display2.set_pen(0, 0, 0)  # Set pen to black
    display2.text("display 2 slot 1", 10, 10, 240, 5)  
    display2.update()
    display2.clear()
    
    time.sleep(2)
    
    display1.set_pen(0, 255, 255)
    display1.clear()
    display1.update()
    display1.set_pen(0, 0, 0)  # Set pen to black
    display1.text("display 1 slot 0 front", 10, 10, 240, 5)  
    display1.update()
    display1.clear()
    
    display2.set_pen(255, 0, 0)
    display2.clear()
    display2.update()
    display2.set_pen(0, 0, 0)  # Set pen to black
    display2.text("display 2 slot 1 back", 10, 10, 240, 5)  
    display2.update()
    display2.clear()
    
    time.sleep(2)
    
    display1.set_pen(255, 0, 0)
    display1.clear()
    display1.update()
    display1.set_pen(0, 0, 0)  # Set pen to black
    display1.text("display 1 slot 0 front cs=(17)", 10, 10, 240, 5) 
    display1.update()
    display1.clear()
    
    display2.set_pen(255, 0, 255)
    display2.clear()
    display2.update()
    display2.set_pen(0, 0, 0)  # Set pen to black
    display2.text("display 2 slot 1 back cs=(22)", 10, 10, 240, 5) 
    display2.update()
    display2.clear()
    
    time.sleep(2)
    
    display1.set_pen(255, 0, 255)
    display1.clear()
    display1.update()
    display1.set_pen(0, 0, 0)  # Set pen to black
    display1.text("display 1 slot 0 front cs=(17) bl=(20)", 10, 10, 240, 5) 
    display1.update()
    display1.clear()
    
    display2.set_pen(255, 255, 0)
    display2.clear()
    display2.update()
    display2.set_pen(0, 0, 0)  # Set pen to black
    display2.text("display 2 slot 1 back cs=(22) bl=(21)", 10, 10, 240, 5)
    display2.update()
    display2.clear()
    
    time.sleep(2)
    
    display1.set_pen(255, 255, 0)
    display1.clear()
    display1.update()
    display1.set_pen(0, 0, 0)  # Set pen to black
    display1.text("display 1 slot 0 front cs=(17) bl=(20) 240x240", 10, 10, 240, 5)  
    display1.update()
    display1.clear()
    
    display2.set_pen(0, 0, 255)
    display2.clear()
    display2.update()
    display2.set_pen(0, 0, 0)  # Set pen to black
    display2.text("display 2 slot 1 back cs=(22) bl=(21) 240x240", 10, 10, 240, 5) 
    display2.update()
    display2.clear()
    
    time.sleep(2)

If I substitute in the following:

import st7789

frame_buffer = bytearray(240 * 240 * 2)  # 2-bytes per pixel (RGB565)
display1 = st7789.ST7789(width=240, height=240, *frame_buffer, slot=0) #front
display2 = st7789.ST7789(width=240, height=240, *frame_buffer, slot=1) #back

I get a memory allocation error

import st7789
and
display1 = st7789.ST7789(width=240, height=240, slot=0) #front
or
display2 = st7789.ST7789(width=240, height=240, slot=1) #back
will run one or the other displays.
all three lines get me the same memory allocation error. 264 kb isn’t enough room for two display buffers.

OK, this was passed on to me by Phil Howard @gadgetoid and works with the new, in the works, Unifying ST7789 driver

frame_buffer = bytearray(240 * 240 * 2)  # 2-bytes per pixel (RGB565)
display1 = st7789.ST7789(width=240, height=240, buffer=frame_buffer, slot=0) 
display2 = st7789.ST7789(width=240, height=240, buffer=frame_buffer, slot=1) 

It works on my test setup with two 240x240 LCD breakouts when substituted into the above posted file.

Having issues tryin g to get it to work on my 320x240 Display Pack V2 though? Landscape mode works but Portrait doesn’t, text is all garbled? All is fine on the smaller 240x135 Display Pack though?

 # This example borrows a CircuitPython hsv_to_rgb function to cycle through some rainbows on Pico Display's screen and RGB LED . If you're into rainbows, HSV (Hue, Saturation, Value) is very useful!

import st7789
import utime

#display = st7789.ST7789(width=240, height=135, slot=0) # Display Pack landscape works
#display = st7789.ST7789(width=135, height=240, slot=0) # Display Pack portrait works

#display = st7789.ST7789(width=320, height=240, slot=0) # Display Pack V2 landscape works
display = st7789.ST7789(width=240, height=320, slot=0) # Display Pack V2 portrait didn't work

print(display)

display.set_backlight(1.0)

# From CPython Lib/colorsys.py
def hsv_to_rgb(h, s, v):
    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
    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


h = 0

while True:
    h += 1
    r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)]  # rainbow magic
    #display.set_led(r, g, b)  # Set LED to a converted HSV value
    display.set_pen(r, g, b)  # Set pen to a converted HSV value
    display.clear()           # Fill the screen with the colour
    display.set_pen(0, 0, 0)  # Set pen to black
    #display.text("pico disco!", 10, 10, 240, 6)  # landscape
    display.text("pico disco!", 10, 10, 135, 4)  # potrait 
    display.update()          # Update the display
    utime.sleep(1.0 / 60)