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.

C6747 McASP0 RX only swaps L/R on i2s

Hello,

I have a C6747 on my own board fed with 15 A/D in i2s mode on McASP0.  I am using the PSP 1.30.01 as my guide to get audio in and out. I also have 4 D/A on McASP1.

McASP0 is only used for input (15 pins) and McASP1 is only used for outputs (4 pins).  The McASPs are in i2s slave mode as the bit and word clocks come from a master A/D which also feeds the master bit/word clocks to other A/D and D/A converters.

I have two problems.

1) No audio input.  I easily fixed this as the PSP McASP driver does not set the ACLKXCTL register correctly if I want to use the port for input only.  i.e. for RX only it should have set the ASYNC bit in the ACLKXCTL to make the McASP clocks come in from the RX side.

2) Audio comes in but 30% of the time L/R are swapped.  The 15 channel all come in fine its only the L/R of each channel that can be swapped.

I would appreciate some help in resolving this issue.

Thanks,

Fawad

 

  • Fawad,

    Could you please share the "Mcasp_HwSetupData" (both Rx and Tx) and the "Mcasp_ChanParams", which are configured in the application?

    Could you please check with the data format which are explained in the section 9.3.3 of C6747_BIOSPSP_Userguide document?

    Thanks and Regards,

    Sandeep K

  • Sandeep,

    For the Receiver

    ----------------------

    Mcasp_HwSetupData mcaspRcvSetup = {
            /* .rmask    = */ 0xFFFFFFFF, /* All the data bits are to be used     */
            /* .rfmt     = */ 0x000180F0, /*
                                           * 0 bit delay from framsync
                                           * MSB first
                                           * No extra bit padding
                                           * Padding bit (ignore)
                                           * slot Size is 32
                                           * Reads from DMA port
                                           * NO rotation
                                           */
            /* .afsrctl  = */ 0x00000110, /* i2s Mode,
                                           * Frame sync is one word
                                           * Rising edge is start of frame
                                           * externally generated frame sync
                                           */
            /* .rtdm     = */ 0x00000003, /* 2 slots (i2s)              */
            /* .rintctl  = */ 0x00000000, /* sync error and overrun error         */
            /* .rstat    = */ 0x000001FF, /* reset any existing status bits       */
            /* .revtctl  = */ 0x00000000, /* DMA request is enabled    */
            {
                 /* .aclkrctl  = */ 0x000000C0,    // rising edge of clock, divide by 1
                 /* .ahclkrctl = */ 0x00000000,    // external clocks
                 /* .rclkchk   = */ 0x00FF0008
            }
    } ;

    For the Transmitter

    -------------------------

    Mcasp_HwSetupData mcaspXmtSetup = {
            /* .xmask    = */ 0xFFFFFFFF, /* All the data bits are to be used     */
            /* .xfmt     = */ 0x000180F0, /*
                                           * 0 bit delay from framsync
                                           * MSB first
                                           * No extra bit padding
                                           * Padding bit (ignore)
                                           * slot Size is 32
                                           * Reads from DMA port
                                           * NO rotation
                                           */
            /* .afsxctl  = */ 0x00000110, /* i2s Mode,
                                           * Frame sync is one word
                                           * Rising edge is start of frame
                                           * externally generated frame sync
                                           */
            /* .xtdm     = */ 0x00000003, /* 2 slots (i2s)               */
            /* .xintctl  = */ 0x00000000, /* sync error,overrun error,clK error   */
            /* .xstat    = */ 0x000001FF, /* reset any existing status bits       */
            /* .xevtctl  = */ 0x00000000, /* DMA request is enabled or disabled   */
            {
                 /* .aclkxctl  = */ 0x00000080,    // rising edge of clock, divide by 1   
                 /* .ahclkxctl = */ 0x00000000,    // external clocks
                 /* .xclkchk   = */ 0x00FF0008
            },
    };

     

    Also I am using Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1 to get multiple i2s channels in and out in i2s mode.

    I just noticed I can also swap L/R on Transmit too, not just on receive. 

    I have been testing TX and found that the XGBLCTL register is 0x1F00.  Setting it to 0x1700 (Reset state machine) and then setting it back to 0x1F00 can swap L/R.  So is the issue that something correct is not being done when the TX state machine comes out of reset?

    Thanks,

    Fawad

  • Fawad,


    As per your configuration, the incoming data should be in the format as,
    [

    <Slot1-Sample1-Serializer1>,<Slot1-Sample1-Serializer2>, .... <Slot1-Sample1-Serializer15 >

    <Slot2-Sample2-Serializer1>, <Slot2-Sample2-Serializer2>, .... <Slot2-Sample2-Serializer15 >

    .......

    <Slot1-SampleN-Serializer1>, <Slot1-SampleN-Serializer2>, ... <Slot1-SampleN-Serializer15>

    <Slot2-SampleN-Serializer1>, <Slot2-SampleN-Serializer2>, ... <Slot2-Sample1-Serializer15>

    ]

    Which is like,

    [

    < L1,L2,L3, ... L15>,

    < R1,R2,R3, ... R15>,

    < L1,L2,L3, ... L15>,

    ......

    < L1,L2,L3, ... L15>,

    < R1,R2,R3, ... R15>

    ]

    Please let me know my understanding of you setting is correct or not?

    Could you please point me where exactly the data is getting swapped by refering to above buffer format?

    Is it possible you to try with lesser number of A/D?

    Note:The point which we need to keep in mind is, the required buffer format is achieved by programming the EDMA accordingly.

    Thanks and Regards,

    Sandeep K

  • Sandeep,

    Yes, I do know I get the data as(First script is sample number 1 to infinity)

    1L1, 1L2, ... 1L15

    1R1, 1R2, ..., 1R15

    2L1, 2L2, ,,,, 2L15

    2R1, 2R2, ..., 2R15

    .

    .

    .

     

    I convert to my processing block (float mono as I sometimes deal with mono channels) which is

    1L1, 2L1, ...128L1 (my blocks are 128 in size)

    1R1, 2R1, ...128R1

    2L1, 2L2, ... 128L2

    2R1, 2R2, ...128R2

    .

    .

    .

    After processing I assemble the data back to the correct format.  If you know a better/faster way to do this i would appreciate it.

    Also The swap is only between L/R.  BTW when I say 15 channels in, 4 out I meant 15 stereo channels in and 4 stereo out.

    So sometimes I see

    1R1, 2R1, ...128R1

    1L1, 2L1, ...128L1

    2R1, 2R2, ...128R2

    2L1, 2L2, ... 128L2

     

     

    and each stereo output is fine (i.e. each stereo channel has the correct two channels in it) but L/R is swapped.  And when the swap happens it happens on all stereo channels.

    I tested to 1 stereo input and 1 stereo output in i2s mode and I saw the same problem.  Also in that I did just did a memcpy from input to output. 

    I also tried this on my OMAP L-137 board with 4 in 4 out spectrum Digital audio board and I see the same problem.  The board is modified to allow master clocks to come from the A/D (bit and word clocks).

    Regards,

    Fawad

     

  • Fawad,

    Could you please refer the section 9.4.3 of the C6747_BIOSPSP_Userguide? Which has the explanation for one of the possible reason for channel swap. 

    Thanks and Regards,

    Sandeep K

  • Sandeep,

    Thanks for the suggestion on a possible cause of L/R swap.  I could not get the user defined loopjob to work.  i.e. If I supplied a buffer for Tx and RX I did not get any more interrupts.  Can you show me an example?  However I looked at the noOfChannels parameter in the same structure.  It says in mcasp.h

        Uint32               noOfChannels;
        /**< No of channels of data to be transmitted after the frame sync        *
         * This input is valid only for TDM in DSP mode mode of                   *
         * communication E

    So I had set noOfChannels=1 for i2s as I am not in DSP mode.  However it is used for the calculation of loopjob buffer size and for my OMAP L-137 reference design (with 4 stereo i2s inputs and 4 stereo i2s outputs) it is calculated as follows in mcasp.c

    chanHandle->loopJobLength =
                                (chanHandle->roundedWordWidth
                                    * chanHandle->noOfSlots
                                    * chanHandle->noOfSerAllocated);

    Hence for my 4 serializers this is 16 bytes.  When I set noOfChannels=2 I get loopJobLength=32 and my channels stop swapping.

    Is this a valid way to fix this issue?

    Thanks,

    Fawad

  • Sandeep,

    I also got the user defined loopjob buffer to work but.  But the size of the buffer was the problem.  It says in Mcasp.h

       Uint16 userLoopJobLength;
        /**< Number of bytes of the userloopjob buffer for each serialiser        *
         * Please note that this is no. of bytes and this should be               *
         * pre-calcuated properly for word width of slot - Please refer the       *
         *  wordWidth of this structure                                           */

    and in the userguide

    userLoopJobLength : Number of bytes of the userloopjob buffer for each serializer.

    So I took this to mean 8 bytes for each serializer so userLoopJobLength=8.  However this did not work and I was not getting McASP dma interrupts.  When I set it to 32 everything works fine.  So am I confused by the wording and should it say userLoopJobLength=totall buffer size for all serializers.

    Thanks,

    Fawad

  • Fawad,

    Thanks for the confirmation.

    If user application does not provide the loopjob buffer, then the loopjob buffer length will be calculated depending on the slot width, number of slot and the number of serializers (as you have mentioned in the previous post). But the number of slot will be derived from the no. of channel, so it is required to configure the number of channel equal to number of slots.

    Fawad Nackvi said:

    So I took this to mean 8 bytes for each serializer so userLoopJobLength=8.  However this did not work and I was not getting McASP dma interrupts.  When I set it to 32 everything works fine.  So am I confused by the wording and should it say userLoopJobLength=totall buffer size for all serializers.

    If the user appluication provides the loopjob buffer and its length, then,

    Loopjob buffer length = <Width of the slot in bytes> * <Number of serializers enabled> * <Number of slots enabled> (as per section 9.4.3 of C6747_BIOSPSP_Userguide).

    Thanks and Regards,

    Sandeep K