summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk2
-rw-r--r--shared-bindings/displayio/Display.h8
-rw-r--r--shared-bindings/displayio/FourWire.c7
-rw-r--r--shared-bindings/displayio/ParallelBus.c7
-rw-r--r--shared-module/displayio/Display.c24
-rw-r--r--shared-module/displayio/__init__.c58
6 files changed, 76 insertions, 30 deletions
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index ce46d7000..b23a8b76e 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -13,6 +13,8 @@ LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+CFLAGS_INLINE_LIMIT = 70
+
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
diff --git a/shared-bindings/displayio/Display.h b/shared-bindings/displayio/Display.h
index ee9106f77..7d6444a2d 100644
--- a/shared-bindings/displayio/Display.h
+++ b/shared-bindings/displayio/Display.h
@@ -48,13 +48,15 @@ void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_
void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self);
-void displayio_display_start_region_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
-void displayio_display_finish_region_update(displayio_display_obj_t* self);
+bool displayio_display_begin_transaction(displayio_display_obj_t* self);
+void displayio_display_end_transaction(displayio_display_obj_t* self);
+
+void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
bool displayio_display_frame_queued(displayio_display_obj_t* self);
bool displayio_display_refresh_queued(displayio_display_obj_t* self);
void displayio_display_finish_refresh(displayio_display_obj_t* self);
-bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length);
+void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length);
bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self);
void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness);
diff --git a/shared-bindings/displayio/FourWire.c b/shared-bindings/displayio/FourWire.c
index 56baa534b..70cd42747 100644
--- a/shared-bindings/displayio/FourWire.c
+++ b/shared-bindings/displayio/FourWire.c
@@ -110,7 +110,12 @@ STATIC mp_obj_t displayio_fourwire_obj_send(mp_obj_t self, mp_obj_t command_obj,
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
- common_hal_displayio_fourwire_begin_transaction(self);
+ // Wait for display bus to be available.
+ while (!common_hal_displayio_fourwire_begin_transaction(self)) {
+#ifdef MICROPY_VM_HOOK_LOOP
+ MICROPY_VM_HOOK_LOOP ;
+#endif
+ }
common_hal_displayio_fourwire_send(self, true, &command, 1);
common_hal_displayio_fourwire_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
common_hal_displayio_fourwire_end_transaction(self);
diff --git a/shared-bindings/displayio/ParallelBus.c b/shared-bindings/displayio/ParallelBus.c
index a54a84471..6a499ed06 100644
--- a/shared-bindings/displayio/ParallelBus.c
+++ b/shared-bindings/displayio/ParallelBus.c
@@ -114,7 +114,12 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
- common_hal_displayio_parallelbus_begin_transaction(self);
+ // Wait for display bus to be available.
+ while (!common_hal_displayio_parallelbus_begin_transaction(self)) {
+#ifdef MICROPY_VM_HOOK_LOOP
+ MICROPY_VM_HOOK_LOOP ;
+#endif
+ }
common_hal_displayio_parallelbus_send(self, true, &command, 1);
common_hal_displayio_parallelbus_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
common_hal_displayio_parallelbus_end_transaction(self);
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index 95c5cdfec..0e76a868f 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -69,7 +69,11 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
self->bus = bus;
uint32_t i = 0;
- self->begin_transaction(self->bus);
+ while (!self->begin_transaction(self->bus)) {
+#ifdef MICROPY_VM_HOOK_LOOP
+ MICROPY_VM_HOOK_LOOP ;
+#endif
+ }
while (i < init_sequence_len) {
uint8_t *cmd = init_sequence + i;
uint8_t data_size = *(cmd + 1);
@@ -198,9 +202,16 @@ bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self,
return ok;
}
-void displayio_display_start_region_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
+bool displayio_display_begin_transaction(displayio_display_obj_t* self) {
+ return self->begin_transaction(self->bus);
+}
+
+void displayio_display_end_transaction(displayio_display_obj_t* self) {
+ self->end_transaction(self->bus);
+}
+
+void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
// TODO(tannewt): Handle displays with single byte bounds.
- self->begin_transaction(self->bus);
uint16_t data[2];
self->send(self->bus, true, &self->set_column_command, 1);
data[0] = __builtin_bswap16(x0 + self->colstart);
@@ -213,10 +224,6 @@ void displayio_display_start_region_update(displayio_display_obj_t* self, uint16
self->send(self->bus, true, &self->write_ram_command, 1);
}
-void displayio_display_finish_region_update(displayio_display_obj_t* self) {
- self->end_transaction(self->bus);
-}
-
bool displayio_display_frame_queued(displayio_display_obj_t* self) {
// Refresh at ~30 fps.
return (ticks_ms - self->last_refresh) > 32;
@@ -234,9 +241,8 @@ void displayio_display_finish_refresh(displayio_display_obj_t* self) {
self->last_refresh = ticks_ms;
}
-bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
+void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
self->send(self->bus, false, (uint8_t*) pixels, length * 4);
- return true;
}
void displayio_display_update_backlight(displayio_display_obj_t* self) {
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index 79014fb5a..546a46b1e 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -22,7 +22,8 @@ static inline void swap(uint16_t* a, uint16_t* b) {
*b = temp;
}
-bool refreshing_displays = false;
+// Check for recursive calls to displayio_refresh_displays.
+bool refresh_displays_in_progress = false;
void displayio_refresh_displays(void) {
if (mp_hal_is_interrupted()) {
@@ -35,20 +36,25 @@ void displayio_refresh_displays(void) {
return;
}
- if (refreshing_displays) {
+ if (refresh_displays_in_progress) {
+ // Don't allow recursive calls to this routine.
return;
}
- refreshing_displays = true;
+
+ refresh_displays_in_progress = true;
+
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].display.base.type == NULL || displays[i].display.base.type == &mp_type_NoneType) {
+ // Skip null display.
continue;
}
displayio_display_obj_t* display = &displays[i].display;
displayio_display_update_backlight(display);
+ // Time to refresh at specified frame rate?
if (!displayio_display_frame_queued(display)) {
- refreshing_displays = false;
- return;
+ // Too soon. Try next display.
+ continue;
}
if (displayio_display_refresh_queued(display)) {
// We compute the pixels. r and c are row and column to match the display memory
@@ -60,7 +66,13 @@ void displayio_refresh_displays(void) {
if (display->transpose_xy) {
swap(&c1, &r1);
}
- displayio_display_start_region_update(display, c0, r0, c1, r1);
+
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't acquire display bus; skip updating this display. Try next display.
+ continue;
+ }
+ displayio_display_set_region_to_update(display, c0, r0, c1, r1);
+ displayio_display_end_transaction(display);
uint16_t x0 = 0;
uint16_t x1 = display->width - 1;
@@ -94,6 +106,8 @@ void displayio_refresh_displays(void) {
size_t index = 0;
uint16_t buffer_size = 256;
uint32_t buffer[buffer_size / 2];
+ bool skip_this_display = false;
+
for (uint16_t y = starty; y0 <= y && y <= y1; y += dy) {
for (uint16_t x = startx; x0 <= x && x <= x1; x += dx) {
uint16_t* pixel = &(((uint16_t*)buffer)[index]);
@@ -110,11 +124,14 @@ void displayio_refresh_displays(void) {
index += 1;
// The buffer is full, send it.
if (index >= buffer_size) {
- if (!displayio_display_send_pixels(display, buffer, buffer_size / 2) || reload_requested) {
- displayio_display_finish_region_update(display);
- refreshing_displays = false;
- return;
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't acquire display bus; skip the rest of the data. Try next display.
+ index = 0;
+ skip_this_display = true;
+ break;
}
+ displayio_display_send_pixels(display, buffer, buffer_size / 2);
+ displayio_display_end_transaction(display);
// TODO(tannewt): Make refresh displays faster so we don't starve other
// background tasks.
usb_background();
@@ -122,17 +139,26 @@ void displayio_refresh_displays(void) {
}
}
}
+
+ if (skip_this_display) {
+ // Go on to next display.
+ continue;
+ }
// Send the remaining data.
- if (index && !displayio_display_send_pixels(display, buffer, index * 2)) {
- displayio_display_finish_region_update(display);
- refreshing_displays = false;
- return;
+ if (index) {
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't get display bus. Skip the rest of the data. Try next display.
+ continue;
+ }
+ displayio_display_send_pixels(display, buffer, index * 2);
}
- displayio_display_finish_region_update(display);
+ displayio_display_end_transaction(display);
}
displayio_display_finish_refresh(display);
}
- refreshing_displays = false;
+
+ // All done.
+ refresh_displays_in_progress = false;
}
void common_hal_displayio_release_displays(void) {