34
34
35
35
#include "py/mpstate.h"
36
36
37
+ static audio_dma_t * audio_dma_state [AUDIO_DMA_CHANNEL_COUNT ];
38
+
39
+ // This cannot be in audio_dma_state because it's volatile.
40
+ static volatile bool audio_dma_pending [AUDIO_DMA_CHANNEL_COUNT ];
41
+
37
42
uint32_t audiosample_sample_rate (mp_obj_t sample_obj ) {
38
43
if (MP_OBJ_IS_TYPE (sample_obj , & audioio_rawsample_type )) {
39
44
audioio_rawsample_obj_t * sample = MP_OBJ_TO_PTR (sample_obj );
@@ -70,7 +75,7 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
70
75
return 1 ;
71
76
}
72
77
73
- void audiosample_reset_buffer (mp_obj_t sample_obj , bool single_channel , uint8_t audio_channel ) {
78
+ static void audiosample_reset_buffer (mp_obj_t sample_obj , bool single_channel , uint8_t audio_channel ) {
74
79
if (MP_OBJ_IS_TYPE (sample_obj , & audioio_rawsample_type )) {
75
80
audioio_rawsample_obj_t * sample = MP_OBJ_TO_PTR (sample_obj );
76
81
audioio_rawsample_reset_buffer (sample , single_channel , audio_channel );
@@ -81,7 +86,10 @@ void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t
81
86
}
82
87
}
83
88
84
- bool audiosample_get_buffer (mp_obj_t sample_obj , bool single_channel , uint8_t channel , uint8_t * * buffer , uint32_t * buffer_length ) {
89
+ static audioio_get_buffer_result_t audiosample_get_buffer (mp_obj_t sample_obj ,
90
+ bool single_channel ,
91
+ uint8_t channel ,
92
+ uint8_t * * buffer , uint32_t * buffer_length ) {
85
93
if (MP_OBJ_IS_TYPE (sample_obj , & audioio_rawsample_type )) {
86
94
audioio_rawsample_obj_t * sample = MP_OBJ_TO_PTR (sample_obj );
87
95
return audioio_rawsample_get_buffer (sample , single_channel , channel , buffer , buffer_length );
@@ -90,7 +98,7 @@ bool audiosample_get_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t ch
90
98
audioio_wavefile_obj_t * file = MP_OBJ_TO_PTR (sample_obj );
91
99
return audioio_wavefile_get_buffer (file , single_channel , channel , buffer , buffer_length );
92
100
}
93
- return true ;
101
+ return GET_BUFFER_DONE ;
94
102
}
95
103
96
104
static void audiosample_get_buffer_structure (mp_obj_t sample_obj , bool single_channel ,
@@ -117,7 +125,6 @@ uint8_t find_free_audio_dma_channel(void) {
117
125
return channel ;
118
126
}
119
127
120
- audio_dma_t * audio_dma_state [AUDIO_DMA_CHANNEL_COUNT ];
121
128
void audio_dma_convert_signed (audio_dma_t * dma , uint8_t * buffer , uint32_t buffer_length ,
122
129
uint8_t * * output_buffer , uint32_t * output_buffer_length ,
123
130
uint8_t * output_spacing ) {
@@ -163,15 +170,21 @@ void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer
163
170
void audio_dma_load_next_block (audio_dma_t * dma ) {
164
171
uint8_t * buffer ;
165
172
uint32_t buffer_length ;
166
- bool last_buffer = audiosample_get_buffer (dma -> sample , dma -> single_channel , dma -> audio_channel ,
167
- & buffer , & buffer_length );
173
+ audioio_get_buffer_result_t get_buffer_result =
174
+ audiosample_get_buffer (dma -> sample , dma -> single_channel , dma -> audio_channel ,
175
+ & buffer , & buffer_length );
168
176
169
177
DmacDescriptor * descriptor = dma -> second_descriptor ;
170
178
if (dma -> first_descriptor_free ) {
171
179
descriptor = dma_descriptor (dma -> dma_channel );
172
180
}
173
181
dma -> first_descriptor_free = !dma -> first_descriptor_free ;
174
182
183
+ if (get_buffer_result == GET_BUFFER_ERROR ) {
184
+ audio_dma_stop (dma );
185
+ return ;
186
+ }
187
+
175
188
uint8_t * output_buffer ;
176
189
uint32_t output_buffer_length ;
177
190
uint8_t output_spacing ;
@@ -180,7 +193,7 @@ void audio_dma_load_next_block(audio_dma_t* dma) {
180
193
181
194
descriptor -> BTCNT .reg = output_buffer_length / dma -> beat_size / output_spacing ;
182
195
descriptor -> SRCADDR .reg = ((uint32_t ) output_buffer ) + output_buffer_length ;
183
- if (last_buffer ) {
196
+ if (get_buffer_result == GET_BUFFER_DONE ) {
184
197
if (dma -> loop ) {
185
198
audiosample_reset_buffer (dma -> sample , dma -> single_channel , dma -> audio_channel );
186
199
} else {
@@ -347,6 +360,7 @@ void audio_dma_init(audio_dma_t* dma) {
347
360
void audio_dma_reset (void ) {
348
361
for (uint8_t i = 0 ; i < AUDIO_DMA_CHANNEL_COUNT ; i ++ ) {
349
362
audio_dma_state [i ] = NULL ;
363
+ audio_dma_pending [i ] = false;
350
364
dma_disable_channel (i );
351
365
dma_descriptor (i )-> BTCTRL .bit .VALID = false;
352
366
MP_STATE_PORT (playing_audio )[i ] = NULL ;
@@ -367,8 +381,12 @@ bool audio_dma_get_playing(audio_dma_t* dma) {
367
381
368
382
// WARN(tannewt): DO NOT print from here. Printing calls background tasks such as this and causes a
369
383
// stack overflow.
384
+
370
385
void audio_dma_background (void ) {
371
386
for (uint8_t i = 0 ; i < AUDIO_DMA_CHANNEL_COUNT ; i ++ ) {
387
+ if (audio_dma_pending [i ]) {
388
+ continue ;
389
+ }
372
390
audio_dma_t * dma = audio_dma_state [i ];
373
391
if (dma == NULL ) {
374
392
continue ;
@@ -379,6 +397,10 @@ void audio_dma_background(void) {
379
397
continue ;
380
398
}
381
399
400
+ // audio_dma_load_next_block() can call Python code, which can call audio_dma_background()
401
+ // recursively at the next background processing time. So disallow recursive calls to here.
402
+ audio_dma_pending [i ] = true;
382
403
audio_dma_load_next_block (dma );
404
+ audio_dma_pending [i ] = false;
383
405
}
384
406
}
0 commit comments