This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1310: I2S Driver Issues

Part Number: CC1310

Hi,

I am trying to read data from this I2S microphone.   The data is I2S, 24-bit, 2’s compliment, MSB first. The data precision is 18 bits; unused bits are zeros.

This is the code for initializing and starting the transfer:

void audioInit(void)
{
    I2S_init();

    I2S_Params_init(&i2sParams);

    i2sParams.trueI2sFormat      = true;
    i2sParams.invertWS           = true;
    i2sParams.isMSBFirst         = true;
    i2sParams.isDMAUnused        = true;
    i2sParams.memorySlotLength   = I2S_MEMORY_LENGTH_24BITS;
    i2sParams.beforeWordPadding  = 0;
    i2sParams.afterWordPadding   = 0;
    i2sParams.bitsPerWord        = 32;
    i2sParams.moduleRole         = I2S_MASTER;
    i2sParams.samplingEdge       = I2S_SAMPLING_EDGE_RISING;
    i2sParams.SD0Use             = I2S_SD0_INPUT;
    i2sParams.SD1Use             = I2S_SD1_DISABLED;
    i2sParams.SD0Channels        = I2S_1_CHANNEL;
    i2sParams.phaseType          = I2S_PHASE_TYPE_DUAL;
    i2sParams.fixedBufferLength  = sizeof(buf);
    i2sParams.startUpDelay       = 0;
    i2sParams.MCLKDivider        = 2;
    i2sParams.samplingFrequency  = 24000;
    i2sParams.readCallback       = i2sReadHandler;
    i2sParams.writeCallback      = NULL;
    i2sParams.errorCallback      = i2sErrorHandler;

    while(1)
    {
    i2sHandle = I2S_open(0, &i2sParams);

    printf("i2sHandle = 0x%x\n", (uint32_t)i2sHandle);

    List_clearList(&i2sReadList);

    I2S_Transaction_init(&i2sRead1);
    i2sRead1.bufPtr  = buf;
    i2sRead1.bufSize = sizeof(buf);

    List_put(&i2sReadList, (List_Elem*)&i2sRead1);

    I2S_setReadQueueHead(i2sHandle, &i2sRead1);

    I2S_startClocks(i2sHandle);
    I2S_startWrite(i2sHandle);
    I2S_startRead(i2sHandle);

    while(1)
    {
        if (readStopped)
        {
            I2S_stopClocks(i2sHandle);
            I2S_close(i2sHandle);
            Task_sleep(OS_TICKS_PER_SECOND*2);
            continue;
         }
    }
    }

When I execute the first transfer the waveform looks like this:

The data in memory after the transfer is here:

Here are my questions:

1) bitsPerWord is set to 32.  If I set to 24 which is what the mic is generating the data is all 0's.  Why is that?

2) Looking at the logic analyzer waveform the bits on AD0 are:

0001 0010 1001 1100 0000 0000 0000 0000  (0x12 0x9c 0x00 0x00 0x00 0x00)

What's in memory (starting at 0x2000326f), though, is 

0000 0000 1001 1100 0000 0000 1000 0000 (0x00 0x9c 0x00 0x80 0x00)

I am not able to extract the exact data I am looking for.  Since the word length is configured for 32-bits I expect the most significant 4 bits are 0 and the least significant 8 bits are 0

according to the mic data-sheet.

3) There are 5x 24-bit cycles prior to the data showing up in memory.  If I set startUpDelay to 5 the data show exactly as above but should start on the 6th cycle.

    Is there an explanation for this?

Victor

  • With more testing I see that the data line sampling is right-justified with respect to the rising WCLK instead of left-justified.  If I change

    my I2S analyzer to right- instead of left-justify I get the same results as what I see in CC1310 memory.

    How do I ensure the the data lines are sampled using left justification?

    Parameters (same as above but repeated for convenience):

    samplingFrequency = 24000

    startUpDelay            = 0

    bitsPerWord             = 32

    memorySlotLength  = 24

    beforeWordPadding  = 0

    afterWordPadding     = 0

  • Hi Victor,

    1. What version of the SimpleLink CC13x0 SDK are you using?

    2. What kind of device is the SPI slave?

  • Hi Victor,

    VICTOR VALENCIA said:
    bitsPerWord is set to 32.  If I set to 24 which is what the mic is generating the data is all 0's.  Why is that?

    This is due to the microphone's requirements. From its datasheet (sorry I could not opened the link your provided), you must have 32 BCLK cycles by WS half-period. Keep in mind that the number of BCLK periods per WS half-period is given by beforeWordPadding bitsPerWord + afterWordPadding. In other words, by setting, beforeWordPadding to 0 and afterWordPadding to 0,  the number of BCLK periods per WS half-period is given by bitsPerWord.

        i2sParams.afterWordPadding   = 0;
        i2sParams.bitsPerWord        = 32;

    Still using the SPH0645LM4H datasheet, you should to do the following modifications:

    • Set trueI2sFormat to false. This is because the microphone requires WS and BCLK to be synchronized (in other words, the microphone you chose is not using a true I2S format).
    • Set beforeWordPadding to 0. This is because the samples are sent on the first BCLK edge of the WS half-period.
    • Set bitPerWord to 24. This is because the samples are 24-bit long.
    • Set afterWordPadding to 8. This is to "complete" the WS half-period (and have 32 BCLK periods in each WS half-period).

    To finish, you can consult the I2S driver documentation to get more details.

    I hope this will help,

    Best regards,

  • Hi Marie,

    I am using version 3.20 of the SDK.  The microphone is https://media.digikey.com/pdf/Data%20Sheets/Knowles%20Acoustics%20PDFs/SPH0645LM4H-B.pdf

    Part number is Knowles SPH0645LM4H-B.

  • Hi Clement,

    I made the changes you suggested.  My new configuration is:

        i2sParams.trueI2sFormat      = false;
        i2sParams.invertWS           = true;
        i2sParams.isMSBFirst         = true;
        i2sParams.isDMAUnused        = true;
        i2sParams.memorySlotLength   = I2S_MEMORY_LENGTH_24BITS;
        i2sParams.beforeWordPadding  = 0;
        i2sParams.afterWordPadding   = 8;
        i2sParams.bitsPerWord        = 24;
        i2sParams.moduleRole         = I2S_MASTER;
        i2sParams.samplingEdge       = I2S_SAMPLING_EDGE_RISING;
        i2sParams.SD0Use             = I2S_SD0_INPUT;
        i2sParams.SD1Use             = I2S_SD1_DISABLED;
        i2sParams.SD0Channels        = I2S_1_CHANNEL;
        i2sParams.phaseType          = I2S_PHASE_TYPE_DUAL;
        i2sParams.fixedBufferLength  = sizeof(buf);
        i2sParams.startUpDelay       = 0;
        i2sParams.MCLKDivider        = 2;
        i2sParams.samplingFrequency  = 24000;
        i2sParams.readCallback       = i2sReadHandler;
        i2sParams.writeCallback      = NULL;
        i2sParams.errorCallback      = i2sErrorHandler;

    It still did not work unfortunately.

    Here is the logic analyzer trace showing the first valid data sample:

    And here is the data I see in the memory buffer:

    I verified that there are 32 BCLKs while WCLK is low.

  • Hi Victor,

    A few more remarks:

    • the logic analyzer is not properly set. It seems to not take in consideration the first bit of each half-period. For example, the last sample shown on your screenshot should be 0xF.... instead of 0xE....
    • the data received by your device are stored as 24 bits (occupying 24 bits and not leaving any padding in between)
    • only one channel is sampled because you SD0Channels set to I2S_1_CHANNEL (you could also chose I2S_CHANNELS_MONO or I2S_CHANNELS_MONO_INV).

    In addition, I would like to suggest you to test the driver against a know signal. I mean it would be probably easier to debug if you could have a known sequence (let's say 0x11 - 0x22 - 0x33 - ...). You can do that with a signal generator or use a second CC26XX/CC13XX device.

    To finish (and if the previous message does not answer your question), can you precise a bit more what data you were expecting in your buffer?

    Thanks and regards,

  • Hi Clement,

    Yes, my logic analyzer was configured incorrectly.  It now includes the first bit of the word and everything seems

    to be working now.

    Thanks!

    Victor