Skip to content

Commit

Permalink
Merge pull request #9989 from eightycc/issue-9983
Browse files Browse the repository at this point in the history
Handle errors during audio DMA playback setup for RP2 ports
  • Loading branch information
tannewt authored Jan 22, 2025
2 parents b323ae6 + 49dd58c commit 78a747e
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 9 deletions.
6 changes: 6 additions & 0 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,11 @@ msgstr ""
msgid "Audio conversion not implemented"
msgstr ""

#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Audio source error"
msgstr ""

#: shared-bindings/wifi/Radio.c
msgid "AuthMode.OPEN is not used with password"
msgstr ""
Expand Down Expand Up @@ -2334,6 +2339,7 @@ msgstr ""

#: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h
#: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h
#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h
msgid "You pressed the BOOT button at start up."
msgstr ""

Expand Down
12 changes: 10 additions & 2 deletions ports/raspberrypi/audio_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ static size_t audio_dma_convert_samples(audio_dma_t *dma, uint8_t *input, uint32

// buffer_idx is 0 or 1.
static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) {
assert(dma->channel[buffer_idx] < NUM_DMA_CHANNELS);
size_t dma_channel = dma->channel[buffer_idx];

audioio_get_buffer_result_t get_buffer_result;
Expand All @@ -128,6 +129,7 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) {

if (get_buffer_result == GET_BUFFER_ERROR) {
audio_dma_stop(dma);
dma->dma_result = AUDIO_DMA_SOURCE_ERROR;
return;
}

Expand Down Expand Up @@ -157,10 +159,10 @@ 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->playing_in_progress = false;
}
}
}
dma->dma_result = AUDIO_DMA_OK;
}

// Playback should be shutdown before calling this.
Expand Down Expand Up @@ -279,8 +281,14 @@ audio_dma_result audio_dma_setup_playback(

// Load the first two blocks up front.
audio_dma_load_next_block(dma, 0);
if (dma->dma_result != AUDIO_DMA_OK) {
return dma->dma_result;
}
if (!single_buffer) {
audio_dma_load_next_block(dma, 1);
if (dma->dma_result != AUDIO_DMA_OK) {
return dma->dma_result;
}
}

// Special case the DMA for a single buffer. It's commonly used for a single wave length of sound
Expand Down Expand Up @@ -464,7 +472,7 @@ static void dma_callback_fun(void *arg) {
void __not_in_flash_func(isr_dma_0)(void) {
for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) {
uint32_t mask = 1 << i;
if ((dma_hw->intr & mask) == 0) {
if ((dma_hw->ints0 & mask) == 0) {
continue;
}
// acknowledge interrupt early. Doing so late means that you could lose an
Expand Down
15 changes: 8 additions & 7 deletions ports/raspberrypi/audio_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@

#include "src/rp2_common/hardware_dma/include/hardware/dma.h"

typedef enum {
AUDIO_DMA_OK,
AUDIO_DMA_DMA_BUSY,
AUDIO_DMA_MEMORY_ERROR,
AUDIO_DMA_SOURCE_ERROR,
} audio_dma_result;

typedef struct {
mp_obj_t sample;
uint8_t *buffer[2];
Expand All @@ -24,6 +31,7 @@ typedef struct {
uint8_t sample_spacing;
uint8_t output_resolution; // in bits
uint8_t sample_resolution; // in bits
audio_dma_result dma_result;
bool loop;
bool single_channel_output;
bool signed_to_unsigned;
Expand All @@ -33,13 +41,6 @@ typedef struct {
bool swap_channel;
} audio_dma_t;

typedef enum {
AUDIO_DMA_OK,
AUDIO_DMA_DMA_BUSY,
AUDIO_DMA_MEMORY_ERROR,
} audio_dma_result;


void audio_dma_init(audio_dma_t *dma);
void audio_dma_deinit(audio_dma_t *dma);
void audio_dma_reset(void);
Expand Down
3 changes: 3 additions & 0 deletions ports/raspberrypi/common-hal/audiobusio/I2SOut.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
} else if (result == AUDIO_DMA_MEMORY_ERROR) {
common_hal_audiobusio_i2sout_stop(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to allocate buffers for signed conversion"));
} else if (result == AUDIO_DMA_SOURCE_ERROR) {
common_hal_audiobusio_i2sout_stop(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("Audio source error"));
}

self->playing = true;
Expand Down
4 changes: 4 additions & 0 deletions ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self,
common_hal_audiopwmio_pwmaudioout_stop(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to allocate buffers for signed conversion"));
}
if (result == AUDIO_DMA_SOURCE_ERROR) {
common_hal_audiopwmio_pwmaudioout_stop(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("Audio source error"));
}
// OK! We got all of the resources we need and dma is ready.
}

Expand Down

0 comments on commit 78a747e

Please sign in to comment.