How to use i2s in full-duplex mode
Posted: Wed Sep 16, 2020 10:39 am
Hello. How to use i2s in full-duplex mode?
I want to use ESP 32 with an external audio codec chip, but only manage to work in half-duplex mode.
I tried a configuration with two i2cs, but the transfer on slave I2C 1 does not work.
It is assumed that both I2S use the same connection lines to the audio codec, but I2S0 leads and controls the outputs of WS and BCK and uses DATA_IN, and I2S1 takes as inputs WS and BCK and controls the output DATA_OUT.
[Codebox]
void ConfigI2S (void)
{
// top mic - RIGHT, lower mic - LEFT
i2s_config_t i2s_config;
i2s_pin_config_t pin_config;
// config I2S0, as TX
i2s_config.mode = I2S_MODE_SLAVE | I2S_MODE_TX;
i2s_config.sample_rate = AUDIO_SAMPLING_FREQUENCY;
i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
i2s_config.communication_format = I2S_COMM_FORMAT_I2S;
i2s_config.dma_buf_count = 4;
i2s_config.dma_buf_len = 256;
i2s_config.use_apll = 0; //apll enable
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; //interrupt level 1(lowest priority)
i2s_config.fixed_mclk =4096000;
pin_config.bck_io_num = BCK;
pin_config.ws_io_num = WS;
pin_config.data_out_num = I2S_PIN_NO_CHANGE;
pin_config.data_in_num = I2SIN;
i2s_driver_install(I2S_NUM_1, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_1, &pin_config);
// config I2S1, as RX
i2s_config.mode = I2S_MODE_MASTER | I2S_MODE_RX;
i2s_config.sample_rate = AUDIO_SAMPLING_FREQUENCY;
i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
i2s_config.communication_format = I2S_COMM_FORMAT_I2S;
i2s_config.dma_buf_count = 4;
i2s_config.dma_buf_len = 256;
i2s_config.use_apll = 1; //apll enable
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; //interrupt level 1(lowest priority)
i2s_config.fixed_mclk = 4096000;
pin_config.bck_io_num = BCK;
pin_config.ws_io_num = WS;
pin_config.data_out_num = I2SOUT;
pin_config.data_in_num = I2S_PIN_NO_CHANGE;
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_start(I2S_NUM_1);
i2s_start(I2S_NUM_0);
}
[/Codebox]
The program performs two tasks, one reads from I2S0, and the second writes to I2S1. I assumed that full-duplex data exchange, in which I2 S1 puts data on the bus at the moment when I2S0 takes data from the bus (while controlling the WS and BCK signals).
But this mechanism does not work, in particular, data on I2S 1 is not sent, the function
[Codebox]
i2c_write (I2S_NUM_1, ... , ... , ... , portMAX_DELAY)
[/Codebox]
is never returned;
Plese help me start I2S in full duplex mode/
I want to use ESP 32 with an external audio codec chip, but only manage to work in half-duplex mode.
I tried a configuration with two i2cs, but the transfer on slave I2C 1 does not work.
It is assumed that both I2S use the same connection lines to the audio codec, but I2S0 leads and controls the outputs of WS and BCK and uses DATA_IN, and I2S1 takes as inputs WS and BCK and controls the output DATA_OUT.
[Codebox]
void ConfigI2S (void)
{
// top mic - RIGHT, lower mic - LEFT
i2s_config_t i2s_config;
i2s_pin_config_t pin_config;
// config I2S0, as TX
i2s_config.mode = I2S_MODE_SLAVE | I2S_MODE_TX;
i2s_config.sample_rate = AUDIO_SAMPLING_FREQUENCY;
i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
i2s_config.communication_format = I2S_COMM_FORMAT_I2S;
i2s_config.dma_buf_count = 4;
i2s_config.dma_buf_len = 256;
i2s_config.use_apll = 0; //apll enable
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; //interrupt level 1(lowest priority)
i2s_config.fixed_mclk =4096000;
pin_config.bck_io_num = BCK;
pin_config.ws_io_num = WS;
pin_config.data_out_num = I2S_PIN_NO_CHANGE;
pin_config.data_in_num = I2SIN;
i2s_driver_install(I2S_NUM_1, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_1, &pin_config);
// config I2S1, as RX
i2s_config.mode = I2S_MODE_MASTER | I2S_MODE_RX;
i2s_config.sample_rate = AUDIO_SAMPLING_FREQUENCY;
i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
i2s_config.communication_format = I2S_COMM_FORMAT_I2S;
i2s_config.dma_buf_count = 4;
i2s_config.dma_buf_len = 256;
i2s_config.use_apll = 1; //apll enable
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; //interrupt level 1(lowest priority)
i2s_config.fixed_mclk = 4096000;
pin_config.bck_io_num = BCK;
pin_config.ws_io_num = WS;
pin_config.data_out_num = I2SOUT;
pin_config.data_in_num = I2S_PIN_NO_CHANGE;
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_start(I2S_NUM_1);
i2s_start(I2S_NUM_0);
}
[/Codebox]
The program performs two tasks, one reads from I2S0, and the second writes to I2S1. I assumed that full-duplex data exchange, in which I2 S1 puts data on the bus at the moment when I2S0 takes data from the bus (while controlling the WS and BCK signals).
But this mechanism does not work, in particular, data on I2S 1 is not sent, the function
[Codebox]
i2c_write (I2S_NUM_1, ... , ... , ... , portMAX_DELAY)
[/Codebox]
is never returned;
Plese help me start I2S in full duplex mode/