Skip to content

Commit 83415e7

Browse files
committed
Make primary display settable, defaults to None unless set by board_init
1 parent 86fe684 commit 83415e7

File tree

4 files changed

+81
-13
lines changed

4 files changed

+81
-13
lines changed

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.

shared-bindings/displayio/__init__.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ typedef enum displayio_colorspace {
2424

2525
void common_hal_displayio_release_displays(void);
2626
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);
2729

2830
extern const mp_obj_type_t displayio_colorspace_type;
2931
extern const cp_enum_obj_t displayio_colorspace_RGB888_obj;

shared-bindings/supervisor/Runtime.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,18 @@ MP_PROPERTY_GETSET(supervisor_runtime_rgb_status_brightness_obj,
209209

210210
#if CIRCUITPY_DISPLAYIO
211211
//| display: Any
212-
//| """The first configured displayio display, if any. Read-only.
212+
//| """The primary configured displayio display, if any. Read-only.
213213
//|
214-
//| If the board has a display that is configured in board setup, in boot.py,
215-
//| or in a previous invocation of code.py, it is available here.
214+
//| If the board has a display that is hard coded, or that was explicitly set
215+
//| in boot.py or code.py (including a previous run of code.py), it is
216+
//| available here until it is released with ``displayio.releasee_displays()``.
216217
//|
217218
//| The display can be of any supported display type, such as `busdisplay.BusDisplay`.
218219
//|
219-
//| If no display is configured, this property is always `None`.
220+
//| If no display is configured, this property is `None`.
221+
//|
222+
//| In a future release of CircuitPython, any display that is not the primary display
223+
//| will be automatically released at the end of running a code file.
220224
//|
221225
//| On boards without displayio, this property is present but the value is always `None`."""
222226
//|
@@ -225,9 +229,15 @@ static mp_obj_t supervisor_runtime_get_display(mp_obj_t self) {
225229
return common_hal_displayio_get_primary_display();
226230
}
227231
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_display_obj, supervisor_runtime_get_display);
232+
static mp_obj_t supervisor_runtime_set_display(mp_obj_t self, mp_obj_t new_primary_display) {
233+
common_hal_displayio_set_primary_display(new_primary_display);
234+
return mp_const_none;
235+
}
236+
MP_DEFINE_CONST_FUN_OBJ_2(supervisor_runtime_set_display_obj, supervisor_runtime_set_display);
228237

229-
MP_PROPERTY_GETTER(supervisor_runtime_display_obj,
230-
(mp_obj_t)&supervisor_runtime_get_display_obj);
238+
MP_PROPERTY_GETSET(supervisor_runtime_display_obj,
239+
(mp_obj_t)&supervisor_runtime_get_display_obj,
240+
(mp_obj_t)&supervisor_runtime_set_display_obj);
231241
#endif
232242

233243
static const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {

shared-module/displayio/__init__.c

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
#include "supervisor/spi_flash_api.h"
4545
#endif
4646

47+
// The default indicates no primary display
48+
static int primary_display_number = -1;
49+
4750
primary_display_bus_t display_buses[CIRCUITPY_DISPLAY_LIMIT];
4851
primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
4952

@@ -108,10 +111,16 @@ void displayio_background(void) {
108111

109112
}
110113

111-
void common_hal_displayio_release_displays(void) {
114+
static void common_hal_displayio_release_displays_impl(bool keep_primary) {
112115
// Release displays before busses so that they can send any final commands to turn the display
113116
// off properly.
117+
if (!keep_primary) {
118+
primary_display_number = -1;
119+
}
114120
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
121+
if (i == primary_display_number) {
122+
continue;
123+
}
115124
mp_const_obj_t display_type = displays[i].display_base.type;
116125
if (display_type == NULL || display_type == &mp_type_NoneType) {
117126
continue;
@@ -177,7 +186,14 @@ void common_hal_displayio_release_displays(void) {
177186
supervisor_stop_terminal();
178187
}
179188

189+
void common_hal_displayio_release_displays(void) {
190+
common_hal_displayio_release_displays_impl(false);
191+
}
192+
180193
void reset_displays(void) {
194+
// In CircuitPython 10, release secondary displays before doing anything else:
195+
// common_hal_displayio_release_displays_impl(true);
196+
181197
// The SPI buses used by FourWires may be allocated on the heap so we need to move them inline.
182198
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
183199
mp_const_obj_t display_bus_type = display_buses[i].bus_base.type;
@@ -392,10 +408,13 @@ void displayio_gc_collect(void) {
392408
}
393409
}
394410

411+
static bool is_display_active(mp_obj_base_t *display_maybe) {
412+
return display_maybe->type != &mp_type_NoneType && display_maybe->type != NULL;
413+
}
414+
395415
primary_display_t *allocate_display(void) {
396416
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
397-
mp_const_obj_t display_type = displays[i].display_base.type;
398-
if (display_type == NULL || display_type == &mp_type_NoneType) {
417+
if (!is_display_active(&displays[i].display_base)) {
399418
// Clear this memory so it is in a known state before init.
400419
memset(&displays[i], 0, sizeof(displays[i]));
401420
// Default to None so that it works as board.DISPLAY.
@@ -435,11 +454,41 @@ primary_display_bus_t *allocate_display_bus_or_raise(void) {
435454
mp_raise_RuntimeError(MP_ERROR_TEXT("Too many display busses; forgot displayio.release_displays() ?"));
436455
}
437456

438-
439457
mp_obj_t common_hal_displayio_get_primary_display(void) {
440-
mp_obj_base_t *first_display = &displays[0].display_base;
441-
if (first_display->type != &mp_type_NoneType && first_display->type != NULL) {
442-
return MP_OBJ_FROM_PTR(first_display);
458+
if (primary_display_number == -1 || primary_display_number >= CIRCUITPY_DISPLAY_LIMIT) {
459+
return mp_const_none;
460+
}
461+
mp_obj_base_t *primary_display = &displays[primary_display_number].display_base;
462+
if (is_display_active(primary_display)) {
463+
return MP_OBJ_FROM_PTR(primary_display);
443464
}
444465
return mp_const_none;
445466
}
467+
468+
void common_hal_displayio_set_primary_display(mp_obj_t new_primary_display) {
469+
if (new_primary_display == mp_const_none) {
470+
primary_display_number = -1;
471+
return;
472+
}
473+
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
474+
mp_obj_t display = MP_OBJ_FROM_PTR(&displays[i]);
475+
if (new_primary_display == display && is_display_active(display)) {
476+
primary_display_number = i;
477+
return;
478+
}
479+
}
480+
// object was not a display after all...
481+
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_Display, MP_QSTR_AnyDisplay, MP_QSTR_None, mp_obj_get_type(new_primary_display)->name);
482+
}
483+
484+
void common_hal_displayio_auto_primary_display(void) {
485+
if (primary_display_number != -1) {
486+
return;
487+
}
488+
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
489+
if (is_display_active(&displays[i].display_base)) {
490+
primary_display_number = i;
491+
return;
492+
}
493+
}
494+
}

0 commit comments

Comments
 (0)