@@ -118,8 +118,7 @@ static size_t audio_dma_convert_samples(audio_dma_t *dma, uint8_t *input, uint32
118118
119119// buffer_idx is 0 or 1.
120120static void audio_dma_load_next_block (audio_dma_t * dma , size_t buffer_idx ) {
121- assert (dma -> channel [buffer_idx ] < NUM_DMA_CHANNELS );
122- size_t dma_channel = dma -> channel [buffer_idx ];
121+ assert (dma -> data_channel < NUM_DMA_CHANNELS );
123122
124123 audioio_get_buffer_result_t get_buffer_result ;
125124 uint8_t * sample_buffer ;
@@ -141,22 +140,20 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) {
141140 dma , sample_buffer , sample_buffer_length ,
142141 dma -> buffer [buffer_idx ], dma -> buffer_length [buffer_idx ]);
143142
144- dma_channel_set_read_addr ( dma_channel , dma -> buffer [ buffer_idx ], false /* trigger */ );
145- dma_channel_set_trans_count (dma_channel , output_length_used / dma -> output_size , false /* trigger */ );
143+ // We're setting this early. It gets loaded when the buffer we're filling is triggered.
144+ dma_channel_set_trans_count (dma -> data_channel , output_length_used / dma -> output_size , false /* trigger */ );
146145
147146 if (get_buffer_result == GET_BUFFER_DONE ) {
148147 if (dma -> loop ) {
149148 audiosample_reset_buffer (dma -> sample , dma -> single_channel_output , dma -> audio_channel );
150149 } else {
151150 // Set channel trigger to ourselves so we don't keep going.
152- dma_channel_hw_t * c = & dma_hw -> ch [dma_channel ];
151+ dma_channel_hw_t * c = & dma_hw -> ch [dma -> data_channel ];
153152 c -> al1_ctrl =
154153 (c -> al1_ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS ) |
155- (dma_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB );
154+ (dma -> data_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB );
156155
157- if (output_length_used == 0 &&
158- !dma_channel_is_busy (dma -> channel [0 ]) &&
159- !dma_channel_is_busy (dma -> channel [1 ])) {
156+ if (output_length_used == 0 && !dma_channel_is_busy (dma -> data_channel )) {
160157 // No data has been read, and both DMA channels have now finished, so it's safe to stop.
161158 audio_dma_stop (dma );
162159 }
@@ -180,19 +177,19 @@ audio_dma_result audio_dma_setup_playback(
180177
181178 // Use two DMA channels to play because the DMA can't wrap to itself without the
182179 // buffer being power of two aligned.
183- int dma_channel_0_maybe = dma_claim_unused_channel (false);
184- if (dma_channel_0_maybe < 0 ) {
180+ int control_channel_maybe = dma_claim_unused_channel (false);
181+ if (control_channel_maybe < 0 ) {
185182 return AUDIO_DMA_DMA_BUSY ;
186183 }
187184
188- int dma_channel_1_maybe = dma_claim_unused_channel (false);
189- if (dma_channel_1_maybe < 0 ) {
190- dma_channel_unclaim ((uint )dma_channel_0_maybe );
185+ int data_channel_maybe = dma_claim_unused_channel (false);
186+ if (data_channel_maybe < 0 ) {
187+ dma_channel_unclaim ((uint )control_channel_maybe );
191188 return AUDIO_DMA_DMA_BUSY ;
192189 }
193190
194- dma -> channel [ 0 ] = (uint8_t )dma_channel_0_maybe ;
195- dma -> channel [ 1 ] = (uint8_t )dma_channel_1_maybe ;
191+ dma -> control_channel = (uint8_t )control_channel_maybe ;
192+ dma -> data_channel = (uint8_t )data_channel_maybe ;
196193
197194 dma -> sample = sample ;
198195 dma -> loop = loop ;
@@ -262,24 +259,20 @@ audio_dma_result audio_dma_setup_playback(
262259 dma_size = DMA_SIZE_32 ;
263260 }
264261
265- for ( size_t i = 0 ; i < 2 ; i ++ ) {
266- dma_channel_config c = dma_channel_get_default_config (dma -> channel [ i ] );
267- channel_config_set_transfer_data_size (& c , dma_size );
268- channel_config_set_dreq (& c , dma_trigger_source );
269- channel_config_set_read_increment (& c , true);
270- channel_config_set_write_increment (& c , false);
262+ // Setup the data channel
263+ dma_channel_config c = dma_channel_get_default_config (dma -> data_channel );
264+ channel_config_set_transfer_data_size (& c , dma_size );
265+ channel_config_set_dreq (& c , dma_trigger_source );
266+ channel_config_set_read_increment (& c , true);
267+ channel_config_set_write_increment (& c , false);
271268
272- // Chain to the other channel by default.
273- channel_config_set_chain_to (& c , dma -> channel [(i + 1 ) % 2 ]);
274- dma_channel_set_config (dma -> channel [i ], & c , false /* trigger */ );
275-
276- dma_channel_set_write_addr (dma -> channel [i ], (void * )output_register_address , false /* trigger */ );
277- }
269+ channel_config_set_chain_to (& c , dma -> control_channel );
270+ dma_channel_set_config (dma -> data_channel , & c , false /* trigger */ );
271+ dma_channel_set_write_addr (dma -> data_channel , (void * )output_register_address , false /* trigger */ );
278272
279273 // We keep the audio_dma_t for internal use and the sample as a root pointer because it
280274 // contains the audiodma structure.
281- MP_STATE_PORT (playing_audio )[dma -> channel [0 ]] = dma ;
282- MP_STATE_PORT (playing_audio )[dma -> channel [1 ]] = dma ;
275+ MP_STATE_PORT (playing_audio )[dma -> data_channel ] = dma ;
283276
284277 // Load the first two blocks up front.
285278 audio_dma_load_next_block (dma , 0 );
@@ -293,44 +286,49 @@ audio_dma_result audio_dma_setup_playback(
293286 }
294287 }
295288
289+ c = dma_channel_get_default_config (dma -> control_channel );
290+ channel_config_set_transfer_data_size (& c , DMA_SIZE_32 );
291+ channel_config_set_dreq (& c , 0x3f ); // dma as fast as possible
292+ channel_config_set_read_increment (& c , true);
293+ channel_config_set_write_increment (& c , false);
294+ if (single_buffer ) {
295+ // Wrap every 4 bytes, aka one word/transaction.
296+ channel_config_set_ring (& c , false, 2 );
297+ } else {
298+ // Wrap every 16 bytes, aka two words/transactions.
299+ channel_config_set_ring (& c , false, 3 );
300+ }
301+ channel_config_set_chain_to (& c , dma -> control_channel ); // Chain to ourselves so we stop.
302+ dma_channel_configure (dma -> control_channel , & c ,
303+ & dma_hw -> ch [dma -> data_channel ].al3_read_addr_trig , // write address
304+ dma -> buffer , // read address
305+ 1 , // transaction count
306+ false); // trigger
307+
296308 // Special case the DMA for a single buffer. It's commonly used for a single wave length of sound
297309 // and may be short. Therefore, we use DMA chaining to loop quickly without involving interrupts.
298310 // On the RP2040 we chain by having a second DMA writing to the config registers of the first.
299311 // Read and write addresses change with DMA so we need to reset the read address back to the
300312 // start of the sample.
301- if (single_buffer ) {
302- dma_channel_config c = dma_channel_get_default_config (dma -> channel [1 ]);
303- channel_config_set_transfer_data_size (& c , DMA_SIZE_32 );
304- channel_config_set_dreq (& c , 0x3f ); // dma as fast as possible
305- channel_config_set_read_increment (& c , false);
306- channel_config_set_write_increment (& c , false);
307- channel_config_set_chain_to (& c , dma -> channel [1 ]); // Chain to ourselves so we stop.
308- dma_channel_configure (dma -> channel [1 ], & c ,
309- & dma_hw -> ch [dma -> channel [0 ]].al3_read_addr_trig , // write address
310- & dma -> buffer [0 ], // read address
311- 1 , // transaction count
312- false); // trigger
313- } else {
313+ if (!single_buffer ) {
314314 // Enable our DMA channels on DMA_IRQ_0 to the CPU. This will wake us up when
315315 // we're WFI.
316- dma_hw -> inte0 |= ( 1 << dma -> channel [ 0 ]) | ( 1 << dma -> channel [ 1 ]) ;
316+ dma_hw -> inte0 |= 1 << dma -> data_channel ;
317317 irq_set_mask_enabled (1 << DMA_IRQ_0 , true);
318318 }
319319
320320 dma -> playing_in_progress = true;
321- dma_channel_start (dma -> channel [0 ]);
321+ dma -> next_buffer = 0 ;
322+ dma_channel_start (dma -> control_channel );
322323
323324 return AUDIO_DMA_OK ;
324325}
325326
326327void audio_dma_stop (audio_dma_t * dma ) {
327328 // Disable our interrupts.
328329 uint32_t channel_mask = 0 ;
329- if (dma -> channel [0 ] < NUM_DMA_CHANNELS ) {
330- channel_mask |= 1 << dma -> channel [0 ];
331- }
332- if (dma -> channel [1 ] < NUM_DMA_CHANNELS ) {
333- channel_mask |= 1 << dma -> channel [1 ];
330+ if (dma -> data_channel < NUM_DMA_CHANNELS ) {
331+ channel_mask |= 1 << dma -> data_channel ;
334332 }
335333 dma_hw -> inte0 &= ~channel_mask ;
336334 if (!dma_hw -> inte0 ) {
@@ -341,57 +339,51 @@ void audio_dma_stop(audio_dma_t *dma) {
341339 // playing_audio.
342340 RUN_BACKGROUND_TASKS ;
343341
344- for (size_t i = 0 ; i < 2 ; i ++ ) {
345- size_t channel = dma -> channel [i ];
346- if (channel == NUM_DMA_CHANNELS ) {
347- // Channel not in use.
348- continue ;
349- }
342+ dma_channel_config c = dma_channel_get_default_config (dma -> data_channel );
343+ channel_config_set_enable (& c , false);
344+ dma_channel_set_config (dma -> data_channel , & c , false /* trigger */ );
345+ dma_channel_set_config (dma -> control_channel , & c , false /* trigger */ );
346+
347+ if (dma_channel_is_busy (dma -> data_channel )) {
348+ dma_channel_abort (dma -> data_channel );
349+ }
350+ if (dma_channel_is_busy (dma -> control_channel )) {
351+ dma_channel_abort (dma -> control_channel );
352+ }
350353
351- dma_channel_config c = dma_channel_get_default_config (dma -> channel [i ]);
352- channel_config_set_enable (& c , false);
353- dma_channel_set_config (channel , & c , false /* trigger */ );
354+ dma_channel_set_read_addr (dma -> data_channel , NULL , false /* trigger */ );
355+ dma_channel_set_write_addr (dma -> data_channel , NULL , false /* trigger */ );
356+ dma_channel_set_trans_count (dma -> data_channel , 0 , false /* trigger */ );
357+ dma_channel_unclaim (dma -> data_channel );
354358
355- if (dma_channel_is_busy (channel )) {
356- dma_channel_abort (channel );
357- }
359+ dma_channel_set_read_addr (dma -> control_channel , NULL , false /* trigger */ );
360+ dma_channel_set_write_addr (dma -> control_channel , NULL , false /* trigger */ );
361+ dma_channel_set_trans_count (dma -> control_channel , 0 , false /* trigger */ );
362+ dma_channel_unclaim (dma -> control_channel );
358363
359- dma_channel_set_read_addr (channel , NULL , false /* trigger */ );
360- dma_channel_set_write_addr (channel , NULL , false /* trigger */ );
361- dma_channel_set_trans_count (channel , 0 , false /* trigger */ );
362- dma_channel_unclaim (channel );
363- MP_STATE_PORT (playing_audio )[channel ] = NULL ;
364- dma -> channel [i ] = NUM_DMA_CHANNELS ;
365- }
364+ MP_STATE_PORT (playing_audio )[dma -> data_channel ] = NULL ;
365+ dma -> data_channel = NUM_DMA_CHANNELS ;
366+ dma -> control_channel = NUM_DMA_CHANNELS ;
366367 dma -> playing_in_progress = false;
367368
368369 // Hold onto our buffers.
369370}
370371
371- // To pause we simply stop the DMA. It is the responsibility of the output peripheral
372- // to hold the previous value.
372+ // To pause we simply stop the data DMA channel . It is the responsibility of the
373+ // output peripheral to hold the previous value.
373374void audio_dma_pause (audio_dma_t * dma ) {
374- dma_hw -> ch [dma -> channel [0 ]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS ;
375- dma_hw -> ch [dma -> channel [1 ]].al1_ctrl &= ~DMA_CH1_CTRL_TRIG_EN_BITS ;
375+ dma_hw -> ch [dma -> data_channel ].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS ;
376376}
377377
378378void audio_dma_resume (audio_dma_t * dma ) {
379- // Always re-enable the non-busy channel first so it's ready to continue when the busy channel
380- // finishes and chains to it. (An interrupt could make the time between enables long.)
381- if (dma_channel_is_busy (dma -> channel [0 ])) {
382- dma_hw -> ch [dma -> channel [1 ]].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS ;
383- dma_hw -> ch [dma -> channel [0 ]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS ;
384- } else {
385- dma_hw -> ch [dma -> channel [0 ]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS ;
386- dma_hw -> ch [dma -> channel [1 ]].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS ;
387- }
379+ dma_hw -> ch [dma -> data_channel ].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS ;
388380}
389381
390382bool audio_dma_get_paused (audio_dma_t * dma ) {
391- if (dma -> channel [ 0 ] >= NUM_DMA_CHANNELS ) {
383+ if (dma -> data_channel >= NUM_DMA_CHANNELS ) {
392384 return false;
393385 }
394- uint32_t control = dma_hw -> ch [dma -> channel [ 0 ] ].ctrl_trig ;
386+ uint32_t control = dma_hw -> ch [dma -> data_channel ].ctrl_trig ;
395387
396388 return (control & DMA_CH0_CTRL_TRIG_EN_BITS ) == 0 ;
397389}
@@ -418,14 +410,24 @@ void audio_dma_unpause_mask(uint32_t channel_mask) {
418410}
419411
420412void audio_dma_init (audio_dma_t * dma ) {
413+ // We allocate four pointers worth so that we can align to a 8 byte boundary.
414+ dma -> read_addr_buffer = port_malloc (4 * sizeof (uint32_t * ), true);
415+ mp_printf (& mp_plat_print , "read_addr_buffer: %p\n" , dma -> read_addr_buffer );
416+ if ((size_t )dma -> read_addr_buffer % 8 == 4 ) {
417+ // Pointer math! So, + 1 is + sizeof(uint32_t *).
418+ dma -> buffer = dma -> read_addr_buffer + 1 ;
419+ } else {
420+ dma -> buffer = dma -> read_addr_buffer ;
421+ }
422+ mp_printf (& mp_plat_print , "buffer: %p\n" , dma -> buffer );
421423 dma -> buffer [0 ] = NULL ;
422424 dma -> buffer [1 ] = NULL ;
423425
424426 dma -> buffer_length [0 ] = 0 ;
425427 dma -> buffer_length [1 ] = 0 ;
426428
427- dma -> channel [ 0 ] = NUM_DMA_CHANNELS ;
428- dma -> channel [ 1 ] = NUM_DMA_CHANNELS ;
429+ dma -> data_channel = NUM_DMA_CHANNELS ;
430+ dma -> control_channel = NUM_DMA_CHANNELS ;
429431}
430432
431433void audio_dma_deinit (audio_dma_t * dma ) {
@@ -436,10 +438,14 @@ void audio_dma_deinit(audio_dma_t *dma) {
436438 port_free (dma -> buffer [1 ]);
437439 dma -> buffer [1 ] = NULL ;
438440 dma -> buffer_length [1 ] = 0 ;
441+
442+ port_free (dma -> read_addr_buffer );
443+ dma -> read_addr_buffer = NULL ;
444+ dma -> buffer = NULL ;
439445}
440446
441447bool audio_dma_get_playing (audio_dma_t * dma ) {
442- if (dma -> channel [ 0 ] == NUM_DMA_CHANNELS ) {
448+ if (dma -> data_channel == NUM_DMA_CHANNELS ) {
443449 return false;
444450 }
445451 return dma -> playing_in_progress ;
@@ -455,25 +461,13 @@ static void dma_callback_fun(void *arg) {
455461 return ;
456462 }
457463
464+ gpio_put (6 , true);
458465 common_hal_mcu_disable_interrupts ();
459- uint32_t channels_to_load_mask = dma -> channels_to_load_mask ;
460- dma -> channels_to_load_mask = 0 ;
466+ uint8_t next_buffer = dma -> next_buffer ;
461467 common_hal_mcu_enable_interrupts ();
462468
463- // Load the blocks for the requested channels.
464- uint32_t channel = 0 ;
465- while (channels_to_load_mask ) {
466- if (channels_to_load_mask & 1 ) {
467- if (dma -> channel [0 ] == channel ) {
468- audio_dma_load_next_block (dma , 0 );
469- }
470- if (dma -> channel [1 ] == channel ) {
471- audio_dma_load_next_block (dma , 1 );
472- }
473- }
474- channels_to_load_mask >>= 1 ;
475- channel ++ ;
476- }
469+ audio_dma_load_next_block (dma , next_buffer );
470+ gpio_put (6 , false);
477471}
478472
479473void __not_in_flash_func (isr_dma_0 )(void ) {
@@ -488,10 +482,12 @@ void __not_in_flash_func(isr_dma_0)(void) {
488482 // affected PIO continuous write more than audio.
489483 dma_hw -> ints0 = mask ;
490484 if (MP_STATE_PORT (playing_audio )[i ] != NULL ) {
485+ gpio_put (45 , true);
491486 audio_dma_t * dma = MP_STATE_PORT (playing_audio )[i ];
492- // Record all channels whose DMA has completed; they need loading .
493- dma -> channels_to_load_mask |= mask ;
487+ // Next buffer is the one we just completed playing and can now load .
488+ dma -> next_buffer = dma -> next_buffer % 2 ;
494489 background_callback_add (& dma -> callback , dma_callback_fun , (void * )dma );
490+ gpio_put (45 , false);
495491 }
496492 if (MP_STATE_PORT (background_pio_read )[i ] != NULL ) {
497493 rp2pio_statemachine_obj_t * pio = MP_STATE_PORT (background_pio_read )[i ];
0 commit comments