Skip to content

Commit e5e7c9e

Browse files
authored
Merge pull request #10062 from jepler/feather-rp2350-autodvi-rebased
Add supervisor.runtime.display & RP2350 DVI autoconfig (rebased version)
2 parents 73c4b46 + e8eed62 commit e5e7c9e

File tree

14 files changed

+338
-11
lines changed

14 files changed

+338
-11
lines changed

docs/environment.rst

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,14 @@ Wi-Fi SSID to auto-connect to even if user code is not running.
101101
Additional board specific keys
102102
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
103103

104-
`MaTouch ESP32-S3 Parallel TFT with Touch 7“ <https://circuitpython.org/board/makerfabs_tft7/>`_
105-
106-
CIRCUITPY_DISPLAY_WIDTH
107-
~~~~~~~~~~~~~~~~~~~~~~~
104+
CIRCUITPY_DISPLAY_WIDTH (Sunton, MaTouch)
105+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108106
Selects the correct screen resolution (1024x600 or 800x640) for the particular board variant.
109107
If the CIRCUITPY_DISPLAY_WIDTH parameter is set to a value of 1024 the display is initialized
110108
during power up at 1024x600 otherwise the display will be initialized at a resolution
111109
of 800x480.
112110

111+
`MaTouch ESP32-S3 Parallel TFT with Touch 7“ <https://circuitpython.org/board/makerfabs_tft7/>`_
113112
`Sunton ESP32-2432S028 <https://circuitpython.org/board/sunton_esp32_2432S028/>`_
114113
`Sunton ESP32-2432S024C <https://circuitpython.org/board/sunton_esp32_2432S024C/>`_
115114

@@ -122,6 +121,8 @@ a rotation of 0. Attempting to initialize the screen with a rotation other than
122121
90, 180 or 270 is not supported and will result in an unexpected screen rotation.
123122

124123
`Sunton ESP32-8048S050 <https://circuitpython.org/board/sunton_esp32_8048S050/>`_
124+
`Adafruit Feather RP2350 <https://circuitpython.org/board/adafruit_feather_rp2350/>`_
125+
`Adafruit Metro RP2350 <https://circuitpython.org/board/adafruit_metro_rp2350/>`_
125126

126127
CIRCUITPY_DISPLAY_FREQUENCY
127128
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -130,3 +131,46 @@ If a valid frequency is not defined the board will initialize the framebuffer wi
130131
frequency of 12500000hz (12.5Mhz). The value should be entered as an integer in hertz
131132
i.e. CIRCUITPY_DISPLAY_FREQUENCY=16000000 will override the default value with a 16Mhz
132133
display frequency.
134+
135+
`Sunton ESP32-8048S050 <https://circuitpython.org/board/sunton_esp32_8048S050/>`_
136+
137+
138+
CIRCUITPY_PICODVI_ENABLE
139+
~~~~~~~~~~~~~~~~~~~~~~~~
140+
Whether to configure the display at board initialization time, one of the following:
141+
142+
.. code-block::
143+
144+
CIRCUITPY_PICODVI_ENABLE="detect" # when EDID EEPROM is detected (default)
145+
CIRCUITPY_PICODVI_ENABLE="always"
146+
CIRCUITPY_PICODVI_ENABLE="never"
147+
148+
A display configured in this manner is available at ``supervisor.runtime.display``
149+
until it is released by ``displayio.release_displays()``. It does not appear at
150+
``board.DISPLAY``.
151+
152+
`Adafruit Feather RP2350 <https://circuitpython.org/board/adafruit_feather_rp2350/>`_
153+
`Adafruit Metro RP2350 <https://circuitpython.org/board/adafruit_metro_rp2350/>`_
154+
155+
CIRCUITPY_DISPLAY_WIDTH, CIRCUITPY_DISPLAY_HEIGHT, and CIRCUITPY_DISPLAY_COLOR_DEPTH (RP2350 boards with DVI or HSTX connector)
156+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
157+
Selects the desired resolution and color depth.
158+
159+
Supported resolutions are:
160+
* 640x480 with color depth 1, 2, 4 or 8 bits per pixel
161+
* 320x240 with color depth 8 or 16 bits per pixel
162+
163+
The default value, if unspecified, is 320x240 with 16 bits per pixel.
164+
165+
If height is unspecified, it is set from the width. For example, a width of 640
166+
implies a height of 480.
167+
168+
Example: Configure the display to 640x480 black and white (1 bit per pixel):
169+
170+
.. code-block::
171+
172+
CIRCUITPY_DISPLAY_WIDTH=640
173+
CIRCUITPY_DISPLAY_COLOR_DEPTH=1
174+
175+
`Adafruit Feather RP2350 <https://circuitpython.org/board/adafruit_feather_rp2350/>`_
176+
`Adafruit Metro RP2350 <https://circuitpython.org/board/adafruit_metro_rp2350/>`_

main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,9 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s
772772
#if CIRCUITPY_ALARM
773773
if (fake_sleeping) {
774774
board_init();
775+
#if CIRCUITPY_DISPLAYIO
776+
common_hal_displayio_auto_primary_display();
777+
#endif
775778
// Pretend that the next run is the first run, as if we were reset.
776779
*simulate_reset = true;
777780
}
@@ -1053,6 +1056,10 @@ int __attribute__((used)) main(void) {
10531056
// displays init after filesystem, since they could share the flash SPI
10541057
board_init();
10551058

1059+
#if CIRCUITPY_DISPLAYIO
1060+
common_hal_displayio_auto_primary_display();
1061+
#endif
1062+
10561063
mp_hal_stdout_tx_str(line_clear);
10571064

10581065
// This is first time we are running CircuitPython after a reset or power-up.

ports/raspberrypi/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ ifeq ($(CIRCUITPY_PICODVI),1)
556556
SRC_C += \
557557
bindings/picodvi/__init__.c \
558558
bindings/picodvi/Framebuffer.c \
559+
common-hal/picodvi/__init__.c \
559560
common-hal/picodvi/Framebuffer_$(CHIP_VARIANT).c \
560561

561562
ifeq ($(CHIP_VARIANT),RP2040)

ports/raspberrypi/bindings/picodvi/Framebuffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
extern const mp_obj_type_t picodvi_framebuffer_type;
1414

15+
bool common_hal_picodvi_framebuffer_preflight(
16+
mp_uint_t width, mp_uint_t height,
17+
mp_uint_t color_depth);
1518
void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self,
1619
mp_uint_t width, mp_uint_t height,
1720
const mcu_pin_obj_t *clk_dp, const mcu_pin_obj_t *clk_dn,

ports/raspberrypi/boards/adafruit_feather_rp2350/board.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
//
55
// SPDX-License-Identifier: MIT
66

7+
#include "py/obj.h"
78
#include "supervisor/board.h"
89

10+
#include "common-hal/picodvi/__init__.h"
11+
912
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.
13+
14+
void board_init(void) {
15+
picodvi_autoconstruct();
16+
}

ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,12 @@
2020
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)
2121

2222
#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8)
23+
24+
#define DEFAULT_DVI_BUS_CLK_DN (&pin_GPIO15)
25+
#define DEFAULT_DVI_BUS_CLK_DP (&pin_GPIO14)
26+
#define DEFAULT_DVI_BUS_RED_DN (&pin_GPIO19)
27+
#define DEFAULT_DVI_BUS_RED_DP (&pin_GPIO18)
28+
#define DEFAULT_DVI_BUS_GREEN_DN (&pin_GPIO17)
29+
#define DEFAULT_DVI_BUS_GREEN_DP (&pin_GPIO16)
30+
#define DEFAULT_DVI_BUS_BLUE_DN (&pin_GPIO13)
31+
#define DEFAULT_DVI_BUS_BLUE_DP (&pin_GPIO12)

ports/raspberrypi/boards/adafruit_metro_rp2350/board.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "shared-bindings/usb_host/Port.h"
1010
#include "supervisor/board.h"
1111

12+
#include "common-hal/picodvi/__init__.h"
13+
1214
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.
1315

1416

@@ -29,8 +31,9 @@ bool board_reset_pin_number(uint8_t pin_number) {
2931
}
3032
#endif
3133

32-
#if defined(DEFAULT_USB_HOST_DATA_PLUS)
3334
void board_init(void) {
35+
#if defined(DEFAULT_USB_HOST_DATA_PLUS)
3436
common_hal_usb_host_port_construct(DEFAULT_USB_HOST_DATA_PLUS, DEFAULT_USB_HOST_DATA_MINUS);
37+
#endif
38+
picodvi_autoconstruct();
3539
}
36-
#endif

ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,12 @@
2626
#define DEFAULT_USB_HOST_DATA_MINUS (&pin_GPIO33)
2727
#define DEFAULT_USB_HOST_5V_POWER (&pin_GPIO29)
2828
#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO47)
29+
30+
#define DEFAULT_DVI_BUS_CLK_DN (&pin_GPIO15)
31+
#define DEFAULT_DVI_BUS_CLK_DP (&pin_GPIO14)
32+
#define DEFAULT_DVI_BUS_RED_DN (&pin_GPIO19)
33+
#define DEFAULT_DVI_BUS_RED_DP (&pin_GPIO18)
34+
#define DEFAULT_DVI_BUS_GREEN_DN (&pin_GPIO17)
35+
#define DEFAULT_DVI_BUS_GREEN_DP (&pin_GPIO16)
36+
#define DEFAULT_DVI_BUS_BLUE_DN (&pin_GPIO13)
37+
#define DEFAULT_DVI_BUS_BLUE_DP (&pin_GPIO12)

ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ static void __not_in_flash_func(dma_irq_handler)(void) {
129129
ch->al3_read_addr_trig = (uintptr_t)active_picodvi->dma_commands;
130130
}
131131

132+
bool common_hal_picodvi_framebuffer_preflight(
133+
mp_uint_t width, mp_uint_t height,
134+
mp_uint_t color_depth) {
135+
136+
// for each supported resolution, check the color depth is supported
137+
if (width == 640 && height == 640) {
138+
return color_depth == 1 || color_depth == 2 || color_depth == 4 || color_depth == 8;
139+
}
140+
if (width == 320 && height == 240) {
141+
return color_depth == 8 || color_depth == 16;
142+
}
143+
return false;
144+
}
145+
132146
void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self,
133147
mp_uint_t width, mp_uint_t height,
134148
const mcu_pin_obj_t *clk_dp, const mcu_pin_obj_t *clk_dn,
@@ -140,7 +154,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self,
140154
mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("%q in use"), MP_QSTR_picodvi);
141155
}
142156

143-
if (!(width == 640 && height == 480) && !(width == 320 && height == 240 && (color_depth == 16 || color_depth == 8))) {
157+
if (!common_hal_picodvi_framebuffer_preflight(width, height, color_depth)) {
144158
mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q and %q"), MP_QSTR_width, MP_QSTR_height);
145159
}
146160

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2025 Jeff Epler for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#include "common-hal/picodvi/__init__.h"
8+
#include "common-hal/picodvi/Framebuffer.h"
9+
#include "bindings/picodvi/Framebuffer.h"
10+
#include "shared-bindings/busio/I2C.h"
11+
#include "shared-bindings/board/__init__.h"
12+
#include "shared-module/displayio/__init__.h"
13+
#include "shared-module/os/__init__.h"
14+
#include "supervisor/shared/safe_mode.h"
15+
#include "py/gc.h"
16+
#include "py/runtime.h"
17+
#include "supervisor/port_heap.h"
18+
19+
#if defined(DEFAULT_DVI_BUS_CLK_DP)
20+
static bool picodvi_autoconstruct_enabled(void) {
21+
char buf[sizeof("detect")];
22+
buf[0] = 0;
23+
24+
// (any failure leaves the content of buf untouched: an empty nul-terminated string
25+
(void)common_hal_os_getenv_str("CIRCUITPY_PICODVI_ENABLE", buf, sizeof(buf));
26+
27+
if (!strcasecmp(buf, "never")) {
28+
return false;
29+
}
30+
if (!strcasecmp(buf, "always")) {
31+
return true;
32+
}
33+
34+
// It's "detect" or else an invalid value which is treated the same as "detect".
35+
36+
// check if address 0x50 is live on the I2C bus
37+
busio_i2c_obj_t *i2c = common_hal_board_create_i2c(0);
38+
if (!i2c) {
39+
return false;
40+
}
41+
if (!common_hal_busio_i2c_try_lock(i2c)) {
42+
return false;
43+
}
44+
bool probed = common_hal_busio_i2c_probe(i2c, 0x50);
45+
common_hal_busio_i2c_unlock(i2c);
46+
return probed;
47+
}
48+
49+
// For picodvi_autoconstruct to work, the 8 DVI/HSTX pin names must be defined, AND
50+
// i2c bus 0 must also be connected to DVI with on-board pull ups
51+
void picodvi_autoconstruct(void) {
52+
if (get_safe_mode() != SAFE_MODE_NONE) {
53+
return;
54+
}
55+
56+
if (!picodvi_autoconstruct_enabled()) {
57+
return;
58+
}
59+
60+
mp_int_t width = 320;
61+
mp_int_t height = 0;
62+
mp_int_t color_depth = 16;
63+
mp_int_t rotation = 0;
64+
65+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_WIDTH", &width);
66+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_HEIGHT", &height);
67+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_COLOR_DEPTH", &color_depth);
68+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_ROTATION", &rotation);
69+
70+
if (height == 0) {
71+
switch (width) {
72+
case 640:
73+
height = 480;
74+
break;
75+
case 320:
76+
height = 240;
77+
break;
78+
}
79+
}
80+
81+
if (rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270) {
82+
// invalid rotation
83+
rotation = 0;
84+
}
85+
86+
if (!common_hal_picodvi_framebuffer_preflight(width, height, color_depth)) {
87+
// invalid configuration, set back to default
88+
width = 320;
89+
height = 240;
90+
color_depth = 16;
91+
}
92+
93+
// construct framebuffer and display
94+
picodvi_framebuffer_obj_t *fb = &allocate_display_bus_or_raise()->picodvi;
95+
fb->base.type = &picodvi_framebuffer_type;
96+
common_hal_picodvi_framebuffer_construct(fb,
97+
width, height,
98+
DEFAULT_DVI_BUS_CLK_DP,
99+
DEFAULT_DVI_BUS_CLK_DN,
100+
DEFAULT_DVI_BUS_RED_DP,
101+
DEFAULT_DVI_BUS_RED_DN,
102+
DEFAULT_DVI_BUS_GREEN_DP,
103+
DEFAULT_DVI_BUS_GREEN_DN,
104+
DEFAULT_DVI_BUS_BLUE_DP,
105+
DEFAULT_DVI_BUS_BLUE_DN,
106+
color_depth);
107+
108+
framebufferio_framebufferdisplay_obj_t *display = &allocate_display()->framebuffer_display;
109+
display->base.type = &framebufferio_framebufferdisplay_type;
110+
common_hal_framebufferio_framebufferdisplay_construct(
111+
display,
112+
MP_OBJ_FROM_PTR(fb),
113+
rotation,
114+
true);
115+
}
116+
#else
117+
void picodvi_autoconstruct(void) {
118+
}
119+
#endif
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2025 Jeff Epler for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#pragma once
8+
9+
extern void picodvi_autoconstruct(void);

shared-bindings/displayio/__init__.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ typedef enum displayio_colorspace {
2323
} displayio_colorspace_t;
2424

2525
void common_hal_displayio_release_displays(void);
26+
mp_obj_t common_hal_displayio_get_primary_display(void);
27+
void common_hal_displayio_set_primary_display(mp_obj_t o);
28+
void common_hal_displayio_auto_primary_display(void);
2629

2730
extern const mp_obj_type_t displayio_colorspace_type;
2831
extern const cp_enum_obj_t displayio_colorspace_RGB888_obj;

0 commit comments

Comments
 (0)