I2S Driver
Posted: Mon Jan 20, 2025 4:05 pm
Hi all,
We have a codec getting audio data from 8 microphones. The audio data is then written to the sd card. When the ESP32 S3 is in master mode, it works perfectly. The problem is when its in slave mode, there is humming noise being introduced to the audio. Even when the mics are removed, the noise is still there. We've probed the data line, without the mics, and the data line is only changing on the last two slots which have audio, while the ones without audio are not changing, on both the master device(device in master mode) and slave device(device in slave mode).
Here's a picture of the waveform where we would expect to not have any audio present. Here is a snippet of the code to set the two devices in either master mode or slave mode
We have a codec getting audio data from 8 microphones. The audio data is then written to the sd card. When the ESP32 S3 is in master mode, it works perfectly. The problem is when its in slave mode, there is humming noise being introduced to the audio. Even when the mics are removed, the noise is still there. We've probed the data line, without the mics, and the data line is only changing on the last two slots which have audio, while the ones without audio are not changing, on both the master device(device in master mode) and slave device(device in slave mode).
Here's a picture of the waveform where we would expect to not have any audio present. Here is a snippet of the code to set the two devices in either master mode or slave mode
- void setupCodecI2SforEthernet(int numberOfActiveChannels, int sampleRate) {
- i2s_config_t i2s_config = {
- // .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), // sets i2s mode, I2S_MODE_MASTER -> ESP32 S3 provides clock, I2S_MODE_RX -> ESP32 S3 receives data
- .sample_rate = sampleRate, // BCLK frequency, which is the frequency at which data is sampled
- .bits_per_sample = NUMBER_OF_BITS_PER_SAMPLE_SET, // word length, set in both codec(pcmd3180) library and here, needs to be the same
- .channel_format = I2S_CHANNEL_FMT_MULTIPLE, // select for multiple channels
- .communication_format = I2S_COMM_FORMAT_STAND_PCM_SHORT, // check datasheet, provide more information. Basically the format of data being received
- .intr_alloc_flags = ESP_INTR_FLAG_LEVEL6, // default interrupt priority
- .dma_buf_count = DMA_BUF_COUNT, // the dma buffer count // this is the number of dma buffers 16 was 2
- .dma_buf_len = AUDIO_BUFFER_LEN, // size of dma buffer
- .use_apll = true, // set to true, clock is more accurate
- .tx_desc_auto_clear = false, //
- .fixed_mclk = 0, // // might not need
- .mclk_multiple = (i2s_mclk_multiple_t)(256), // // might not need
- .total_chan = numberOfActiveChannels, // total numeber of channels
- };
- if (DEVICE_TYPE == MASTER_DEVICE) {
- i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX);
- } else if (DEVICE_TYPE == SLAVE_DEVICE) {
- i2s_config.mode = (i2s_mode_t)(I2S_MODE_SLAVE | I2S_MODE_RX);
- }
- // Set the chan_mask conditionally
- if (numberOfActiveChannels == 4) {
- i2s_config.chan_mask = (i2s_channel_t)(I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1 | I2S_TDM_ACTIVE_CH2 | I2S_TDM_ACTIVE_CH3);
- } else {
- i2s_config.chan_mask = (i2s_channel_t)(I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1 | I2S_TDM_ACTIVE_CH2 | I2S_TDM_ACTIVE_CH3 | I2S_TDM_ACTIVE_CH4 | I2S_TDM_ACTIVE_CH5 | I2S_TDM_ACTIVE_CH6 | I2S_TDM_ACTIVE_CH7);
- }
- // Install and start I2S driver
- esp_err_t i2s_driver_install_result = i2s_driver_install((i2s_port_t)i2s_num, &i2s_config, 0, NULL);
- // i2s_set_pin error handling
- if (i2s_driver_install_result == ESP_OK) {
- debugln("i2s_driver_install result: Success!");
- } else if (i2s_driver_install_result == ESP_ERR_INVALID_ARG) {
- debugln("i2s_driver_install result: Parameter error!");
- } else if (i2s_driver_install_result == ESP_ERR_NO_MEM) {
- debugln("i2s_driver_install result: Out of memory!");
- } else if (i2s_driver_install_result == ESP_ERR_INVALID_STATE) {
- debugln("i2s_driver_install result: Current I2S port is in use!");
- } else {
- debugln("i2s_driver_install result: Unknown error!");
- }
- // Set I2S pins
- esp_err_t i2s_set_pin_result = i2s_set_pin((i2s_port_t)i2s_num, &pin_config);
- // i2s_set_pin error handling
- if (i2s_set_pin_result == ESP_OK) {
- debugln("i2s_set_pin result: Success!");
- } else if (i2s_set_pin_result == ESP_ERR_INVALID_ARG) {
- debugln("i2s_set_pin result: parameter error!");
- } else if (i2s_set_pin_result == ESP_FAIL) {
- debugln("i2s_set_pin result: IO error!");
- } else {
- debugln("i2s_set_pin result: Unknown error!");
- }
- if (numberOfActiveChannels == 4) {
- esp_err_t i2s_set_clk_result = i2s_set_clk((i2s_port_t)i2s_num, sampleRate, I2S_BITS_PER_SAMPLE_16BIT, (i2s_channel_t)(I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1 | I2S_TDM_ACTIVE_CH2 | I2S_TDM_ACTIVE_CH3));
- // i2s_set_clk error handling
- if (i2s_set_clk_result == ESP_OK) {
- debugln("i2s_set_clk result: success!");
- } else if (i2s_set_clk_result == ESP_ERR_INVALID_ARG) {
- debugln("i2s_set_clk result: Parameter error!");
- } else if (i2s_set_clk_result == ESP_ERR_NO_MEM) {
- debugln("i2s_set_clk result: Out of memory!");
- } else {
- debugln("i2s_set_clk result: Unknown error!");
- }
- } else if (numberOfActiveChannels == 8) {
- esp_err_t i2s_set_clk_result = i2s_set_clk((i2s_port_t)i2s_num, sampleRate, I2S_BITS_PER_SAMPLE_16BIT, (i2s_channel_t)(I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1 | I2S_TDM_ACTIVE_CH2 | I2S_TDM_ACTIVE_CH3 | I2S_TDM_ACTIVE_CH4 | I2S_TDM_ACTIVE_CH5 | I2S_TDM_ACTIVE_CH6 | I2S_TDM_ACTIVE_CH7));
- // i2s_set_clk error handling
- if (i2s_set_clk_result == ESP_OK) {
- debugln("i2s_set_clk result: success!");
- } else if (i2s_set_clk_result == ESP_ERR_INVALID_ARG) {
- debugln("i2s_set_clk result: Parameter error!");
- } else if (i2s_set_clk_result == ESP_ERR_NO_MEM) {
- debugln("i2s_set_clk result: Out of memory!");
- } else {
- debugln("i2s_set_clk result: Unknown error!");
- }
- } else { // can't get here
- debugln("Error!!!");
- }
- // set sample rate
- esp_err_t i2s_set_sample_rate_result = i2s_set_sample_rates((i2s_port_t)i2s_num, sampleRate);
- if (i2s_set_sample_rate_result == ESP_OK) {
- debugln("Set Sample Rate Success!!!");
- } else if (i2s_set_sample_rate_result != ESP_OK) {
- debugln("Set Sample Rate fail");
- }
- // check sample frequency
- debug("Sample frequency set: ");
- debugln(i2s_get_clk((i2s_port_t)i2s_num));
- }