Skip to content

Commit 952bea2

Browse files
committed
Run background tasks during display refresh
This allows audio buffers to be filled during display refresh. Howevere, this only works during explicit refreshes though because background tasks cannot be recursive. Also, on RP2, disable a finished audio DMA so it isn't accidentally triggered and restart the channels if needed.
1 parent dc325a3 commit 952bea2

File tree

4 files changed

+28
-6
lines changed

4 files changed

+28
-6
lines changed

ports/raspberrypi/audio_dma.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,13 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) {
159159
!dma_channel_is_busy(dma->channel[1])) {
160160
// No data has been read, and both DMA channels have now finished, so it's safe to stop.
161161
audio_dma_stop(dma);
162+
dma->dma_result = AUDIO_DMA_OK;
163+
return;
162164
}
163165
}
164166
}
167+
// Enable the channel so that it can be played.
168+
dma_hw->ch[dma_channel].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS;
165169
dma->dma_result = AUDIO_DMA_OK;
166170
}
167171

@@ -462,18 +466,26 @@ static void dma_callback_fun(void *arg) {
462466

463467
// Load the blocks for the requested channels.
464468
uint32_t channel = 0;
469+
size_t filled_count = 0;
465470
while (channels_to_load_mask) {
466471
if (channels_to_load_mask & 1) {
467472
if (dma->channel[0] == channel) {
468473
audio_dma_load_next_block(dma, 0);
474+
filled_count++;
469475
}
470476
if (dma->channel[1] == channel) {
471477
audio_dma_load_next_block(dma, 1);
478+
filled_count++;
472479
}
473480
}
474481
channels_to_load_mask >>= 1;
475482
channel++;
476483
}
484+
// If we had to fill both buffers, then we missed the trigger from the other
485+
// buffer. So restart the DMA.
486+
if (filled_count == 2) {
487+
dma_channel_start(dma->channel[0]);
488+
}
477489
}
478490

479491
void __not_in_flash_func(isr_dma_0)(void) {
@@ -491,6 +503,8 @@ void __not_in_flash_func(isr_dma_0)(void) {
491503
audio_dma_t *dma = MP_STATE_PORT(playing_audio)[i];
492504
// Record all channels whose DMA has completed; they need loading.
493505
dma->channels_to_load_mask |= mask;
506+
// Disable the channel so that we don't play it without filling it.
507+
dma_hw->ch[i].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS;
494508
background_callback_add(&dma->callback, dma_callback_fun, (void *)dma);
495509
}
496510
if (MP_STATE_PORT(background_pio_read)[i] != NULL) {

shared-module/busdisplay/BusDisplay.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,11 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
296296
_send_pixels(self, (uint8_t *)buffer, subrectangle_size_bytes);
297297
displayio_display_bus_end_transaction(&self->bus);
298298

299-
// TODO(tannewt): Make refresh displays faster so we don't starve other
300-
// background tasks.
299+
// Run background tasks so they can run during an explicit refresh.
300+
// Auto-refresh won't run background tasks here because it is a background task itself.
301+
RUN_BACKGROUND_TASKS;
302+
303+
// Run USB background tasks so they can run during an implicit refresh.
301304
#if CIRCUITPY_TINYUSB
302305
usb_background();
303306
#endif

shared-module/epaperdisplay/EPaperDisplay.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,11 @@ static bool epaperdisplay_epaperdisplay_refresh_area(epaperdisplay_epaperdisplay
360360
self->bus.send(self->bus.bus, DISPLAY_DATA, self->chip_select, (uint8_t *)buffer, subrectangle_size_bytes);
361361
displayio_display_bus_end_transaction(&self->bus);
362362

363-
// TODO(tannewt): Make refresh displays faster so we don't starve other
364-
// background tasks.
363+
// Run background tasks so they can run during an explicit refresh.
364+
// Auto-refresh won't run background tasks here because it is a background task itself.
365+
RUN_BACKGROUND_TASKS;
366+
367+
// Run USB background tasks so they can run during an implicit refresh.
365368
#if CIRCUITPY_TINYUSB
366369
usb_background();
367370
#endif

shared-module/framebufferio/FramebufferDisplay.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,11 @@ static bool _refresh_area(framebufferio_framebufferdisplay_obj_t *self, const di
200200
dest += rowstride;
201201
src += rowsize;
202202
}
203+
// Run background tasks so they can run during an explicit refresh.
204+
// Auto-refresh won't run background tasks here because it is a background task itself.
205+
RUN_BACKGROUND_TASKS;
203206

204-
// TODO(tannewt): Make refresh displays faster so we don't starve other
205-
// background tasks.
207+
// Run USB background tasks so they can run during an implicit refresh.
206208
#if CIRCUITPY_TINYUSB
207209
usb_background();
208210
#endif

0 commit comments

Comments
 (0)