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.

TMS320C5535: I2s Format

Part Number: TMS320C5535
Other Parts Discussed in Thread: TLV320AIC3254

Hello,

we have the following system which works with synchronous clocks. One AIC3204 is the i2s master of the whole system and generates the clocks for all i2s slaves. Servicing of c5535 i2s is done by dma. The c5535 just loop through the audio data at the moment. The audio transfers work, but sometimes the audio is scrambled after power on. When we reinit the codec and the dsp i2s and dma, scrambling dissappears. What could be the reason for this scrambling?!

I2sStream.pdf

The init procedure of AIC3204 is as follows. The only difference in initialization of master or slave is the register 27 in page 0 (marked in red).

CSL_Status AIC3254_Init(Bool master)
{
CSL_Status result = CSL_SOK;

result = AIC3254_Write(0, 0); // write 0 to page register to select page 0
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(1, 1); // reset codec
if (result != CSL_SOK)
{
return result;
}

/* Select the PLL input and CODEC_CLKIN */
/* PLL input is assumed as 12MHz */
result = AIC3254_Write(4, 0x03);
if (result != CSL_SOK)
{
return result;
}

/*
PLL_CLK = (PLL_CLKIN * R * J.D)/P
DAC_FS = PLL_CLK/(NDAC * MDAC * DOSR)
ADC_FS = PLL_CLK/(NADC * MADC * AOSR)
DAC_CLK = PLL_CLK/NDAC
BCLK = DAC_CLK/BDIV_CLKIN

DAC_FS, BCLK:
16 kHz: P=1, R=1, J=7, D=1754 (0x6da)
NDAC=6, MDAC=7, DOSR=128
BCLK = 28
PLL_CLK = (12e6 * 1 * 7.1754)/1 = 86104800
DAC_FS = PLL_CLK/(6 * 7 * 128) = 16016.52
BCLK = PLL_CLK/NDAC/BCLK = 28701600/2/28 = 512528.57
ADC_FS:
16 kHz: P=1, R=1, J=7, D=1754 (0x6da)
NADC=6, MADC=7, AOSR=128
ADC_FS = PLL_CLK/(2 * 7 * 128) = 16016.52
*/

// Power up the PLL and set P = 1 & R = 1
result = AIC3254_Write(5, 0x91); // 16khz
if (result != CSL_SOK)
{
return result;
}

// Set J value to 7
result = AIC3254_Write(6, 0x07); // 16khz
if (result != CSL_SOK)
{
return result;
}

//
// CODEC_CLKIN = 12MHz *(R * J.D)/P
//

// Set D value(MSB) = 0x06
result = AIC3254_Write(7, 0x6); // 16khz
if (result != CSL_SOK)
{
return result;
}

// Set D value(LSB) = 0xda
result = AIC3254_Write(8, 0xda); // 16khz
if (result != CSL_SOK)
{
return result;
}

// Set NDAC to 6 - this along with BCLK N configures BCLK
result = AIC3254_Write(11, 0x86); // 16khz
if (result != CSL_SOK)
{
return result;
}

// Set MDAC to 7
result = AIC3254_Write(12, 0x87); // 16khz
if (result != CSL_SOK)
{
return result;
}

//
// DAC_FS = (12MHz *(R * J.D)/P)/(NDAC * MDAC * DOSR)
//

/* Set DAC OSR MSB value to 0 */
result = AIC3254_Write(13, 0x0);
if (result != CSL_SOK)
{
return result;
}

// Set DAC OSR LSB value to 128
// This generates the DAC_FS = 16KHz
result = AIC3254_Write(14, 128); // 16khz
if (result != CSL_SOK)
{
return result;
}

//
// BCLK = (12MHz *(R * J.D)/P)/(NDAC * BCLK N)
//
// Set BCLK N value to 28
// This along with NDAC generates the BCLK = 512 kHz
// BCLK = (12MHz *(R * J.D)/P)/(NDAC * BCLK N)
result = AIC3254_Write(30, 0x9C); // 16khz
if (result != CSL_SOK)
{
return result;
}

// Set ADC_FS to 16 kHZ

// Set NADC to 6
result = AIC3254_Write(18, 0x86); // 16khz
if (result != CSL_SOK)
{
return result;
}

// Set MADC to 7
result = AIC3254_Write(19, 0x87); // 16khz
if (result != CSL_SOK)
{
return result;
}

// Set ADC OSR LSB value to 128
// This generates the ADC_FS = 16KHz
// ADC_FS = (12MHz *(R * J.D)/P)/(NADC * MADC * AOSR)
result = AIC3254_Write(20, 128); // 16khz
if (result != CSL_SOK)
{
return result;
}

if (master == TRUE)
{
result = AIC3254_Write(27,0xd); // BCLK and WCLK is set as op to AIC3254(Master)
if (result != CSL_SOK)
{
return result;
}
}

result = AIC3254_Write(0, 1); // select page 1
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(51, 0x48); // power up Mic Bias using LDO-IN
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(1, 0x8); // Disable crude AVDD generation from DVDD
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(2, 1); // Enable Analog Blocks and internal LDO
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(20, 0); // Depop reg R=6K,t=8RC(2.256ms),ramp time=0ms
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(14, 0x8); // LDAC AFIR routed to LOL
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(15, 0x8); // RDAC AFIR routed to LOR
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(52, 0xC0); // Route IN1L to LEFT_P with 40K input impedance
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(54, 0xC0); // Route Common Mode to LEFT_M with impedance of 40K
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(55, 0xC0); // Route IN1R to RIGHT_P with 40K input impedance
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(57, 0xC0); // Route Common Mode to RIGHT_M with impedance of 40K
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(59, 0x00); // Unmute Left MICPGA, Gain = 0 dB
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(60, 0x00); // Unmute Right MICPGA, Gain = 0 dB
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(0, 0); // write 0 to page register to select page 0
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(86, 0x90); // Enable LEFT AGC, target level -8dBFs
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(94, 0x90); // Enable RIGHT AGC, target level -8dBFs
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(64, 0x2); // DAC left vol=right vol
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(63, 0xd4); // DAC power up left, right data paths and set channel
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(64, 0xc); // DAC mute
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(0, 1); // select page 1
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(18, 0); // unmute LOL, 0dB gain
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(19, 0); // unmute LOR, 0dB gain
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(9, 0x0C); // power up LOL, LOR
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(0, 0x0); // select page 0
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(64, 0x2); // unmute DAC with right vol=left vol
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(65, 0); // set DAC gain to 0dB
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(66, 0); // set DAC gain to 0dB
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(81, 0xc0); // Powerup left and right ADC
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(82, 0x00); // Unmute left and right ADC
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(83, 0); // Set left ADC Gain to 0dB
if (result != CSL_SOK)
{
return result;
}

result = AIC3254_Write(84, 0); // Set right ADC Gain to 0dB
if (result != CSL_SOK)
{
return result;
}

return result;
}

Initialization of C5535 i2s is as follows:

CSL_Status I2sInit(void)
{
CSL_Status status;
I2S_Config hwConfig;

hI2sLoc->configured = false;

/* Set the value for the configure structure */
hwConfig.dataFormat = I2S_DATAFORMAT_LJUST;
hwConfig.dataType = I2S_STEREO_ENABLE;
hwConfig.loopBackMode = I2S_LOOPBACK_DISABLE;
hwConfig.fsPol = I2S_FSPOL_LOW; // I2S_FSPOL_HIGH
hwConfig.clkPol = I2S_RISING_EDGE; // I2S_FALLING_EDGE
hwConfig.datadelay = I2S_DATADELAY_ONEBIT;
hwConfig.datapack = I2S_DATAPACK_ENABLE;
hwConfig.signext = I2S_SIGNEXT_DISABLE;
hwConfig.wordLen = I2S_WORDLEN_16;
hwConfig.i2sMode = I2S_SLAVE;
hwConfig.clkDiv = I2S_CLKDIV2; // don't care for slave mode
hwConfig.fsDiv = I2S_FSDIV32; // don't care for slave mode
hwConfig.FError = I2S_FSERROR_DISABLE;
hwConfig.OuError = I2S_OUERROR_DISABLE;

/* Configure hardware registers */
status = I2S_setup(hI2sLoc, &hwConfig);
if (status != CSL_SOK)
{
printf("Setup I2S Loc Module failed\n");
return (status);
}

hI2sRem->configured = false;

/* Set the value for the configure structure */
hwConfig.dataFormat = I2S_DATAFORMAT_LJUST;
hwConfig.dataType = I2S_STEREO_ENABLE;
hwConfig.loopBackMode = I2S_LOOPBACK_DISABLE;
hwConfig.fsPol = I2S_FSPOL_LOW; // I2S_FSPOL_HIGH
hwConfig.clkPol = I2S_RISING_EDGE; // I2S_FALLING_EDGE
hwConfig.datadelay = I2S_DATADELAY_ONEBIT;
hwConfig.datapack = I2S_DATAPACK_ENABLE;
hwConfig.signext = I2S_SIGNEXT_DISABLE;
hwConfig.wordLen = I2S_WORDLEN_16;
hwConfig.i2sMode = I2S_SLAVE;
hwConfig.clkDiv = I2S_CLKDIV2; // don't care for slave mode
hwConfig.fsDiv = I2S_FSDIV32; // don't care for slave mode
hwConfig.FError = I2S_FSERROR_DISABLE;
hwConfig.OuError = I2S_OUERROR_DISABLE;

/* Configure hardware registers */
status = I2S_setup(hI2sRem, &hwConfig);
if (status != CSL_SOK)
{
printf("Setup I2S Rem failed\n");
return (status);
}

return CSL_SOK;

}

I2s WCLK and BCLK look as follows:

The peaks at the BCLK occur due to not connected ground on oscilloscope.

I2s WCLK and Data:

I2s BCLK and Data:

We don't know if the initialization of the aic3204 and c5535 i2s is correct and match each other. We took them out of example code from ti (Beam form application and C55x USB Audio Class Framework). It would be fine if you could take a look at the init procedures and the screenshots. Perhaps you can see the reason for the scrambled sound?! As already mentioned, scrambling only appears sporadic after init of codec and c5535 i2s. When we do a reinit, it dissappears. 

Is the data delay of one bit correct? In my understanding this means that the data is valid after the second rising edge on BCLK after WCLK change.But then only 15 rising BCLK edges remain?!?! What about the c5535 Frame Clock Timing Requirement in Slave Mode mentioned in chapter 2.4 in http://www.ti.com/lit/ug/sprufp4a/sprufp4a.pdf?? It is mentioned that the WCLK can be delayed by a RC combination. But why is the RC placed at the DOUT pin and not at the WCLK pin in Figure 6??

Thanks in advance and have a nice day

Marc

  • Hello Marc,

    Q: Are these scope shots captured while the scrambled audio is happening?
    Q: Did you compare the signals during scrambled data verses when the data is not scrambled sounding? Can you attach both here?
    Q: Can you describe the scrambled sound a bit?

    Q: Are you running from CCS or from the bootloader (stand-alone)?

    Q: Can you halt the execution with a JTAG emulator while the scrambled audio is happening and dump the all of the I2S registers? If you are running from a bootloaded image, connect to the target without using any GEL file init so it preserves the state of the execution.

    I would check first if  hwConfig.i2sMode = I2S_SLAVE. Scrambled audio can occur when there are two masters driving the I2S CLK and FS signals.

    Perhaps you can do some debugging with I2S_DATAPACK disabled also...

    =-=-

    Marc48067 said:

    What about the c5535 Frame Clock Timing Requirement in Slave Mode mentioned in chapter 2.4 in www.ti.com/.../sprufp4a.pdf It is mentioned that the WCLK can be delayed by a RC combination. But why is the RC placed at the DOUT pin and not at the WCLK pin in Figure 6??


    This is a mistake in the figure. The RC delay must be placed on the I2S_FS trace going into each C55xx I2S_FS input (not the data trace). There is a LitBug filed for this already. Sorry about that. This delay is meant to satisfy datasheet timing No 10 in Table 5-24. Timing Requirements for I2S and Table 5-25. Timing Requirements for I2S.
    Typically I2S_FS transitions on the BCLK edge that it is not latched on, but this device requires I2S_FS to remain valid for 0.6ns after the edge it typically transitions on. An RC delay or non-inverting buffer can achive this delay requirement.

    =-=-=-

    Marc48067 said:

    Is the data delay of one bit correct?



    The Philips I2S spec states that the serial data shall begin 1 serial bit clock delay from the FS edge. The 0th bit is actually transmitted after the FS edge marking the next frame.
    I think the audio would probably still sound close to expected much of the time - maybe noisy. You can verify the data delay from the C55xx at least by sending some test samples like all F's and all 0's.

    http://read.pudn.com/downloads95/doc/comm/386760/Philips_I2S.pdf



    =-=-=-
    I am assuming AIC3254_Init(Bool master) is always called with master == TRUE.
    result = AIC3254_Write(27,0xd) looks good for setting up the codec as master.

    =-=-=-
    Refer also to this appnote: Common Noise Issues in Audio Codecs:
    http://www.ti.com/lit/pdf/slaa749

    CODEC registers are described in SLAA408A: http://www.ti.com/lit/an/slaa408a/slaa408a.pdf

    =-=-
    Delay after resetting codec

    According to the TLV320AIC3254 Application Reference Guide (SLAA408A), the codec requires a 1ms delay after calling SW reset. I don't even think our example software adheres to that requirement! Give it a try.

    3.2 Device Startup Lockout Times
    After the TLV320AIC3254 initializes through hardware reset at power-up or software reset, the internal registers initialize to default values. This initialization takes place within 1ms after pulling the RESET signal high. During this initialization phase, no register-read or register-write operation should be performed on ADC or DAC coefficient buffers. Also, no block within the codec should be powered up during the initialization phase.

    result = AIC3254_Write(1, 1); // reset codec
    if (result != CSL_SOK)
    {
    return result;
    }

    for(1ms delay);

    ...

    You might try writing a debug function that reads the I2C registers back from the codec to confirm they match what you write (or their reset values).

    =-=-=-
    If none of this is getting you anywhere, it may be worth probing the I2C signals before the scrambled audio appears and compare against when there is no scrambled audio.

    Hope this helps,
    Mark

  • Hi Mark,

    thanks a lot for the usefull information. I inserted a wait time of 5ms after codec reset and made a change in the order of dma init. It seems as if the distorted sound, which occurred sometimes after power up, is gone now. 

    At the moment we manually generate a sinus table in the dsp and send it to the codec dac via i2s. When we generate positive and negative sinus values, the output at the line out doesn't loot like a sinus. Does the dac not understand two's complement negative numbers? When the sinus table just contains positive values, we can see the sinus at the line out. But the sinus only looks good as long as the digital values are in the range 0...32767 (15Bit). When we use greater values, the sinus is completely distorted. Does the dac only process 15Bit positive numbers?

    15 Bit sinus table:

    for(i = 0; i < 16; i++)
    {
    sinus[i] = (sin((i*2*3.14)/16)*0x3FFF)+0x3FFF;
    }

    table:

    16383
    22649
    27962
    31515
    32765
    31525
    27981
    22673
    16409
    10140
    4821
    1260
    0
    1230
    4766
    10068

    Line out signal at aic3204:

    16 Bit sinus table:

    for(i = 0; i < 16; i++)
    {
    sinus[i] = (sin((i*2*3.14)/16)*0x3FFF)+0x3FFF+20;
    }

    table:

    16403
    22669
    27982
    31535
    32785
    31545
    28001
    22693
    16429
    10160
    4841
    1280
    20
    1250
    4786
    10088

    Line out signal at aic3204:

     

    Thanks a lot

    Marc

  • Hi Mark,

    one additional question. We want to feed the i2s data coming from the aic3204 adc into aer/aec echo cancellation library functions. And the processed data is sent to the dac. Now I am not sure if the data format of the codec matches those of the library functions.

    The library functions use this format for the samples:

    /*! Portable linear sample.
    *
    * Portable linear sample has at least 16 bits of precision.
    *
    * <b>Suggested usage:</b> linear signal samples are always in [-32768, 32767]
    * range. They may be obtained from the PCM compressed samples using
    * appropriate expansion lookup table. Internally, linSample is based on
    * the Fract type. Signal processing algorithms assume that the analog sine
    * wave of +3dBm power is scaled into a digital sine wave that has a full
    * scale amplitude of 32768. On a fixed point platform linear samples are
    * in Q0 format.
    *
    * <b>NOTE:</b> On floating point platforms linear samples would also have the
    * range [-32768.0, 32767.0].
    */
    typedef tint linSample;

    Our codec uses 16Bit data. Is this data signed or unsigned? Do we have to set the sign extend bit in dsp i2s initialization or use a look up table? As mentioned above, the dac had some problems with our self generated sinus when it contains negative numbers?!

    Thanks in advance

    Marc

  • Hi,

    I did some more tests and found out that the sinus table wasn't correctly copied into the dma out buffer. Data was corrupt when negative and positive values were put into the U32 dma out buffer. This is now fixed and the dac works with positive and negative sinus values. So I think the codec works with 16 Bit signed values which can directly be processed by the algorithms. Am I right here?

    Thanks a lot

    Marc

  • Hi Marc

    Were you able to resolve the issues you were encountering here?

    Regards

    Mukul 

  • Hi Mukul,

    thanks for your post. Yes, as already mentioned we were able to solve the problem (see answers above). 

    Thanks for your support

    Marc