3131
3232#include "shared-bindings/audiocore/RawSample.h"
3333#include "shared-bindings/audiocore/WaveFile.h"
34- #include "supervisor/shared/tick .h"
34+ #include "supervisor/background_callback .h"
3535
3636#include "py/mpstate.h"
3737#include "py/runtime.h"
@@ -61,7 +61,6 @@ void audio_dma_free_channel(uint8_t channel) {
6161 assert (audio_dma_allocated [channel ]);
6262 audio_dma_disable_channel (channel );
6363 audio_dma_allocated [channel ] = false;
64- supervisor_disable_tick ();
6564}
6665
6766void audio_dma_disable_channel (uint8_t channel ) {
@@ -73,7 +72,6 @@ void audio_dma_disable_channel(uint8_t channel) {
7372void audio_dma_enable_channel (uint8_t channel ) {
7473 if (channel >= AUDIO_DMA_CHANNEL_COUNT )
7574 return ;
76- supervisor_enable_tick ();
7775 dma_enable_channel (channel );
7876}
7977
@@ -259,6 +257,15 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
259257 dma -> beat_size *= 2 ;
260258 }
261259
260+ #ifdef SAM_D5X_E5X
261+ int irq = dma -> event_channel < 4 ? EVSYS_0_IRQn + dma -> event_channel : EVSYS_4_IRQn ;
262+ #else
263+ int irq = EVSYS_IRQn ;
264+ #endif
265+
266+ NVIC_DisableIRQ (irq );
267+ NVIC_ClearPendingIRQ (irq );
268+
262269 DmacDescriptor * first_descriptor = dma_descriptor (dma_channel );
263270 setup_audio_descriptor (first_descriptor , dma -> beat_size , output_spacing , output_register_address );
264271 if (single_buffer ) {
@@ -281,6 +288,8 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
281288 dma_configure (dma_channel , dma_trigger_source , true);
282289 audio_dma_enable_channel (dma_channel );
283290
291+ NVIC_EnableIRQ (irq );
292+
284293 return AUDIO_DMA_OK ;
285294}
286295
@@ -321,9 +330,6 @@ void audio_dma_reset(void) {
321330 for (uint8_t i = 0 ; i < AUDIO_DMA_CHANNEL_COUNT ; i ++ ) {
322331 audio_dma_state [i ] = NULL ;
323332 audio_dma_pending [i ] = false;
324- if (audio_dma_allocated [i ]) {
325- supervisor_disable_tick ();
326- }
327333 audio_dma_allocated [i ] = false;
328334 audio_dma_disable_channel (i );
329335 dma_descriptor (i )-> BTCTRL .bit .VALID = false;
@@ -343,29 +349,39 @@ bool audio_dma_get_playing(audio_dma_t* dma) {
343349 return (status & DMAC_CHINTFLAG_TERR ) == 0 ;
344350}
345351
346- // WARN(tannewt): DO NOT print from here. Printing calls background tasks such as this and causes a
347- // stack overflow.
352+ // WARN(tannewt): DO NOT print from here, or anything it calls. Printing calls
353+ // background tasks such as this and causes a stack overflow.
354+ STATIC void dma_callback_fun (void * arg ) {
355+ audio_dma_t * dma = arg ;
356+ if (dma == NULL ) {
357+ return ;
358+ }
359+
360+ audio_dma_load_next_block (dma );
361+ }
348362
349- void audio_dma_background (void ) {
363+ void evsyshandler_common (void ) {
350364 for (uint8_t i = 0 ; i < AUDIO_DMA_CHANNEL_COUNT ; i ++ ) {
351- if (audio_dma_pending [i ]) {
352- continue ;
353- }
354365 audio_dma_t * dma = audio_dma_state [i ];
355366 if (dma == NULL ) {
356367 continue ;
357368 }
358-
359369 bool block_done = event_interrupt_active (dma -> event_channel );
360370 if (!block_done ) {
361371 continue ;
362372 }
363-
364- // audio_dma_load_next_block() can call Python code, which can call audio_dma_background()
365- // recursively at the next background processing time. So disallow recursive calls to here.
366- audio_dma_pending [i ] = true;
367- audio_dma_load_next_block (dma );
368- audio_dma_pending [i ] = false;
373+ background_callback_add (& dma -> callback , dma_callback_fun , (void * )dma );
369374 }
370375}
376+
377+ #ifdef SAM_D5X_E5X
378+ void EVSYS_0_Handler (void ) { evsyshandler_common (); }
379+ void EVSYS_1_Handler (void ) { evsyshandler_common (); }
380+ void EVSYS_2_Handler (void ) { evsyshandler_common (); }
381+ void EVSYS_3_Handler (void ) { evsyshandler_common (); }
382+ void EVSYS_4_Handler (void ) { evsyshandler_common (); }
383+ #else
384+ void EVSYS_Handler (void ) { evsyshandler_common (); }
385+ #endif
386+
371387#endif
0 commit comments