I2S - detect empty DMA queue

palmerr23
Posts: 1
Joined: Mon Feb 22, 2021 3:59 am

I2S - detect empty DMA queue

Postby palmerr23 » Mon Feb 22, 2021 4:14 am

Hi (newbie here),

I'm working on a project that inputs audio packets via UDP (VBAN protocol) and outputs them to an external I2S DAC. It's working fine, other than occasional crackles.

I suspect that I'm suffering DMA buffer underrun, but don't know a way to detect when the I2S/DMA has run out of fresh data and is going to re-use old buffers.

Simply, my code is an interrupt driven routine to put incoming packets into a double-buffered queue.

udpIn.onPacket(UDPtoQ)

The I2S writing code, which I have tried as both an xTask and in the main program loop, refills the I2S DMA buffers (I've tried 2 - 6 * 256 sample buffers with no real difference) using i2s_write().

I can detect when the DMA queue was full, by measuring the time it takes to execute i2s_write().

Is there a way to detect when the DMA queue is empty? I've tried reading I2S0.state.tx_idle, I2S0.int_st.out_done, I2S0.int_st.tx_rempty, I2S0.int_st.out_eof and I2S0.int_raw.tx_rempty.

None of them seem to return useful data for this purpose - possibly because the DMA is continually re-using the old buffers.

Thanks in anticipation.

KickAss101
Posts: 1
Joined: Fri Mar 05, 2021 12:54 am

Re: I2S - detect empty DMA queue

Postby KickAss101 » Fri Mar 05, 2021 1:17 am

Hi palmerr23, I'm a newbie too.

I'm having a similar problem, I want to trigger a wave sample every now and then. It's a random pulse generator. I want the I2S to stop whenever the buffer's empty. However, as you said, the I2S IDF driver hijacks the I2S interrupts to keep refilling the buffer. I tried to reallocate as a shared interrupt (ESP_INTR_FLAG_SHARED), i.e.

Code: Select all

i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
int flags = ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM ;
esp_intr_alloc(ETS_I2S0_INTR_SOURCE, flags, i2sInterrupt, NULL, &my_interrupt_handle);
but it didn't work. So I don't think there's a way to listen to the I2S interrupts without rewriting a version the IDF I2S library itself. However the code seems complex, since it has to play nice with the RTOS functions. It would need some patience to do that.

I found an article that does it for the ADC:
https://www.toptal.com/embedded/esp32-audio-sampling

Who is online

Users browsing this forum: No registered users and 41 guests