Skip to content

Commit c37e3a7

Browse files
committed
Fix display bus transaction handling.
Fixes #10569
1 parent 117b5d1 commit c37e3a7

File tree

4 files changed

+39
-26
lines changed

4 files changed

+39
-26
lines changed

shared-module/busdisplay/BusDisplay.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,10 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
273273
}
274274
remaining_rows -= rows_per_buffer;
275275

276-
displayio_display_bus_set_region_to_update(&self->bus, &self->core, &subrectangle);
276+
if (!displayio_display_bus_set_region_to_update(&self->bus, &self->core, &subrectangle)) {
277+
// This is a failure to acquire the bus, skip the rest of the refresh.
278+
return false;
279+
}
277280

278281
uint16_t subrectangle_size_bytes;
279282
if (self->core.colorspace.depth >= 8) {
@@ -287,12 +290,11 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
287290

288291
displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer);
289292

290-
// Can't acquire display bus; skip the rest of the data.
291-
if (!displayio_display_bus_is_free(&self->bus)) {
293+
// If we can't acquire display bus; skip the rest of the data.
294+
if (!displayio_display_bus_begin_transaction(&self->bus)) {
292295
return false;
293296
}
294297

295-
displayio_display_bus_begin_transaction(&self->bus);
296298
_send_pixels(self, (uint8_t *)buffer, subrectangle_size_bytes);
297299
displayio_display_bus_end_transaction(&self->bus);
298300

@@ -310,7 +312,7 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
310312

311313
static void _refresh_display(busdisplay_busdisplay_obj_t *self) {
312314
if (!displayio_display_bus_is_free(&self->bus)) {
313-
// A refresh on this bus is already in progress. Try next display.
315+
// Don't bother with the refresh if the bus is already busy
314316
return;
315317
}
316318
displayio_display_core_start_refresh(&self->core);

shared-module/displayio/bus_core.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ void displayio_display_bus_end_transaction(displayio_display_bus_t *self) {
101101
self->end_transaction(self->bus);
102102
}
103103

104-
void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area) {
104+
// Determine if this is run from a background task or not. Should we skip sending the data or wait for the bus?
105+
bool displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area) {
105106
uint16_t x1 = area->x1 + self->colstart;
106107
uint16_t x2 = area->x2 + self->colstart;
107108
uint16_t y1 = area->y1 + self->rowstart;
@@ -127,8 +128,12 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d
127128
chip_select = CHIP_SELECT_TOGGLE_EVERY_BYTE;
128129
}
129130

131+
if (!displayio_display_bus_begin_transaction(self)) {
132+
// Can't acquire display bus; skip and report failure.
133+
return false;
134+
}
135+
130136
// Set column.
131-
displayio_display_bus_begin_transaction(self);
132137
uint8_t data[5];
133138
data[0] = self->column_command;
134139
uint8_t data_length = 1;
@@ -163,20 +168,16 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d
163168
}
164169

165170
self->send(self->bus, data_type, chip_select, data, data_length);
166-
displayio_display_bus_end_transaction(self);
167171

168172
if (self->set_current_column_command != NO_COMMAND) {
169173
uint8_t command = self->set_current_column_command;
170-
displayio_display_bus_begin_transaction(self);
171174
self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1);
172175
// Only send the first half of data because it is the first coordinate.
173176
self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2);
174-
displayio_display_bus_end_transaction(self);
175177
}
176178

177179

178180
// Set row.
179-
displayio_display_bus_begin_transaction(self);
180181
data[0] = self->row_command;
181182
data_length = 1;
182183
if (!self->data_as_commands) {
@@ -207,16 +208,15 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d
207208
}
208209

209210
self->send(self->bus, data_type, chip_select, data, data_length);
210-
displayio_display_bus_end_transaction(self);
211211

212212
if (self->set_current_row_command != NO_COMMAND) {
213213
uint8_t command = self->set_current_row_command;
214-
displayio_display_bus_begin_transaction(self);
215214
self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1);
216215
// Only send the first half of data because it is the first coordinate.
217216
self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2);
218-
displayio_display_bus_end_transaction(self);
219217
}
218+
displayio_display_bus_end_transaction(self);
219+
return true;
220220
}
221221

222222
void displayio_display_bus_collect_ptrs(displayio_display_bus_t *self) {

shared-module/displayio/bus_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ bool displayio_display_bus_is_free(displayio_display_bus_t *self);
4747
bool displayio_display_bus_begin_transaction(displayio_display_bus_t *self);
4848
void displayio_display_bus_end_transaction(displayio_display_bus_t *self);
4949

50-
void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area);
50+
bool displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area);
5151

5252
void release_display_bus(displayio_display_bus_t *self);
5353

shared-module/epaperdisplay/EPaperDisplay.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@ static void send_command_sequence(epaperdisplay_epaperdisplay_obj_t *self,
162162
data_size = ((data_size & ~DELAY) << 8) + *(cmd + 2);
163163
data = cmd + 3;
164164
}
165-
displayio_display_bus_begin_transaction(&self->bus);
165+
while (!displayio_display_bus_begin_transaction(&self->bus)) {
166+
RUN_BACKGROUND_TASKS;
167+
}
166168
self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, cmd, 1);
167169
self->bus.send(self->bus.bus, DISPLAY_DATA, self->chip_select, data, data_size);
168170
displayio_display_bus_end_transaction(&self->bus);
@@ -310,14 +312,21 @@ static bool epaperdisplay_epaperdisplay_refresh_area(epaperdisplay_epaperdisplay
310312
uint16_t remaining_rows = displayio_area_height(&clipped);
311313

312314
if (self->bus.row_command != NO_COMMAND) {
313-
displayio_display_bus_set_region_to_update(&self->bus, &self->core, &clipped);
315+
if (!displayio_display_bus_set_region_to_update(&self->bus, &self->core, &clipped)) {
316+
// This is a failure to acquire the bus, skip the rest of the refresh.
317+
return false;
318+
}
314319
}
315320

316321
uint8_t write_command = self->write_black_ram_command;
317322
if (pass == 1) {
318323
write_command = self->write_color_ram_command;
319324
}
320-
displayio_display_bus_begin_transaction(&self->bus);
325+
326+
if (!displayio_display_bus_begin_transaction(&self->bus)) {
327+
// We can't acquire the bus skip the rest of the refresh.
328+
return false;
329+
}
321330
self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1);
322331
displayio_display_bus_end_transaction(&self->bus);
323332

@@ -394,24 +403,26 @@ static bool _clean_area(epaperdisplay_epaperdisplay_obj_t *self) {
394403
memset(buffer, 0x77, width / 2);
395404

396405
uint8_t write_command = self->write_black_ram_command;
397-
displayio_display_bus_begin_transaction(&self->bus);
406+
407+
if (!displayio_display_bus_begin_transaction(&self->bus)) {
408+
// Can't acquire display bus; skip the rest of the data. Try next display.
409+
return false;
410+
}
398411
self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1);
399-
displayio_display_bus_end_transaction(&self->bus);
400412

401413
for (uint16_t j = 0; j < height; j++) {
402-
if (!displayio_display_bus_begin_transaction(&self->bus)) {
403-
// Can't acquire display bus; skip the rest of the data. Try next display.
404-
return false;
405-
}
406414
self->bus.send(self->bus.bus, DISPLAY_DATA, self->chip_select, buffer, width / 2);
407-
displayio_display_bus_end_transaction(&self->bus);
408415

409416
// TODO(tannewt): Make refresh displays faster so we don't starve other
410417
// background tasks.
411418
#if CIRCUITPY_TINYUSB
412-
usb_background();
419+
displayio_display_bus_end_transaction(&self->bus);
420+
do {
421+
usb_background();
422+
} while (!displayio_display_bus_begin_transaction(&self->bus));
413423
#endif
414424
}
425+
displayio_display_bus_end_transaction(&self->bus);
415426

416427
return true;
417428
}

0 commit comments

Comments
 (0)