Skip to content

Commit db8d517

Browse files
committed
Auto-configure display on Feather RP2350
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.
1 parent 455d856 commit db8d517

File tree

5 files changed

+115
-0
lines changed

5 files changed

+115
-0
lines changed

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/boards/adafruit_feather_rp2350/board.c

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

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

10+
#include "shared-module/displayio/__init__.h"
11+
#include "common-hal/picodvi/__init__.h"
12+
913
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.
14+
15+
16+
extern void mp_module_board_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
17+
18+
void mp_module_board_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
19+
if (attr == MP_QSTR_DISPLAY && dest[0] == MP_OBJ_NULL) {
20+
mp_obj_base_t *first_display = &displays[0].display_base;
21+
if (first_display->type != &mp_type_NoneType && first_display->type != NULL) {
22+
dest[0] = MP_OBJ_FROM_PTR(first_display);
23+
}
24+
}
25+
}
26+
27+
MP_REGISTER_MODULE_DELEGATION(board_module, mp_module_board_attr);
28+
29+
void board_init(void) {
30+
picodvi_autoconstruct();
31+
}

ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,15 @@
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)
32+
33+
// delegate board.DISPLAY attribute
34+
#define MICROPY_MODULE_ATTR_DELEGATION (1)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
void picodvi_autoconstruct(void) {
20+
if (get_safe_mode() != SAFE_MODE_NONE) {
21+
return;
22+
}
23+
#if defined(DEFAULT_DVI_BUS_CLK_DP)
24+
// check if address 0x50 is live on the I2C bus -- return if not
25+
busio_i2c_obj_t *i2c = common_hal_board_create_i2c(0);
26+
if (!i2c) {
27+
return;
28+
}
29+
if (!common_hal_busio_i2c_try_lock(i2c)) {
30+
return;
31+
}
32+
bool probed = common_hal_busio_i2c_probe(i2c, 0x50);
33+
common_hal_busio_i2c_unlock(i2c);
34+
if (!probed) {
35+
return;
36+
}
37+
38+
mp_int_t width = 320;
39+
mp_int_t height = 240;
40+
mp_int_t color_depth = 16;
41+
42+
// TODO: User configuration can cause safe mode errors without a self-explanatory message.
43+
common_hal_os_getenv_int("CIRCUITPY_DISPLAY_WIDTH", &width);
44+
common_hal_os_getenv_int("CIRCUITPY_DISPLAY_HEIGHT", &height);
45+
common_hal_os_getenv_int("CIRCUITPY_DISPLAY_COLOR_DEPTH", &color_depth);
46+
47+
// construct framebuffer and display
48+
49+
picodvi_framebuffer_obj_t *fb = &allocate_display_bus_or_raise()->picodvi;
50+
fb->base.type = &picodvi_framebuffer_type;
51+
common_hal_picodvi_framebuffer_construct(fb,
52+
width, height,
53+
DEFAULT_DVI_BUS_CLK_DP,
54+
DEFAULT_DVI_BUS_CLK_DN,
55+
DEFAULT_DVI_BUS_RED_DP,
56+
DEFAULT_DVI_BUS_RED_DN,
57+
DEFAULT_DVI_BUS_GREEN_DP,
58+
DEFAULT_DVI_BUS_GREEN_DN,
59+
DEFAULT_DVI_BUS_BLUE_DP,
60+
DEFAULT_DVI_BUS_BLUE_DN,
61+
color_depth);
62+
63+
framebufferio_framebufferdisplay_obj_t *display = &allocate_display()->framebuffer_display;
64+
display->base.type = &framebufferio_framebufferdisplay_type;
65+
common_hal_framebufferio_framebufferdisplay_construct(
66+
display,
67+
MP_OBJ_FROM_PTR(fb),
68+
0,
69+
true);
70+
#endif
71+
}
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);

0 commit comments

Comments
 (0)