How to use i2s in full-duplex mode
Re: How to use i2s in full-duplex mode
I have now configured I2S0 as a master receiver (which works) and try to configure I2S1 as a slave transmitter (which does not work). I'm trying to configure the gpio matrix so that I2S1 clock and word select use the same pins as I2S0, but I2S1 is not running. Even the first i2s_write() times out although the DMA buffers should be more than enough to hold the data.
Is it possible to do this? It's so annoying trying all things and not even knowing if I'm trying something that's impossible. I _think_ it should be possible to get the clock and ws to I2S1 from the same pins used by I2S0, but why isn't it working?
I have set the FUN_IE bit in IO_MUX_x_REG for the clock and ws pins. I have also configured GPIO_FUNCn_OUT_SEL_CFG_REG registers for the outputs used by I2S0 (configuring both interfaces to the same pins messes up the config, so I have to fix it manually).
Sigh.
Is it possible to do this? It's so annoying trying all things and not even knowing if I'm trying something that's impossible. I _think_ it should be possible to get the clock and ws to I2S1 from the same pins used by I2S0, but why isn't it working?
I have set the FUN_IE bit in IO_MUX_x_REG for the clock and ws pins. I have also configured GPIO_FUNCn_OUT_SEL_CFG_REG registers for the outputs used by I2S0 (configuring both interfaces to the same pins messes up the config, so I have to fix it manually).
Sigh.
Re: How to use i2s in full-duplex mode
I'm going to make some assumptions as I haven't tested full-duplex.
You should only need to configure a single I2S port, so I2S0 or I2S1. You should configure it to be master or slave based on what you are going to connect to the clock inputs. If you don't have an external clock then you need to be set the device as master.
I assume that when you use i2s_write you are just adding data to a transmit queue, which is then clocked out based on the sample rate.
So, if you are reading from the rx buffers the slave device will be clocked by the esp32 i2s master. I am unsure how the clock is controlled in a "Master Receive" mode but I assume that you can enable/disable the output clocks as required.
Are you using a custom driver for the i2s, or using the esp-idf HAL/library?
You should only need to configure a single I2S port, so I2S0 or I2S1. You should configure it to be master or slave based on what you are going to connect to the clock inputs. If you don't have an external clock then you need to be set the device as master.
I assume that when you use i2s_write you are just adding data to a transmit queue, which is then clocked out based on the sample rate.
So, if you are reading from the rx buffers the slave device will be clocked by the esp32 i2s master. I am unsure how the clock is controlled in a "Master Receive" mode but I assume that you can enable/disable the output clocks as required.
Are you using a custom driver for the i2s, or using the esp-idf HAL/library?
Re: How to use i2s in full-duplex mode
I'm using the driver in idf v4.2 and first I tried using only one I2S interface. TX worked, but RX never returned any data. Then I found (googled) a note that full-duplex mode is not supported by the driver, so I tried using two interfaces instead. Either way, I can make TX _or_ RX work, but not both.
Are there better drivers? Ones that work in full-duplex mode?
I guess using two interfaces should just work if it's possible for the slave interface to get the clocks from the same pins driven by the master. Or is it that the slave doesn't work? I have seen comments about having problems with the slave I2S which disappeared when switching to master mode.
I have simple shift registers connected to I2S to get 40 extra I/O pins. The pins must be "polled" at regular intervals and I2S is great for that - I can generate and process the data in a non-critical task while still keeping the exact timing. IF I can ever make I2S work.
Are there better drivers? Ones that work in full-duplex mode?
I guess using two interfaces should just work if it's possible for the slave interface to get the clocks from the same pins driven by the master. Or is it that the slave doesn't work? I have seen comments about having problems with the slave I2S which disappeared when switching to master mode.
I have simple shift registers connected to I2S to get 40 extra I/O pins. The pins must be "polled" at regular intervals and I2S is great for that - I can generate and process the data in a non-critical task while still keeping the exact timing. IF I can ever make I2S work.
Re: How to use i2s in full-duplex mode
Slave mode works - I have tested this with an external codec.I guess using two interfaces should just work if it's possible for the slave interface to get the clocks from the same pins driven by the master. Or is it that the slave doesn't work? I have seen comments about having problems with the slave I2S which disappeared when switching to master mode.
In regards to full duplex, take a look at the i2s driver (i2s.c), there seems to be some code related to running in full duplex, such as:
Code: Select all
#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE)
#define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER)
Good luck
Re: How to use i2s in full-duplex mode
Yeah, I was originally using I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX and TX worked just fine, but RX never returned any data.
I agree that it would be great to get some feedback from espressif so I knew whether to keep trying or if it just won't work.
I already read the idf changelog in hopes that the i2s driver has been fixed to work, but didn't find any indication of that.
I agree that it would be great to get some feedback from espressif so I knew whether to keep trying or if it just won't work.
I already read the idf changelog in hopes that the i2s driver has been fixed to work, but didn't find any indication of that.
Re: How to use i2s in full-duplex mode
Okay, I realized that when I built my app using an old idf version, full-duplex was working and yes, that's still the case. Some #defines have changed between idf versions and I finally found out that full-duplex doesn't work with I2S_COMM_FORMAT_STAND_MSB, but it works with I2S_COMM_FORMAT_STAND_I2S, so I changed my code a bit and both directions work now. (Luckily, my hardware "supports" both formats (or, it's too stupid to really care).)
So, I2S full-duplex mode does work with idf v4.2 if you use I2S_COMM_FORMAT_STAND_I2S data format.
So, I2S full-duplex mode does work with idf v4.2 if you use I2S_COMM_FORMAT_STAND_I2S data format.
Re: How to use i2s in full-duplex mode
Thanks for the update.
That's very interesting, I will need to test this as I assumed the hardware was only capable of half-duplex (which is what the official documentation states). I wonder if Espressif managed to get it running in full duplex but did not update the documentation.
I have been working on HFP for BT voice comms so will investigate why the I2S format allows full-duplex in the i2s.c driver from esp-idf.
Running in full-duplex from a single I2S port would be very advantageous for my application.
That's very interesting, I will need to test this as I assumed the hardware was only capable of half-duplex (which is what the official documentation states). I wonder if Espressif managed to get it running in full duplex but did not update the documentation.
I have been working on HFP for BT voice comms so will investigate why the I2S format allows full-duplex in the i2s.c driver from esp-idf.
Running in full-duplex from a single I2S port would be very advantageous for my application.
Re: How to use i2s in full-duplex mode
Please let us know if you get it working. Good luck!
Re: How to use i2s in full-duplex mode
I just noticed that if I use the I2S driver to configure I2S in full-duplex master mode with data format set to I2S_COMM_FORMAT_STAND_I2S and then clear the I2S_RX_MSB_SHIFT and I2S_TX_MSB_SHIFT bits in I2S_CONF_REG, I get the mode I wanted. So it's definately the driver that is broken, the hardware works just fine.
EDIT: It wasn't that simple. I think there's something timing critical or random here. Sometimes the method above works, sometimes the RX side doesn't work after a reboot. I then added a delay before clearing the MSB_SHIFT bits and RX seemed to work every time, but the incoming word rate was only half of what it should have been. Now I'm testing clearing only I2S_TX_MSB_SHIFT and leaving RX in Philips mode.. so far, so good. Needs more testing.
EDIT: It wasn't that simple. I think there's something timing critical or random here. Sometimes the method above works, sometimes the RX side doesn't work after a reboot. I then added a delay before clearing the MSB_SHIFT bits and RX seemed to work every time, but the incoming word rate was only half of what it should have been. Now I'm testing clearing only I2S_TX_MSB_SHIFT and leaving RX in Philips mode.. so far, so good. Needs more testing.
Re: How to use i2s in full-duplex mode
Hi. Just wondering if there's any update on this issue...? Were you able to get full duplex mode working without needing the delay?
Thanks.
Thanks.
Who is online
Users browsing this forum: No registered users and 121 guests