Skip to content
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

Auto-configure display on some RP2350 boards #10028

Closed
wants to merge 20 commits into from

Conversation

jepler
Copy link

@jepler jepler commented Feb 4, 2025

If a board has a HSTX or DVI connector, and it has I2C pull-ups built in, it's possible to auto-configure the display.

This is implemented for 2 boards: feather rp2350 & metro rp2350. It's expected to be added to fruit jam when that board definition is added.

It can't be applied to rp2040 boards right now because a particular routine to check if a video mode is valid is not yet implemented there.

it can't be applied to general rp2040/rp2350 boards because without i2c pull-ups, attempting to instantiate the i2c bus would throw an exception. This'll land you in safe mode.

The default resolution is 320x240@16bpp but this can be set via settings.toml (as can display rotation, in case you want a portrait hdmi display)

An earlier iteration of this PR changed how board.DISPLAY worked, but this is no longer the case. Instead, there's a new supervisor.runtime.display property that persists across soft resets. If board_init sets up a display, then that display is also set up there (in addition to appearing as board.DISPLAY). Otherwise, the property can be set by boot.py or code.py. This is a partial implementation of #8675, excluding the incompatible change of resetting "non-default displays" at the end of a code run, and excluding the idea of allocating SPI & I2C buses outside the GC heap.

This should be considered an RFC. Some bits should probably be
moved to common code & tidied up.

If connected to a HDMI monitor, an eeprom will be on the i2c bus
with address 0x50.

When it's found, configure the display to 320x240x16 (default), or to
user settings. Invalid user settings cause a safe mode with a misleading
error: "Heap allocation when VM not running." This is because
common_hal_picodvi_framebuffer_construct throws an exception for invalid
parameters (width, height, and color depth), but the circuitpy VM is not
running.

With the default framebuffer configuration, about 256KiB is left for the
CircuitPython VM.

When a display is configured (whether picodvi or not), board.DISPLAY
exits and can be retrieved. When there's no display (including after
`release_displays()`), accessing `board.DISPLAY` raises an AttributeError.
This behavior should maybe adapted everywhere, but I'm not sure how
much flash size it takes.
@jepler jepler requested a review from tannewt February 4, 2025 20:39
@jepler
Copy link
Author

jepler commented Feb 4, 2025

ping @ladyada

Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! I'm very excited for a CP computer.

@tannewt
Copy link
Member

tannewt commented Feb 10, 2025

Is this ready now? Would love to add it to the metro and fruit jam too.

@jepler jepler marked this pull request as ready for review February 12, 2025 20:20
@jepler jepler requested a review from tannewt February 12, 2025 20:20
Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of things in addition to the build failing.

@RetiredWizard
Copy link

I threw an artifact onto a pimoroni_pico_dv_base_w board using the CIRCUITPY_PICODVI_ENABLE="always" setting and the display didn't come up. A dir(board.DISPLAY) just returned ['__class__']

When the new artifacts come up I'll try again with the non-w version (and a feather-dvi just to be sure I know how it's supposed to work).

@jepler jepler changed the title Auto-configure display on Feather RP2350 Auto-configure display on some RP2350 boards Feb 12, 2025
@jepler
Copy link
Author

jepler commented Feb 12, 2025

The code is only enabled on a few boards and it's not available at all on rp2040 at all right now. I updated the initial comment to explain this more. Do I need to clarify the docs? It lists the specific boards that are supported.

@jepler
Copy link
Author

jepler commented Feb 12, 2025

(I do like the idea that boards with defined video pins but no guaranteed i2c pull-ups could still take an "always" setting via settings.toml and I would like to support more boards .. but that's not part of this PR)

@jepler
Copy link
Author

jepler commented Feb 12, 2025

The way board.DISPLAY is available everywhere also means that with this PR you should be able to configure a display in boot.py and use it in code.py as board.DISPLAY.

@RetiredWizard
Copy link

RetiredWizard commented Feb 12, 2025

Sorry, no, I just jumped the gun before looking close enough. Checking for the existence of board.DISPLAY was a way of determining whether a builtin display was available, but I guess I can check the type now as board.DISPLAY is a Nonetype on boards that the new code is not enabled on.

An interesting observation though is that if you create a picodvi instance to bring up a display on a board not supported the board.DISPLAY object type changes to FramebufferDisplay. That's a pretty cool feature 😁
edit just saw the post you made while I was typing this...

@jepler
Copy link
Author

jepler commented Feb 12, 2025

I appreciate the comments, it's a chance to figure out if there's more to say in documenting this.

Yes, it's true that hasattr(board, "DISPLAY") will now return True on boards with no factory-configured display, as long as they have displayio enabled. I see that this is checked at least two places in our libraries and I'm going to file a few bugs about it.

libraries/helpers/bitmapsaver/adafruit_bitmapsaver.py:        if not hasattr(board, "DISPLAY"):
libraries/helpers/displayio_layout/adafruit_displayio_layout/layouts/tab_layout.py:            if hasattr(board, "DISPLAY"):

@jepler
Copy link
Author

jepler commented Feb 12, 2025

if not getattr(board, 'DISPLAY', None): ... will work across versions of circuitpython, I think

@RetiredWizard
Copy link

Your opening comment is clear enough regarding the supported boards, I just got excited when I saw all the DISPLAY entries being dropped from pins.c on other boards, I thought there may have been a scope change. I should have looked closer and realized that none of the board.c files were updated so any existing display initializations would still be in effect.

jepler added a commit to adafruit/Adafruit_CircuitPython_BitmapSaver that referenced this pull request Feb 12, 2025
Historically, boards with no built-in display have not had a `board.DISPLAY` property.

Soon, with adafruit/circuitpython#10028, any board with displayio will have a `board.DISPLAY` property. This property will be `None` if no display is configured, or a truthy non-`None` value if a display is configured (including dynamically at runtime).

This revised check will work on both old and new circuitpython versions.
jepler added a commit to adafruit/Adafruit_CircuitPython_DisplayIO_Layout that referenced this pull request Feb 12, 2025
Historically, boards with no built-in display have not had a `board.DISPLAY` property.

Soon, with adafruit/circuitpython#10028, any board with displayio will have a `board.DISPLAY` property. This property will be `None` if no display is configured, or a truthy non-`None` value if a display is configured (including dynamically at runtime).

This revised check will work on both old and new circuitpython versions.
@jepler
Copy link
Author

jepler commented Feb 12, 2025

The schematic shows pull ups are present on the pico dv base so it would be a candidate for enabling the auto-dvi code.

@jepler jepler requested a review from tannewt February 12, 2025 23:10
@tannewt
Copy link
Member

tannewt commented Feb 13, 2025

@jepler I don't think board.DISPLAY should exist on everything because it is on "board". board should only have board specific things in it. I think it is valid to check hasattr.

Instead I'd like to move to supervisor.runtime.display: #8675

Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small thing plus changing board.DISPLAY presence on some boards.

Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple small things. Otherwise this looks right! Thank you.

@@ -204,6 +207,39 @@ MP_PROPERTY_GETSET(supervisor_runtime_rgb_status_brightness_obj,
(mp_obj_t)&supervisor_runtime_get_rgb_status_brightness_obj,
(mp_obj_t)&supervisor_runtime_set_rgb_status_brightness_obj);

#if CIRCUITPY_DISPLAYIO
//| display: Any
//| """The primary configured displayio display, if any. Read-only.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//| """The primary configured displayio display, if any. Read-only.
//| """The primary configured displayio display, if any.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, good catch.

for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (i == primary_display_number) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is what you want.

Suggested change
if (i == primary_display_number) {
if (keep_primary && i == primary_display_number) {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's originally what I had, but I changed it. Here's my logic: If !keep_primary, then primary_display_number was updated just above and will always be -1 here. -1 will never be equal to the loop counter.

@jepler
Copy link
Author

jepler commented Feb 13, 2025

Closing in favor of rebased version

@jepler jepler closed this Feb 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants