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

How to read I2S configuration and print in UART using NRF52-DK ?

Hello,

I have an analogue audio mic connected to external ADC. The external ADC can give an output of 16bit, 20bits, 24bits and 32 bits I2S data. I have configured to send 20 bit as I2S output.

To enable the I2S communication between the ADC and NRF52 I use below configuration.

    config.sdin_pin  = I2S_SDIN_PIN;
    config.sdout_pin = NRFX_I2S_PIN_NOT_USED;
    config.mck_pin   = NRFX_I2S_PIN_NOT_USED;
    config.mck_setup = NRF_I2S_MCK_32MDIV15;
    config.ratio     = NRF_I2S_RATIO_48X;
    config.format    = NRF_I2S_FORMAT_I2S;
    config.sample_width  = NRF_I2S_SWIDTH_24BIT;
    config.channels      = NRF_I2S_CHANNELS_STEREO;

In the SDK config, I have selected the pin of SDIN as 28. SCK - 31 , LRCK - 30.

While debugging, I watch the RX buffer of the nrf_I2S the data to check values most of the time starts as 0xFF8 or 0xFF9 or 0x00.

I understand that if the 24-bit I2S communication is chosen then when storing NRF stores it with  0xFF"24bit value".

1. Can I communicated with 20 bits from the ADC side or should I use only 16 or 24?

2. If 20 bits can be configured then should I expect the RX buffer data should always starting as 0xFF0"20bits value"? Because I want to store it in SD card. So I need to store the raw data to a WAV header. And the raw data should be removed of first 12 bits.

When I use NRF RTT to print the 32-bit value from RX buffer it seems like NRF LOG stuck in a loop. Without NRF LOG statement I can see that RX buffer updating each time I debug. Need a suggestion for this problem as well.

Thanks

Cecil

Parents
  • Hello,

    So you do receive values with 0xFF'24bit-value'? 

    If the external ADC is using a 20 bit I2S, you must use the 24 bit, in order to capture all of the data. 

    2. Have you tried to manage this? I guess you need to do some bit shifting in order to store this. I assume you want to store samples in whole bytes on the SD card. If each sample is 20 bits, and you store 8 samples, you have 160 bits=20 bytes. So perhaps you want to wait until you have 8 samples (you can use more/less samples, as long as it adds up to n*8 bits. 2 samples are sufficient, but you probably want to store up a decent amount of data before writing to the SD card. 

    // Let us say you stored 8 samples, and they are stored in uint32_t samples[0] -> samples[7]:
    // The actual data are the last 5 bytes of the uint32_t sample[i]: sample[i] & 0x000FFFFF;
    
    static void process_data(uint32_t samples[], uint8_t length, uint8_t processed_data[])
    {
        memset(processed_data, 0x00, sizeof(processed_data); //sizeof(processed_data) should be 5/2*length.
        
        processed_data[0] |= (uint8_t)((samples[0] & 0x000FF000) >> 12);
        processed_data[1] |= (uint8_t)((samples[0] & 0x00000FF0) >>  4);
        processed_data[2] |= (uint8_t)((samples[0] & 0x0000000F) <<  4);
        processed_data[2] |= (uint8_t)((samples[1] & 0x000F0000) >> 16);
        processed_data[3] |= (uint8_t)((samples[1] & 0x0000FF00) >> 16);
        processed_data[4] |= (uint8_t)((samples[1] & 0x000000FF) <<  0);
        
        // At this point, the 2 first buffers (2*20 bits = 40 bits) are stored in the first 5 bytes (5*8bits = 40 bits)
        // transform this into a for loop to handle the entire length:
        
        for (uint8_t i=0; i<length/2; i++)
        {
            processed_data[2*i+0] |= (uint8_t)((samples[5*i+0] & 0x000FF000) >> 12);
            processed_data[2*i+1] |= (uint8_t)((samples[5*i+0] & 0x00000FF0) >>  4);
            processed_data[2*i+2] |= (uint8_t)((samples[5*i+0] & 0x0000000F) <<  4);
            processed_data[2*i+2] |= (uint8_t)((samples[5*i+1] & 0x000F0000) >> 16);
            processed_data[2*i+3] |= (uint8_t)((samples[5*i+1] & 0x0000FF00) >> 16);
            processed_data[2*i+4] |= (uint8_t)((samples[5*i+1] & 0x000000FF) <<  0);
        }
    }

    RTT print issue:

    From where do you print this, and how do you attempt to print it? Can you show some snippets?

    Best regards,

    Edvin

  • Hello Edvin,

    I have attached one set of I2S samples in a text file. Some times i get 0xFF'24bits data' other times it is 0x00'24bitdata'. I used only one mic through the left channel.512_Samples.txt.

    I still have a doubt is the data is stored as 0xFF"4bits as 0 ,20-bits data " or 0xFF"20-bits data, 4bits as 0"

    Below is the snippet.

    static bool check_samples(uint32_t const * p_block)
    {
        // [each data word contains two 16-bit samples]
        uint16_t i;
        for (i = 0; i < I2S_DATA_BLOCK_WORDS; ++i)
        {
            uint32_t const * p_word = &p_block[i];
            uint32_t sample_actual = *p_word;
            NRF_LOG_INFO("P_word: 0x%x ",sample_actual);
            //Process data for SD card storage/ Uart print
        }
        NRF_LOG_INFO("%3u: OK", m_blocks_transferred);
        return true;
    }

Reply
  • Hello Edvin,

    I have attached one set of I2S samples in a text file. Some times i get 0xFF'24bits data' other times it is 0x00'24bitdata'. I used only one mic through the left channel.512_Samples.txt.

    I still have a doubt is the data is stored as 0xFF"4bits as 0 ,20-bits data " or 0xFF"20-bits data, 4bits as 0"

    Below is the snippet.

    static bool check_samples(uint32_t const * p_block)
    {
        // [each data word contains two 16-bit samples]
        uint16_t i;
        for (i = 0; i < I2S_DATA_BLOCK_WORDS; ++i)
        {
            uint32_t const * p_word = &p_block[i];
            uint32_t sample_actual = *p_word;
            NRF_LOG_INFO("P_word: 0x%x ",sample_actual);
            //Process data for SD card storage/ Uart print
        }
        NRF_LOG_INFO("%3u: OK", m_blocks_transferred);
        return true;
    }

Children
Related