This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Need I2S help

Hi there,

I'm just trying to start to code my project. I want to stream 48k 16 bit audio from one nrf52840 dongle to the other one. I only need one way transfer.

I have looked at every example I could find but still dont seem to get how to send the packets to the radio and over the wireless connection.

Is there anyone that can help get me started with some simple no frills code.

I'm using Segger and sdk v17.

I would be most grateful if someone could assist me here.  Once I get the streaming part working successfully I think I can work out how to do the other things I need but this I2S is very tricky it seems to know what to do. It needs to be a steady stream.

Kind regards,

Dam076

Parents
  • Hi 

    Are you planning to do any compression of the audio stream, or do you want to send raw data?

    You should be able to handle the raw data stream if the link is good, but you won't have a lot of overhead to handle packet loss. 

    If you are planning to do something proprietary (ie not Bluetooth) I would recommend having a look at the nrf_esb library. Then you don't have to spend time on low level radio setup, but can instead focus on integrating the I2S sensor. 

    There are some examples in the SDK showing how to use the nrf_esb library, in the following folder:

    \nRF5_SDK_17.0.2_d674dde\examples\proprietary_rf

    Best regards
    Torbjørn

  • No compression. 2 MBIT should be ample throughput as 48k 16bit audio needs around 1,5 MBIT. Also I'm struggling to understand how the Queue works in the code because the audio stream is obviously slower than the RF-RF connection so, how does it pause and then start sending again when the buffer starts to empty? I will need a small buffer, no error correction and no ACK to achieve the lowest latency possible. Then if I have any headroom, I can possibly add CRC if needed but given the low latency specs I require and the likely possibily that any 'correction' will drastically slow down the stream, I dont think its going to be useful. It would be great if there was some type of interpolation of audio samples in the event that there is a CRC error but I fear that is going to be very complicated. But my theory would be to average out the 'before' error sample and the 'after' error sample, average the 2 samples and then replace the sample in the buffer that is detected as corrupt with the 'averaged' value,..  This should eliminate any glitch and cause minimal auditory changes. I guess mathematically this is not hard, I just need help working out what flag will be set to indicate that specific packet has a CRC error and then call the error correction function to replace the value in the buffer. Hope that makes sense. 

  • Now that was really helpful thankyou. One issue I have found when trying to copy and paste some code i found is that the function nrf_drv_i2s_start is different from nrfx_i2s_start even though the nrf_drv_i2s.h file links the 2 functions with a #define macro. Are you able to help me with specific code to 1) activate I2S in RX mode only, and 2) in TX mode only. It seems the new nrfx function requires both buffers to be passed as a structure in the first argument, yet the old driver allowed for them to be split. Is it possible I can pass the structure but give the value NULL in the rx (or tx) pointer where required or do I have to provide both buffers?  This would help me out because I only need I2S as a one way device and only want to deal with 1 set of buffers on each RF module, if possible.  and thanks again. 

  • "

    The trick is to assign the EasyDMA of both the radio and the I2S interface to the same buffer, then no copying is needed. 

    As I mentioned earlier you can implement a FIFO/ringbuffer in RAM (an array of buffers essentially), and start filling it up using the I2S interface. Once the first buffer is filled you point the EasyDMA of the I2S to the second buffer in the FIFO, and ask the RADIO to send the data stored in the first. 

    Then the I2S will be busy filling the second buffer, while the RADIO is busy transmitting the first buffer over the air. Once the radio operation is complete you can mark the first buffer as free for more I2S data. "

    This is exactly what i needed help to code. Is there any example of this or are you able to help me with a basic code structure for this? I am still getting my head around how I2S utilises the easyDMA.. tbh I am struggling to understand how it implements the alternating buffers in the data_handler

  • Hi

    The driver allows you to set one of the buffers to NULL in case you only need one directional data flow. 

    If you look at the start of the nrfx_i2s_start(..) function you can see that is checks to make sure one of these buffers is set, otherwise it will trigger an error. Having both set is not a requirement:

    nrfx_err_t nrfx_i2s_start(nrfx_i2s_buffers_t const * p_initial_buffers,
                              uint16_t                   buffer_size,
                              uint8_t                    flags)
    {
        NRFX_ASSERT(p_initial_buffers != NULL);
        NRFX_ASSERT(p_initial_buffers->p_rx_buffer != NULL ||
                    p_initial_buffers->p_tx_buffer != NULL);
        .
        .

    Once you  have this running let me know, and I will do my best to guide you in integrating the rest. 

    Best regards
    Torbjørn

  • I did it using circular buffers. Happy to help anyone if they need assistance. The code is complicated. cheers

Reply Children
No Data
Related