AnsweredAssumed Answered

2D DMA for I2S Left Right Separation

Question asked by WallWart on Sep 27, 2011
Latest reply on Oct 4, 2011 by PrasanthR

I am seeing an unexplained data offset in a 2D DMA transfer.  I am using a BF526 ez-board and I am trying to interface 2 ADMP441 microphones on a single SPORT.  The interface is I2S and each microphone has a L/R select input and word select input.  My setup will eventually be exactly as shown in the ADMP441 data sheet (attached as ADMP441.jpg). To test the 2D DMA I setup a simpler circuit (attached as setup.jpg) that simply had RFS tied to DRPRI of SPORT1.  The idea behind this was that I would be able to see all zeroes on the left channel and all ones on the right channel.  Using a normal DMA buffer the left channel data is interleaved with the right side data, so I thought I could use a 2D dma buffer to separate the two channels. Below is the buffer chain initialization I used.

 

ADI_DEV_2D_BUFFER bufStruct[3];

u32 buffer[3][256];

 

bufStruct[0].Data                          = (void*)&buffer[0][0];
bufStruct[0].ElementWidth                = (4);            //32 bit data.
bufStruct[0].XCount                         = (2);                      //Left and right channels
bufStruct[0].XModify                         = (128*4);              //(Buffer size/2) * Element width
bufStruct[0].YCount                         = (128);                  //(Buffer size/2)
bufStruct[0].YModify                         = ((-1*128*4) + 4);  //-((Buffer size/2) * Element Width) + Element Width
bufStruct[0].CallbackParameter          = (void*)&parm
bufStruct[0].ProcessedFlag               = FALSE;
bufStruct[0].ProcessedElementCount     = 0;
bufStruct[0].pNext                         = &bufStruct[1];

 

bufStruct[1].Data = (void*)&buffer[1][0];
bufStruct[1].ElementWidth = (4);            //32 bit data.
bufStruct[1].XCount      = (2);                      //Left and right channels
bufStruct[1].XModify      = (128*4);              //(Buffer size/2) * Element width
bufStruct[1].YCount      = (128);                  //(Buffer size/2)
bufStruct[1].YModify      = ((-1*128*4) + 4);  //-((Buffer size/2) * Element Width) + Element Width
bufStruct[1].CallbackParameter      = (void*)&parm
bufStruct[1].ProcessedFlag      = FALSE;
bufStruct[1].ProcessedElementCount     = 0;
bufStruct[1].pNext      = &bufStruct[2];

 

bufStruct[2].Data = (void*)&buffer[2][0];
bufStruct[2].ElementWidth = (4);            //32 bit data.
bufStruct[2].XCount      = (2);                      //Left and right channels
bufStruct[2].XModify      = (128*4);              //(Buffer size/2) * Element width
bufStruct[2].YCount      = (128);                  //(Buffer size/2)
bufStruct[2].YModify      = ((-1*128*4) + 4);  //-((Buffer size/2) * Element Width) + Element Width
bufStruct[2].CallbackParameter      = (void*)&parm
bufStruct[2].ProcessedFlag      = FALSE;
bufStruct[2].ProcessedElementCount     = 0;
bufStruct[2].pNext      = NULL;

 

The SPORT device driver was used.  The SPORT initialization is below:

 

ADI_SPORT_RX_CONFIG1_REG Config1;

ADI_SPORT_RX_CONFIG2_REG Config2;

u32 FsDivider;

u32 ClkDivider;

 

Config1.irclk           = 1;       /* internal clock                   */
Config1.rdtype      = 0;       /* zero fill                          */
Config1.rlsbit      = 0;       /* Most significant bit first       */
Config1.irfs           = 1;       /* internal rx frame sync           */
Config1.rfsr           = 1;       /* requires RFS for every data word */
Config1.lrfs           = 0;       /* Active high RFS                  */
Config1.larfs           = 0;       /* Early TFS                        */
Config1.rckfe           = 1;       /* Drive falling edge, sample rising*/
Config2.slen           = 31;      /* data length -1                   */
Config2.rxse           = 0;       /* Secondary side disabled             */
Config2.rsfse           = 1;       /* Frame sync is L/R select         */
Config2.rrfst           = 0;       /* Left channel first                  */
FsDivider                = 31;      /* Bits between frame syncs - 1      */
ClkDivider           = 16;   /* SCLK/nCClkDivider                    */

 

I would expect that first half of buffer[0], buffer[1] and buffer[2] would contain the data from the left, which should be all zeros, and the second half would contain data from the right channel, which should be all ones.  However, sometimes the first half is ones and sometimes it is zeros.  Additionally, sometimes the first half will be all zeros, but there will be several elements at the beginning that are all ones.

 

Do you see anything wrong with my setup?  Is there some explanation for this behavior?  If rrfst is 0 why do I sometimes get right channel data first?

Attachments

Outcomes