From 4964133117e41a50cb5cb68218da7b558183d476 Mon Sep 17 00:00:00 2001 From: tomcombriat <tomcombriat@live.fr> Date: Sun, 19 Jan 2025 23:59:41 +0100 Subject: [PATCH] ESP32: added PWM output support --- internal/MozziGuts_impl_ESP32.hpp | 30 ++++++++++++++++++++++++------ internal/config_checks_esp32.h | 15 +++++++++++++-- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/internal/MozziGuts_impl_ESP32.hpp b/internal/MozziGuts_impl_ESP32.hpp index 3103528fb..0e9b3624c 100644 --- a/internal/MozziGuts_impl_ESP32.hpp +++ b/internal/MozziGuts_impl_ESP32.hpp @@ -43,12 +43,12 @@ namespace MozziPrivate { //# include <driver/i2s.h> // for I2S-based output modes, including - technically - internal DAC #include<driver/i2s_std.h> - +/* #elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) #include<driver/dac_continuous.h> namespace MozziPrivate { - /* static*/ dac_continuous_handle_t dac_handle; -} + static dac_continuous_handle_t dac_handle; + }*/ #endif //#elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_I2S) @@ -99,7 +99,8 @@ namespace MozziPrivate { return _esp32_can_buffer_next; } -# if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_I2S_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_I2S) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) + +# if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_I2S_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_I2S) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM) inline void audioOutput(const AudioOutput f) { /* # if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) @@ -115,6 +116,13 @@ namespace MozziPrivate { # if (MOZZI_AUDIO_CHANNELS > 1) dacWrite(26, f.l() + MOZZI_AUDIO_BIAS); # endif + +# elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM) + ledcWrite(MOZZI_AUDIO_PIN_1,(f.l()+MOZZI_AUDIO_BIAS)); +# if (MOZZI_AUDIO_CHANNELS > 1) + ledcWrite(MOZZI_AUDIO_PIN_2,(f.l()+MOZZI_AUDIO_BIAS)); +# endif + # elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_I2S) for (uint8_t i=0; i<MOZZI_PDM_RESOLUTION; ++i) { _esp32_prev_sample[i] = pdmCode32(f.l() + MOZZI_AUDIO_BIAS); @@ -124,14 +132,16 @@ namespace MozziPrivate { _esp32_prev_sample[0] = f.l(); _esp32_prev_sample[1] = f.r(); # endif +# if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_I2S_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_I2S) _esp32_can_buffer_next = esp32_tryWriteSample(); +# endif } #endif } // namespace MozziPrivate namespace MozziPrivate { -#if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_INTERNAL_DAC) +#if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_INTERNAL_DAC, MOZZI_OUTPUT_PWM) #include <driver/gptimer.h> bool CACHED_FUNCTION_ATTR timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx) @@ -144,7 +154,7 @@ namespace MozziPrivate { static void startAudio() { /* Normally, the internal DAC can run on DMA, hence self triggering. Did not managed to get that to work (see: https://github.com/espressif/arduino-esp32/issues/10851) so, for now, we are just using the Mozzi buffer and send dacWrite orders. */ -#if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM) // set up a timer running a audio rate +#if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_INTERNAL_DAC, MOZZI_OUTPUT_PWM) //|| MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM) // set up a timer running a audio rate gptimer_handle_t gptimer = NULL; gptimer_config_t timer_config = { @@ -166,9 +176,17 @@ namespace MozziPrivate { .on_alarm = timer_on_alarm_cb, // register user callback }; + gptimer_register_event_callbacks(gptimer,&cbs,NULL); gptimer_enable(gptimer); gptimer_start(gptimer); + +# if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM) + ledcAttach(MOZZI_AUDIO_PIN_1, MOZZI_AUDIO_RATE, MOZZI_AUDIO_BITS); +# if (MOZZI_AUDIO_CHANNELS > 1) + ledcAttach(MOZZI_AUDIO_PIN_2, MOZZI_AUDIO_RATE, MOZZI_AUDIO_BITS); +# endif +# endif # elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_I2S_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_I2S) diff --git a/internal/config_checks_esp32.h b/internal/config_checks_esp32.h index 0184c8826..0b6eda631 100644 --- a/internal/config_checks_esp32.h +++ b/internal/config_checks_esp32.h @@ -100,7 +100,7 @@ #if !defined(MOZZI_AUDIO_MODE) #define MOZZI_AUDIO_MODE MOZZI_OUTPUT_INTERNAL_DAC #endif -MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_EXTERNAL_CUSTOM, MOZZI_OUTPUT_PDM_VIA_I2S, MOZZI_OUTPUT_I2S_DAC, MOZZI_OUTPUT_INTERNAL_DAC) +MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_EXTERNAL_CUSTOM, MOZZI_OUTPUT_PDM_VIA_I2S, MOZZI_OUTPUT_I2S_DAC, MOZZI_OUTPUT_INTERNAL_DAC, MOZZI_OUTPUT_PWM) #if !defined(MOZZI_AUDIO_RATE) #define MOZZI_AUDIO_RATE 32768 @@ -155,6 +155,16 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) # endif #endif +#if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM) +# define MOZZI_AUDIO_BITS 10 // not configurable (could be 8) +# if !defined(MOZZI_AUDIO_PIN_1) +# define MOZZI_AUDIO_PIN_1 18 +# endif +# if !defined(MOZZI_AUDIO_PIN_2) +# define MOZZI_AUDIO_PIN_2 19 +# endif +#endif + #if !defined(MOZZI_AUDIO_BITS) # if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) # define MOZZI_AUDIO_BITS 8 @@ -171,8 +181,9 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) # define MOZZI_PDM_RESOLUTION 1 // unconditionally, no other value allowed #endif + // All modes besides timed external bypass the output buffer! -#if !MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_INTERNAL_DAC) +#if !MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_INTERNAL_DAC, MOZZI_OUTPUT_PWM) # define BYPASS_MOZZI_OUTPUT_BUFFER true #endif