Content-Length: 641404 | pFad | http://github.com/adafruit/circuitpython/commit/e172e15cf34f41b76e0bcdacb0df5cf117ed5b13

8E Merge pull request #10182 from dhalbert/audioout-fixes · adafruit/circuitpython@e172e15 · GitHub
Skip to content

Commit e172e15

Browse files
authored
Merge pull request #10182 from dhalbert/audioout-fixes
Disallow identical AudioOut channel pins. Work around ESP-IDF ESP32-S2 bug that swaps DAC channels randomly.
2 parents 81d96ac + 725f8f1 commit e172e15

File tree

3 files changed

+51
-47
lines changed

3 files changed

+51
-47
lines changed

ports/atmel-samd/common-hal/audioio/AudioOut.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ static void ramp_value(uint16_t start, uint16_t end) {
7979
// Caller validates that pins are free.
8080
void common_hal_audioio_audioout_construct(audioio_audioout_obj_t *self,
8181
const mcu_pin_obj_t *left_channel, const mcu_pin_obj_t *right_channel, uint16_t quiescent_value) {
82+
83+
// The case of left_channel == right_channel is already disallowed in shared-bindings.
84+
8285
#ifdef SAM_D5X_E5X
8386
bool dac_clock_enabled = hri_mclk_get_APBDMASK_DAC_bit(MCLK);
8487
#endif
@@ -107,10 +110,6 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t *self,
107110
if (right_channel != NULL && right_channel != &pin_PA02 && right_channel != &pin_PA05) {
108111
raise_ValueError_invalid_pin_name(MP_QSTR_right_channel);
109112
}
110-
if (right_channel == left_channel) {
111-
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q and %q must be different"),
112-
MP_QSTR_left_channel, MP_QSTR_right_channel);
113-
}
114113
claim_pin(left_channel);
115114
if (right_channel != NULL) {
116115
claim_pin(right_channel);

ports/espressif/common-hal/audioio/AudioOut.c

+35-41
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
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+
307332
static 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-
579569
void 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);

shared-bindings/audioio/AudioOut.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,16 @@
2828
//| """Create a AudioOut object associated with the given pin(s). This allows you to
2929
//| play audio signals out on the given pin(s).
3030
//|
31-
//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
32-
//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
31+
//| :param ~microcontroller.Pin left_channel: Output left channel data to this pin
32+
//| :param ~microcontroller.Pin right_channel: Output right channel data to this pin. May be ``None``.
3333
//| :param int quiescent_value: The output value when no signal is present. Samples should start
3434
//| and end with this value to prevent audible popping.
3535
//|
36+
//| .. note:: On ESP32 and ESP32-S2, the DAC channels are usually designated
37+
//| as ``DAC_1`` (right stereo channel) and DAC_2 (left stereo channel).
38+
//| These pins are sometimes labelled as ``A0`` and ``A1``, but they may be assigned
39+
//| in either order. Check your board's pinout to verify which pin is which channel.
40+
//|
3641
//| Simple 8ksps 440 Hz sin wave::
3742
//|
3843
//| import audiocore
@@ -90,6 +95,12 @@ static mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar
9095
const mcu_pin_obj_t *right_channel_pin =
9196
validate_obj_is_free_pin_or_none(args[ARG_right_channel].u_obj, MP_QSTR_right_channel);
9297

98+
// Can't use the same pin for both left and right channels.
99+
if (left_channel_pin == right_channel_pin) {
100+
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q and %q must be different"),
101+
MP_QSTR_left_channel, MP_QSTR_right_channel);
102+
}
103+
93104
// create AudioOut object from the given pin
94105
audioio_audioout_obj_t *self = mp_obj_malloc_with_finaliser(audioio_audioout_obj_t, &audioio_audioout_type);
95106
common_hal_audioio_audioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int);

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/adafruit/circuitpython/commit/e172e15cf34f41b76e0bcdacb0df5cf117ed5b13

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy