ESP32 I2S Read Timeout Problem

JP5654
Posts: 17
Joined: Fri Jul 07, 2023 11:50 pm

ESP32 I2S Read Timeout Problem

Postby JP5654 » Sat Apr 20, 2024 10:08 pm

I'm using an ESP32-D0WD-V3 with esp-idf v5.1.2. I'm trying to communicate with a codec that is i2s master that is sending 64 bclks per wclk. The data is 16bits stereo and the sample rate is 16000hz. With the following configuration I am able to transmit data correctly but the read always times out. If I set data_bit_width=I2S_DATA_BIT_WIDTH_32BIT the reads are successful but this leads to incorrect tx data. I attached a logic analyzer trace showing the i2s transaction. What gives?

Code: Select all

            i2s_chan_config_t chan_cfg = {
                .id=I2S_NUM_AUTO,                 /*!< I2S port id */
                .role = I2S_ROLE_SLAVE,//I2S_ROLE_MASTER,               /*!< I2S role, I2S_ROLE_MASTER or I2S_ROLE_SLAVE */
                /* DMA configurations */
                .dma_desc_num = 2,       /*!< I2S DMA buffer number, it is also the number of DMA descriptor */
                .dma_frame_num = 160,      /*!< I2S frame number in one DMA buffer. One frame means one-time sample data in all slots,
                                                         *   it should be the multiple of '3' when the data bit width is 24.
                                                         */
                .auto_clear = true,         /*!< Set to auto clear DMA TX buffer, i2s will always send zero automatically if no data to send */
            };

            ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan));


            i2s_std_config_t std_cfg = {
                    .clk_cfg  = {
                            .sample_rate_hz = 16000,     /*!< I2S sample rate */
                            .clk_src = I2S_CLK_SRC_DEFAULT,            /*!< Choose clock source */
                            .mclk_multiple = I2S_MCLK_MULTIPLE_384, //**Ignored in slave mode
                    },
                   // .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
                    .slot_cfg = {
                            .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
                            .slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT,
                            .slot_mode = I2S_SLOT_MODE_STEREO,
                            .slot_mask = I2S_STD_SLOT_BOTH,
                            .ws_width = I2S_DATA_BIT_WIDTH_32BIT,
                            .ws_pol = true,
                            .bit_shift = true,
                            .msb_right = true
                    },
                    .gpio_cfg = {
                            .mclk = I2S_GPIO_UNUSED,
                            .bclk = params.bclk,
                            .ws   = params.ws,
                            .dout = params.dout,
                            .din  = params.din,
                            .invert_flags = {
                                    .mclk_inv = false,
                                    .bclk_inv = false,
                                    .ws_inv   = false,
                            },
                    },
            };

            /* Initialize the channels */
            ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg));
            ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_chan, &std_cfg));
Attachments
Capture.PNG
Capture.PNG (58.45 KiB) Viewed 1525 times

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

Re: ESP32 I2S Read Timeout Problem

Postby djixon » Sat Apr 20, 2024 10:58 pm

Why don't you make two separated i.e std_cfg_rx and std_cfg_tx variables with proper values in each of them, then in last two functions i2s_channel_init_std_mode() pass one variable for tx_chan and another for rx_chan.

JP5654
Posts: 17
Joined: Fri Jul 07, 2023 11:50 pm

Re: ESP32 I2S Read Timeout Problem

Postby JP5654 » Sun Apr 21, 2024 2:49 pm

Because the values I'm using are the "proper" values. The rx data will be wrong also if I set data_bit_width=I2S_DATA_BIT_WIDTH_32BIT. The RX should work just fine data_bit_width=I2S_DATA_BIT_WIDTH_16BIT, so my question is why is it not?

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

Re: ESP32 I2S Read Timeout Problem

Postby djixon » Sun Apr 21, 2024 4:13 pm

The first strange thing is that you have 64 pulses for only 2 channels of 16 bits. There should be 32 and not 64. So you have to adapt to that (what you have) by providing different setups for rx and tx.
But you passed the single variable to both functions which means if you change value in that single variable to match i.e. tx it will mess with rx and viceverse. So just try to make two different variables for testing and if it work you have to search for why you have 64 instead 32 pulses (if you want to go deeper to what causes problem). So try something like:

Code: Select all

           i2s_chan_config_t chan_cfg = {
                .id=I2S_NUM_AUTO,                 /*!< I2S port id */
                .role = I2S_ROLE_SLAVE,//I2S_ROLE_MASTER,               /*!< I2S role, I2S_ROLE_MASTER or I2S_ROLE_SLAVE */
                /* DMA configurations */
                .dma_desc_num = 2,       /*!< I2S DMA buffer number, it is also the number of DMA descriptor */
                .dma_frame_num = 160,      /*!< I2S frame number in one DMA buffer. One frame means one-time sample data in all slots,
                                                         *   it should be the multiple of '3' when the data bit width is 24.
                                                         */
                .auto_clear = true,         /*!< Set to auto clear DMA TX buffer, i2s will always send zero automatically if no data to send */
            };

            ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan));


            i2s_std_config_t std_cfg_rx = {
                    .clk_cfg  = {
                            .sample_rate_hz = 16000,     /*!< I2S sample rate */
                            .clk_src = I2S_CLK_SRC_DEFAULT,            /*!< Choose clock source */
                            .mclk_multiple = I2S_MCLK_MULTIPLE_384, //**Ignored in slave mode
                    },
                   // .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
                    .slot_cfg = {
                            .data_bit_width = I2S_DATA_BIT_WIDTH_32BIT,
                            .slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT,
                            .slot_mode = I2S_SLOT_MODE_STEREO,
                            .slot_mask = I2S_STD_SLOT_BOTH,
                            .ws_width = I2S_DATA_BIT_WIDTH_32BIT,
                            .ws_pol = true,
                            .bit_shift = true,
                            .msb_right = true
                    },
                    .gpio_cfg = {
                            .mclk = I2S_GPIO_UNUSED,
                            .bclk = params.bclk,
                            .ws   = params.ws,
                            .dout = params.dout,
                            .din  = params.din,
                            .invert_flags = {
                                    .mclk_inv = false,
                                    .bclk_inv = false,
                                    .ws_inv   = false,
                            },
                    },
            };

            i2s_std_config_t std_cfg_tx = {
                    .clk_cfg  = {
                            .sample_rate_hz = 16000,     /*!< I2S sample rate */
                            .clk_src = I2S_CLK_SRC_DEFAULT,            /*!< Choose clock source */
                            .mclk_multiple = I2S_MCLK_MULTIPLE_384, //**Ignored in slave mode
                    },
                   // .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
                    .slot_cfg = {
                            .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
                            .slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT,
                            .slot_mode = I2S_SLOT_MODE_STEREO,
                            .slot_mask = I2S_STD_SLOT_BOTH,
                            .ws_width = I2S_DATA_BIT_WIDTH_32BIT,
                            .ws_pol = true,
                            .bit_shift = true,
                            .msb_right = true
                    },
                    .gpio_cfg = {
                            .mclk = I2S_GPIO_UNUSED,
                            .bclk = params.bclk,
                            .ws   = params.ws,
                            .dout = params.dout,
                            .din  = params.din,
                            .invert_flags = {
                                    .mclk_inv = false,
                                    .bclk_inv = false,
                                    .ws_inv   = false,
                            },
                    },
            };

            /* Initialize the channels */
            ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg_tx));
            ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_chan, &std_cfg_rx));

JP5654
Posts: 17
Joined: Fri Jul 07, 2023 11:50 pm

Re: ESP32 I2S Read Timeout Problem

Postby JP5654 » Sun Apr 21, 2024 6:26 pm

Sorry if my previous response sounded snippy, it wasn't intended that way. I wanted to say that I do very much appreciate your response. The separate configurations is at least a workaround. I can make it work that way, but it's a waste of RAM because my dma and application buffers will need to be double the size, and a waste of cpu because I'll have to manually extract the real data.

Now, while I agree it seems silly to have 64 bcks for 32bits of data, there should be nothing wrong with that from an i2s perspective, also I have an explanation for that. My codec allows me to select 32 or 64 bcks per wclk. When I use 32, the esp periodically (~ every 23ms) drops one 16 bit slot of transmit data, which is maddening. It's not a dma buffer problem as the drops do not occur on buffer boundaries. I have run the exact same code on the esp32-s3 and same codec without a problem. Moving to 64bclks/wclk seemed to work around that problem, I assumed maybe the i2s hardware fifo wasn't able to setup quickly enough to meet the timing?

Anyhow, this is the source of my frustration, I workaround one issue on the tx side and it makes an rx problem. It just seems to me that this is either a driver bug or a hardware bug on the esp32 and I'm hoping Espressif can offer an explanation.

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

Re: ESP32 I2S Read Timeout Problem

Postby djixon » Sun Apr 21, 2024 7:08 pm

Don't worry, its ok. I also sometimes get frustrated when being stuck at some ridiculous problem. Also consider to move this thread to subgroup related to audio on this forum /English forum/ESP-ADF . Or just ask the question there too with increased chances to reach the answer.

Who is online

Users browsing this forum: No registered users and 89 guests