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.
This commit is contained in:
parent
dc325a3f42
commit
952bea23f8
4 changed files with 28 additions and 6 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue