From 52a9be72381b884cfe27b7fd76c690c37dedadf9 Mon Sep 17 00:00:00 2001 From: Phil Schatzmann Date: Fri, 10 Mar 2023 15:09:02 +0100 Subject: [PATCH 01/10] Feature esp32 input (#1) * DRAFT read * ESP32 Input Corrections * Mode In Correctioins * Remove intrernal ADC * Final Cleanup --- AudioConfigESP32.h | 55 +++++++++++-- AudioOutput.h | 4 + MozziGuts.cpp | 2 +- MozziGuts_impl_ESP32.hpp | 173 +++++++++++++++++++++++++++------------ mozzi_config.h | 8 ++ 5 files changed, 183 insertions(+), 59 deletions(-) diff --git a/AudioConfigESP32.h b/AudioConfigESP32.h index fd3fcba76..0c8d1ca15 100644 --- a/AudioConfigESP32.h +++ b/AudioConfigESP32.h @@ -1,6 +1,9 @@ #ifndef AUDIOCONFIGESP32_H #define AUDIOCONFIGESP32_H +#include +#include + #if not IS_ESP32() #error This header should be included for ESP32 architecture, only #endif @@ -9,27 +12,42 @@ #error HIFI mode is not available for this CPU architecture (but check ESP32_AUDIO_OUT_MODE, and PDM_RESOLUTION) #endif -// Audio output options +// Audio IO options #define INTERNAL_DAC 1 // output using internal DAC via I2S, output on pin 26 -#define PT8211_DAC 2 // output using an external PT8211 DAC via I2S -#define PDM_VIA_I2S 3 // output PDM coded sample on the I2S data pin (pin 33, by default, configurable, below) +#define PT8211_DAC 2 // OBSOLETE: use PT8211_DAC instead +#define PDM_VIA_I2S 3 // output PDM coded sample on the I2S data pin (pin 33, by default, configurable, below) +#define I2S_DAC_AND_I2S_ADC 4 // output using an external DAC , input with exteran ADC - both via I2S -// Set output mode +// Set output & input mode #define ESP32_AUDIO_OUT_MODE INTERNAL_DAC // For external I2S output, only: I2S_PINS #define ESP32_I2S_BCK_PIN 26 #define ESP32_I2S_WS_PIN 25 #define ESP32_I2S_DATA_PIN 33 +#define ESP32_I2S_DATA_PIN_IN 32 // relevant with I2S_ADC -#include + +// Preferred I2S port: note that this might be taken into consideration if there is a choice +// The Internal ADC and DAC only work on port 0 and can not be used at the same time! const i2s_port_t i2s_num = I2S_NUM_0; + + +// Select the data range of the ADC +//#define ADC_VALUE(in) (in) // no scaling +#define ADC_VALUE(in) ((in + 32768)*0.015625) // scale to 0 to 1023 + +// Optionally select a higher Sample Rate +//#define ESP32_AUDIO_RATE 8000 + + /// User config end. Do not modify below this line +///-------------------------------------------------------------------------------------------------------- -#if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) +#if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC || ESP32_AUDIO_OUT_MODE == INTERNAL_DAC_AND_I2S_ADC ) #define AUDIO_BITS 8 #define PDM_RESOLUTION 1 -#elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC) +#elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC || ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_INTERNAL_ADC || ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_I2S_ADC) #define AUDIO_BITS 16 #define PDM_RESOLUTION 1 #elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) @@ -39,7 +57,30 @@ const i2s_port_t i2s_num = I2S_NUM_0; #error Invalid output mode configured in AudioConfigESP32.h #endif +/// Activate Analog Input +#if (ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_INTERNAL_ADC || ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_I2S_ADC || ESP32_AUDIO_OUT_MODE == INTERNAL_DAC_AND_I2S_ADC) +# define MOZZI_FAST_ANALOG_IMPLEMENTED // not yet +#endif + +/// Logic for Output Buffer +#define IS_INTERNAL_DAC() (ESP32_AUDIO_OUT_MODE==INTERNAL_DAC || ESP32_AUDIO_OUT_MODE==INTERNAL_DAC_AND_I2S_ADC) +#define IS_I2S_DAC() (ESP32_AUDIO_OUT_MODE==I2S_DAC || ESP32_AUDIO_OUT_MODE==I2S_DAC_AND_INTERNAL_ADC||ESP32_AUDIO_OUT_MODE==I2S_DAC_AND_I2S_ADC) +#define IS_PDM() (ESP32_AUDIO_OUT_MODE==PDM_VIA_I2S) + #define AUDIO_BIAS ((uint16_t) 1<<(AUDIO_BITS-1)) #define BYPASS_MOZZI_OUTPUT_BUFFER true +// Use defined rate as new AUDIO_RATE_PLATFORM_DEFAULT +#ifdef ESP32_AUDIO_RATE +# undef AUDIO_RATE_PLATFORM_DEFAULT +# define AUDIO_RATE_PLATFORM_DEFAULT ESP32_AUDIO_RATE +#endif + +// If ADC is available we support getAudioInput() +#if ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC +int getAudioInput(); +#endif + + + #endif // #ifndef AUDIOCONFIGESP_H diff --git a/AudioOutput.h b/AudioOutput.h index 8ad297844..fc2a28374 100644 --- a/AudioOutput.h +++ b/AudioOutput.h @@ -216,4 +216,8 @@ inline uint32_t pdmCode32(uint16_t sample) { #warning "Mozzi is configured to use an external void 'audioOutput(const AudioOutput f)' function. Please define one in your sketch" #endif +#if (EXTERNAL_AUDIO_INPUT == true) +#warning "Mozzi is configured to use an external int 'audioRead()' function. Please define one in your sketch" +#endif + #endif diff --git a/MozziGuts.cpp b/MozziGuts.cpp index 82077d9d3..87a82d495 100644 --- a/MozziGuts.cpp +++ b/MozziGuts.cpp @@ -117,7 +117,7 @@ int mozziAnalogRead(uint8_t pin) { #endif } -#if (USE_AUDIO_INPUT == true) +#if (USE_AUDIO_INPUT == true && !defined(USE_CUSTOM_AUDIO_INPUT) && !EXTERNAL_AUDIO_INPUT) // ring buffer for audio input CircularBuffer input_buffer; // fixed size 256 diff --git a/MozziGuts_impl_ESP32.hpp b/MozziGuts_impl_ESP32.hpp index 7657eb62c..67c54c7b7 100644 --- a/MozziGuts_impl_ESP32.hpp +++ b/MozziGuts_impl_ESP32.hpp @@ -9,59 +9,109 @@ * Attribution-NonCommercial-ShareAlike 4.0 International License. * */ - #if !(IS_ESP32()) # error "Wrong implementation included for this platform" #endif +#include "AudioConfigESP32.h" +#include +#include + +static const char module[]="Mozzi-ESP32"; + +/// Make sure that we provide a supported port +int getWritePort(){ + switch (ESP32_AUDIO_OUT_MODE){ + case INTERNAL_DAC: + return 0; + case PDM_VIA_I2S: + return 0; + case PT8211_DAC: + return i2s_num; + case I2S_DAC_AND_I2S_ADC: + return i2s_num; + } + ESP_LOGE(module, "%s - %s", __func__, "ESP32_AUDIO_OUT_MODE invalid"); + return -1; +} + + +/// Determine the I2S Output Mode (and input mode if on same port) +int getI2SModeOut(){ + switch (ESP32_AUDIO_OUT_MODE){ + case INTERNAL_DAC: + return I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN; + case PDM_VIA_I2S: + return I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM; + case PT8211_DAC: + return I2S_MODE_MASTER | I2S_MODE_TX; + case I2S_DAC_AND_I2S_ADC: + return I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX; + } + ESP_LOGE(module, "%s - %s", __func__, "ESP32_AUDIO_OUT_MODE invalid"); + return -1; +} + + +// We provide a custom implementation of getAudioInput() avoiding the complex standard handling +#define USE_CUSTOM_AUDIO_INPUT + +/// @brief Reads a sample from the I2S buffer. I2S is stereo, so we combine the result to one single sample +int getAudioInput() { + static const int i2s_port = getWritePort(); + if (i2s_port==-1) return 0; + + int16_t tmp[2]; + size_t result; + esp_err_t rc = i2s_read((i2s_port_t)i2s_port, tmp, sizeof(tmp), &result, portMAX_DELAY); + return ADC_VALUE((tmp[0]+tmp[1]) / 2); +} + + +// ////// BEGIN analog input code //////// +#define getADCReading() 0; -////// BEGIN analog input code //////// -//#define MOZZI_FAST_ANALOG_IMPLEMENTED // not yet -#define getADCReading() 0 #define channelNumToIndex(channel) channel uint8_t adcPinToChannelNum(uint8_t pin) { return pin; } void adcStartConversion(uint8_t channel) { -#warning Fast analog read not implemented on this platform +// ESP_LOGD(module, "%s", __func__); } void startSecondADCReadOnCurrentChannel() { -#warning Fast analog read not implemented on this platform +// ESP_LOGD(module, "%s", __func__); } void setupFastAnalogRead(int8_t speed) { -#warning Fast analog read not implemented on this platform +// ESP_LOGD(module, "%s", __func__); } void setupMozziADC(int8_t speed) { -#warning Fast analog read not implemented on this platform +// ESP_LOGD(module, "%s: %d", __func__, speed); } ////// END analog input code //////// - - //// BEGIN AUDIO OUTPUT code /////// #include // for I2S-based output modes #include // for EXTERNAL_AUDIO_OUTPUT #if (EXTERNAL_AUDIO_OUTPUT != true) -# include "AudioConfigESP32.h" // On ESP32 we cannot test wether the DMA buffer has room. Instead, we have to use a one-sample mini buffer. In each iteration we // _try_ to write that sample to the DMA buffer, and if successful, we can buffer the next sample. Somewhat cumbersome, but works. // TODO: Should ESP32 gain an implemenation of i2s_available(), we should switch to using that, instead. static bool _esp32_can_buffer_next = true; -# if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) +# if (IS_INTERNAL_DAC()) static uint16_t _esp32_prev_sample[2]; -# define ESP_SAMPLE_SIZE (2*sizeof(uint16_t)) -# elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC) +# elif (IS_I2S_DAC()) static int16_t _esp32_prev_sample[2]; -# define ESP_SAMPLE_SIZE (2*sizeof(int16_t)) -# elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) +# elif (IS_PDM()) static uint32_t _esp32_prev_sample[PDM_RESOLUTION]; -# define ESP_SAMPLE_SIZE (PDM_RESOLUTION*sizeof(uint32_t)) # endif inline bool esp32_tryWriteSample() { + static i2s_port_t port = (i2s_port_t) getWritePort(); size_t bytes_written; - i2s_write(i2s_num, &_esp32_prev_sample, ESP_SAMPLE_SIZE, &bytes_written, 0); + int write_len = sizeof(_esp32_prev_sample); + i2s_write(port, &_esp32_prev_sample, write_len, &bytes_written, 0); + //ESP_LOGD(module, "%s port:%d, len: %d, written: %d, value: %d", __func__, port, write_len, bytes_written, _esp32_prev_sample[0]); return (bytes_written != 0); } @@ -101,8 +151,54 @@ void CACHED_FUNCTION_ATTR timer0_audio_output_isr(void *) { } #endif -static void startAudio() { + +static void startI2SAudio(i2s_port_t port, int mode){ + ESP_LOGI(module, "%s: port=%d, mode=0x%x, rate=%d", __func__, port, mode, AUDIO_RATE * PDM_RESOLUTION); + + static i2s_config_t i2s_config = { + .mode = (i2s_mode_t)mode, + .sample_rate = AUDIO_RATE * PDM_RESOLUTION, + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // only the top 8 bits will actually be used by the internal DAC, but using 8 bits straight away seems buggy + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // always use stereo output. mono seems to be buggy, and the overhead is insignifcant on the ESP32 + .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S), // this appears to be the correct setting for internal DAC and PT8211, but not for other dacs + .intr_alloc_flags = 0, // default interrupt priority + .dma_buf_count = 8, // 8*128 bytes of buffer corresponds to 256 samples (2 channels, see above, 2 bytes per sample per channel) + .dma_buf_len = 128, + .use_apll = false, + }; + + // install i2s driver + if (i2s_driver_install(port, &i2s_config, 0, NULL)!=ESP_OK){ + ESP_LOGE(module, "%s - %s : %d", __func__, "i2s_driver_install", port); + } + + // Internal DAC + if (mode & I2S_MODE_DAC_BUILT_IN){ + if (i2s_set_pin(port, NULL)!=ESP_OK) { + ESP_LOGE(module, "%s - %s", __func__, "i2s_set_pin"); + } + if (i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN)!=ESP_OK) { + ESP_LOGE(module, "%s - %s", __func__, "i2s_set_dac_mode"); + } + // Regular I2S + } else { + static const i2s_pin_config_t pin_config = { + .bck_io_num = ESP32_I2S_BCK_PIN, + .ws_io_num = ESP32_I2S_WS_PIN, + .data_out_num = ESP32_I2S_DATA_PIN, + .data_in_num = ESP32_I2S_DATA_PIN_IN, + }; + if (i2s_set_pin(port, &pin_config)!=ESP_OK) { + ESP_LOGE(module, "%s - %s", __func__, "i2s_set_pin"); + } + } + i2s_zero_dma_buffer(port); +} + + #if (BYPASS_MOZZI_OUTPUT_BUFFER != true) // for external audio output, set up a timer running a audio rate + +static void startAudio() { static intr_handle_t s_timer_handle; const int div = 2; timer_config_t config = { @@ -120,43 +216,18 @@ static void startAudio() { timer_enable_intr(TIMER_GROUP_0, TIMER_0); timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer0_audio_output_isr, nullptr, 0, &s_timer_handle); timer_start(TIMER_GROUP_0, TIMER_0); - +} #else - static const i2s_config_t i2s_config = { -# if (ESP32_AUDIO_OUT_MODE == PT8211_DAC) || (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) - .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), -# elif (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) - .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN), -# endif - .sample_rate = AUDIO_RATE * PDM_RESOLUTION, - .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // only the top 8 bits will actually be used by the internal DAC, but using 8 bits straight away seems buggy - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // always use stereo output. mono seems to be buggy, and the overhead is insignifcant on the ESP32 - .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB), // this appears to be the correct setting for internal DAC and PT8211, but not for other dacs - .intr_alloc_flags = 0, // default interrupt priority - .dma_buf_count = 8, // 8*128 bytes of buffer corresponds to 256 samples (2 channels, see above, 2 bytes per sample per channel) - .dma_buf_len = 128, - .use_apll = false - }; - i2s_driver_install(i2s_num, &i2s_config, 0, NULL); -# if (ESP32_AUDIO_OUT_MODE == PT8211_DAC) || (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) - static const i2s_pin_config_t pin_config = { - .bck_io_num = ESP32_I2S_BCK_PIN, - .ws_io_num = ESP32_I2S_WS_PIN, - .data_out_num = ESP32_I2S_DATA_PIN, - .data_in_num = -1 - }; - i2s_set_pin((i2s_port_t)i2s_num, &pin_config); -# elif (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) - i2s_set_pin((i2s_port_t)i2s_num, NULL); - i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); -# endif - i2s_zero_dma_buffer((i2s_port_t)i2s_num); +/// Use I2S for the Output and Input +static void startAudio() { + // start output + startI2SAudio((i2s_port_t)getWritePort(), getI2SModeOut()); +} #endif -} void stopMozzi() { - // TODO: implement me + i2s_driver_uninstall((i2s_port_t)getWritePort()); } //// END AUDIO OUTPUT code /////// diff --git a/mozzi_config.h b/mozzi_config.h index 1881e2de9..03412dbef 100644 --- a/mozzi_config.h +++ b/mozzi_config.h @@ -112,4 +112,12 @@ Only used when EXTERNAL_AUDIO_OUTPUT is set to true: The resolution to use for a output resolution of your DAC. 16 is the default value, here. Note that 16 bits is also the maximum currently supported on AVR. */ //#define EXTERNAL_AUDIO_BITS 16 +/** @ingroup core +Defining this option as true in mozzi_config.h allows to completely customize the audio input, e.g. for connecting from an external DACs. +For more detail, @see AudioInput . +*/ +#define EXTERNAL_AUDIO_INPUT false +//#define EXTERNAL_AUDIO_INPUT true + + #endif // #ifndef MOZZI_CONFIG_H From e523259d05da37520c11a025bcb5cbcbff9a74bc Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Fri, 10 Mar 2023 15:23:04 +0100 Subject: [PATCH 02/10] Remove EXTERNAL_AUDIO_INPUT --- AudioConfigESP32.h | 6 +++--- AudioOutput.h | 4 ---- MozziGuts.cpp | 2 +- mozzi_config.h | 6 ------ 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/AudioConfigESP32.h b/AudioConfigESP32.h index 0c8d1ca15..760b46210 100644 --- a/AudioConfigESP32.h +++ b/AudioConfigESP32.h @@ -44,10 +44,10 @@ const i2s_port_t i2s_num = I2S_NUM_0; /// User config end. Do not modify below this line ///-------------------------------------------------------------------------------------------------------- -#if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC || ESP32_AUDIO_OUT_MODE == INTERNAL_DAC_AND_I2S_ADC ) +#if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) #define AUDIO_BITS 8 #define PDM_RESOLUTION 1 -#elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC || ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_INTERNAL_ADC || ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_I2S_ADC) +#elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC || ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC) #define AUDIO_BITS 16 #define PDM_RESOLUTION 1 #elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) @@ -58,7 +58,7 @@ const i2s_port_t i2s_num = I2S_NUM_0; #endif /// Activate Analog Input -#if (ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_INTERNAL_ADC || ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_I2S_ADC || ESP32_AUDIO_OUT_MODE == INTERNAL_DAC_AND_I2S_ADC) +#if (ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_INTERNAL_ADC || ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC || ESP32_AUDIO_OUT_MODE == INTERNAL_DAC_AND_I2S_ADC) # define MOZZI_FAST_ANALOG_IMPLEMENTED // not yet #endif diff --git a/AudioOutput.h b/AudioOutput.h index fc2a28374..8ad297844 100644 --- a/AudioOutput.h +++ b/AudioOutput.h @@ -216,8 +216,4 @@ inline uint32_t pdmCode32(uint16_t sample) { #warning "Mozzi is configured to use an external void 'audioOutput(const AudioOutput f)' function. Please define one in your sketch" #endif -#if (EXTERNAL_AUDIO_INPUT == true) -#warning "Mozzi is configured to use an external int 'audioRead()' function. Please define one in your sketch" -#endif - #endif diff --git a/MozziGuts.cpp b/MozziGuts.cpp index 87a82d495..adc9d357c 100644 --- a/MozziGuts.cpp +++ b/MozziGuts.cpp @@ -117,7 +117,7 @@ int mozziAnalogRead(uint8_t pin) { #endif } -#if (USE_AUDIO_INPUT == true && !defined(USE_CUSTOM_AUDIO_INPUT) && !EXTERNAL_AUDIO_INPUT) +#if (USE_AUDIO_INPUT == true && !defined(USE_CUSTOM_AUDIO_INPUT)) // ring buffer for audio input CircularBuffer input_buffer; // fixed size 256 diff --git a/mozzi_config.h b/mozzi_config.h index 03412dbef..25b2ee6ba 100644 --- a/mozzi_config.h +++ b/mozzi_config.h @@ -112,12 +112,6 @@ Only used when EXTERNAL_AUDIO_OUTPUT is set to true: The resolution to use for a output resolution of your DAC. 16 is the default value, here. Note that 16 bits is also the maximum currently supported on AVR. */ //#define EXTERNAL_AUDIO_BITS 16 -/** @ingroup core -Defining this option as true in mozzi_config.h allows to completely customize the audio input, e.g. for connecting from an external DACs. -For more detail, @see AudioInput . -*/ -#define EXTERNAL_AUDIO_INPUT false -//#define EXTERNAL_AUDIO_INPUT true #endif // #ifndef MOZZI_CONFIG_H From 3816fc619521050dfab7de946dd30faf94f2ed66 Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Fri, 10 Mar 2023 15:30:55 +0100 Subject: [PATCH 03/10] README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 7e495b4dc..c47815a0f 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,9 @@ port by Dieter Vandoren and Thomas Friedrichsmeier - Output (DATA) pin can be configured in AudioConfigESP32.h. Default 33. Note that the BCK and WS pins are also used in this mode. - The PDM_RESOLUTION parameter can be used to reduce noise at the cost of more CPU power. - Mono, only. + - I2S_DAC_AND_I2S_ADC: Output is sent via I2S in a format, Input is read from I2S in douplex mode. + - 16 bits resolution, mono or stereo. Remember to shift your audio accordingly. + - I2S ins can be configured in AudioConfigESP32.h. Default is BCK: 26, WS: 15, DATA: 33, DATA_IN: 32. - "HIFI_MODE" is not currently implemented, but could conceivably be realized for the INTERNAL_DAC mode. Patches welcome. - WIFI-activity not yet tested, but likely the same notes as for ESP8266 apply. Consider turning off WIFI. - The implementation of audioTicks() may be slightly inaccurate on this platform. From 785f1c1c6a6fe36b31253fe52a3dc41b7c72086c Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sat, 11 Mar 2023 08:36:58 +0100 Subject: [PATCH 04/10] ADC scaling --- AudioConfigESP32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AudioConfigESP32.h b/AudioConfigESP32.h index 760b46210..67e8cde0a 100644 --- a/AudioConfigESP32.h +++ b/AudioConfigESP32.h @@ -35,7 +35,7 @@ const i2s_port_t i2s_num = I2S_NUM_0; // Select the data range of the ADC //#define ADC_VALUE(in) (in) // no scaling -#define ADC_VALUE(in) ((in + 32768)*0.015625) // scale to 0 to 1023 +#define ADC_VALUE(in) (0.015625*(in + 32768)) // scale to 0 to 1023 // Optionally select a higher Sample Rate //#define ESP32_AUDIO_RATE 8000 From e9665bf8387a7b6d8837e7f1805378a94babf85f Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sat, 11 Mar 2023 09:12:24 +0100 Subject: [PATCH 05/10] Cleanup --- AudioConfigESP32.h | 17 +++++------------ MozziGuts_impl_ESP32.hpp | 24 ++++++++++-------------- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/AudioConfigESP32.h b/AudioConfigESP32.h index 67e8cde0a..118edfac6 100644 --- a/AudioConfigESP32.h +++ b/AudioConfigESP32.h @@ -14,7 +14,7 @@ // Audio IO options #define INTERNAL_DAC 1 // output using internal DAC via I2S, output on pin 26 -#define PT8211_DAC 2 // OBSOLETE: use PT8211_DAC instead +#define PT8211_DAC 2 // output using an external PT8211 DAC via I2S #define PDM_VIA_I2S 3 // output PDM coded sample on the I2S data pin (pin 33, by default, configurable, below) #define I2S_DAC_AND_I2S_ADC 4 // output using an external DAC , input with exteran ADC - both via I2S @@ -25,7 +25,7 @@ #define ESP32_I2S_BCK_PIN 26 #define ESP32_I2S_WS_PIN 25 #define ESP32_I2S_DATA_PIN 33 -#define ESP32_I2S_DATA_PIN_IN 32 // relevant with I2S_ADC +#define ESP32_I2S_DATA_PIN_IN 32 // Preferred I2S port: note that this might be taken into consideration if there is a choice @@ -47,26 +47,19 @@ const i2s_port_t i2s_num = I2S_NUM_0; #if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) #define AUDIO_BITS 8 #define PDM_RESOLUTION 1 +#define IS_INTERNAL_DAC #elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC || ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC) #define AUDIO_BITS 16 #define PDM_RESOLUTION 1 +#define IS_I2S_DAC #elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) #define AUDIO_BITS 16 #define PDM_RESOLUTION 4 +#define IS_PDM #else #error Invalid output mode configured in AudioConfigESP32.h #endif -/// Activate Analog Input -#if (ESP32_AUDIO_OUT_MODE == PT8211_DAC_AND_INTERNAL_ADC || ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC || ESP32_AUDIO_OUT_MODE == INTERNAL_DAC_AND_I2S_ADC) -# define MOZZI_FAST_ANALOG_IMPLEMENTED // not yet -#endif - -/// Logic for Output Buffer -#define IS_INTERNAL_DAC() (ESP32_AUDIO_OUT_MODE==INTERNAL_DAC || ESP32_AUDIO_OUT_MODE==INTERNAL_DAC_AND_I2S_ADC) -#define IS_I2S_DAC() (ESP32_AUDIO_OUT_MODE==I2S_DAC || ESP32_AUDIO_OUT_MODE==I2S_DAC_AND_INTERNAL_ADC||ESP32_AUDIO_OUT_MODE==I2S_DAC_AND_I2S_ADC) -#define IS_PDM() (ESP32_AUDIO_OUT_MODE==PDM_VIA_I2S) - #define AUDIO_BIAS ((uint16_t) 1<<(AUDIO_BITS-1)) #define BYPASS_MOZZI_OUTPUT_BUFFER true diff --git a/MozziGuts_impl_ESP32.hpp b/MozziGuts_impl_ESP32.hpp index 67c54c7b7..d70673769 100644 --- a/MozziGuts_impl_ESP32.hpp +++ b/MozziGuts_impl_ESP32.hpp @@ -13,8 +13,8 @@ # error "Wrong implementation included for this platform" #endif #include "AudioConfigESP32.h" -#include -#include +#include // for I2S-based output modes +#include // for EXTERNAL_AUDIO_OUTPUT static const char module[]="Mozzi-ESP32"; @@ -26,7 +26,7 @@ int getWritePort(){ case PDM_VIA_I2S: return 0; case PT8211_DAC: - return i2s_num; + return i2s_num; case I2S_DAC_AND_I2S_ADC: return i2s_num; } @@ -36,7 +36,7 @@ int getWritePort(){ /// Determine the I2S Output Mode (and input mode if on same port) -int getI2SModeOut(){ +int getI2SMode(){ switch (ESP32_AUDIO_OUT_MODE){ case INTERNAL_DAC: return I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN; @@ -89,20 +89,16 @@ void setupMozziADC(int8_t speed) { ////// END analog input code //////// -//// BEGIN AUDIO OUTPUT code /////// -#include // for I2S-based output modes -#include // for EXTERNAL_AUDIO_OUTPUT - #if (EXTERNAL_AUDIO_OUTPUT != true) // On ESP32 we cannot test wether the DMA buffer has room. Instead, we have to use a one-sample mini buffer. In each iteration we // _try_ to write that sample to the DMA buffer, and if successful, we can buffer the next sample. Somewhat cumbersome, but works. // TODO: Should ESP32 gain an implemenation of i2s_available(), we should switch to using that, instead. static bool _esp32_can_buffer_next = true; -# if (IS_INTERNAL_DAC()) +# if defined(IS_INTERNAL_DAC) static uint16_t _esp32_prev_sample[2]; -# elif (IS_I2S_DAC()) +# elif defined(IS_I2S_DAC) static int16_t _esp32_prev_sample[2]; -# elif (IS_PDM()) +# elif defined(IS_PDM) static uint32_t _esp32_prev_sample[PDM_RESOLUTION]; # endif @@ -122,7 +118,7 @@ inline bool canBufferAudioOutput() { } inline void audioOutput(const AudioOutput f) { -# if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) +# if defined(IS_INTERNAL_DAC) _esp32_prev_sample[0] = (f.l() + AUDIO_BIAS) << 8; # if (AUDIO_CHANNELS > 1) _esp32_prev_sample[1] = (f.r() + AUDIO_BIAS) << 8; @@ -130,7 +126,7 @@ inline void audioOutput(const AudioOutput f) { // For simplicity of code, even in mono, we're writing stereo samples _esp32_prev_sample[1] = _esp32_prev_sample[0]; # endif -# elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) +# elif defined(IS_PDM) for (uint8_t i=0; i Date: Sat, 11 Mar 2023 09:18:30 +0100 Subject: [PATCH 06/10] Cleanup USE_CUSTOM_AUDIO_INPUT --- AudioConfigESP32.h | 3 +-- MozziGuts_impl_ESP32.hpp | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/AudioConfigESP32.h b/AudioConfigESP32.h index 118edfac6..08ceeab50 100644 --- a/AudioConfigESP32.h +++ b/AudioConfigESP32.h @@ -71,9 +71,8 @@ const i2s_port_t i2s_num = I2S_NUM_0; // If ADC is available we support getAudioInput() #if ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC +# define USE_CUSTOM_AUDIO_INPUT int getAudioInput(); #endif - - #endif // #ifndef AUDIOCONFIGESP_H diff --git a/MozziGuts_impl_ESP32.hpp b/MozziGuts_impl_ESP32.hpp index d70673769..e6509874d 100644 --- a/MozziGuts_impl_ESP32.hpp +++ b/MozziGuts_impl_ESP32.hpp @@ -51,10 +51,6 @@ int getI2SMode(){ return -1; } - -// We provide a custom implementation of getAudioInput() avoiding the complex standard handling -#define USE_CUSTOM_AUDIO_INPUT - /// @brief Reads a sample from the I2S buffer. I2S is stereo, so we combine the result to one single sample int getAudioInput() { static const int i2s_port = getWritePort(); From 5ad8be21ed3f46be43f56e6ebf27326f4dde8de7 Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sat, 11 Mar 2023 09:43:16 +0100 Subject: [PATCH 07/10] Cleanup mozzi_config.h --- mozzi_config.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/mozzi_config.h b/mozzi_config.h index 25b2ee6ba..1881e2de9 100644 --- a/mozzi_config.h +++ b/mozzi_config.h @@ -112,6 +112,4 @@ Only used when EXTERNAL_AUDIO_OUTPUT is set to true: The resolution to use for a output resolution of your DAC. 16 is the default value, here. Note that 16 bits is also the maximum currently supported on AVR. */ //#define EXTERNAL_AUDIO_BITS 16 - - #endif // #ifndef MOZZI_CONFIG_H From 58c714f7753f64291f4b8dfc07524ece5add4a6b Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sat, 11 Mar 2023 10:05:51 +0100 Subject: [PATCH 08/10] Add original warnings for ADC --- MozziGuts_impl_ESP32.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MozziGuts_impl_ESP32.hpp b/MozziGuts_impl_ESP32.hpp index e6509874d..48fdf958e 100644 --- a/MozziGuts_impl_ESP32.hpp +++ b/MozziGuts_impl_ESP32.hpp @@ -71,16 +71,16 @@ uint8_t adcPinToChannelNum(uint8_t pin) { return pin; } void adcStartConversion(uint8_t channel) { -// ESP_LOGD(module, "%s", __func__); +#warning Fast analog read not implemented on this platform } void startSecondADCReadOnCurrentChannel() { -// ESP_LOGD(module, "%s", __func__); +#warning Fast analog read not implemented on this platform } void setupFastAnalogRead(int8_t speed) { -// ESP_LOGD(module, "%s", __func__); +#warning Fast analog read not implemented on this platform } void setupMozziADC(int8_t speed) { -// ESP_LOGD(module, "%s: %d", __func__, speed); +#warning Fast analog read not implemented on this platform } ////// END analog input code //////// From 96b1110883320cd3b1d8e18cfb69d96dba14a8ba Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sat, 11 Mar 2023 10:52:23 +0100 Subject: [PATCH 09/10] Support External ouput --- AudioConfigESP32.h | 3 ++- MozziGuts_impl_ESP32.hpp | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/AudioConfigESP32.h b/AudioConfigESP32.h index 08ceeab50..8965e6310 100644 --- a/AudioConfigESP32.h +++ b/AudioConfigESP32.h @@ -41,6 +41,7 @@ const i2s_port_t i2s_num = I2S_NUM_0; //#define ESP32_AUDIO_RATE 8000 +///-------------------------------------------------------------------------------------------------------- /// User config end. Do not modify below this line ///-------------------------------------------------------------------------------------------------------- @@ -61,7 +62,7 @@ const i2s_port_t i2s_num = I2S_NUM_0; #endif #define AUDIO_BIAS ((uint16_t) 1<<(AUDIO_BITS-1)) -#define BYPASS_MOZZI_OUTPUT_BUFFER true +#define BYPASS_MOZZI_OUTPUT_BUFFER !EXTERNAL_AUDIO_OUTPUT // Use defined rate as new AUDIO_RATE_PLATFORM_DEFAULT #ifdef ESP32_AUDIO_RATE diff --git a/MozziGuts_impl_ESP32.hpp b/MozziGuts_impl_ESP32.hpp index 48fdf958e..a700996f6 100644 --- a/MozziGuts_impl_ESP32.hpp +++ b/MozziGuts_impl_ESP32.hpp @@ -19,7 +19,7 @@ static const char module[]="Mozzi-ESP32"; /// Make sure that we provide a supported port -int getWritePort(){ +int getI2SPort(){ switch (ESP32_AUDIO_OUT_MODE){ case INTERNAL_DAC: return 0; @@ -53,7 +53,7 @@ int getI2SMode(){ /// @brief Reads a sample from the I2S buffer. I2S is stereo, so we combine the result to one single sample int getAudioInput() { - static const int i2s_port = getWritePort(); + static const int i2s_port = getI2SPort(); if (i2s_port==-1) return 0; int16_t tmp[2]; @@ -99,7 +99,7 @@ static uint32_t _esp32_prev_sample[PDM_RESOLUTION]; # endif inline bool esp32_tryWriteSample() { - static i2s_port_t port = (i2s_port_t) getWritePort(); + static i2s_port_t port = (i2s_port_t) getI2SPort(); size_t bytes_written; int write_len = sizeof(_esp32_prev_sample); i2s_write(port, &_esp32_prev_sample, write_len, &bytes_written, 0); @@ -214,12 +214,12 @@ static void startAudio() { /// Use I2S for the Output and Input static void startAudio() { // start output - startI2SAudio((i2s_port_t)getWritePort(), getI2SMode()); + startI2SAudio((i2s_port_t)getI2SPort(), getI2SMode()); } #endif void stopMozzi() { - i2s_driver_uninstall((i2s_port_t)getWritePort()); + i2s_driver_uninstall((i2s_port_t)getI2SPort()); } //// END AUDIO OUTPUT code /////// From c49ecaafaf4f29c966f0708c3f8a48960fe12a1b Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sat, 11 Mar 2023 12:42:16 +0100 Subject: [PATCH 10/10] Cleanup Logic --- AudioConfigESP32.h | 51 +++++++------ MozziGuts_impl_ESP32.hpp | 161 +++++++++++++++++++++------------------ 2 files changed, 112 insertions(+), 100 deletions(-) diff --git a/AudioConfigESP32.h b/AudioConfigESP32.h index 8965e6310..26d19476d 100644 --- a/AudioConfigESP32.h +++ b/AudioConfigESP32.h @@ -44,36 +44,37 @@ const i2s_port_t i2s_num = I2S_NUM_0; ///-------------------------------------------------------------------------------------------------------- /// User config end. Do not modify below this line ///-------------------------------------------------------------------------------------------------------- - -#if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) -#define AUDIO_BITS 8 -#define PDM_RESOLUTION 1 -#define IS_INTERNAL_DAC -#elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC || ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC) -#define AUDIO_BITS 16 -#define PDM_RESOLUTION 1 -#define IS_I2S_DAC -#elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) -#define AUDIO_BITS 16 -#define PDM_RESOLUTION 4 -#define IS_PDM -#else -#error Invalid output mode configured in AudioConfigESP32.h -#endif - -#define AUDIO_BIAS ((uint16_t) 1<<(AUDIO_BITS-1)) -#define BYPASS_MOZZI_OUTPUT_BUFFER !EXTERNAL_AUDIO_OUTPUT +#if !EXTERNAL_AUDIO_OUTPUT +# if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC) +# define AUDIO_BITS 8 +# define PDM_RESOLUTION 1 +# define IS_INTERNAL_DAC +# elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC || ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC) +# define AUDIO_BITS 16 +# define PDM_RESOLUTION 1 +# define IS_I2S_DAC +# elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S) +# define AUDIO_BITS 16 +# define PDM_RESOLUTION 4 +# define IS_PDM +# else +# error Invalid output mode configured in AudioConfigESP32.h +# endif + +# define AUDIO_BIAS ((uint16_t) 1<<(AUDIO_BITS-1)) +# define BYPASS_MOZZI_OUTPUT_BUFFER true // Use defined rate as new AUDIO_RATE_PLATFORM_DEFAULT -#ifdef ESP32_AUDIO_RATE -# undef AUDIO_RATE_PLATFORM_DEFAULT -# define AUDIO_RATE_PLATFORM_DEFAULT ESP32_AUDIO_RATE -#endif +# ifdef ESP32_AUDIO_RATE +# undef AUDIO_RATE_PLATFORM_DEFAULT +# define AUDIO_RATE_PLATFORM_DEFAULT ESP32_AUDIO_RATE +# endif // If ADC is available we support getAudioInput() -#if ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC -# define USE_CUSTOM_AUDIO_INPUT +# if ESP32_AUDIO_OUT_MODE == I2S_DAC_AND_I2S_ADC +# define USE_CUSTOM_AUDIO_INPUT int getAudioInput(); +# endif #endif #endif // #ifndef AUDIOCONFIGESP_H diff --git a/MozziGuts_impl_ESP32.hpp b/MozziGuts_impl_ESP32.hpp index a700996f6..a5cb72efd 100644 --- a/MozziGuts_impl_ESP32.hpp +++ b/MozziGuts_impl_ESP32.hpp @@ -18,6 +18,78 @@ static const char module[]="Mozzi-ESP32"; + +// ////// BEGIN analog input code //////// +#define getADCReading() 0; + +#define channelNumToIndex(channel) channel +uint8_t adcPinToChannelNum(uint8_t pin) { + return pin; +} +void adcStartConversion(uint8_t channel) { +#warning Fast analog read not implemented on this platform +} +void startSecondADCReadOnCurrentChannel() { +#warning Fast analog read not implemented on this platform +} +void setupFastAnalogRead(int8_t speed) { +#warning Fast analog read not implemented on this platform +} +void setupMozziADC(int8_t speed) { +#warning Fast analog read not implemented on this platform +} +////// END analog input code //////// + + +#if (EXTERNAL_AUDIO_OUTPUT) // for external audio output, set up a timer running a audio rate + +void CACHED_FUNCTION_ATTR timer0_audio_output_isr(void *) { + TIMERG0.int_clr_timers.t0 = 1; + TIMERG0.hw_timer[0].config.alarm_en = 1; + defaultAudioOutput(); +} + + +static void startAudio() { + static intr_handle_t s_timer_handle; + const int div = 2; + timer_config_t config = { + .alarm_en = (timer_alarm_t)true, + .counter_en = (timer_start_t)false, + .intr_type = (timer_intr_mode_t) TIMER_INTR_LEVEL, + .counter_dir = TIMER_COUNT_UP, + .auto_reload = (timer_autoreload_t) true, + .divider = div // For max available precision: The APB_CLK clock signal is running at 80 MHz, i.e. 2/80 uS per tick + // Min acceptable value is 2 + }; + timer_init(TIMER_GROUP_0, TIMER_0, &config); + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 80000000UL / AUDIO_RATE / div); + timer_enable_intr(TIMER_GROUP_0, TIMER_0); + timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer0_audio_output_isr, nullptr, 0, &s_timer_handle); + timer_start(TIMER_GROUP_0, TIMER_0); +} + +void stopMozzi() { + timer_pause(TIMER_GROUP_0, TIMER_0); + timer_disable_intr(TIMER_GROUP_0, TIMER_0); +} + +#else // I2S Output + +// On ESP32 we cannot test wether the DMA buffer has room. Instead, we have to use a one-sample mini buffer. In each iteration we +// _try_ to write that sample to the DMA buffer, and if successful, we can buffer the next sample. Somewhat cumbersome, but works. +// TODO: Should ESP32 gain an implemenation of i2s_available(), we should switch to using that, instead. +static bool _esp32_can_buffer_next = true; +# if defined(IS_INTERNAL_DAC) +static uint16_t _esp32_prev_sample[2]; +# elif defined(IS_I2S_DAC) +static int16_t _esp32_prev_sample[2]; +# elif defined(IS_PDM) +static uint32_t _esp32_prev_sample[PDM_RESOLUTION]; +# endif + + /// Make sure that we provide a supported port int getI2SPort(){ switch (ESP32_AUDIO_OUT_MODE){ @@ -39,15 +111,19 @@ int getI2SPort(){ int getI2SMode(){ switch (ESP32_AUDIO_OUT_MODE){ case INTERNAL_DAC: + ESP_LOGD(module, "%s: %s", __func__, "I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN"); return I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN; case PDM_VIA_I2S: + ESP_LOGD(module, "%s: %s", __func__, "I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM"); return I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM; case PT8211_DAC: + ESP_LOGD(module, "%s: %s", __func__, "I2S_MODE_MASTER | I2S_MODE_TX"); return I2S_MODE_MASTER | I2S_MODE_TX; case I2S_DAC_AND_I2S_ADC: + ESP_LOGD(module, "%s: %s", __func__, "I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX"); return I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX; } - ESP_LOGE(module, "%s - %s", __func__, "ESP32_AUDIO_OUT_MODE invalid"); + ESP_LOGE(module, "%s: %s", __func__, "ESP32_AUDIO_OUT_MODE invalid"); return -1; } @@ -63,41 +139,6 @@ int getAudioInput() { } -// ////// BEGIN analog input code //////// -#define getADCReading() 0; - -#define channelNumToIndex(channel) channel -uint8_t adcPinToChannelNum(uint8_t pin) { - return pin; -} -void adcStartConversion(uint8_t channel) { -#warning Fast analog read not implemented on this platform -} -void startSecondADCReadOnCurrentChannel() { -#warning Fast analog read not implemented on this platform -} -void setupFastAnalogRead(int8_t speed) { -#warning Fast analog read not implemented on this platform -} -void setupMozziADC(int8_t speed) { -#warning Fast analog read not implemented on this platform -} -////// END analog input code //////// - - -#if (EXTERNAL_AUDIO_OUTPUT != true) -// On ESP32 we cannot test wether the DMA buffer has room. Instead, we have to use a one-sample mini buffer. In each iteration we -// _try_ to write that sample to the DMA buffer, and if successful, we can buffer the next sample. Somewhat cumbersome, but works. -// TODO: Should ESP32 gain an implemenation of i2s_available(), we should switch to using that, instead. -static bool _esp32_can_buffer_next = true; -# if defined(IS_INTERNAL_DAC) -static uint16_t _esp32_prev_sample[2]; -# elif defined(IS_I2S_DAC) -static int16_t _esp32_prev_sample[2]; -# elif defined(IS_PDM) -static uint32_t _esp32_prev_sample[PDM_RESOLUTION]; -# endif - inline bool esp32_tryWriteSample() { static i2s_port_t port = (i2s_port_t) getI2SPort(); size_t bytes_written; @@ -133,16 +174,6 @@ inline void audioOutput(const AudioOutput f) { # endif _esp32_can_buffer_next = esp32_tryWriteSample(); } -#endif - -#if (BYPASS_MOZZI_OUTPUT_BUFFER != true) -void CACHED_FUNCTION_ATTR timer0_audio_output_isr(void *) { - TIMERG0.int_clr_timers.t0 = 1; - TIMERG0.hw_timer[0].config.alarm_en = 1; - defaultAudioOutput(); -} -#endif - static void startI2SAudio(i2s_port_t port, int mode){ ESP_LOGI(module, "%s: port=%d, mode=0x%x, rate=%d", __func__, port, mode, AUDIO_RATE * PDM_RESOLUTION); @@ -165,7 +196,7 @@ static void startI2SAudio(i2s_port_t port, int mode){ } // Internal DAC - if (mode & I2S_MODE_DAC_BUILT_IN){ + if (ESP32_AUDIO_OUT_MODE==INTERNAL_DAC){ if (i2s_set_pin(port, NULL)!=ESP_OK) { ESP_LOGE(module, "%s - %s", __func__, "i2s_set_pin"); } @@ -187,39 +218,19 @@ static void startI2SAudio(i2s_port_t port, int mode){ i2s_zero_dma_buffer(port); } - -#if (BYPASS_MOZZI_OUTPUT_BUFFER != true) // for external audio output, set up a timer running a audio rate - -static void startAudio() { - static intr_handle_t s_timer_handle; - const int div = 2; - timer_config_t config = { - .alarm_en = (timer_alarm_t)true, - .counter_en = (timer_start_t)false, - .intr_type = (timer_intr_mode_t) TIMER_INTR_LEVEL, - .counter_dir = TIMER_COUNT_UP, - .auto_reload = (timer_autoreload_t) true, - .divider = div // For max available precision: The APB_CLK clock signal is running at 80 MHz, i.e. 2/80 uS per tick - // Min acceptable value is 2 - }; - timer_init(TIMER_GROUP_0, TIMER_0, &config); - timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); - timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 80000000UL / AUDIO_RATE / div); - timer_enable_intr(TIMER_GROUP_0, TIMER_0); - timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer0_audio_output_isr, nullptr, 0, &s_timer_handle); - timer_start(TIMER_GROUP_0, TIMER_0); -} -#else - /// Use I2S for the Output and Input static void startAudio() { // start output - startI2SAudio((i2s_port_t)getI2SPort(), getI2SMode()); + i2s_port_t port = (i2s_port_t)getI2SPort(); + startI2SAudio(port, getI2SMode()); } -#endif - void stopMozzi() { - i2s_driver_uninstall((i2s_port_t)getI2SPort()); + i2s_port_t port = (i2s_port_t)getI2SPort(); + i2s_stop(port); + i2s_driver_uninstall(port); } + +#endif + //// END AUDIO OUTPUT code ///////