4#if defined(ESP32) && !USE_LEGACY_I2S || defined(DOXYGEN)
8#include "driver/i2s_pdm.h"
9#include "driver/i2s_std.h"
10#include "driver/i2s_tdm.h"
11#include "esp_system.h"
14#define IS_I2S_IMPLEMENTED
18#define I2S_MIN_DMA_DESC_NUM 2
19#ifndef I2S_MAX_DMA_BUFFER_BYTES
20# include "soc/soc_caps.h"
21# if defined(SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE) && SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
22# define I2S_MAX_DMA_BUFFER_BYTES (4095 - 63)
24# define I2S_MAX_DMA_BUFFER_BYTES (4095 - 3)
31#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
36#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 1, 4)
37#define I2S_MCLK_MULTIPLE_192 static_cast<i2s_mclk_multiple_t>(192)
48#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 2, 0)
51template <
typename T,
typename =
void>
57template <
typename T,
typename =
void>
67template <
typename T = i2s_chan_config_t>
72 result.dma_desc_num = 6;
73 result.dma_frame_num = 240;
75 result.dma_burst_size = 0;
77 result.auto_clear_after_cb =
false;
78 result.auto_clear_before_cb =
false;
80 result.dma_buffer_in_psram =
false;
82 result.allow_pd =
false;
83 result.intr_priority = 0;
89#define I2S_CHANNEL_DEFAULT_CONFIG_SAFE(port, role) getDefaultChannelConfig(port, role)
91#define I2S_CHANNEL_DEFAULT_CONFIG_SAFE(port, role) I2S_CHANNEL_DEFAULT_CONFIG(port, role)
152 LOGE(
"Did not expect go get here");
174 uint32_t backlog = written > sent ? written - sent : 0;
230 if (i2s_channel_write(
tx_chan, src, size_bytes, &result,
240 if (i2s_channel_read(
rx_chan, dest, size_bytes, &result,
278 std::memory_order_relaxed);
285 i2s_chan_handle_t &
rx_chan,
int txPin,
303 i2s_chan_handle_t &
rx_chan,
int txPin,
int rxPin,
306 LOGI(
"tx: %d, rx: %d", txPin, rxPin);
307 i2s_std_config_t std_cfg;
314 .dout = (gpio_num_t)txPin,
315 .din = (gpio_num_t)rxPin,
326 if (i2s_channel_init_std_mode(
tx_chan, &std_cfg) != ESP_OK) {
327 LOGE(
"i2s_channel_init_std_mode %s",
"tx");
332 i2s_event_callbacks_t cbs = {};
334 if (i2s_channel_register_event_callback(
tx_chan, &cbs, self) != ESP_OK) {
335 LOGE(
"i2s_channel_register_event_callback %s",
"tx");
345 if (frame_size <= 0) frame_size = 1;
347 chan_cfg.dma_frame_num * frame_size;
351 if (i2s_channel_enable(
tx_chan) != ESP_OK) {
352 LOGE(
"i2s_channel_enable %s",
"tx");
358 if (i2s_channel_init_std_mode(
rx_chan, &std_cfg) != ESP_OK) {
359 LOGE(
"i2s_channel_init_std_mode %s",
"rx");
362 if (i2s_channel_enable(
rx_chan) != ESP_OK) {
363 LOGE(
"i2s_channel_enable %s",
"rx");
368 LOGD(
"%s - %s", __func__,
"started");
375 i2s_std_slot_config_t result;
379 result = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(
384 result = I2S_STD_PCM_SLOT_DEFAULT_CONFIG(
389 result = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(
398 result.slot_mask = I2S_STD_SLOT_LEFT;
401 result.slot_mask = I2S_STD_SLOT_RIGHT;
404 LOGW(
"Using channel_format: I2SChannelSelect::Left for mono");
405 result.slot_mask = I2S_STD_SLOT_LEFT;
421 frame_size = (frame_size == 0) ? 1 : frame_size;
426 uint32_t total_frames = result.dma_desc_num * result.dma_frame_num;
427 LOGW(
"dma_desc_num %d too small, using %d", (
int)result.dma_desc_num,
434 if (result.dma_frame_num > max_frames) {
435 LOGW(
"dma_frame_num %d exceeds max %d: limited", (
int)result.dma_frame_num,
437 result.dma_frame_num = max_frames;
439 if (result.dma_frame_num == 0) result.dma_frame_num = 1;
440 LOGI(
"frame_size: %d", (
int)frame_size);
441 LOGI(
"dma_frame_num: %d", (
int)result.dma_frame_num);
442 LOGI(
"dma_desc_num: %d", (
int)result.dma_desc_num);
443 LOGI(
"total buffer size: %d",
444 (
int)(result.dma_desc_num * result.dma_frame_num * frame_size));
451 i2s_std_clk_config_t clk_cfg;
452 memset(&clk_cfg, 0,
sizeof(i2s_std_clk_config_t));
459 LOGI(
"mclk_multiple=%d", clk_cfg.mclk_multiple);
465 LOGI(
"mclk_multiple=384");
469 clk_cfg.mclk_multiple =
cfg.
use_apll ? I2S_MCLK_MULTIPLE_128 : I2S_MCLK_MULTIPLE_256;
470 LOGI(
"mclk_multiple=%d", clk_cfg.mclk_multiple);
479 soc_periph_i2s_clk_src_t result = I2S_CLK_SRC_DEFAULT;
482#if SOC_I2S_HW_VERSION_2
483 LOGI(
"pin_mclk is input");
484 result = I2S_CLK_SRC_EXTERNAL;
487 LOGE(
"pin_mclk as input not supported");
494#if SOC_I2S_SUPPORTS_APLL
495 result = I2S_CLK_SRC_APLL;
496 LOGI(
"clk_src is I2S_CLK_SRC_APLL");
497#elif SOC_I2S_SUPPORTS_PLL_F160M
498 result = I2S_CLK_SRC_PLL_160M;
499 LOGI(
"clk_src is I2S_CLK_SRC_PLL_160M");
507 i2s_chan_handle_t &
rx_chan)
override {
512 rc = i2s_channel_reconfig_std_clock(
tx_chan, &clock_cfg) == ESP_OK;
517 rc = i2s_channel_reconfig_std_clock(
rx_chan, &clock_cfg) == ESP_OK;
527 struct DriverPDM :
public DriverCommon {
529 i2s_chan_handle_t &rx_chan,
int txPin,
int rxPin,
532 return startTX(cfg, tx_chan, txPin);
534 return startRX(cfg, rx_chan, rxPin);
536 LOGE(
"Only RX and TX is supported for PDM")
541 i2s_pdm_tx_slot_config_t getTxSlotConfig(I2SConfigESP32V1 &cfg) {
542#ifdef SOC_I2S_HW_VERSION_2
543 return I2S_PDM_TX_SLOT_DAC_DEFAULT_CONFIG(
544 (i2s_data_bit_width_t)cfg.bits_per_sample,
545 (i2s_slot_mode_t)cfg.channels);
547 return I2S_PDM_TX_SLOT_DEFAULT_CONFIG(
548 (i2s_data_bit_width_t)cfg.bits_per_sample,
549 (i2s_slot_mode_t)cfg.channels);
553 i2s_chan_config_t getChannelConfig(I2SConfigESP32V1 &cfg) {
555 (i2s_port_t)cfg.port_no,
556 cfg.is_master ? I2S_ROLE_MASTER : I2S_ROLE_SLAVE);
559 i2s_pdm_tx_clk_config_t getTxClockConfig(I2SConfigESP32V1 &cfg) {
560#if defined(I2S_PDM_TX_CLK_DAC_DEFAULT_CONFIG)
561 return I2S_PDM_TX_CLK_DAC_DEFAULT_CONFIG((
uint32_t)cfg.sample_rate);
563 return I2S_PDM_TX_CLK_DEFAULT_CONFIG((
uint32_t)cfg.sample_rate);
567 bool startTX(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan,
int txPin) {
568 i2s_pdm_tx_config_t pdm_tx_cfg = {
569 .clk_cfg = getTxClockConfig(cfg),
570 .slot_cfg = getTxSlotConfig(cfg),
573 .clk = (gpio_num_t)cfg.pin_bck,
574 .dout = (gpio_num_t)txPin,
575#if SOC_I2S_PDM_MAX_TX_LINES > 1
576 .dout2 = I2S_GPIO_UNUSED,
585 if (i2s_channel_init_pdm_tx_mode(tx_chan, &pdm_tx_cfg) != ESP_OK) {
586 LOGE(
"i2s_channel_init_pdm_tx_mode %s",
"tx");
589 if (i2s_channel_enable(tx_chan) != ESP_OK) {
590 LOGE(
"i2s_channel_enable %s",
"tx");
596#if defined(USE_PDM_RX)
597 i2s_pdm_rx_slot_config_t getRxSlotConfig(I2SConfigESP32V1 &cfg) {
598 return I2S_PDM_RX_SLOT_DEFAULT_CONFIG(
599 (i2s_data_bit_width_t)cfg.bits_per_sample,
600 (i2s_slot_mode_t)cfg.channels);
602 i2s_pdm_rx_clk_config_t getRxClockConfig(I2SConfigESP32V1 &cfg) {
603 return I2S_PDM_RX_CLK_DEFAULT_CONFIG((
uint32_t)cfg.sample_rate);
605 bool startRX(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &rx_chan,
int rxPin) {
606 i2s_pdm_rx_config_t pdm_rx_cfg = {
607 .clk_cfg = getRxClockConfig(cfg),
608 .slot_cfg = getRxSlotConfig(cfg),
611 .clk = (gpio_num_t)cfg.pin_bck,
612 .din = (gpio_num_t)rxPin,
620 if (i2s_channel_init_pdm_rx_mode(rx_chan, &pdm_rx_cfg) != ESP_OK) {
621 LOGE(
"i2s_channel_init_pdm_rx_mode %s",
"rx");
624 if (i2s_channel_enable(rx_chan) != ESP_OK) {
625 LOGE(
"i2s_channel_enable %s",
"tx");
631 bool startRX(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &rx_chan,
int rxPin) {
632 LOGE(
"PDM RX not supported");
643 struct DriverTDM :
public DriverCommon {
644 bool startChannels(I2SConfigESP32V1 &cfg, i2s_chan_handle_t &tx_chan,
645 i2s_chan_handle_t &rx_chan,
int txPin,
int rxPin,
646 I2SDriverESP32V1 * ) {
647 i2s_tdm_config_t tdm_cfg = {
648 .clk_cfg = getClockConfig(cfg),
649 .slot_cfg = getSlotConfig(cfg),
652 .mclk = (gpio_num_t)cfg.pin_mck,
653 .bclk = (gpio_num_t)cfg.pin_bck,
654 .ws = (gpio_num_t)cfg.pin_ws,
655 .dout = (gpio_num_t)txPin,
656 .din = (gpio_num_t)rxPin,
666 if (cfg.rx_tx_mode == TX_MODE || cfg.rx_tx_mode == RXTX_MODE) {
667 if (i2s_channel_init_tdm_mode(tx_chan, &tdm_cfg) != ESP_OK) {
668 LOGE(
"i2s_channel_init_tdm_tx_mode %s",
"tx");
672 if (cfg.rx_tx_mode == RX_MODE || cfg.rx_tx_mode == RXTX_MODE) {
673 if (i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg) != ESP_OK) {
674 LOGE(
"i2s_channel_init_tdm_tx_mode %s",
"rx");
682 i2s_tdm_slot_config_t getSlotConfig(I2SConfigESP32V1 &cfg) {
684 for (
int j = 0; j < cfg.channels; j++) {
688 i2s_tdm_slot_config_t slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(
689 (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO,
690 (i2s_tdm_slot_mask_t)slots);
692 switch (cfg.i2s_format) {
697 slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(
698 (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO,
699 (i2s_tdm_slot_mask_t)slots);
703 slot_cfg = I2S_TDM_MSB_SLOT_DEFAULT_CONFIG(
704 (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO,
705 (i2s_tdm_slot_mask_t)slots);
708 slot_cfg = I2S_TDM_PCM_LONG_SLOT_DEFAULT_CONFIG(
709 (i2s_data_bit_width_t)cfg.bits_per_sample, I2S_SLOT_MODE_STEREO,
710 (i2s_tdm_slot_mask_t)slots);
713 LOGE(
"TDM: Unsupported format");
719 i2s_chan_config_t getChannelConfig(I2SConfigESP32V1 &cfg) {
721 (i2s_port_t)cfg.port_no,
722 cfg.is_master ? I2S_ROLE_MASTER : I2S_ROLE_SLAVE);
725 i2s_tdm_clk_config_t getClockConfig(I2SConfigESP32V1 &cfg) {
726 return I2S_TDM_CLK_DEFAULT_CONFIG((
uint32_t)cfg.sample_rate);
754 LOGE(
"Channels not started");
767 if (i2s_new_channel(&chan_cfg, NULL, &
rx_chan) != ESP_OK) {
773 if (i2s_new_channel(&chan_cfg, &
tx_chan, NULL) != ESP_OK) {
803 LOGE(
"Unsupported signal_type");
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define TRACEE()
Definition AudioLoggerIDF.h:34
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define IRAM_ATTR
Definition AudioStreams.h:13
#define portMAX_DELAY
Definition BufferBlocking.h:14
#define pdMS_TO_TICKS(ms)
Definition BufferBlocking.h:17
#define I2S_MIN_DMA_DESC_NUM
Definition I2SDriverESP32V1.h:18
#define I2S_MAX_DMA_BUFFER_BYTES
Definition I2SDriverESP32V1.h:24
#define I2S_CHANNEL_DEFAULT_CONFIG_SAFE(port, role)
Definition I2SDriverESP32V1.h:89
#define I2S_MCLK_MULTIPLE_192
Definition I2SDriverESP32V1.h:37
#define assert(T)
Definition avr.h:10
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:26
@ RXTX_MODE
Definition AudioTypes.h:26
@ TX_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26
Definition InitializerList.h:7
#define I2S_BUFFER_SIZE
Definition tangnano20k.h:11
#define I2S_BUFFER_COUNT
Definition tangnano20k.h:13