Skip to content

Improvements to Audio DMA management #2043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions ports/atmel-samd/audio_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#include "py/mpstate.h"
#include "py/runtime.h"

#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO

static audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT];

// This cannot be in audio_dma_state because it's volatile.
Expand All @@ -50,6 +52,18 @@ uint8_t find_free_audio_dma_channel(void) {
return channel;
}

void audio_dma_disable_channel(uint8_t channel) {
if (channel >= AUDIO_DMA_CHANNEL_COUNT)
return;
dma_disable_channel(channel);
}

void audio_dma_enable_channel(uint8_t channel) {
if (channel >= AUDIO_DMA_CHANNEL_COUNT)
return;
dma_enable_channel(channel);
}

void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer_length,
uint8_t** output_buffer, uint32_t* output_buffer_length,
uint8_t* output_spacing) {
Expand Down Expand Up @@ -252,16 +266,19 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
}

dma_configure(dma_channel, dma_trigger_source, true);
dma_enable_channel(dma_channel);
audio_dma_enable_channel(dma_channel);

return AUDIO_DMA_OK;
}

void audio_dma_stop(audio_dma_t* dma) {
dma_disable_channel(dma->dma_channel);
disable_event_channel(dma->event_channel);
MP_STATE_PORT(playing_audio)[dma->dma_channel] = NULL;

uint8_t channel = dma->dma_channel;
if (channel < AUDIO_DMA_CHANNEL_COUNT) {
audio_dma_disable_channel(channel);
disable_event_channel(dma->event_channel);
MP_STATE_PORT(playing_audio)[channel] = NULL;
audio_dma_state[channel] = NULL;
}
dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT;
}

Expand Down Expand Up @@ -290,7 +307,7 @@ void audio_dma_reset(void) {
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
audio_dma_state[i] = NULL;
audio_dma_pending[i] = false;
dma_disable_channel(i);
audio_dma_disable_channel(i);
dma_descriptor(i)->BTCTRL.bit.VALID = false;
MP_STATE_PORT(playing_audio)[i] = NULL;
}
Expand Down Expand Up @@ -333,3 +350,4 @@ void audio_dma_background(void) {
audio_dma_pending[i] = false;
}
}
#endif
3 changes: 3 additions & 0 deletions ports/atmel-samd/audio_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
bool output_signed,
uint32_t output_register_address,
uint8_t dma_trigger_source);

void audio_dma_disable_channel(uint8_t channel);
void audio_dma_enable_channel(uint8_t channel);
void audio_dma_stop(audio_dma_t* dma);
bool audio_dma_get_playing(audio_dma_t* dma);
void audio_dma_pause(audio_dma_t* dma);
Expand Down
2 changes: 1 addition & 1 deletion ports/atmel-samd/background.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void run_background_tasks(void) {
assert_heap_ok();
running_background_tasks = true;

#if (defined(SAMD21) && defined(PIN_PA02)) || defined(SAMD51)
#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
audio_dma_background();
#endif
#if CIRCUITPY_DISPLAYIO
Expand Down
4 changes: 2 additions & 2 deletions ports/atmel-samd/common-hal/audiobusio/PDMIn.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
init_event_channel_interrupt(event_channel, CORE_GCLK, EVSYS_ID_GEN_DMAC_CH_0 + dma_channel);
// Turn on serializer now to get it in sync with DMA.
i2s_set_serializer_enable(self->serializer, true);
dma_enable_channel(dma_channel);
audio_dma_enable_channel(dma_channel);

// Record
uint32_t buffers_processed = 0;
Expand Down Expand Up @@ -466,7 +466,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
}

disable_event_channel(event_channel);
dma_disable_channel(dma_channel);
audio_dma_disable_channel(dma_channel);
// Turn off serializer, but leave clock on, to avoid mic startup delay.
i2s_set_serializer_enable(self->serializer, false);

Expand Down