8000 Merge pull request #1620 from dhalbert/display-transactions-fix · rhwlo/circuitpython@2de8236 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2de8236

Browse files
authored
Merge pull request adafruit#1620 from dhalbert/display-transactions-fix
Rework displayio display bus transaction handling during refresh
2 parents 2eaa98a + 26ed411 commit 2de8236

File tree

6 files changed

+76
-30
lines changed

6 files changed

+76
-30
lines changed

ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ LONGINT_IMPL = MPZ
1313
CHIP_VARIANT = SAMD21G18A
1414
CHIP_FAMILY = samd21
1515

16+
CFLAGS_INLINE_LIMIT = 70
17+
1618
CIRCUITPY_NETWORK = 1
1719
MICROPY_PY_WIZNET5K = 5500
1820

shared-bindings/displayio/Display.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@ void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_
4848

4949
void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self);
5050

51-
void displayio_display_start_region_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
52-
void displayio_display_finish_region_update(displayio_display_obj_t* self);
51+
bool displayio_display_begin_transaction(displayio_display_obj_t* self);
52+
void displayio_display_end_transaction(displayio_display_obj_t* self);
53+
54+
void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
5355
bool displayio_display_frame_queued(displayio_display_obj_t* self);
5456

5557
bool displayio_display_refresh_queued(displayio_display_obj_t* self);
5658
void displayio_display_finish_refresh(displayio_display_obj_t* self);
57-
bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length);
59+
void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length);
5860

5961
bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self);
6062
void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness);

shared-bindings/displayio/FourWire.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ STATIC mp_obj_t displayio_fourwire_obj_send(mp_obj_t self, mp_obj_t command_obj,
110110
mp_buffer_info_t bufinfo;
111111
mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
112112

113-
common_hal_displayio_fourwire_begin_transaction(self);
113+
// Wait for display bus to be available.
114+
while (!common_hal_displayio_fourwire_begin_transaction(self)) {
115+
#ifdef MICROPY_VM_HOOK_LOOP
116+
MICROPY_VM_HOOK_LOOP ;
117+
#endif
118+
}
114119
common_hal_displayio_fourwire_send(self, true, &command, 1);
115120
common_hal_displayio_fourwire_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
116121
common_hal_displayio_fourwire_end_transaction(self);

shared-bindings/displayio/ParallelBus.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,12 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o
114114
mp_buffer_info_t bufinfo;
115115
mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
116116

117-
common_hal_displayio_parallelbus_begin_transaction(self);
117+
// Wait for display bus to be available.
118+
while (!common_hal_displayio_parallelbus_begin_transaction(self)) {
119+
#ifdef MICROPY_VM_HOOK_LOOP
120+
MICROPY_VM_HOOK_LOOP ;
121+
#endif
122+
}
118123
common_hal_displayio_parallelbus_send(self, true, &command, 1);
119124
common_hal_displayio_parallelbus_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
120125
common_hal_displayio_parallelbus_end_transaction(self);

shared-module/displayio/Display.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
6969
self->bus = bus;
7070

7171
uint32_t i = 0;
72-
self->begin_transaction(self->bus);
72+
while (!self->begin_transaction(self->bus)) {
73+
#ifdef MICROPY_VM_HOOK_LOOP
74+
MICROPY_VM_HOOK_LOOP ;
75+
#endif
76+
}
7377
while (i < init_sequence_len) {
7478
uint8_t *cmd = init_sequence + i;
7579
uint8_t data_size = *(cmd + 1);
@@ -198,9 +202,16 @@ bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self,
198202
return ok;
199203
}
200204

201-
void displayio_display_start_region_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
205+
bool displayio_display_begin_transaction(displayio_display_obj_t* self) {
206+
return self->begin_transaction(self->bus);
207+
}
208+
209+
void displayio_display_end_transaction(displayio_display_obj_t* self) {
210+
self->end_transaction(self->bus);
211+
}
212+
213+
void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
202214
// TODO(tannewt): Handle displays with single byte bounds.
203-
self->begin_transaction(self->bus);
204215
uint16_t data[2];
205216
self->send(self->bus, true, &self->set_column_command, 1);
206217
data[0] = __builtin_bswap16(x0 + self->colstart);
@@ -213,10 +224,6 @@ void displayio_display_start_region_update(displayio_display_obj_t* self, uint16
213224
self->send(self->bus, true, &self->write_ram_command, 1);
214225
}
215226

216-
void displayio_display_finish_region_update(displayio_display_obj_t* self) {
217-
self->end_transaction(self->bus);
218-
}
219-
220227
bool displayio_display_frame_queued(displayio_display_obj_t* self) {
221228
// Refresh at ~30 fps.
222229
return (ticks_ms - self->last_refresh) > 32;
@@ -234,9 +241,8 @@ void displayio_display_finish_refresh(displayio_display_obj_t* self) {
234241
self->last_refresh = ticks_ms;
235242
}
236243

237-
bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
244+
void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
238245
self->send(self->bus, false, (uint8_t*) pixels, length * 4);
239-
return true;
240246
}
241247

242248
void displayio_display_update_backlight(displayio_display_obj_t* self) {

shared-module/displayio/__init__.c

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ static inline void swap(uint16_t* a, uint16_t* b) {
2222
*b = temp;
2323
}
2424

25-
bool refreshing_displays = false;
25+
// Check for recursive calls to displayio_refresh_displays.
26+
bool refresh_displays_in_progress = false;
2627

2728
void displayio_refresh_displays(void) {
2829
if (mp_hal_is_interrupted()) {
@@ -35,20 +36,25 @@ void displayio_refresh_displays(void) {
3536
return;
3637
}
3738

38-
if (refreshing_displays) {
39+
if (refresh_displays_in_progress) {
40+
// Don't allow recursive calls to this routine.
3941
return;
4042
}
41-
refreshing_displays = true;
43+
44+
refresh_displays_in_progress = true;
45+
4246
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
4347
if (displays[i].display.base.type == NULL || displays[i].display.base.type == &mp_type_NoneType) {
48+
// Skip null display.
4449
continue;
4550
}
4651
displayio_display_obj_t* display = &displays[i].display;
4752
displayio_display_update_backlight(display);
4853

54+
// Time to refresh at specified frame rate?
4955
if (!displayio_display_frame_queued(display)) {
50-
refreshing_displays = false;
51-
return;
56+
// Too soon. Try next display.
57+
continue;
5258
}
5359
if (displayio_display_refresh_queued(display)) {
5460
// 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) {
6066
if (display->transpose_xy) {
6167
swap(&c1, &r1);
6268
}
63-
displayio_display_start_region_update(display, c0, r0, c1, r1);
69+
70+
if (!displayio_display_begin_transaction(display)) {
71+
// Can't acquire display bus; skip updating this display. Try next display.
72+
continue;
73+
}
74+
displayio_display_set_region_to_update(display, c0, r0, c1, r1);
75+
displayio_display_end_transaction(display);
6476

6577
uint16_t x0 = 0;
6678
uint16_t x1 = display->width - 1;
@@ -94,6 +106,8 @@ void displayio_refresh_displays(void) {
94106
size_t index = 0;
95107
uint16_t buffer_size = 256;
96108
uint32_t buffer[buffer_size / 2];
109+
bool skip_this_display = false;
110+
97111
for (uint16_t y = starty; y0 <= y && y <= y1; y += dy) {
98112
for (uint16_t x = startx; x0 <= x && x <= x1; x += dx) {
99113
uint16_t* pixel = &(((uint16_t*)buffer)[index]);
@@ -110,29 +124,41 @@ void displayio_refresh_displays(void) {
110124
index += 1;
111125
// The buffer is full, send it.
112126
if (index >= buffer_size) {
113-
if (!displayio_display_send_pixels(display, buffer, buffer_size / 2) || reload_requested) {
114-
displayio_display_finish_region_update(display);
115-
refreshing_displays = false;
116-
return;
127+
if (!displayio_display_begin_transaction(display)) {
128+
// Can't acquire display bus; skip the rest of the data. Try next display.
129+
index = 0;
130+
skip_this_display = true;
131+
break;
117132
}
133+
displayio_display_send_pixels(display, buffer, buffer_size / 2);
134+
displayio_display_end_transaction(display);
118135
// TODO(tannewt): Make refresh displays faster so we don't starve other
119136
// background tasks.
120137
usb_background();
121138
index = 0;
122139
}
123140
}
124141
}
142+
143+
if (skip_this_display) {
144+
// Go on to next display.
145+
continue;
146+
}
125147
// Send the remaining data.
126-
if (index && !displayio_display_send_pixels(display, buffer, index * 2)) {
127-
displayio_display_finish_region_update(display);
128-
refreshing_displays = false;
129-
return;
148+
if (index) {
149+
if (!displayio_display_begin_transaction(display)) {
150+
// Can't get display bus. Skip the rest of the data. Try next display.
151+
continue;
152+
}
153+
displayio_display_send_pixels(display, buffer, index * 2);
130154
}
131-
displayio_display_finish_region_update(display);
155+
displayio_display_end_transaction(display);
132156
}
133157
displayio_display_finish_refresh(display);
134158
}
135-
refreshing_displays = false;
159+
160+
// All done.
161+
refresh_displays_in_progress = false;
136162
}
137163

138164
void common_hal_displayio_release_displays(void) {

0 commit comments

Comments
 (0)
0