Content-Length: 719421 | pFad | https://github.com/adafruit/circuitpython/issues/1760

0B displayio: Impossible to have more than one display on the same bus · Issue #1760 · adafruit/circuitpython · GitHub
Skip to content

displayio: Impossible to have more than one display on the same bus #1760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
deshipu opened this issue Apr 6, 2019 · 87 comments
Open

displayio: Impossible to have more than one display on the same bus #1760

deshipu opened this issue Apr 6, 2019 · 87 comments

Comments

@deshipu
Copy link

deshipu commented Apr 6, 2019

In theory, I could have several SPI displays connected to the same bus, and displayio has provisions for that — locking of the SPI bus, toggling of the CS pin, even re-setting of the SPI frequency, polarity and phase. However, it's not possible to create two (or more) FourWire objects sharing the same DC and/or reset pins, but with different CS pins — because we will get a "Pin in use" error when the FourWire object tries to create them.

@tannewt
Copy link
Member

tannewt commented Apr 7, 2019

So we need a separate FourWireDevice then. (To match I2CDevice for example.)

@deshipu
Copy link
Author

deshipu commented Apr 7, 2019

I think it would be sufficient to be able to pass a DigitalInOut object as the pins during the initialization, at which point it wouldn't try to create new ones.

@tannewt
Copy link
Member

tannewt commented Apr 16, 2019

This would be super cool but I think it's pretty niche.

@3ach
Copy link

3ach commented Sep 25, 2019

I would like this feature as well. I have not-very-much experience in this type of development, but am happy to open a pull request if I can get a little guidance on where to start.

@3ach
Copy link

3ach commented Sep 25, 2019

I am currently doing the following to drive three displays, but would like to add a fourth. I get a 'too many busses' error if I just allocate four more pins.

displayio.release_displays()
for d in range(3):
    cs_pin = 13 - (d * 3)
    rs_pin = 13 - (d * 3) - 1
    dc_pin = 13 - (d * 3) - 2
    
    spi = board.SPI()
    tft_cs = getattr(board, "D" + str(cs_pin))
    tft_rs = getattr(board, "D" + str(rs_pin))
    tft_dc = getattr(board, "D" + str(dc_pin))

    display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_rs)
    display = ST7735R(display_bus, width=128, height=128, colstart=2, rowstart=1)

@siddacious
Copy link

@tannewt should displays on different busses work? I had an issue a few weeks ago with one SPI and one I2C display. I don't recall the exact error but I can create an issue for it

@tannewt
Copy link
Member

tannewt commented Sep 26, 2019

@3ach What version are you using? I'm actually very surprised three worked. I think I've knocked it down to 1 in 5.x. All display objects and their busses are statically allocated so they can live outside the vm. The limit is controlled by CIRCUITPY_DISPLAY_LIMIT.

I'm unsure if that's how I want it to keep working because the terminal can only show on one screen at a time now. If we stick with that, then we could statically allocate the first display and bus and dynamically allocate the rest. On the other hand, on the monster mask for example, it might be nice to actually split the terminal across the two displays. To do that, we need to allow two displays to show the same Group and statically allocate them both.

@3ach
Copy link

3ach commented Oct 1, 2019 via email

@pbricmont
Copy link

Would it be possible to make the display limit a user definable value? Defaults to 1 but can be set higher for more capable hardware, use at your own risk. I've got 3 running on a Grand Central with 4.1.

@tannewt
Copy link
Member

tannewt commented Dec 18, 2019

@pbricmont Can you get multiple running on 5.x? There was a number of changes made to displayio in 5.x for OLED and ePaper support.

@pbricmont
Copy link

@tannewt I can only create 1 display bus with 5 b1. I'm going to revert to the Arduino code I've been running. I can run 6 128x128 7735Rs on the Metro M4 Express with that code. Still holding out hope for CircuitPython as I really like displayio.

@tannewt
Copy link
Member

tannewt commented Dec 19, 2019

@pbricmont you can try changing CIRCUITPY_DISPLAY_LIMIT as I mention in #1760 (comment) and then rebuilding 5.x. If it works we can bump it back up for 5.0.0.

@pbricmont
Copy link

@tannewt I got 5 displays working. 2 on board.SPI, 2 on SERCOM 6 and 1 on SERCOM 2. Not sure why it won't do more than 5, plenty of RAM available. 5 x 128x128 7735Rs uses about 3K. Adding a 6th display bus results in a hard crash.

@tannewt
Copy link
Member

tannewt commented Jan 2, 2020

@pbricmont that is impressive! Any chance you have a debugger that can snag a backtrace from the hard crash?

@Marius-450
Copy link

hello.
I managed to build CP with CIRCUITPY_DISPLAY_LIMIT = 2 for the monster m4sk, and made the 2 displays working nicely. It would be a great idea to allow, at least for this board, multiple displays...

@pbricmont
Copy link

@tannewt Unfortunately, I don't have a debugger.

@tannewt
Copy link
Member

tannewt commented Jan 3, 2020

@Marius-450 please make a PR to bump it to 2. I don't think we want more than that due to the RAM it takes but 2 makes sense for the m4sk.

@pbricmont Bummer. How many would you like to support in the end? What are you using them for?

@pbricmont
Copy link

pbricmont commented Jan 4, 2020

@tannewt I would need to get six working. Would like to port this project to CP: https://www.hackster.io/paul-bricmont/nearly-nimo-clock-9309ec

@kevinjwalters
Copy link

@pbricmont Your url text and link differ for https://www.hackster.io/paul-bricmont/nearly-nimo-clock-9309ec

I didn't know about NIMOs. At a glance, I would have assumed your project emulated a vacuum fluorescent display but that's probably based mostly on the colour.

@Marius-450
Copy link

@tannewt : Is there a way to use ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk, or I change the value directly in py/circuitpy_mpconfig.h ?

@dhalbert
Copy link
Collaborator

dhalbert commented Jan 4, 2020

(Not tested): What you could do is change these lines in circuitpy_mpconfig.h:

#if CIRCUITPY_DISPLAYIO
extern const struct _mp_obj_module_t displayio_module;
extern const struct _mp_obj_module_t fontio_module;
extern const struct _mp_obj_module_t terminalio_module;
#define DISPLAYIO_MODULE       { MP_OBJ_NEW_QSTR(MP_QSTR_displayio), (mp_obj_t)&displayio_module },
#define FONTIO_MODULE       { MP_OBJ_NEW_QSTR(MP_QSTR_fontio), (mp_obj_t)&fontio_module },
#define TERMINALIO_MODULE      { MP_OBJ_NEW_QSTR(MP_QSTR_terminalio), (mp_obj_t)&terminalio_module },
#define CIRCUITPY_DISPLAY_LIMIT (1)
#else
#define DISPLAYIO_MODULE
#define FONTIO_MODULE
#define TERMINALIO_MODULE
#define CIRCUITPY_DISPLAY_LIMIT (0)
#endif

to this (see // ***NEW lines), to allow overriding the default value:

#if CIRCUITPY_DISPLAYIO
extern const struct _mp_obj_module_t displayio_module;
extern const struct _mp_obj_module_t fontio_module;
extern const struct _mp_obj_module_t terminalio_module;
#define DISPLAYIO_MODULE       { MP_OBJ_NEW_QSTR(MP_QSTR_displayio), (mp_obj_t)&displayio_module },
#define FONTIO_MODULE       { MP_OBJ_NEW_QSTR(MP_QSTR_fontio), (mp_obj_t)&fontio_module },
#define TERMINALIO_MODULE      { MP_OBJ_NEW_QSTR(MP_QSTR_terminalio), (mp_obj_t)&terminalio_module },
#ifndef CIRCUITPY_DISPLAY_LIMIT       // ***NEW
#define CIRCUITPY_DISPLAY_LIMIT (1)
#endif     // ***NEW
#else
#define DISPLAYIO_MODULE
#define FONTIO_MODULE
#define TERMINALIO_MODULE
#define CIRCUITPY_DISPLAY_LIMIT (0)
#endif

and then in `mpconfigboard.h, do:

#define CIRCUITPY_DISPLAY_LIMIT (6)

or whatever you want.

@Marius-450
Copy link

perfect. I will do that very soon

@Marius-450
Copy link

my first PR ... sorry if something is wrong...

@tannewt
Copy link
Member

tannewt commented Jan 7, 2020

@pbricmont Thanks for the link! Are the displays all on the same bus or are they different? Would you be interested in debugging if we got you a JLinkEDU?

@pbricmont
Copy link

@tannewt

@pbricmont Thanks for the link! Are the displays all on the same bus or are they different?
In the Arduino version, all six displays are on the same SPI bus. The CP SPI buses seem much faster (24mHz?) but multiple buses are required due to the 2 per bus limit. Also, I had to make all the wiring as short as possible to get it to work at all.
Would you be interested in debugging if we got you a JLinkEDU?
Yes, I would be happy to investigate further. I have reviewed the CP debugging guide. I just did a build of 5.0b3 for the Grand Central and got the same "Crash into the HardFault_Handler" when adding the 6th display bus.

@tannewt
Copy link
Member

tannewt commented Jan 10, 2020

@pbricmont Please email me scott@adafruit.com and we'll get you setup.

@tannewt
Copy link
Member

tannewt commented Jun 7, 2021

@tannewt Couldn't you just have the concept of a primary display that has that additional functionality of persisting and extra ones being instatiated as non-primary ones with a different life cycle?

You could but it's not implemented that way. Having things behave differently is tricky.

@kevinjwalters
Copy link

kevinjwalters commented Aug 8, 2021

I only discovered the twin display Adafruit Monster Mask today. It was mentioned previously in the comments but it's also in the very recent A CircuitPython Board Tour with Ladyada #CircuitPythonDay2021 (YouTube).

@dgoadby
Copy link

dgoadby commented May 10, 2022

I want to drive two 1.28 inch displays on a RPi Pico. The controllers are GCA901 so I need to run two SPI devices with, presumably, device selection using Chip Select. How do I configure disaplyio to work with two displays on a common bus? I see a reference to the configuration definition CIRCUITPY_DISPLAY_LIMIT - what is the current default value?

@FoamyGuy
Copy link
Collaborator

I want to drive two 1.28 inch displays on a RPi Pico. The controllers are GCA901 so I need to run two SPI devices with, presumably, device selection using Chip Select. How do I configure disaplyio to work with two displays on a common bus? I see a reference to the configuration definition CIRCUITPY_DISPLAY_LIMIT - what is the current default value?

I believe the default setting on almost all devices is 1. I think the only device with limit of 2 is the Monster M4sk https://github.com/adafruit/circuitpython/blob/main/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h

@dastels
Copy link

dastels commented May 10, 2022

I believe the default setting on almost all devices is 1. I think the only device with limit of 2 is the Monster M4sk https://github.com/adafruit/circuitpython/blob/main/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h

That was my finding as well.

@knox1138
Copy link

knox1138 commented May 10, 2022 via email

@dgoadby
Copy link

dgoadby commented May 12, 2022

Thanks for the information. I have chosen to use an extra XIAO RP2040 board to drive the second display and use I2C to take the data from the main processor. The RP2040 is a lot cheaper than many hours of my time trying to get dual display to work.
Again, thanks for your help.

@rgrizzell
Copy link

I've been experimenting with multi-display support on the LILYGO T-Keyboard-S3, and was able to initialize and render a displayio.Group on each screen. I can also confirm that it is very unstable! CircuitPython will crash on reloads, so any file changes will require a manual reset of the device. 🙃

However, with as niche as this feature would be, I wanted to contribute in the hopes that we can push this forward.

LILYGO T-Keyboard-S3 with 4 individually rendered displays

For the T-Keyboard-S3, the DC, RST pins are shared, and each display is controlled through individual CS pins. To get this working the FourWire library needs to be "patched" to share pins. This was relatively simple to do, just don't bother to check if the pin is in-use!

--- a/shared-bindings/fourwire/FourWire.c
+++ b/shared-bindings/fourwire/FourWire.c
@@ -88,9 +88,9 @@ STATIC mp_obj_t fourwire_fourwire_make_new(const mp_obj_type_t *type, size_t n_a
     mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
     mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
 
-    const mcu_pin_obj_t *command = validate_obj_is_free_pin_or_none(args[ARG_command].u_obj, MP_QSTR_command);
+    const mcu_pin_obj_t *command = validate_obj_is_pin_or_none(args[ARG_command].u_obj, MP_QSTR_command);
     const mcu_pin_obj_t *chip_select = validate_obj_is_free_pin_or_none(args[ARG_chip_select].u_obj, MP_QSTR_chip_select);
-    const mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj, MP_QSTR_reset);
+    const mcu_pin_obj_t *reset = validate_obj_is_pin_or_none(args[ARG_reset].u_obj, MP_QSTR_reset);
 
     mp_obj_t spi = mp_arg_validate_type(args[ARG_spi_bus].u_obj, &busio_spi_type, MP_QSTR_spi_bus);

#define CIRCUITPY_DISPLAY_LIMIT (4) was also added to the board configuration.

As for testing, I used the latest version of CircuitPython at the time: 9.1.0-beta1. For the displays, I used adafruit_st7789 from the Community Bundle. The T-Keyboard-S3 has the GC9107 chip for its 128x128 screens, but the ST7789 initialization sequence works just fine.

I also tried to configure CircuitPython to start all 4 displays at boot, but that didn't pan out. It sort of worked, but one the next display was initialized the previous one was de-initialized. However, the following script does work as I exepcted so, I'm willing to bet I'm missing a crucial detail or two.

import board
import busio
import displayio
import time
import adafruit_st7789
from adafruit_display_shapes.rect import Rect
from adafruit_display_shapes.circle import Circle

_WIDTH = 128
_HEIGHT = 128

tft_sck = board.IO47
tft_mosi = board.IO48
tft_blk = board.IO39
tft_dc = board.IO45
tft_rst = board.IO38
tft_cs1 = board.IO12
tft_cs2 = board.IO13
tft_cs3 = board.IO14
tft_cs4 = board.IO21

displayio.release_displays()
tft_spi = busio.SPI(tft_sck, tft_mosi)
tft_bus_1 = displayio.FourWire(spi_bus=tft_spi, command=tft_dc, reset=tft_rst, chip_select=tft_cs1)
tft_bus_2 = displayio.FourWire(spi_bus=tft_spi, command=tft_dc, reset=tft_rst, chip_select=tft_cs2)
tft_bus_3 = displayio.FourWire(spi_bus=tft_spi, command=tft_dc, reset=tft_rst, chip_select=tft_cs3)
tft_bus_4 = displayio.FourWire(spi_bus=tft_spi, command=tft_dc, reset=tft_rst, chip_select=tft_cs4)
display_1 = adafruit_st7789.ST7789(bus=tft_bus_1, backlight_pin=tft_blk, rotation=0, width=_WIDTH, height=_HEIGHT)
display_2 = adafruit_st7789.ST7789(bus=tft_bus_2, backlight_pin=None, rotation=0, width=_WIDTH, height=_HEIGHT)
display_3 = adafruit_st7789.ST7789(bus=tft_bus_3, backlight_pin=None, rotation=0, width=_WIDTH, height=_HEIGHT)
display_4 = adafruit_st7789.ST7789(bus=tft_bus_4, backlight_pin=None, rotation=0, width=_WIDTH, height=_HEIGHT)

red_group = displayio.Group()
red_group.append(Rect(x=0, y=0, width=128, height=128, fill=0xFFFFFF))
red_group.append(Circle(x0=64, y0=64, r=32, fill=0xFF0000))
display_1.root_group = red_group

blue_group = displayio.Group()
blue_group.append(Rect(x=0, y=0, width=128, height=128, fill=0xFFFFFF))
blue_group.append(Circle(x0=64, y0=64, r=32, fill=0x0000FF))
display_2.root_group = blue_group

green_group = displayio.Group()
green_group.append(Rect(x=0, y=0, width=128, height=128, fill=0xFFFFFF))
green_group.append(Circle(x0=64, y0=64, r=32, fill=0x00FF00))
display_3.root_group = green_group

black_group = displayio.Group()
black_group.append(Rect(x=0, y=0, width=128, height=128, fill=0xFFFFFF))
black_group.append(Circle(x0=64, y0=64, r=32, fill=0x000000))
display_4.root_group = black_group

while True:
    time.sleep(1)

@MariuszCwikla
Copy link

MariuszCwikla commented Mar 14, 2025

Just like many others I I wanted to connect more than 1 display. I will try recompiling CircuitPython tomorrow.

I also understand that it's a tradeoff and objects live outside of VM, etc.

It still would be easier if we could do it without recompiling.
Thus, I am thinking: would it be possible if we could specify max number of displays in boot.py instead of hardcoding CIRCUITPY_DISPLAY_LIMIT?

@RetiredWizard
Copy link

RetiredWizard commented Mar 18, 2025

I took a quick look at trying to use a settings.toml parameter to define the display limit. Unfortunately the display/bus structures are allocated (dimensioned) at compile time (as earlier messages had explained 😁) so in order to set the display limit without recompiling, the memory for the structures would have to be changed to a dynamically allocated model (also mentioned above, I really should have read the whole thread) which probably makes it over my head....

@MariuszCwikla
Copy link

Yes, I know, it's at compile time... now.
I am suggesting to make it configurable, make new new API, e.g. displayio.set_max_displays(4) that could be called only in boot.py. CircuitPython could then allocate memory of dynamic size instead of hardcoded size.

@tannewt
Copy link
Member

tannewt commented Mar 19, 2025

which probably makes it over my head....

Give it a try! I bet you can do it. We now have port_malloc which allows you to dynamically allocate outside of the VM.

I am suggesting to make it configurable

I think settings.toml is a better way to make it configurable. That way it can be read really early.

@Neradoc
Copy link

Neradoc commented Mar 19, 2025

If it's allocated dynamically, do we even need a display limit in settings or anywhere ?
Won't it just be limited by available memory ?
Maybe a hard one of 8, just in case ?

@tannewt
Copy link
Member

tannewt commented Mar 19, 2025

Allocating each display individually will be trickier. It is something I'd like to do in CP11. For now, resizing the "static" array will be simpler and probably work.

@RetiredWizard
Copy link

RetiredWizard commented Mar 20, 2025

I'm struggling with C pointers/malloc usage. I've declared the following extern variables:

primary_display_bus_t display_busesx[CIRCUITPY_DISPLAY_LIMIT];
primary_display_t displaysx[CIRCUITPY_DISPLAY_LIMIT];
primary_display_bus_t *display_buses = &display_busesx[0];
primary_display_t *displays = &displaysx[0];

and then I attempt to allocate new memory and point my variables as follows:

display_buses = (primary_display_bus_t*)port_malloc(sizeof(primary_display_bus_t) * CIRCUITPY_DISPLAY_LIMIT, false);
displays = (primary_display_t*)port_malloc(sizeof(primary_display_t) * CIRCUITPY_DISPLAY_LIMIT, false);
memcpy(display_buses, &display_busesx[0], sizeof(primary_display_bus_t) * CIRCUITPY_DISPLAY_LIMIT);
memcpy(displays, &displaysx[0], sizeof(primary_display_t) * CIRCUITPY_DISPLAY_LIMIT);

However the memcpy is clearly running wild and trashing Circuitpython memory. If I include the two memcpy lines the display doesn't show up and the circuitpython repl doesn't recognize any python instructions.

EDIT: I think I've gotten past this stumbling block 😁 onward!!!

@RetiredWizard
Copy link

PR #10158 seems to work on the configuration I've been testing. I plan to test more configurations but after several long nights I needed to step back for a couple days. If anyone is anxious to help out and test the artifacts, that would be great 😁

@todbot
Copy link

todbot commented Mar 27, 2025

[...] If anyone is anxious to help out and test the artifacts, that would be great 😁

This is very cool! I will try some tests on RP2040/RP2350 this afternoon. Thanks!

@RetiredWizard
Copy link

RetiredWizard commented Mar 27, 2025

Beware, I just hooked up an I2C display and it's having issues 😦

Edit: It turns out the issues maybe hardware related and not the PRs fault....

@RetiredWizard
Copy link

I was able to get a Feather RP2350 displaying on a DVI display, an I2C display and an SPI display using CIRCUITPY_DISPLAY_LIMIT=3 in settings.toml.

Tomorrow I'll try setting up multiple displays on an Espressif micro controller .

During my testing I've noticed pressing ctrl-D without performing a displayio.release_displays() seems to cause a Safemode Crash which I need to track down (possibly related to #10084)

@rgrizzell
Copy link

Tomorrow I'll try setting up multiple displays on an Espressif micro controller .

I've been keeping an eye on this thread and your PR for the past few weeks. Thanks so much for your efforts! I've dug out the old T-Keyboard-S3, so if you're looking for some more Espressif testing, let me know.

@todbot
Copy link

todbot commented Mar 28, 2025

I had some time to try this today. My results:

  • CIRCUITPY_DISPLAY_LIMIT=2 works great
  • CIRCUITPY_DISPLAY_LIMIT=3 works but Ctrl-C-ing and restarting a program results in a ValueError: GP17 in use, as if I wasn't calling displayio.release_displays() (Perhaps it's only releasing N-1 displays?)
  • CIRCUITPY_DISPLAY_LIMIT=4 works but the system seems very slow now. Display updates are slow, REPL is slow, USB negotiation is slow
  • With 3 or more displays, CircuitPython would occasionally crash with Hard fault: memory access or instruction error.
  • CIRCUITPY_DISPLAY_LIMIT changes in settings.toml must be accompanied by a board reset

My test setup is an RP2040 Pico clone with multiple SSD1306 monochrome I2C OLEDs. (minimizes wiring and memory footprint). The setup looks like this:

Image

And my code looked like this:

import time
import board, busio, displayio, i2cdisplaybus, terminalio
import adafruit_displayio_ssd1306
from adafruit_display_text import label

displayio.release_displays()

i2c0 = busio.I2C(sda=board.GP16, scl=board.GP17) 
i2c1 = busio.I2C(sda=board.GP14, scl=board.GP15) 

dw, dh = 128, 64
displays = [
    adafruit_displayio_ssd1306.SSD1306(
        i2cdisplaybus.I2CDisplayBus(i2c1, device_address=0x3c), width=dw, height=dh),
    adafruit_displayio_ssd1306.SSD1306(
        i2cdisplaybus.I2CDisplayBus(i2c1, device_address=0x3d), width=dw, height=dh),
    adafruit_displayio_ssd1306.SSD1306(
        i2cdisplaybus.I2CDisplayBus(i2c0, device_address=0x3c), width=dw, height=dh),
    adafruit_displayio_ssd1306.SSD1306(
        i2cdisplaybus.I2CDisplayBus(i2c0, device_address=0x3d), width=dw, height=dh),
]

text_areas=[]
for d in displays:
    d.root_group = displayio.Group()
    text_area = label.Label(terminalio.FONT, text="HI", color=0xFFFFFF, x=10, y=dh//2, scale=2)
    d.root_group.append(text_area)
    text_areas.append(text_area)
    
while True:
    print("hi")
    for i,ta in enumerate(text_areas):
        ta.text = "hi %d %2.1f" % (i,time.monotonic())
    time.sleep(0.1)

@RetiredWizard
Copy link

RetiredWizard commented Mar 28, 2025

I've been keeping an eye on this thread and your PR for the past few weeks. Thanks so much for your efforts! I've dug out the old T-Keyboard-S3, so if you're looking for some more Espressif testing, let me know.

I was thinking that I would follow this PR up with a settings.toml parameter that allowed the sharing of DC/RST pins, something like CIRCUITPY_FOURWIRE_SHAREPINS. But since that's not available yet, If it would help your testing, I could post a UF2 with your mods from above to allow the sharing.

Edit: Oh wait, the T-Keyboard-S3 doesn't have an official CP build yet.... 😦

@rgrizzell
Copy link

rgrizzell commented Mar 28, 2025

I was thinking that I would follow this PR up with a settings.toml parameter that allowed the sharing of DC/RST pins, something like CIRCUITPY_FOURWIRE_SHAREPINS.

This is another one I need to follow-up on. I vaguely recall that there were some FourWire changes since I last tested.

Edit: Oh wait, the T-Keyboard-S3 doesn't have an official CP build yet....

That was something I was working on initially, but chose not to merge in the board definitions until we could get the all of the displays working. The branch is still hanging around and it builds just fine, but I just need to rebase and open the PR.

A generic ESP32-S3 build works in a pinch, but I didn't want to get anyone's hopes that this thing was fully supported yet.

@RetiredWizard
Copy link

I had to use the hack from @rgrizzell to allow sharing of the DC pins but here is 6 displays off an ESP32-S3 Feather 😁

Image

@RetiredWizard
Copy link

  • CIRCUITPY_DISPLAY_LIMIT=3 works but Ctrl-C-ing and restarting a program results in a ValueError: GP17 in use, as if I wasn't calling displayio.release_displays() (Perhaps it's only releasing N-1 displays?)

I haven't seen this in my testing, I'll try and reproduce your setup and see if I can make it happen.

*Hopefully the hard faults you were seeing are fixed, I haven't seen any since my last commit.....

@RetiredWizard
Copy link

RetiredWizard commented Mar 29, 2025

  • CIRCUITPY_DISPLAY_LIMIT=3 works but Ctrl-C-ing and restarting a program results in a ValueError: GP17 in use, as if I wasn't calling displayio.release_displays() (Perhaps it's only releasing N-1 displays?)

I haven't been able to reproduce this with three displays (all the I2C I have 😁). I'm assuming you have the program in code.py and you are just pressing ctrl-D to restart after Ctrl-C-ing?

I actually was able to get the GP17 in use if I ran the code from a shell (PyDOS) and then restarted it, but that made sense since the I2C busses are never deinit'd in that case. Just to be sure, I put last while loop inside a try/except and deinit both I2C busses in the except block and then I could re-run the test without issue.

@todbot
Copy link

todbot commented Mar 29, 2025

  • CIRCUITPY_DISPLAY_LIMIT=3 works but Ctrl-C-ing and restarting a program results in a ValueError: GP17 in use, as if I wasn't calling displayio.release_displays() (Perhaps it's only releasing N-1 displays?)

I haven't been able to reproduce this with three displays (all the I2C I have 😁). I'm assuming you have the program in code.py and you are just pressing ctrl-D to restart after Ctrl-C-ing?

Yes, I had it as code.py and was just Ctrl-C-ing then Ctrl-D-ing.

But I just tried the CI artifact from g4b151d68ef and I can do four displays now, it hasn't hard faulted on me, and I don't get the "in use" error! Very cool!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests









ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: https://github.com/adafruit/circuitpython/issues/1760

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy