From 4680312952248ab7cdac04e2901549cad28d0354 Mon Sep 17 00:00:00 2001 From: tomcombriat Date: Thu, 16 Jan 2025 21:59:14 +0100 Subject: [PATCH] Config of I2S for ESP32 and documentation Config of I2S for ESP32 Updated documentation on ESP32 --- internal/MozziGuts_impl_ESP32.hpp | 32 ++++++++++++++++------ internal/config_checks_esp32.h | 45 ++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/internal/MozziGuts_impl_ESP32.hpp b/internal/MozziGuts_impl_ESP32.hpp index 0dabec056..90abb2b2e 100644 --- a/internal/MozziGuts_impl_ESP32.hpp +++ b/internal/MozziGuts_impl_ESP32.hpp @@ -4,6 +4,7 @@ * This file is part of Mozzi. * * Copyright 2020-2024 Dieter Vandoren, Thomas Friedrichsmeier and the Mozzi Team + * Copyright 2025 Thomas Combriat and the Mozzi Team * * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later. * @@ -81,7 +82,11 @@ namespace MozziPrivate { size_t bytes_written; //i2s_write(i2s_num, &_esp32_prev_sample, ESP_SAMPLE_SIZE, &bytes_written, 0); #if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_I2S_DAC) || MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_I2S) - i2s_channel_write(tx_handle,_esp32_prev_sample, sizeof(_esp32_prev_sample[0]), &bytes_written, 0);// TODO STEREO +# if (MOZZI_AUDIO_CHANNELS > 1) + i2s_channel_write(tx_handle,_esp32_prev_sample, sizeof(_esp32_prev_sample[0]), &bytes_written, 0); +# else + i2s_channel_write(tx_handle,_esp32_prev_sample, 2*sizeof(_esp32_prev_sample[0]), &bytes_written, 0); +# endif #elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC) dac_continuous_write(dac_handle, _esp32_prev_sample, ESP_SAMPLE_SIZE, &bytes_written, 0); /*uint8_t tt = 120; @@ -118,7 +123,7 @@ namespace MozziPrivate { _esp32_prev_sample[0] = f.l(); _esp32_prev_sample[1] = f.r(); # endif - _esp32_can_buffer_next = esp32_tryWriteSample(); + _esp32_can_buffer_next = esp32_tryWriteSample(); } #endif } // namespace MozziPrivate @@ -168,9 +173,20 @@ namespace MozziPrivate { i2s_new_channel(&chan_cfg, &tx_handle, NULL); //static const i2s_config_t i2s_config = { i2s_std_config_t std_cfg = { - .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(MOZZI_AUDIO_RATE), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(ESP_SAMPLE_SIZE, I2S_SLOT_MODE_MONO), // TODO: add between the different modes? AND STEREO - //.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(ESP_SAMPLE_SIZE, I2S_SLOT_MODE_MONO), + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(MOZZI_AUDIO_RATE), +# if (MOZZI_IS, MOZZI_I2S_FORMAT_PLAIN) +# if (MOZZI_AUDIO_CHANNELS > 1) + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(ESP_SAMPLE_SIZE, I2S_SLOT_MODE_STEREO), +# else + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(ESP_SAMPLE_SIZE, I2S_SLOT_MODE_MONO), +# endif +# elif (MOZZI_IS, MOZZI_I2S_FORMAT_LSBJ) +# if (MOZZI_AUDIO_CHANNELS > 1) + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(ESP_SAMPLE_SIZE, I2S_SLOT_MODE_STEREO), // TODO: add STEREO +# else + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(ESP_SAMPLE_SIZE, I2S_SLOT_MODE_MONO), // TODO: add STEREO +# endif +# endif .gpio_cfg = { .mclk = gpio_num_t(MOZZI_I2S_PIN_MCLK), .bclk = gpio_num_t(MOZZI_I2S_PIN_BCK), @@ -178,9 +194,9 @@ namespace MozziPrivate { .dout = gpio_num_t(MOZZI_I2S_PIN_DATA), .din = I2S_GPIO_UNUSED, .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = true, + .mclk_inv = MOZZI_I2S_MBCK_INV, + .bclk_inv = MOZZI_I2S_BCK_INV, + .ws_inv = MOZZI_I2S_WS_INV, }, }, diff --git a/internal/config_checks_esp32.h b/internal/config_checks_esp32.h index 7ecdb7342..f217ac0f6 100644 --- a/internal/config_checks_esp32.h +++ b/internal/config_checks_esp32.h @@ -15,7 +15,7 @@ /** * @page hardware_esp32 Mozzi on ESP32-based boards. * - * port by Dieter Vandoren and Thomas Friedrichsmeier + * port by Dieter Vandoren, Thomas Friedrichsmeier and Thomas Combriat * * @section esp32_status Port status and notes * - Since flash memory is not built into the ESP32, but connected, externally, it is much too slow for keeping wave tables, audio samples, etc. Instead, these are kept in RAM on this platform. @@ -51,19 +51,34 @@ * @endcode * * @section esp32_i2s_dac MOZZI_OUTPUT_I2S_DAC - * This mode outputs to a PT8211 (or compatible) I2S DAC, which allows for very high quality (mono or stereo) output. Communication needs the BCK, WS, and DATA(out) pins - * of one I2S interface. Presumably, any pins qualify, and you can configure this using: + * This mode outputs to a PT8211 (or compatible) I2S DAC, which allows for very high quality (mono or stereo) output. By default this mode outputs a plain I2S signal, with BCK, WS and DATA lines defined (but configurable, see after), which is equivalent to defining: + * + * @code + * #define MOZZI_I2S_FORMAT MOZZI_I2S_FORMAT_PLAIN + * @endcode + * + * The mode can be changed to LSBJ format (the PT8211 DAC for instance uses this format) by using: + * + * @code + * #define MOZZI_I2S_FORMAT MOZZI_I2S_FORMAT_LSBJ + * @endcode + * + * In addition to the three pins referred above, MCLK pin, which is of use in some DAC can be defined. + * Presumably, any pins qualify, and you can configure this using: * @code * #define MOZZI_I2S_PIN_BCK ... // (default: 26) * #define MOZZI_I2S_PIN_WS ... // (default: 15) * #define MOZZI_I2S_PIN_DATA ... // (default: 33) + * #define MOZZI_I2S_PIN_MCLK ... // (default: UNDEFINED) * #define MOZZI_I2S_PORT ... // (default: I2S_NUM_0) * @endcode * - * See the note above (@ref esp_internal_dac) regarding pin numbering. Also, please always test the default pinout, should a custom setting fail! - * - * As a technical note, I2S support in the ESP32 SDK has been reworked since this was implemented in Mozzi, and Mozzi uses the "legacy" implementation "i2s.h". - * This should not be an issue, unless you want to connect additional I2S components, yourself. In which case contributions are certainly welcome! + * For further customization, the signals outputted on some of these pins can be inverted, to accomodate DAC that would not fall into the standard, by using: + * @code + * #define MOZZI_I2S_BCK_INV ... // (default: 0) + * #define MOZZI_I2S_WS_INV ... // (default: 0 for PLAIN format, 1 for LSBJ) + * #define MOZZI_I2S_MBCK_INV ... // (default: 0) + * @endcode * * @section esp32_pdm_via_i2s MOZZI_OUTPUT_PDM_VIA_I2S * This mode uses the same setup as @ref esp32_i2s_dac, but rather than using an external DAC, the communication signal itself is modulated in PDM @@ -103,6 +118,9 @@ MOZZI_CHECK_SUPPORTED(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE) MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) #if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_I2S_DAC, MOZZI_OUTPUT_PDM_VIA_I2S) +# if !defined(MOZZI_I2S_FORMAT) +# define MOZZI_I2S_FORMAT MOZZI_I2S_FORMAT_PLAIN +# endif # if !defined(MOZZI_I2S_PIN_BCK) # define MOZZI_I2S_PIN_BCK 26 # endif @@ -115,6 +133,19 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) # if !defined(MOZZI_I2S_PIN_MCLK) # define MOZZI_I2S_PIN_MCLK I2S_GPIO_UNUSED # endif +# if !defined(MOZZI_I2S_BCK_INV) +# define MOZZI_I2S_BCK_INV 0 +# endif +# if !defined(MOZZI_I2S_WS_INV) +# if MOZZI_IS(MOZZI_I2S_FORMAT, MOZZI_I2S_FORMAT_PLAIN) +# define MOZZI_I2S_WS_INV 0 +# elif MOZZI_IS(MOZZI_I2S_FORMAT, MOZZI_I2S_FORMAT_LSBJ) +# define MOZZI_I2S_WS_INV 1 +# endif +# endif +# if !defined(MOZZI_I2S_MBCK_INV) +# define MOZZI_I2S_MBCK_INV 0 +# endif #endif #if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC, MOZZI_OUTPUT_I2S_DAC, MOZZI_OUTPUT_PDM_VIA_I2S)