diff --git a/src/AudioTools/CoreAudio/AudioI2S/I2SESP32V1.h b/src/AudioTools/CoreAudio/AudioI2S/I2SESP32V1.h index 3292d00c2..e870975b2 100644 --- a/src/AudioTools/CoreAudio/AudioI2S/I2SESP32V1.h +++ b/src/AudioTools/CoreAudio/AudioI2S/I2SESP32V1.h @@ -11,8 +11,7 @@ #include "driver/i2s_tdm.h" #include "esp_system.h" -#define IS_I2S_IMPLEMENTED - +#define IS_I2S_IMPLEMENTED namespace audio_tools { @@ -106,7 +105,7 @@ class I2SDriverESP32V1 { size_t writeBytes(const void *src, size_t size_bytes) { TRACED(); size_t result; - assert(tx_chan !=nullptr); + assert(tx_chan != nullptr); if (i2s_channel_write(tx_chan, src, size_bytes, &result, ticks_to_wait_write) != ESP_OK) { TRACEE(); @@ -140,11 +139,12 @@ class I2SDriverESP32V1 { TickType_t ticks_to_wait_write = portMAX_DELAY; struct DriverCommon { - virtual i2s_chan_config_t getChannelConfig(I2SConfigESP32V1 &cfg) = 0; virtual bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, i2s_chan_handle_t &rx_chan, int txPin, int rxPin) = 0; + + virtual i2s_chan_config_t getChannelConfig(I2SConfigESP32V1 &cfg) = 0; // changes the sample rate virtual bool changeSampleRate(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, @@ -154,6 +154,56 @@ class I2SDriverESP32V1 { }; struct DriverI2S : public DriverCommon { + bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, + i2s_chan_handle_t &rx_chan, int txPin, int rxPin) { + TRACED(); + LOGI("tx: %d, rx: %d", txPin, rxPin); + i2s_std_config_t std_cfg = { + .clk_cfg = getClockConfig(cfg), + .slot_cfg = getSlotConfig(cfg), + .gpio_cfg = + { + .mclk = (gpio_num_t)cfg.pin_mck, + .bclk = (gpio_num_t)cfg.pin_bck, + .ws = (gpio_num_t)cfg.pin_ws, + .dout = (gpio_num_t)txPin, + .din = (gpio_num_t)rxPin, + .invert_flags = + { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + + if (cfg.rx_tx_mode == RXTX_MODE || cfg.rx_tx_mode == TX_MODE) { + if (i2s_channel_init_std_mode(tx_chan, &std_cfg) != ESP_OK) { + LOGE("i2s_channel_init_std_mode %s", "tx"); + return false; + } + if (i2s_channel_enable(tx_chan) != ESP_OK) { + LOGE("i2s_channel_enable %s", "tx"); + return false; + } + } + + if (cfg.rx_tx_mode == RXTX_MODE || cfg.rx_tx_mode == RX_MODE) { + if (i2s_channel_init_std_mode(rx_chan, &std_cfg) != ESP_OK) { + LOGE("i2s_channel_init_std_mode %s", "rx"); + return false; + } + if (i2s_channel_enable(rx_chan) != ESP_OK) { + LOGE("i2s_channel_enable %s", "rx"); + return false; + } + } + + LOGD("%s - %s", __func__, "started"); + return true; + } + + protected: i2s_std_slot_config_t getSlotConfig(I2SConfigESP32V1 &cfg) { TRACED(); i2s_std_slot_config_t result; @@ -212,10 +262,10 @@ class I2SDriverESP32V1 { TRACED(); i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG((uint32_t)cfg.sample_rate); - if (cfg.mclk_multiple > 0){ - clk_cfg.mclk_multiple = (i2s_mclk_multiple_t) cfg.mclk_multiple; + if (cfg.mclk_multiple > 0) { + clk_cfg.mclk_multiple = (i2s_mclk_multiple_t)cfg.mclk_multiple; } else { - if (cfg.pin_mck !=-1 && cfg.bits_per_sample == 24) { + if (cfg.pin_mck != -1 && cfg.bits_per_sample == 24) { // mclk_multiple' should be the multiple of 3 while using 24-bit clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_384; LOGI("mclk_multiple=384"); @@ -224,55 +274,6 @@ class I2SDriverESP32V1 { return clk_cfg; } - bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, - i2s_chan_handle_t &rx_chan, int txPin, int rxPin) { - TRACED(); - LOGI("tx: %d, rx: %d", txPin, rxPin); - i2s_std_config_t std_cfg = { - .clk_cfg = getClockConfig(cfg), - .slot_cfg = getSlotConfig(cfg), - .gpio_cfg = - { - .mclk = (gpio_num_t)cfg.pin_mck, - .bclk = (gpio_num_t)cfg.pin_bck, - .ws = (gpio_num_t)cfg.pin_ws, - .dout = (gpio_num_t)txPin, - .din = (gpio_num_t)rxPin, - .invert_flags = - { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - }, - }, - }; - - if (cfg.rx_tx_mode == RXTX_MODE || cfg.rx_tx_mode == TX_MODE) { - if (i2s_channel_init_std_mode(tx_chan, &std_cfg) != ESP_OK) { - LOGE("i2s_channel_init_std_mode %s", "tx"); - return false; - } - if (i2s_channel_enable(tx_chan) != ESP_OK) { - LOGE("i2s_channel_enable %s", "tx"); - return false; - } - } - - if (cfg.rx_tx_mode == RXTX_MODE || cfg.rx_tx_mode == RX_MODE) { - if (i2s_channel_init_std_mode(rx_chan, &std_cfg) != ESP_OK) { - LOGE("i2s_channel_init_std_mode %s", "rx"); - return false; - } - if (i2s_channel_enable(rx_chan) != ESP_OK) { - LOGE("i2s_channel_enable %s", "rx"); - return false; - } - } - - LOGD("%s - %s", __func__, "started"); - return true; - } - bool changeSampleRate(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, i2s_chan_handle_t &rx_chan) override { bool rc = false; @@ -295,12 +296,30 @@ class I2SDriverESP32V1 { #ifdef USE_PDM struct DriverPDM : public DriverCommon { + bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, + i2s_chan_handle_t &rx_chan, int txPin, int rxPin) { + if (cfg.rx_tx_mode == TX_MODE) { + return startTX(cfg, tx_chan, txPin); + } else if (cfg.rx_tx_mode == RX_MODE) { + return startRX(cfg, tx_chan, txPin); + } + LOGE("Only RX and TX is supported for PDM") + return false; + } + + protected: i2s_pdm_tx_slot_config_t getTxSlotConfig(I2SConfigESP32V1 &cfg) { return I2S_PDM_TX_SLOT_DEFAULT_CONFIG( (i2s_data_bit_width_t)cfg.bits_per_sample, (i2s_slot_mode_t)cfg.channels); } + i2s_pdm_rx_slot_config_t getRxSlotConfig(I2SConfigESP32V1 &cfg) { + return I2S_PDM_RX_SLOT_DEFAULT_CONFIG( + (i2s_data_bit_width_t)cfg.bits_per_sample, + (i2s_slot_mode_t)cfg.channels); + } + i2s_chan_config_t getChannelConfig(I2SConfigESP32V1 &cfg) { return I2S_CHANNEL_DEFAULT_CONFIG( (i2s_port_t)cfg.port_no, @@ -311,37 +330,62 @@ class I2SDriverESP32V1 { return I2S_PDM_TX_CLK_DEFAULT_CONFIG((uint32_t)cfg.sample_rate); } - bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, - i2s_chan_handle_t &rx_chan, int txPin, int rxPin) { - if (cfg.rx_tx_mode == TX_MODE) { - i2s_pdm_tx_config_t pdm_tx_cfg = { - .clk_cfg = getTxClockConfig(cfg), - .slot_cfg = getTxSlotConfig(cfg), - .gpio_cfg = - { - .clk = (gpio_num_t)cfg.pin_bck, - .dout = (gpio_num_t)txPin, - .invert_flags = - { - .clk_inv = false, - }, - }, - }; - - if (i2s_channel_init_pdm_tx_mode(tx_chan, &pdm_tx_cfg) != ESP_OK) { - LOGE("i2s_channel_init_pdm_tx_mode %s", "tx"); - return false; - } - if (i2s_channel_enable(tx_chan) != ESP_OK) { - LOGE("i2s_channel_enable %s", "tx"); - return false; - } - } else { - LOGE("Only TX supported for PDM"); + i2s_pdm_rx_clk_config_t getRxClockConfig(I2SConfigESP32V1 &cfg) { + return I2S_PDM_RX_CLK_DEFAULT_CONFIG((uint32_t)cfg.sample_rate); + } + + bool startTX(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, int txPin) { + i2s_pdm_tx_config_t pdm_tx_cfg = { + .clk_cfg = getTxClockConfig(cfg), + .slot_cfg = getTxSlotConfig(cfg), + .gpio_cfg = + { + .clk = (gpio_num_t)cfg.pin_bck, + .dout = (gpio_num_t)txPin, + .invert_flags = + { + .clk_inv = false, + }, + }, + }; + + if (i2s_channel_init_pdm_tx_mode(tx_chan, &pdm_tx_cfg) != ESP_OK) { + LOGE("i2s_channel_init_pdm_tx_mode %s", "tx"); + return false; + } + if (i2s_channel_enable(tx_chan) != ESP_OK) { + LOGE("i2s_channel_enable %s", "tx"); return false; } return true; } + + bool startRX(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &rx_chan, int rxPin) { + i2s_pdm_rx_config_t pdm_rx_cfg = { + .clk_cfg = getRxClockConfig(cfg), + .slot_cfg = getRxSlotConfig(cfg), + .gpio_cfg = + { + .clk = (gpio_num_t)cfg.pin_bck, + .din = (gpio_num_t)rxPin, + .invert_flags = + { + .clk_inv = false, + }, + }, + }; + + if (i2s_channel_init_pdm_rx_mode(rx_chan, &pdm_rx_cfg) != ESP_OK) { + LOGE("i2s_channel_init_pdm_rx_mode %s", "rx"); + return false; + } + if (i2s_channel_enable(rx_chan) != ESP_OK) { + LOGE("i2s_channel_enable %s", "tx"); + return false; + } + return true; + } + } pdm; #endif @@ -350,6 +394,45 @@ class I2SDriverESP32V1 { // example at // https://github.com/espressif/esp-idf/blob/v5.3-dev/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/i2s_tdm_example_main.c struct DriverTDM : public DriverCommon { + bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, + i2s_chan_handle_t &rx_chan, int txPin, int rxPin) { + i2s_tdm_config_t tdm_cfg = { + .clk_cfg = getClockConfig(cfg), + .slot_cfg = getSlotConfig(cfg), + .gpio_cfg = + { + .mclk = (gpio_num_t)cfg.pin_mck, + .bclk = (gpio_num_t)cfg.pin_bck, + .ws = (gpio_num_t)cfg.pin_ws, + .dout = (gpio_num_t)txPin, + .din = (gpio_num_t)rxPin, + .invert_flags = + { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + + if (cfg.rx_tx_mode == TX_MODE) { + if (i2s_channel_init_tdm_mode(tx_chan, &tdm_cfg) != ESP_OK) { + LOGE("i2s_channel_init_tdm_tx_mode %s", "tx"); + return false; + } + } + if (cfg.rx_tx_mode == RX_MODE) { + if (i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg) != ESP_OK) { + LOGE("i2s_channel_init_tdm_tx_mode %s", "rx"); + return false; + } + return true; + } + LOGE("Only RX and TX is supported for TDM") + return false; + } + + protected: i2s_tdm_slot_config_t getSlotConfig(I2SConfigESP32V1 &cfg) { int slots = 0; for (int j = 0; j < cfg.channels; j++) { @@ -357,11 +440,11 @@ class I2SDriverESP32V1 { } // setup default format i2s_tdm_slot_config_t slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG( - (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO, - (i2s_tdm_slot_mask_t)slots); + (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO, + (i2s_tdm_slot_mask_t)slots); - switch(cfg.i2s_format){ - case I2S_RIGHT_JUSTIFIED_FORMAT: + switch (cfg.i2s_format) { + case I2S_RIGHT_JUSTIFIED_FORMAT: case I2S_LSB_FORMAT: case I2S_PHILIPS_FORMAT: case I2S_STD_FORMAT: @@ -369,7 +452,7 @@ class I2SDriverESP32V1 { (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO, (i2s_tdm_slot_mask_t)slots); break; - case I2S_LEFT_JUSTIFIED_FORMAT: + case I2S_LEFT_JUSTIFIED_FORMAT: case I2S_MSB_FORMAT: slot_cfg = I2S_TDM_MSB_SLOT_DEFAULT_CONFIG( (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO, @@ -397,42 +480,6 @@ class I2SDriverESP32V1 { return I2S_TDM_CLK_DEFAULT_CONFIG((uint32_t)cfg.sample_rate); } - bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan, - i2s_chan_handle_t &rx_chan, int txPin, int rxPin) { - i2s_tdm_config_t tdm_cfg = { - .clk_cfg = getClockConfig(cfg), - .slot_cfg = getSlotConfig(cfg), - .gpio_cfg = - { - .mclk = (gpio_num_t)cfg.pin_mck, - .bclk = (gpio_num_t)cfg.pin_bck, - .ws = (gpio_num_t)cfg.pin_ws, - .dout = (gpio_num_t)txPin, - .din = (gpio_num_t)rxPin, - .invert_flags = - { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - }, - }, - }; - - if (cfg.rx_tx_mode == TX_MODE) { - if (i2s_channel_init_tdm_mode(tx_chan, &tdm_cfg) != ESP_OK) { - LOGE("i2s_channel_init_tdm_tx_mode %s", "tx"); - return false; - } - } - if (cfg.rx_tx_mode == RX_MODE) { - if (i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg) != ESP_OK) { - LOGE("i2s_channel_init_tdm_tx_mode %s", "rx"); - return false; - } - return true; - } - return false; - } } tdm; #endif