From 24b30965c41ae32b82c56b166f3287cf2c14f419 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 20 Aug 2019 21:35:42 -0700 Subject: [PATCH] Refresh ePaper displays once code.py is done running --- main.c | 8 ++++++++ shared-bindings/displayio/__init__.c | 2 +- shared-module/displayio/EPaperDisplay.c | 27 +++++++++++++++++++++++++ shared-module/displayio/EPaperDisplay.h | 1 + shared-module/displayio/__init__.c | 24 ++++++++++++---------- shared-module/displayio/display_core.c | 3 ++- 6 files changed, 52 insertions(+), 13 deletions(-) diff --git a/main.c b/main.c index 6ab50fc3ca..076674c442 100755 --- a/main.c +++ b/main.c @@ -253,6 +253,7 @@ bool run_code_py(safe_mode_t safe_mode) { } bool serial_connected_before_animation = false; + bool refreshed_epaper_display = false; rgb_status_animation_t animation; prep_rgb_status_animation(&result, found_main, safe_mode, &animation); while (true) { @@ -290,6 +291,13 @@ bool run_code_py(safe_mode_t safe_mode) { } serial_connected_before_animation = serial_connected(); + // Refresh the ePaper display if we have one. That way it'll show an error message. + #if CIRCUITPY_DISPLAYIO + if (!refreshed_epaper_display) { + refreshed_epaper_display = maybe_refresh_epaperdisplay(); + } + #endif + tick_rgb_status_animation(&animation); } } diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c index 8c5d1f2284..f783255930 100644 --- a/shared-bindings/displayio/__init__.c +++ b/shared-bindings/displayio/__init__.c @@ -77,7 +77,7 @@ //| //| Releases any actively used displays so their busses and pins can be used again. This will also //| release the builtin display on boards that have one. You will need to reinitialize it yourself -//| afterwards. +//| afterwards. This may take seconds to complete if an active EPaperDisplay is refreshing. //| //| Use this once in your code.py if you initialize a display. Place it right before the //| initialization so the display is active as long as possible. diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index 6ff060a6a6..7e65502d4d 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -170,6 +170,9 @@ void displayio_epaperdisplay_start_refresh(displayio_epaperdisplay_obj_t* self) } uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaperdisplay_obj_t* self) { + if (self->core.last_refresh == 0) { + return 0; + } // Refresh at seconds per frame rate. uint32_t elapsed_time = ticks_ms - self->core.last_refresh; if (elapsed_time > self->milliseconds_per_frame) { @@ -343,6 +346,13 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) { } void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) { + if (self->refreshing) { + wait_for_busy(self); + self->refreshing = false; + // Run stop sequence but don't wait for busy because busy is set when sleeping. + send_command_sequence(self, false, self->stop_sequence, self->stop_sequence_len); + } + release_display_core(&self->core); if (self->busy.base.type == &digitalio_digitalinout_type) { common_hal_digitalio_digitalinout_deinit(&self->busy); @@ -352,3 +362,20 @@ void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) { void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self) { displayio_display_core_collect_ptrs(&self->core); } + +bool maybe_refresh_epaperdisplay(void) { + for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + if (displays[i].epaper_display.base.type != &displayio_epaperdisplay_type || + displays[i].epaper_display.core.current_group != &circuitpython_splash) { + // Skip regular displays and those not showing the splash. + continue; + } + displayio_epaperdisplay_obj_t* display = &displays[i].epaper_display; + if (common_hal_displayio_epaperdisplay_get_time_to_refresh(display) != 0) { + return false; + } + return common_hal_displayio_epaperdisplay_refresh(display); + } + // Return true if no ePaper displays are available to pretend it was updated. + return true; +} diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h index 88b5ebfaf2..2be2add4b7 100644 --- a/shared-module/displayio/EPaperDisplay.h +++ b/shared-module/displayio/EPaperDisplay.h @@ -60,6 +60,7 @@ typedef struct { void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self); void release_epaperdisplay(displayio_epaperdisplay_obj_t* self); +bool maybe_refresh_epaperdisplay(void); void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self); diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 0a3b1fd108..a41884c78c 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -54,6 +54,19 @@ void displayio_background(void) { } void common_hal_displayio_release_displays(void) { + // Release displays before busses so that they can send any final commands to turn the display + // off properly. + for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + mp_const_obj_t display_type = displays[i].display.base.type; + if (display_type == NULL || display_type == &mp_type_NoneType) { + continue; + } else if (display_type == &displayio_display_type) { + release_display(&displays[i].display); + } else if (display_type == &displayio_epaperdisplay_type) { + release_epaperdisplay(&displays[i].epaper_display); + } + displays[i].display.base.type = &mp_type_NoneType; + } for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { mp_const_obj_t bus_type = displays[i].fourwire_bus.base.type; if (bus_type == NULL || bus_type == &mp_type_NoneType) { @@ -67,17 +80,6 @@ void common_hal_displayio_release_displays(void) { } displays[i].fourwire_bus.base.type = &mp_type_NoneType; } - for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { - mp_const_obj_t display_type = displays[i].display.base.type; - if (display_type == NULL || display_type == &mp_type_NoneType) { - continue; - } else if (display_type == &displayio_display_type) { - release_display(&displays[i].display); - } else if (display_type == &displayio_epaperdisplay_type) { - release_epaperdisplay(&displays[i].epaper_display); - } - displays[i].display.base.type = &mp_type_NoneType; - } supervisor_stop_terminal(); } diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c index f8a8d8feaa..24d8ab51f0 100644 --- a/shared-module/displayio/display_core.c +++ b/shared-module/displayio/display_core.c @@ -52,6 +52,7 @@ void displayio_display_core_construct(displayio_display_core_t* self, self->current_group = NULL; self->colstart = colstart; self->rowstart = rowstart; + self->last_refresh = 0; if (MP_OBJ_IS_TYPE(bus, &displayio_parallelbus_type)) { self->bus_reset = common_hal_displayio_parallelbus_reset; @@ -140,7 +141,7 @@ bool displayio_display_core_show(displayio_display_core_t* self, displayio_group if (!circuitpython_splash.in_group) { root_group = &circuitpython_splash; } else if (self->current_group == &circuitpython_splash) { - return false; + return true; } } if (root_group == self->current_group) {