8000 Add `supervisor.runtime.display` · WaveyD/circuitpython@7519691 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7519691

Browse files
committed
Add supervisor.runtime.display
This partially implements adafruit#8675. Releasing non-primary displays is left for a 10.0 incompatible change. The allocation of I2C and SPI bus objects is unchanged, rather than allocating them outside the GC heap as suggested in that PR.
1 parent dabb0aa commit 7519691

File tree

4 files changed

+113
-4
lines changed

4 files changed

+113
-4
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: 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;

shared-bindings/supervisor/Runtime.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
#include "supervisor/shared/status_leds.h"
2121
#include "supervisor/shared/bluetooth/bluetooth.h"
2222

23+
#if CIRCUITPY_DISPLAYIO
24+
#include "shared-bindings/displayio/__init__.h"
25+
#endif
26+
2327
#if CIRCUITPY_TINYUSB
2428
#include "tusb.h"
2529
#endif
@@ -183,7 +187,6 @@ MP_PROPERTY_GETSET(supervisor_runtime_ble_workflow_obj,
183187
//| after the current code finishes and the status LED is used to show
184188
//| the finish state."""
185189
//|
186-
//|
187190
static mp_obj_t supervisor_runtime_get_rgb_status_brightness(mp_obj_t self) {
188191
return MP_OBJ_NEW_SMALL_INT(get_status_brightness());
189192
}
@@ -204,6 +207,39 @@ MP_PROPERTY_GETSET(supervisor_runtime_rgb_status_brightness_obj,
204207
(mp_obj_t)&supervisor_runtime_get_rgb_status_brightness_obj,
205208
(mp_obj_t)&supervisor_runtime_set_rgb_status_brightness_obj);
206209

210+
#if CIRCUITPY_DISPLAYIO
211+
//| display: Any
212+
//| """The primary configured displayio display, if any.
213+
//|
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()``.
217+
//|
218+
//| The display can be of any supported display type, such as `busdisplay.BusDisplay`.
219+
//|
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.
224+
//|
225+
//| On boards without displayio, this property is present but the value is always `None`."""
226+
//|
227+
//|
228+
static mp_obj_t supervisor_runtime_get_display(mp_obj_t self) {
229+
return common_hal_displayio_get_primary_display();
230+
}
231+
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);
237+
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);
241+
#endif
242+
207243
static const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
208244
{ MP_ROM_QSTR(MP_QSTR_usb_connected), MP_ROM_PTR(&supervisor_runtime_usb_connected_obj) },
209245
{ MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_runtime_serial_connected_obj) },
@@ -213,6 +249,11 @@ static const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
213249
{ MP_ROM_QSTR(MP_QSTR_autoreload), MP_ROM_PTR(&supervisor_runtime_autoreload_obj) },
214250
{ MP_ROM_QSTR(MP_QSTR_ble_workflow), MP_ROM_PTR(&supervisor_runtime_ble_workflow_obj) },
215251
{ MP_ROM_QSTR(MP_QSTR_rgb_status_brightness), MP_ROM_PTR(&supervisor_runtime_rgb_status_brightness_obj) },
252+
#if CIRCUITPY_DISPLAYIO
253+
{ MP_ROM_QSTR(MP_QSTR_display), MP_ROM_PTR(&supervisor_runtime_display_obj) },
254+
#else
255+
{ MP_ROM_QSTR(MP_QSTR_display), MP_ROM_NONE },
256+
#endif
216257
};
217258

218259
static MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table);

shared-module/displayio/__init__.c

Lines changed: 61 additions & 3 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.
@@ -434,3 +453,42 @@ primary_display_bus_t *allocate_display_bus_or_raise(void) {
434453
}
435454
mp_raise_RuntimeError(MP_ERROR_TEXT("Too many display busses; forgot displayio.release_displays() ?"));
436455
}
456+
457+
mp_obj_t common_hal_displayio_get_primary_display(void) {
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);
464+
}
465+
return mp_const_none;
466+
}
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 A7E0 +
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)
0