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.

Can't get correct master I2S signaling

Other Parts Discussed in Thread: CC2564

Hi!

I'm trying to setup a CC2564 demo, using the HFP demo for STM32 from Bluetopia stack. I have a CODEC connected to the CC2564, and I've been unsuccessfully trying to get audio through the CC2564 using I2S protocol.

My original setup is to use the CODEC as I2S master, and CC2564 as slave.

Just for the kicks, I took the CC2564 EM, and set it up as I2S master, by making a copy of BTVS.c::VS_PCM_Codec_Config_Slave_I2S(), and simply modifying CommandBuffer[2] to contain 0x00 (sets up the CC2564 as master), and of course CommandBuffer[7] and [8] contain 0x0000 (50% duty cycle FrameSync).

So my surprise was when I hooked my scope probe to FrameSync pin (in the debug header) and found that FrameSync was anything, but 50% duty cycle. The frequency was 8kHz, as per my settings, but duty cycle was not 50%.

Is there any known issue with this?


Also, could you explain, with the HFP demo, how can I activate the I2S port, for example to listen to the ringtone on the speaker? So far, I could only activate audio on an ongoing call, but not during phone standby, as to listen to the ringtone on the handsfree device's speaker.

Thanks!!

  • Nico,

    Did you modify the STM32 side as well? Are you sure that the signal is coming from the CC256x side and not the STM32 side? Is the CC2564 EM board configured as I2S Master (level shifters)?

    ~Miguel
  • Hi Miguel!

    At this time, the CC2564 I2S port is not connected to anything. On the other side of the I2S link, I have a Cirrus Logic/Wolfson WM8962 CODEC. But right now I disconnected it to avoid any issue or CODEC misconfiguration that may affect the I2S signaling.

    I set the CC2564 I2S as master. Please read my setup function below, based on BTVS.c::VS_PCM_Codec_Config_Slave_I2S():


    int BTPSAPI VS_PCM_Codec_Config_Master_I2S(unsigned int BluetoothStackID, Word_t PCMFreq, DWord_t FSyncFreq)
    {
        int    ret_val;
        Byte_t CommandBuffer[CODEC_CONFIG_LENGTH], CommandLength, OGF, Length, Status;
        Word_t OCF;

        /* Verify that the parameters that were passed in appear valid.      */
        if(BluetoothStackID)
        {
            BTPS_MemInitialize(CommandBuffer, 0, sizeof(CommandBuffer));

            /* PCM clock rate (kHz) and direction (0 = output, 1 = input)     */
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[0], PCMFreq);
            CommandBuffer[2] = 0x00;    /* 0x01=Slave; 0x00=Master. */

            /* Frame-sync freq (Hz) and duty cycle. For duty cycle, 0 will    */
            /* generate 50% duty cycle, >= 1 uses number of PCM clock cycles. */
            ASSIGN_HOST_DWORD_TO_LITTLE_ENDIAN_UNALIGNED_DWORD(&CommandBuffer[3], FSyncFreq);

            /* 0x0000 = Set to 50% */
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[7], 0x0000);
            
            CommandBuffer[9]  = 0x00;   /* FSYNC edge: 0 = sample at rising edge, 1 = falling edge */
            CommandBuffer[10] = 0x01;   /* FSYNC polarity: 0 = active high, 1 = active low */
            CommandBuffer[11] = 0x00;   /* Reserved */

            /* CH1: data out size, offset in clocks = 1, and edge (0 = rise, 1 = fall) */
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[12], 16);
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[14], 1);
            CommandBuffer[16] = 0x01; /* CH1 DOUT: 0 = driven at rising edge, 1 = falling edge. */

            /* CH1: data in size, offset, and edge (0 = rise, 1 = fall)  */
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[17], 16);
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[19], 1);
            /* Channel 1 input edge: 0 = sampled at rising edge, 1 = falling edge  */
            CommandBuffer[21] = 0x00;

            /* Fsynch Multiplier = 0 -> No multiplier (Not effective in Slave mode)  */
            CommandBuffer[22] = 0x20;

            /* CH2: data out size, offset in clocks = 1, and edge (0 = rise, 1 = fall) */
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[23], 16);
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[25], 17);
            /* Channel 2 output edge: 0 = driven at rising edge, 1 = falling edge  */
            CommandBuffer[27] = 0x01;

            /* CH2: data in size, offset, and edge (0 = rise, 1 = fall)  */
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[28], 16);
            ASSIGN_HOST_WORD_TO_LITTLE_ENDIAN_UNALIGNED_WORD(&CommandBuffer[30], 17);
            /* Channel 2 input edge: 0 = sampled at rising edge, 1 = falling edge  */
            CommandBuffer[32] = 0x00;

            Length        = sizeof(CommandBuffer);
            CommandLength = sizeof(CommandBuffer);
            OGF           = VS_COMMAND_OGF(VS_WRITE_CODEC_CONFIG_COMMAND_OPCODE);
            OCF           = VS_COMMAND_OCF(VS_WRITE_CODEC_CONFIG_COMMAND_OPCODE);

            ret_val = HCI_Send_Raw_Command(BluetoothStackID, OGF, OCF, CommandLength, CommandBuffer,
                                                  &Status, &Length, CommandBuffer, TRUE);
            ret_val = MapSendRawResults(ret_val, Status, Length, CommandBuffer);
        }
        else
        {
            ret_val = BTPS_ERROR_INVALID_PARAMETER;
        }

        return(ret_val);
    }

    For my application, FSyncFreq = 8000Hz and PCMFreq = 384kHz. That accounts for 24 PCM periods per channel, which complies with the CC256x datasheet spec that limits each channel to 40 PCM periods (CC256x datasheet, doc# SWRS141D, page 18, header 3.5.3.2).

    Maybe the Fsynch Multiplier parameter on CommandBuffer[22] has anything to do with this? So far, I couldn't find an explanation of what this parameter means.

    Thanks!

  • Hi,

    The description is located in the following link: processors.wiki.ti.com/.../CC256x_VS_HCI_Commands

    "When setting the values 0x00 or 0xFF the command will act the same as previously, but when entering a value of 32/64 the Clock Rate will be: Clock Rate = Fsynch Multiplier X Frame Synch frequnecy , for example 44,100Hz X 32 = 1441,200Hz "

    ~Miguel
  • Hi Miguel!

    Yes, I already read that description. However, I don't understand what it means by "will act the same as previously". As previously to what? What was that previous behaviour?

    So, if I understand correctly, this variable controls the bit clock frequency, to be 32 or 64 times the FSYNC frequency... If this is correct, then how is the conflict between this variable and the PCM frequency parameter solved?

    Suppose I have:
    - FSYNC Frequency = 8kHz
    - PCM Frequency = 384kHz (8kHz * 48, because I need to have 24 PCM periods per half FSYNC period).
    - FSYNC Multiplier = 32

    So, on one side I'm specifying PCM Frq to be 384kHz, and on the other side 8kHz * 32 = 256kHz... Who wins this battle?

    Still, this doesn't answer my original question on why I don't get 50% FSYNC duty cycle when I setup the audio port to I2S protocol.

    Thanks!
  • Nico,

    If you define a value of "32 or 64" in the "Fsynch Multiplier" field, then the "Frame-sync frequency" field is ignored.

    With respect to the FSYNC duty cycle, I am not sure why you are getting 50% duty cycle. I have to reproduce it with your exact configuration to double check.

    ~Miguel

  • Nico,

    There is an actual bug in the command when using the "Fsynch Multiplier" field. If the "Frame Sync duty cycle" field is set to "0" (for 50% duty cycle) and the "Fsynch Multiplier" is used (set to 32 or 64), the "Fram Sync duty cycle" might not be calculated correctly and it will depend on the "PCM Clock rate". Therefore, I recommend the following:

    1) Do not use the "Fsync Multiplier" (set to 0) and use the "PCM Clock rate" instead.

    2) If you use the "Fsync Multiplier" (set to 32/64), then set the "Frame Sync duty cycle" with the actual number of "PCM clock cycles" instead.

    ~Miguel
  • Hi Miguel!

    Thanks a lot for your reply and for the clarification.

    Can you please make sure this bug is documented in the CC2564 Wiki? I haven't seen this info. I've spent many hours trying to figure what was going on with my setup, and I could have saved them if I knew about this issue.


    Thanks!