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.

24 bit codec on Omap 3530 McBSP3

Other Parts Discussed in Thread: TPS65930, TLV320AIC23B, TXS0104E

I  have a project that requires a 24 bit codec on McMSP3 configured in I2S/PCM mode. We have the driver for McBSP2/TPS65930 16 bit interface and that works fine. What I am finding is that even though the McBSP3 port is setup with a 32 bit frame width and a 24 bit word length, the data that is being outputted seems to be :-

 

1st frame (right) - 32 bits of data

2nd frame ) left - 16 bits of data and 16 1's

This gives the result of audio from the left speaker and a high pitched squeal from the right.

Couple of questions:-

In what format is the data placed in the DXR register? Is the padding required ( 24bits + 8 padding zeros) already in place, as there seems to be no setting in the McBSP setup to set the number of padding bits.

How is that data clocked out into the McBSP shift register? If you set the word length to 24 bits, will 24 bits be clocked out of the DXR, if so where do the padding bits come from, or are the entire 32 bits of the DXR register clocked out.

  • A bit more information :-

     

    XCR1 register = 0x80

    XCR2 register = 0x8085

    SRGR1 register = 0x1f03

     

    The 256fs clock is generated by the TPS65930 device and is used by McBSP3 as its master clock. The divide settings are correct as the data clock is 64fs and all clocks and frame sync are locked together.

  • Let me address your questions first:

     

    In what format is the data placed in the DXR register? Is the padding required (24bits + 8 padding zeros) already in place, as there seems to be no setting in the McBSP setup to set the number of padding bits.

     

    Data is written to the DXR, right justified. For example:

     

    For  8bit data, only bits  7:0 are used, 31:8  are ignored.

    For 16bit data, only bits 15:0 are used, 31:16 are ignored.

    For 24bit data, only bits 23:0 are used, 31:24 are ignored.

    For 32bit data, all bits are used.

     

    Padding is automatic.

     

     

    How is that data clocked out into the McBSP shift register? If you set the word length to 24 bits, will 24 bits be clocked out of the DXR, if so where do the padding bits come from, or are the entire 32 bits of the DXR register clocked out.

     

    Since you have the data transfer configured for MSB first the serial data stream will start with b23 and end with 8 zero padded bits to complete the necessary 32 bits required by each phase.  

     

     

    Your register settings for XCR2 has bit 2 set. This is a reserved bit and should not be set.

     

    Since you are using the TPS65930 in master mode you do not need to use the SRG.

     

    Can you dump all your McBSP register settings?

     

     

      Paul

  • How is your data organized in memory?  Are your 24-bit samples stored in 32-bit words?  If so, I think this would be a lot easier if you were able to simply do everything as 32-bit transfers because then these 8 bits of padding disappear.

  • Paul,

     

    I'll get you the register settings as soon as I can. The XCR2 bit 2 register is not set by us, but when we read it, it is always a '1'.

    We are only using the TPS65930 device as a source for the 256fs clock, the end product will actually supply a 256fs clock. The McBSP3 port is actually the master when it is transfering data to the external codec ( th eTPS65930 internal codec is connected to McBSP2) so I think we need to use the SRG.

     

    How does the McBSP port know that the data in the DXR register is a particular length, i.e 16 bits/24bits etc. or to put it another way how does the DXr register know that the data coming in is a particular length and to ignore the unused bits.  the way we have got it working is to make sure that the data coming into the DXR register is in the correct format already ( a 32 bit word consisting of 24 bits of data followed by 8 zero's)?

  • Brad,

     

    Thats the way we are doing it. The Audio has been encoded as either 16 bit pcm in a 32 bit word or 24 bit pcm in a 32 bit word with the LSB's set to zero and just pump that into the McBSP port.

    I was just wondering if there was some "magic" that needed to be done.

  • Register settings as requested:-

    SPCR2 = 0x00000230
       SPCR1 = 0x00000030
       RCR2 = 0x000080A5
       RCR1 = 0x000000A0
       XCR2 = 0x000080A5
       XCR1 = 0x000000A0
       SRGR2 = 0x0000103F
       SRGR1 = 0x00001F03
       MCR2 = 0x00000000
       MCR1 = 0x00000000
       PCR0 = 0x00000F0F
       XCCR = 0x00001008
       RCCR = 0x00000808

     

  • The behavior you're seeing is expected as the McBSP does not have any kind of configurable setting to the effect of "bits between words".  The McBSP always spits out all the words contiguously.  The way I usually have worked around this in the past has been to make the number of bits per frame EXACTLY equal to the number of data bits.  For example in your case rather than spitting out 64 bits per frame I would only spit out 48 bits which removes the whole issue of padding.

    Many of TI's audio codecs have a data mode called "DSP mode" specifically for this reason.  In "DSP mode" the data comes out all lumped together with any "extra" bits output at the end, e.g. in your case 24 data, 24 data, 16 extra.

  • Andy

    The information in my previous post is not accurate for a dual phase frame. I'll explain further below.

    Yes, since McBSP is the master then you will need to use the SRG.

    Since the encoder is receiving 32 bit words with either 16 or 24 bit data you'll need to set the following:

      Dual phase 

      Frame period  64 bits

      Frame width   32 bits

    Frame length   1 word per phase

    This is already done in the register setting you provided.

    Since each phase is one word of 32 bits, the software writing to the DXR must align the data to suite the encoder. 

    Examples;

    For 24 bit data, MSB first, left justified the software must shift the data 8 bits left (data<<8) before writing to the DXR. The remaining 8 bits will be zero filled by the shift operation.

    For 16 bit data, MSB first, left justified the software must shift the data 16 bits left (data<<16) before writing to the DXR. The remaining 16 bits will be zero filled by the shift operation.

    In your previous setup with 24 bit word size the two data words were transmitted contiguously. Since the frame size was still 64 bits with a FW of 32 bits this meant that the MSB of the second word was actually transmitted as the LSB of the first phase word. The second phase word was effectively shifted left by 8 bits with the remaining 16 bits at the same state the lsb of the second phase word.

    If the phase word size was changed to 16 bits the settings would become:

      Dual phase 

      Frame period  32 bits

      Frame width   16 bits

    Frame length   1 word per phase 

    Now only bits 15:0 of the DXR are used. So 16 bit data would be written to the DXR unmodified, 8 bit data would need to be shifted to the left by 8 bits (for left justified frames).

      Paul

     

     

  • Paul,

    We have sorted the audio play by arranging the data correctly and doing a full 32 bit transfer to the DXR register. On the record side the software reports RX frame sync errors (sometimes) - this is a bit confusing as the codec does not generate the frame sync it is the Omap, is the frame sync error a symptom of the data coming from the codec not being there when the Omap expects it i.e. not  there at the first rising edge of the data clock after the frame sync pulse due to inherent delays in the system. Would we need to insert a 1 bit delay into the receive side?

  • Andy

    The RSYNCERR bit is set when there is an early frame synchronization.

    How often is sometimes? Is there noise on the lines?

    Please take a look at section 20.4.4.3.3 Preventing Unexpected Receive Frame-sync Pulses of the TRM http://focus.ti.com/general/docs/litabsmultiplefilelist.tsp?literatureNumber=spruf98d.

      Paul

     

     

  • Paul

    It happens basically all the time ( if I cool the Omap then they go away). The RX frame syncs are the same as the TX frame syncs which are interally generated by the Omap so the RX circuitry will see the frame sync before it gets to the outside world. This is what is confusing me - we are not externally generating the frame syncs and supplying them to the Omap, they are all generated internally.

     

  • Andy

    Since FSR = FXR you should be able to check the DR signal against FXR.

    I'll see what else I can find out.

    Paul

  • I have checked the RX data against the frame sync and it lines up nicely  -24 bits per 32 bit word MSB justifed and padded with zeros. The same applies for both left and right frames. I can't see any spurious frame syncs and everything is locked together ( as you would expect, as they are all generated from the 256fs clock supplied to CLKS).

  • Paul,

    Could you clarify something for me please. The TRM states that the  RX side of the McBSP port clocks in the data on the falling edge of the clock. This is the same edge as the codec places the data on the bus which could account for the strange behaviour we are seeing - Am I reading the TRM correctly?

    Also, on McBSP3 the CLKR pin is internal - is it connected internally to the CLKX pin as implied in the TRM? So can you set the RX side to take its clock from the CLKR pin?

    Can you change the edge that the RX side clocks in the data on. Also is there a way to verify that the data is being clocked in on the correct edge?

  • Andy

    The transmit edge and capture edge are programmable via the CLKXP and CLKRP bits of the MCBSPLP_PCR_REG

    CLKXP Transmit Clock Polarity
         0x0: Transmit data driven on rising edge of CLKX
         0x1: Transmit data driven on falling edge of CLKX
    CLKRP Receive Clock Polarity
        0x0: Receive data sampled on falling edge of CLKR
        0x1: Receive data sampled on rising edge of CLKR

    For all 4 pin McBSP modules, CLKR and FSR is connected internally to CLKX pin   FSR is connected internally to the FSX  pin.  I'm not aware of any way to verify that they are being clocked on the correct edge.

    Is there a reason you need to have the McBSP as Master? Other setup I have seen all use the Codec as master.

    Paul

     

     

  • Paul,

    The customer chose the codec that he wanted to use and it requires the Omap to be the master. It is a fairly dull beast and needs to be provided with a main clock (256fs), data clock and frame sync.

     

    Andy

     

  • Andy

    What's the current status? If you are still seeing issues could you provide me with an updated register dump?

    BRs 
      Paul

  • Paul,

    Yes we are still having issues with the record. One thing I did find in the TRM ( it is only mentioned once) is that the receive cycle requires 3 clock cycles after the receipt of the frame to transfer the data to the DRR. We have set each phase to be 32 bits long as the codec places 24 bits of data and 8 padding bits on the bus, so the receive word length is set to 32 bits. Is this correct ? as there is an option to set the justification and the padding for the receive side. Would we be better to set the receive word length to 24 bits and let the Omap do the justification and the padding, or would we need to read the first word as 32 bits then the second as 24 bits, let the Omap padd and justify that bit then wait fo the next active frame sync to indicate more data.

     

    Register settings as they stand:-

     

    SPCR2 0x00000230 ( this gets changed as the receive cycle goes on)

    SPCR1 0x00000030 ( this also gets modified)

    RCR2 0x000080a4

    RCR1 0x000000a4

    XCR2 0x000080a4

    XCR1 0x000000a4

    SRGR2 0x0000103f

    SRGR1 0x00001f03

    MCR2 0x00000000

    MCR1 0x00000000

    PCR 0x00000f0f

    XCCR 0x000010008

    RCCR 0x00000008

    Could you suggest some register settings for an MCBSP port in master transmit and receive mode handling 24 bit sterao audio data in a 32 bit phase. I get the feeling that we are missing something here.

    Thanks

    Andy

  • Andy

    Yes, your word length setting is correct. Since the codec is set to 32 bit sample length, 24 bit data width the McBSP should be configured with word1 & 2 as 32 bits, 64 bit total frame. The McBSP will only transfer the received 24bit data to the DRR.

    What are the settings for the TPS65930 AUDIO_IF register?

    What do you currently have the PCR , XCCR and RCCR set to?

    BRs
      Paul

     

  • The PCR, XCCR and RCCR are given above. We are not using the TPX65930 as the codec on McBSP3 ( the port we are having problems with). The codec on that port is an AK4620. The TPS5930 device is on McBSP2 and is working fine.

  • Sorry, my bad.

    Which mode is the AK4620 configured? Mode 3?

      Paul

  • Paul,

    The customer wanted it to run in the default mode, mode 2. I've just noticed that the Sync is inverted in mode 3 compared with all the other modes.

    Andy

  • Andy

     

    I took a look at the Codec data sheet and I came up with very similar register settings. Biggest difference is the PCR register.

     

     

       // SPCRC2 & 1 use your original settings
      
    SPCR2 = 0x00000230   FREE + XINITM=XSYNCERR
      
    SPCR1 = 0x00000030   RINTM=RSYNCERR

     

       // RCR2/1 & XCR2/1 are set to DUAL-PHASE + 32BIT-WORD + 0BIT-DELAY
      
    // Still not sure why you see bit2 set as this reserved bit should read back “0”.
      
    RCR2  = 0x000080A4   DUAL-PHASE + 32BIT-WORD + 0BIT-DELAY
      
    RCR1  = 0x000000A4   32BIT-WORD – [3] RESERVED!
      
    XCR2  = 0x000080A4   DUAL-PHASE + 32BIT-WORD + 0BIT-DELAY
      
    XCR1  = 0x000000A4   32BIT-WORD - [3] RESERVED!

     

       // SRGR2 looks fine with FSGM set and a Frame period of 64 bits
      
    SRGR2 = 0x0000103F   FSGM + 64BIT-FP

     

       // SRGR1 is also good with a Frame pulse widthe of 32 bits, I assume the divider is correct. 
      
    SRGR1 = 0x00001F03   32BIT-FW + CLKGDV=3

     

       //PCR REGISTER
      
    //   FSXM = CLKXM = 1 - are what you need for transmit master.
       //   CLKRM = FSRM = 0 - since this is a 4 pin McBSP you can leave the FSRM + CLKRM reset so these signals will loopback from the transmitter equivalents.
       //   CLKXP = 1 - Since the FSX is internally generated on the rising edge of CLKX it is necessary to invert the CLKX signal sent to the Codec.
      //    CLKRP = 1 – Use the opposite edge to capture the data
      //    FSXP = FSRP = 1 – Codec mode 2 needs the frame sync active low.
     
    PCR0  = 0x00000A0F

     

    // RCCR by default is set to full cycle. If you still see RSYNCERR errors then try resetting this bit to use half cycle mode.

     

    I have this configuration successfully setup with a TLV320AIC23B device.

     

    Paul

     


  • Paul,

     

    I take it that you have it running with the Omap?. What we have going on here is that the data is coming out of the codec correctly ( we have looped the I2S codec out back into it's I2S inputs and the sound from the speakers is correct, so we know that the data going to the Omap is correct). What we are finding is that the Omap is still either corrupting the incoming data or failing to transfer it into memory correctly.

    Do you have the code that you used and could you let me have a look at it please in case there is something silly going on in ours.

     

    Thanks

    Andy

  • Andy

     

    Here's some code I came up with this morning. Nothing complicated or smart. I'm using McBSP2 Master to talk to a  TLV320AIC23B in slave mode. Both are configured for I2S.

    The code records around 10 seconds of audio while playing it back via the codec. The recorded audio is then played again using the codec. The loop then repeats. No error checking is done!

    Only the McBSP setup and record/playback functions are listed.

    Hopefully this helps solve you issue.

    ////////////////////////////////////////////////////////////////////////////
      // McBSP Initialization
      //
      mcbsp_base = MCBSP2_REG_BASE;                                     // Select McBSP
      LOAD_PINMUX(mcbsp2_pin_mux_master);                               // Setup the pins so that MCBSP2 is master - Enabkle inputs on all pins except DX!
      CLRBIT_REGL(CONTROL_DEVCONF1,DEVCONF1_MCBSP4_CLKS);               // Select 96MHz clock (device specific)

      ////////////////////////////////////////////////////////////////////////////
      // Put McBSP into reset (only necessary if not coming from a global reset)
      //
      // McBSP will be master
      // Clock source will be 96MHz
      //
      CLRBIT_REGL(mcbsp_base + MCBSPLP_SPCR1_REG, SPCR1_RRST);
      CLRBIT_REGL(mcbsp_base + MCBSPLP_SPCR2_REG, (SPCR2_XRST + SPCR2_FRST + SPCR2_GRST));
      while(CHKBIT_REGL(mcbsp_base + MCBSPLP_SPCR2_REG, SPCR2_GRST));   // Wait until GRST bit is clear
      SETBIT_REGL(mcbsp_base + MCBSPLP_PCR_REG, PCR_FSXP | PCR_FSRP);   // FSX/FRX Active low
      SETBIT_REGL(mcbsp_base + MCBSPLP_PCR_REG, PCR_FSXM | PCR_CLKXM);  // enable FSX & CLKX outputs
      CLRBIT_REGL(mcbsp_base + MCBSPLP_SRGR2_REG, SRGR2_CLKSM);         // 2 lines to select the SRG CLKG source to CLKS (defaults to FCLK_96)
      CLRBIT_REGL(mcbsp_base + MCBSPLP_PCR_REG, PCR_SCLKME);           
      SETBIT_REGL(mcbsp_base + MCBSPLP_SRGR2_REG, 63);                  // Frame sync period (64 clocks))   
      OUT_REGL   (mcbsp_base + MCBSPLP_SRGR1_REG, 0x0000);              // Clear SRG
      SETBIT_REGL(mcbsp_base + MCBSPLP_SRGR1_REG, 0x1F00);              // FWID   = 32 bit Frame Sync pulse
      SETBIT_REGL(mcbsp_base + MCBSPLP_SRGR1_REG, 31);                  // 32 bits per word x 2 words * 46.875KHz sample gives bit clock of 3MHz, CLKDIV = 96MHz/32=3MHz
      // CLRBIT_REGL(mcbsp_base + MCBSPLP_RCCR_REG, RCCR_RFULL_CYCLE);  // Switch receiver to half cycle mode
      SETBIT_REGL(mcbsp_base + MCBSPLP_SRGR2_REG, SRGR2_FSGM);          // Transmit frame-sync signal driven by the SRG frame-sync signal, FSG. NOT GATED

      // I2S: Dual Phase, 32 bits per word. MSB first, 1 data delay
      OUT_REGL   (mcbsp_base + MCBSPLP_RCR2_REG, 0x000080A1);
      OUT_REGL   (mcbsp_base + MCBSPLP_RCR1_REG, 0x000080A1);
      OUT_REGL   (mcbsp_base + MCBSPLP_XCR2_REG, 0x000080A1);
      OUT_REGL   (mcbsp_base + MCBSPLP_XCR1_REG, 0x000080A1);

      SETBIT_REGL(mcbsp_base + MCBSPLP_PCR_REG, PCR_CLKXP | PCR_CLKRP); // Transmit data on falling edge, Capture on rising
      USTIMER_delay(100000);                                            // Wait for at least 2 SRG clock cycles
      SETBIT_REGL(mcbsp_base + MCBSPLP_SPCR2_REG, SPCR2_GRST);          // Remove resets
      USTIMER_delay(100000);                                            // Wait for at least 2 SRG clock cycles


      ////////////////////////////////////////////////////////////////////////////
      //
      // Record an playback
      //

      while (1) {                                                       // Loop forever
         SETBIT_REGL(mcbsp_base+MCBSPLP_SPCR1_REG, SPCR1_RRST);         // Enable receiver
         SETBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRST);         // Enable transmitter
         SETBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_FRST);         // Enable frame sync
         for (sample = 0 ; sample < MAXSAMPLE ; sample++)               // Record some samples (playback while recording)
         {
            while (!CHKBIT_REGL(mcbsp_base+MCBSPLP_SPCR1_REG, SPCR1_RRDY));
            left_channel[sample] = IN_REGL(mcbsp_base+MCBSPLP_DRR_REG);
            while (!CHKBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRDY));
            OUT_REGL(mcbsp_base+MCBSPLP_DXR_REG, left_channel[sample]);
            while (!CHKBIT_REGL(mcbsp_base+MCBSPLP_SPCR1_REG, SPCR1_RRDY));
            right_channel[sample] = IN_REGL(mcbsp_base+MCBSPLP_DRR_REG);
            while (!CHKBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRDY));
            OUT_REGL(mcbsp_base+MCBSPLP_DXR_REG, right_channel[sample]);

         }
         CLRBIT_REGL(mcbsp_base+MCBSPLP_SPCR1_REG, SPCR1_RRST);         // disable receiver
         CLRBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRST);         // disable transmitter
         SETBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRST);         // Enable transmitter
         for (sample = 0 ; sample < MAXSAMPLE ; sample++)               // Play recorded sample
         {
            while (!CHKBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRDY));
            OUT_REGL(mcbsp_base+MCBSPLP_DXR_REG, left_channel[sample]);
            while (!CHKBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRDY));
            OUT_REGL(mcbsp_base+MCBSPLP_DXR_REG, right_channel[sample]);
         }
         CLRBIT_REGL(mcbsp_base+MCBSPLP_SPCR2_REG, SPCR2_XRST);       // disable transmitter
      }
    }

  • Paul,

     

    Good news we have manged to fix the issue. The problem occurred because of the level translators in the circuit. I initially chose a TXS0104E ( a bi-directional push-pull/open drain type) and we were seeing a small glitch on the codec side which was then translated back through the level translator and the RX side of the Omap was seeing it and reporting an error. We have changed the translator to a TXD0104 and problem solved.

     

    Thanks for all your help.

    Andy.

  • That's great news!

      Paul