diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c index 1d9642a16ea10..d9adc3064a841 100644 --- a/ports/raspberrypi/audio_dma.c +++ b/ports/raspberrypi/audio_dma.c @@ -159,9 +159,13 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) { !dma_channel_is_busy(dma->channel[1])) { // No data has been read, and both DMA channels have now finished, so it's safe to stop. audio_dma_stop(dma); + dma->dma_result = AUDIO_DMA_OK; + return; } } } + // Enable the channel so that it can be played. + dma_hw->ch[dma_channel].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS; dma->dma_result = AUDIO_DMA_OK; } @@ -462,18 +466,26 @@ static void dma_callback_fun(void *arg) { // Load the blocks for the requested channels. uint32_t channel = 0; + size_t filled_count = 0; while (channels_to_load_mask) { if (channels_to_load_mask & 1) { if (dma->channel[0] == channel) { audio_dma_load_next_block(dma, 0); + filled_count++; } if (dma->channel[1] == channel) { audio_dma_load_next_block(dma, 1); + filled_count++; } } channels_to_load_mask >>= 1; channel++; } + // If we had to fill both buffers, then we missed the trigger from the other + // buffer. So restart the DMA. + if (filled_count == 2) { + dma_channel_start(dma->channel[0]); + } } void __not_in_flash_func(isr_dma_0)(void) { @@ -491,6 +503,8 @@ void __not_in_flash_func(isr_dma_0)(void) { audio_dma_t *dma = MP_STATE_PORT(playing_audio)[i]; // Record all channels whose DMA has completed; they need loading. dma->channels_to_load_mask |= mask; + // Disable the channel so that we don't play it without filling it. + dma_hw->ch[i].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS; background_callback_add(&dma->callback, dma_callback_fun, (void *)dma); } if (MP_STATE_PORT(background_pio_read)[i] != NULL) { diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index 001f2f20c03e3..ac57f3bf3e019 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -296,8 +296,11 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are _send_pixels(self, (uint8_t *)buffer, subrectangle_size_bytes); displayio_display_bus_end_transaction(&self->bus); - // TODO(tannewt): Make refresh displays faster so we don't starve other - // background tasks. + // Run background tasks so they can run during an explicit refresh. + // Auto-refresh won't run background tasks here because it is a background task itself. + RUN_BACKGROUND_TASKS; + + // Run USB background tasks so they can run during an implicit refresh. #if CIRCUITPY_TINYUSB usb_background(); #endif diff --git a/shared-module/epaperdisplay/EPaperDisplay.c b/shared-module/epaperdisplay/EPaperDisplay.c index 14fbc3341b5ff..86ecff29b1102 100644 --- a/shared-module/epaperdisplay/EPaperDisplay.c +++ b/shared-module/epaperdisplay/EPaperDisplay.c @@ -360,8 +360,11 @@ static bool epaperdisplay_epaperdisplay_refresh_area(epaperdisplay_epaperdisplay self->bus.send(self->bus.bus, DISPLAY_DATA, self->chip_select, (uint8_t *)buffer, subrectangle_size_bytes); displayio_display_bus_end_transaction(&self->bus); - // TODO(tannewt): Make refresh displays faster so we don't starve other - // background tasks. + // Run background tasks so they can run during an explicit refresh. + // Auto-refresh won't run background tasks here because it is a background task itself. + RUN_BACKGROUND_TASKS; + + // Run USB background tasks so they can run during an implicit refresh. #if CIRCUITPY_TINYUSB usb_background(); #endif diff --git a/shared-module/framebufferio/FramebufferDisplay.c b/shared-module/framebufferio/FramebufferDisplay.c index c9fe52e0e40b1..4ba2b1325815c 100644 --- a/shared-module/framebufferio/FramebufferDisplay.c +++ b/shared-module/framebufferio/FramebufferDisplay.c @@ -200,9 +200,11 @@ static bool _refresh_area(framebufferio_framebufferdisplay_obj_t *self, const di dest += rowstride; src += rowsize; } + // Run background tasks so they can run during an explicit refresh. + // Auto-refresh won't run background tasks here because it is a background task itself. + RUN_BACKGROUND_TASKS; - // TODO(tannewt): Make refresh displays faster so we don't starve other - // background tasks. + // Run USB background tasks so they can run during an implicit refresh. #if CIRCUITPY_TINYUSB usb_background(); #endif