1111
1212#include "driver/dac_continuous.h"
1313
14-
1514#if defined(CONFIG_IDF_TARGET_ESP32 )
1615#define pin_CHANNEL_0 pin_GPIO25
1716#define pin_CHANNEL_1 pin_GPIO26
@@ -304,6 +303,32 @@ static audioout_sample_convert_func_t audioout_get_samples_convert_func(
304303 }
305304}
306305
306+ static void audioio_audioout_start (audioio_audioout_obj_t * self ) {
307+ esp_err_t ret ;
308+
309+ self -> playing = true;
310+ self -> paused = false;
311+
312+ ret = dac_continuous_start_async_writing (self -> handle );
313+ if (ret != ESP_OK ) {
314+ mp_raise_RuntimeError (MP_ERROR_TEXT ("Failed to start async audio" ));
315+ }
316+ }
317+
318+ static void audioio_audioout_stop (audioio_audioout_obj_t * self , bool full_stop ) {
319+ dac_continuous_stop_async_writing (self -> handle );
320+ if (full_stop ) {
321+ self -> get_buffer_index = 0 ;
322+ self -> put_buffer_index = 0 ;
323+ self -> sample_buffer = NULL ;
324+ self -> sample = NULL ;
325+ self -> playing = false;
326+ self -> paused = false;
327+ } else {
328+ self -> paused = true;
329+ }
330+ }
331+
307332static bool audioout_fill_buffer (audioio_audioout_obj_t * self ) {
308333 if (!self -> playing ) {
309334 return false;
@@ -342,7 +367,7 @@ static bool audioout_fill_buffer(audioio_audioout_obj_t *self) {
342367 & raw_sample_buf , & raw_sample_buf_size );
343368
344369 if (get_buffer_result == GET_BUFFER_ERROR ) {
345- common_hal_audioio_audioout_stop (self );
370+ audioio_audioout_stop (self , true );
346371 return false;
347372 }
348373
@@ -390,7 +415,7 @@ static bool audioout_fill_buffer(audioio_audioout_obj_t *self) {
390415 } else {
391416 // TODO: figure out if it is ok to call this here or do we need
392417 // to somehow wait for all of the samples to be flushed
393- common_hal_audioio_audioout_stop (self );
418+ audioio_audioout_stop (self , true );
394419 return false;
395420 }
396421 }
@@ -492,24 +517,15 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t *self,
492517 self -> paused = false;
493518 self -> freq_hz = DEFAULT_SAMPLE_RATE ;
494519
495- /* espressif has two dac channels and it can support true stereo or
496- * outputting the same signal to both channels (dual mono).
497- * if different pins are supplied for left and right then use true stereo.
498- * if the same pin is supplied for left and right then use dual mono.
499- */
520+ // The case of left_channel == right_channel is already disallowed in shared-bindings.
521+
500522 if ((left_channel_pin == & pin_CHANNEL_0 &&
501523 right_channel_pin == & pin_CHANNEL_1 ) ||
502524 (left_channel_pin == & pin_CHANNEL_1 &&
503525 right_channel_pin == & pin_CHANNEL_0 )) {
504526 self -> channel_mask = DAC_CHANNEL_MASK_ALL ;
505527 self -> num_channels = 2 ;
506528 self -> channel_mode = DAC_CHANNEL_MODE_ALTER ;
507- } else if ((left_channel_pin == & pin_CHANNEL_0 ||
508- left_channel_pin == & pin_CHANNEL_1 ) &&
509- right_channel_pin == left_channel_pin ) {
510- self -> channel_mask = DAC_CHANNEL_MASK_ALL ;
511- self -> num_channels = 1 ;
512- self -> channel_mode = DAC_CHANNEL_MODE_SIMUL ;
513529 } else if (left_channel_pin == & pin_CHANNEL_0 &&
514530 right_channel_pin == NULL ) {
515531 self -> channel_mask = DAC_CHANNEL_MASK_CH0 ;
@@ -550,32 +566,6 @@ void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t *self) {
550566 _active_handle = NULL ;
551567}
552568
553- static void audioio_audioout_start (audioio_audioout_obj_t * self ) {
554- esp_err_t ret ;
555-
556- self -> playing = true;
557- self -> paused = false;
558-
559- ret = dac_continuous_start_async_writing (self -> handle );
560- if (ret != ESP_OK ) {
561- mp_raise_RuntimeError (MP_ERROR_TEXT ("Failed to start async audio" ));
562- }
563- }
564-
565- static void audioio_audioout_stop (audioio_audioout_obj_t * self , bool full_stop ) {
566- dac_continuous_stop_async_writing (self -> handle );
567- if (full_stop ) {
568- self -> get_buffer_index = 0 ;
569- self -> put_buffer_index = 0 ;
570- self -> sample_buffer = NULL ;
571- self -> sample = NULL ;
572- self -> playing = false;
573- self -> paused = false;
574- } else {
575- self -> paused = true;
576- }
577- }
578-
579569void common_hal_audioio_audioout_play (audioio_audioout_obj_t * self ,
580570 mp_obj_t sample , bool loop ) {
581571
@@ -597,7 +587,11 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self,
597587 self -> looping = loop ;
598588 freq_hz = audiosample_get_sample_rate (self -> sample );
599589
600- if (freq_hz != self -> freq_hz ) {
590+ // Workaround: always reset the DAC completely between plays,
591+ // due to a bug that causes the left and right channels to be swapped randomly.
592+ // See https://github.com/espressif/esp-idf/issues/11425
593+ // TODO: Remove the `true` when this issue is fixed.
594+ if (true || freq_hz != self -> freq_hz ) {
601595 common_hal_audioio_audioout_deinit (self );
602596 self -> freq_hz = freq_hz ;
603597 audioout_init (self );
0 commit comments