diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c index 481a420cbc..0478cc9bf4 100644 --- a/ports/atmel-samd/audio_dma.c +++ b/ports/atmel-samd/audio_dma.c @@ -42,14 +42,24 @@ static audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT]; // This cannot be in audio_dma_state because it's volatile. static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT]; -uint8_t find_free_audio_dma_channel(void) { +static bool audio_dma_allocated[AUDIO_DMA_CHANNEL_COUNT]; + +uint8_t audio_dma_allocate_channel(void) { uint8_t channel; for (channel = 0; channel < AUDIO_DMA_CHANNEL_COUNT; channel++) { - if (!dma_channel_enabled(channel)) { + if (!audio_dma_allocated[channel]) { + audio_dma_allocated[channel] = true; return channel; } } - return channel; + return channel; // i.e., return failure +} + +void audio_dma_free_channel(uint8_t channel) { + assert(channel < AUDIO_DMA_CHANNEL_COUNT); + assert(audio_dma_allocated[channel]); + audio_dma_disable_channel(channel); + audio_dma_allocated[channel] = false; } void audio_dma_disable_channel(uint8_t channel) { @@ -167,7 +177,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma, bool output_signed, uint32_t output_register_address, uint8_t dma_trigger_source) { - uint8_t dma_channel = find_free_audio_dma_channel(); + uint8_t dma_channel = audio_dma_allocate_channel(); if (dma_channel >= AUDIO_DMA_CHANNEL_COUNT) { return AUDIO_DMA_DMA_BUSY; } @@ -278,6 +288,7 @@ void audio_dma_stop(audio_dma_t* dma) { disable_event_channel(dma->event_channel); MP_STATE_PORT(playing_audio)[channel] = NULL; audio_dma_state[channel] = NULL; + audio_dma_free_channel(dma->dma_channel); } dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT; } @@ -307,6 +318,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; + audio_dma_allocated[i] = false; audio_dma_disable_channel(i); dma_descriptor(i)->BTCTRL.bit.VALID = false; MP_STATE_PORT(playing_audio)[i] = NULL; diff --git a/ports/atmel-samd/audio_dma.h b/ports/atmel-samd/audio_dma.h index 9d923c5ce1..1ebec6f7e9 100644 --- a/ports/atmel-samd/audio_dma.h +++ b/ports/atmel-samd/audio_dma.h @@ -64,7 +64,8 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj); void audio_dma_init(audio_dma_t* dma); void audio_dma_reset(void); -uint8_t find_free_audio_dma_channel(void); +uint8_t audio_dma_allocate_channel(void); +void audio_dma_free_channel(uint8_t channel); // This sets everything up but doesn't start the timer. // Sample is the python object for the sample to play. diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c index 76010a6843..3a51cce8f1 100644 --- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -355,7 +355,7 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) { // output_buffer_length is the number of slots, not the number of bytes. uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self, uint16_t* output_buffer, uint32_t output_buffer_length) { - uint8_t dma_channel = find_free_audio_dma_channel(); + uint8_t dma_channel = audio_dma_allocate_channel(); uint8_t event_channel = find_sync_event_channel(); if (event_channel >= EVSYS_SYNCH_NUM) { mp_raise_RuntimeError(translate("All sync event channels in use")); @@ -464,7 +464,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se } disable_event_channel(event_channel); - audio_dma_disable_channel(dma_channel); + audio_dma_free_channel(dma_channel); // Turn off serializer, but leave clock on, to avoid mic startup delay. i2s_set_serializer_enable(self->serializer, false); diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c index 90f1aa41f6..bb7e76414f 100644 --- a/ports/atmel-samd/common-hal/audioio/AudioOut.c +++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -312,6 +312,10 @@ void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self) { return; } + if (common_hal_audioio_audioout_get_playing(self)) { + common_hal_audioio_audioout_stop(self); + } + // Ramp the DAC down. ramp_value(self->quiescent_value, 0);