I2S Rx in Slave mode

Dave B
Posts: 3
Joined: Tue Aug 11, 2020 9:45 am

I2S Rx in Slave mode

Postby Dave B » Wed Aug 12, 2020 3:10 pm

I've been trying to get I2S Rx working in Slave mode.

I feel that I must be missing something. I'm building for the devkit-v1 using espidf 4.0.1 under platformio.

There are no examples of I2S Rx, only I2S Tx Master mode.

I'm setting the config as follows :
  1.    
  2. i2s_config_t i2s_config = {
  3.         .mode = I2S_MODE_SLAVE | I2S_MODE_RX,
  4.         .sample_rate = 31250,
  5.         .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
  6.         .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
  7.         .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
  8.         .dma_buf_count = 6,
  9.         .dma_buf_len = 256,
  10.         .use_apll = false,
  11.         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
  12.     };
  13.  
  14. i2s_pin_config_t pin_config = {
  15.         .bck_io_num = GPIO_NUM_21,
  16.         .ws_io_num = GPIO_NUM_19,
  17.         .data_out_num = -1,  //  Not used
  18.         .data_in_num = GPIO_NUM_22
  19.     };
I have the pins connected to an I2S source, running at 31250. I've tested this against an I2S DAC and it works fine. I've also looked at it using pulseview logic analyser and it can decode the I2S frames.

I then call i2s_driver_install(). Looking at the source this allocates some config memory for the device. It adds an interrupt handler. It then calls i2s_set_clk() which sets up a DMA Queue in turn calls i2s_start().

How can it is2_start() work when I haven't yet assigned the IO pins?
  1.    
  2.     err = i2s_driver_install(I2S_NUM_0, & i2s_config, 0, 0);
  3.     if (err != ESP_OK)
  4.     {
  5.         ESP_LOGI(TAG, "i2s_driver_install %d", err);
  6.     }
  7.  
  8.     err= i2s_set_pin(I2S_NUM_0, & pin_config);
  9.     if (err != ESP_OK)
  10.     {
  11.         ESP_LOGI(TAG, "i2s_set_pin %d", err);
  12.     }
  13.  
The i2s_set_pin() call copies data into the driver config allocated in i2s_driver_install(). It must be called after i2s_driver_install().

If I then try to read data, I get a timeout and zero data.
  1.        
  2.     esp_err_t err = i2s_read(I2S_NUM_0, buff, sizeof(buff), & read, 10);
I can't help feeling that I'm missing a step. Can anyone please advise?

Dave B
Posts: 3
Joined: Tue Aug 11, 2020 9:45 am

Re: I2S Rx in Slave mode

Postby Dave B » Fri Aug 14, 2020 8:22 am

Well it looks like slave mode doesn't work at all.

I've switched to using master mode, which means I'll have to redesign the system that sends I2S to work in slave mode.

The other problem I've seen is that switching to 16-bit mode, the I2S frame is just 2 * 16 bits long. The I2S spec has 64 clock periods per frame. I was hoping that 16-bit mode would send the correct I2S frame, but only sample the top 16-bits of the 32-bit word. This is not what happens, so I have to manually extract the 16 MSBs from the Rx buffer.

The other problem I have is that the data is getting intermittently shift by 1 bit. So I am seeing bits 14-0 and presumably a trailing bit, instead of bits 15-0. This results in the Rx waveform being scrambled.

Image

This must be down to some timing error. I've attached a logic analyser to the same pins, and used pulseview to decode the I2S frames. The timing looks fine. I used sigrok-cli to extract these and convert to a WAV file. This looks fine. So the timing problem is an ESP32 problem.

Any suggestions on how I can fix this? I have full control over the other end (it is an FPGA), so I could advance or retard the data relative to the clock, but I seem to be making a lots of changes to get round problems with the ESP32.

Apart from the lack of slave mode and the bit timing errors it is all working okay.

Dave B
Posts: 3
Joined: Tue Aug 11, 2020 9:45 am

Re: I2S Rx in Slave mode

Postby Dave B » Fri Sep 11, 2020 12:00 pm

silence. I presume that no-one is using I2S in slave mode.

embedded-creations
Posts: 13
Joined: Thu Feb 15, 2018 11:22 am

Re: I2S Rx in Slave mode

Postby embedded-creations » Thu Dec 17, 2020 11:46 am

I'm looking for working I2S Slave example code and striking out... I found this on another thread, not sure if it's accurate or if there's a workaround, but at least it's some information:
ESP32's I2S interface has problem in slave mode. It use its internal clock to clock the state machine, when the internal clock is faster than the mclk, it will cause I2S FIFO underrun. So, you must use the codec as slave and ESP32 as master.
viewtopic.php?p=33980#p33980

I have working (with a few limitations) I2S Slave RX parallel camera mode code, but that probably doesn't help:

https://www.esp32.com/viewtopic.php?p=69115#p69115

Sports5115
Posts: 12
Joined: Mon Jul 24, 2023 2:32 pm

Re: I2S Rx in Slave mode

Postby Sports5115 » Sat Jun 15, 2024 2:18 pm

I tried using I2S in slave mode, i2s_channel_read simply times out every time,

input correctly shows up in signal generator,
same pins work correctly in master mode as output,
tried different pins too, no effect.
sample rate is only 44.1K

You get what you pay for.

Who is online

Users browsing this forum: No registered users and 258 guests