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.

CC2564MODA: A2DP decoded data are all zero

Part Number: CC2564MODA
Other Parts Discussed in Thread: , CC256XM4BTBLESW, CC2564

Hi,

I have a customer using CC2564MODA with TM4C129x.
He is evaluating A2DP (not A3DP) demo.

Environments:
CC2564MODAEM
DK-TM4C129X
CC256XM4BTBLESW 1.2R2

CC2564 is successfully connected with smartphone and some data are received from CC2564 to Tiva.
But after SBC_Decode_data() is returned (AudioDecoder.c line#175), all data inside DecodedData.LeftChannelDataPtr and RightPtr are zero.
Customer confirmed the return value of SBC_Decode_data() is SBC_PROCESSING_COMPLETE.
What is possible cause of the issue?

Here are some additional information.
teraterm.txt
SBC buffer contents before SBC_Decode_data() is called.

<DataPtr>
9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,9c,bd,35,7d,00,00,00,00,00,00,00,00,00,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,77,76,db,6e,ed,b6,db,bb,b6,db,77,6d,b6,dd,dd,b6,db,bb,6d,b6,ee,ed,b6,dd,db,6d,b7,77,6d,b6,ee,db,6d,bb,bb,6d,b7,76,db,6d,dd,db,6d,bb,b6,db,6e,ee,db,6d,dd,b6,db,


Frame Length   : 119
Bit Pool       : 53
Bit Rate       : 327993
Buffer Length  : 128
Frames/GAVD    : 16

SBC_DECODE_DATA.png
CCS screen shot with parameters just after SBC_Decode_data() is returned.
(this screen shot was taken with different music, so SBC data are different than teraterm.txt)


Thanks and regards,
Koichiro Tashiro

  • Hi,

    Additional information from customer:

    The original post is the case when iPhone7 is used as source.
    Customer also tried android phone and Windows10 PC as sources.
    In case android or Windows10 is used, output data from SBC_Decode_data() are all zero at the beginning, but some data are received in the middle and afterward.
    In case iPhone7 is used, decoded data are all zero forever.

    It seems iPhone supports SBC and AAC, android supports SBC and aptX.
    And iPhone first tries to use AAC, then if it fails, it switches to SBC.
    Is such mechanism implemented in the A2DP demo?

    Thanks and regards,
    Koichiro Tashiro

  • Koichiro-san,

    Koichiro Tashiro said:
    It seems iPhone supports SBC and AAC, android supports SBC and aptX.
    And iPhone first tries to use AAC, then if it fails, it switches to SBC.

    According to A2DP profile specifications, both source and sink are supposed to use SBC (mandatory codec) by default. If additional codecs (optional) are supported, the source and sink may negotiate to use one of the additional codecs that is supported on both sides. So I don't think it is the problem here.

    Koichiro Tashiro said:
    Is such mechanism implemented in the A2DP demo?

    The CC256XM4BTBLESW release used here has not been maintained in over last 5 years. So, it is likely that the issue you are seeing is due to some interoperability issue in this old stack release.

    You can try to narrow down the root cause by examining the air sniffer logs (e.g. frontline or ellisys sniffer) to determine whether the encoded data transferred over the air is valid. If yes, then the problem might be decoding on the host side. 

    Best regards,

    Vihang

  • Hi Vihang,

    Do you have any debug suggestions without using sniffer?
    I am afraid customer does not have such environment.

    Thanks and regards,
    Koichiro Tashiro

  • Koichiro-san,

    Koichiro Tashiro said:
    Do you have any debug suggestions without using sniffer?

    Not that I can think of.

    Is it the unmodified A2DPDemo or it was ported from another release/platform?

    Best regards,

    Vihang

  • Hi Vihang,

    Customer modified below parts in MainThread() in Main.c.
    (as customer does not connect an external codec for now)
    Blue lines are commented out.

    /* Attempt to initialize the codec. If this function fails, then  */
          /* either the codec is not present or there is an error condition.*/
          if(SoundInit())
          {
             /* We need to execute Add a function to process the command    */
             /* line to the BTPS Scheduler.                                 */
             if(BTPS_AddFunctionToScheduler(ProcessCharacters, NULL, 200))
             {
                /* Add the idle function (which determines if LPM3 may be   */
                /* entered) to the scheduler.                               */
                if(BTPS_AddFunctionToScheduler(IdleFunction, NULL, 0))
                {
                   /* Loop forever and execute the scheduler.               */
                   while(1)
                      BTPS_ExecuteScheduler();
                }
             }
          }
          else
          {
             Display(("ERROR: Could not initialize AIC3262 codec.\r\n"));
             Display(("Please double the codec power and connectivity (may need reset).\r\n"));
          }



    Other parts of code are unmodified.

    Thanks and regards,
    Koichiro Tashiro

  • Vihang,

    Below lines in above code are removed.

    Line#3:
          if(SoundInit())

    Line#19 to #23:
          else
          {
             Display(("ERROR: Could not initialize AIC3262 codec.\r\n"));
             Display(("Please double the codec power and connectivity (may need reset).\r\n"));
          }

    Thanks and regards,
    Koichiro Tashiro

  • Vihang,

    Could you try the A2DP demo on your side and reproduce the issue?
    I think it is much faster for you to debug the issue.

    Thanks and regards,
    Koichiro Tashiro

  • Koichiro-san,

    I am not able to commit to much hands on debug at this point. I will check if someone else from my team can bring up this demo for further debug. BTW, does the customer only see this behavior with the TI-RTOS version of the A2DP demo or with the No-OS version of the demo as well?

    Best regards,

    Vihang

  • Hi Vihang,

    Please find someone to debug this issue.

    As for the demo, I thought there is only No-OS version for Tiva A2DP demo, so customer uses this one.

    Thanks and regards,
    Koichiro Tashiro

  • Hi Koichiro,

    I'm still trying to bring up the example to example your problem. Have been working with Vihang on this. Please give me more time.

    Jesu

  • Hi Koichiro,

    Finally was able to bring up the example. Moving on to the issue, if I'm understanding everything correctly seems to me like what the customer is seeing is expected. Since I am not using a codec also, I too had to comment out the lines you mentioned as well as the lines below in AudioDecoder.c

    //            /* Go ahead and configure the output device.                */
    //            if(!_ConfigureOutputDevice(&PlaybackContext))
    //            {
    //               /* Now, we are ready to start decoding.  First, let's    */
    //               /* initialize the Decoder.                               */
    //               if((PlaybackContext.DecoderHandle = SBC_Initialize_Decoder()) != NULL)
    //               {
    //                  Initialized = TRUE;
    //
    //                  if(BTPS_AddFunctionToScheduler(PlaybackThread, NULL, 1))
    //                     Result = 0;
    //                  else
    //                  {
    //                     Initialized = FALSE;
    //
    //                     Display(("Unable to start Playback task.\r\n"));
    //                  }
    //               }
    //               else
    //                  Display(("Failed to initialize decoder.\r\n"));
    //            }
    //            else
    //               Display(("Failed to configure output device.\r\n"));

    Without commenting the lines above I would end up in a fault ISR because it would try to use a peripheral SountInit() which was commented out. Given that, the decode data will always be 0 because the PlaybackThread is never added to the scheduler due to the comments necessary. The PlaybackThread is important because it updates the left and right channels.

    Jesu

  • Hi Jesu,

    Thanks for your debug.

    Based on your feedback, customer modified the codes so that the differences are minimized compared to the original codes.
    Now everything is back to the original demo codes and only below two files are modified as attached.
    As you can see, some external audio codec related functions are modified and they always return “true”.

    //*****************************************************************************
    //
    // dac.c - Functions supporting the TLV320AIC3262 audio codec.
    //
    // Copyright (c) 2012 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_i2c.h"
    #include "inc/hw_ssi.h"
    #include "driverlib/ssi.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/systick.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/udma.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/timer.h"
    #include "drivers/dac.h"
    
    #include "BTPSKRNL.h"
    
    //*****************************************************************************
    //
    //! \addtogroup dac_api
    //! @{
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // The system clock frequency in Hz. it must be supplied by the application.
    //
    //*****************************************************************************
    extern uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // The I2C and reset pins that are used by this application.
    //
    //*****************************************************************************
    #define DAC_I2C_PERIPH                  (SYSCTL_PERIPH_I2C7)
    #define DAC_I2C_GPIO_PERIPH             (SYSCTL_PERIPH_GPIOA)
    #define DAC_I2CSCL_GPIO                 (GPIO_PA4_I2C7SCL)
    #define DAC_I2CSDA_GPIO                 (GPIO_PA5_I2C7SDA)
    #define DAC_I2C_BASE                    (GPIO_PORTA_BASE)
    #define DAC_I2CSDA_PIN                  (GPIO_PIN_5)
    #define DAC_I2CSCL_PIN                  (GPIO_PIN_4)
    #define DAC_I2C_MASTER_BASE             (I2C7_BASE)
    
    #define DAC_RESET_GPIO_PERIPH           (SYSCTL_PERIPH_GPIOJ)
    #define DAC_RESET_GPIO_PORT             (GPIO_PORTJ_BASE)
    #define DAC_RESET_PIN                   (GPIO_PIN_7)
    
    //*****************************************************************************
    //
    // The amount of time (in milliseconds) allowed to elapse before an I2C
    // transaction is considered timed out.
    //
    //*****************************************************************************
    #define I2C_TRANSMISSION_TIMEOUT        (2000)
    
    //*****************************************************************************
    //
    //! Writes a register in the TLV320AIC3262 codec.
    //!
    //! \param ucRegister is the codec's register address to be written.
    //! \param ucData is the data to be written to the codec's register address.
    //!
    //! This function will write to the address passed in ucRegister with the
    //! value passed in to ulData. The data in ucData is 8 bits and the value in
    //! ucRegister is interpreted as 7 bits (LSBs).
    //!
    //! \return True on success or false on error.
    //
    //*****************************************************************************
    bool
    DACWriteRegister(unsigned char ucRegister, unsigned char ucData)
    {
        unsigned long TickCount;
    
        //
        // Add a delay before writing. This delay is around 50us.
        //
        SysCtlDelay((50 * (g_ui32SysClock / 1000000) + 1 ) / 3);
    
        //
        // Set the slave address and "WRITE".
        //
        ROM_I2CMasterSlaveAddrSet(DAC_I2C_MASTER_BASE, TI_TLV320AIC3262_ADDR,
                              false);
    
        //
        // Place the register address to be sent the codec.
        //
        ROM_I2CMasterDataPut(DAC_I2C_MASTER_BASE, ucRegister);
    
        //
        // Send the register address to the codec.
        //
        ROM_I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    
        //
        // Check for errors.
        //
        if(ROM_I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE)
        {
            ROM_I2CMasterIntClear(DAC_I2C_MASTER_BASE);
            return(false);
        }
    
        //
        // Wait for transmission completion.
        //
        TickCount = BTPS_GetTickCount();
        while(ROM_I2CMasterBusy(DAC_I2C_MASTER_BASE))
        {
            if((BTPS_GetTickCount() - TickCount) > I2C_TRANSMISSION_TIMEOUT)
                return(false);
        }
    
        //
        // Place the register data to be sent the codec.
        //
        ROM_I2CMasterDataPut(DAC_I2C_MASTER_BASE, ucData);
    
        //
        // Indicate the end of the transfer.
        //
        ROM_I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    
        //
        // Check for errors.
        //
        if(ROM_I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE)
        {
            I2CMasterIntClear(DAC_I2C_MASTER_BASE);
            return(false);
        }
    
        //
        // Wait for transmission completion.
        //
        TickCount = BTPS_GetTickCount();
        while(ROM_I2CMasterBusy(DAC_I2C_MASTER_BASE))
        {
            if((BTPS_GetTickCount() - TickCount) > I2C_TRANSMISSION_TIMEOUT)
                return(false);
        }
    
        return(true);
    }
    
    //*****************************************************************************
    //
    //! Configures the TLV320AIC3262 codec.
    //!
    //! \param uiFrequency is the sampling frequency of the audio to be played.
    //!  e.g FSS or WCLK
    //!
    //! This function configures the TLV320AIC3262 Codec according to the sampling
    //! frequency and enables audio output at the headset. DACInit() must be called
    //! prior to this function.
    //!
    //! \return Returns \b true on success or \b false on failure.
    //
    //*****************************************************************************
    bool
    DACConfigure(unsigned int uiFrequency)
    {
        bool bRetcode = true;
    /*
        //
        // Page Select Register
        // Bx, Px, R0
        // b0-7 = 0x00, Switch to Page 0
        //
        bRetcode = bRetcode && DACWriteRegister(TI_PAGE_SELECT_R, 0x00);
    
        //
        // Book Selection Register
        // Bx, P0, R127
        // b0-7 = 0x00, Switch to Book 0
        //
        bRetcode = bRetcode && DACWriteRegister(TI_BOOK_SELECT_R, 0x00);
    
        //
        // Software Reset Register - Apply a Software Reset to the Codec.
        // B0, P0, R1
        // b0 = 1, SW Reset - Internal Registers
        //
        bRetcode = bRetcode && DACWriteRegister(TI_SOFTWARE_RESET_R, 0x01);
    
        //*************************************************************************
        //
        // Clock Configuration
        //
        //*************************************************************************
    
        //
        // Clock Control Register 1, Clock Input Multiplexers
        // B0, P0, R4
        // b4-7 = 0011, Select PLL_CLK for DAC_CLKIN clock input
        // b3-0 = 0011, Select PLL_CLK for ADC_CLKIN clock input
        //
        bRetcode = bRetcode && DACWriteRegister(0x04, 0x33);
    
        //
        // Clock Control Register 2, PLL Input Multiplexer
        // B0, P0, R5
        // b6 = 1, Select high PLL clock range - TBC
        // b5-2 = 0000, Select MCLK1 for PLL_CLKIN clock input
        //
        bRetcode = bRetcode && DACWriteRegister(0x05, 0x40);
    
        //
        // Clock Control Register 4, PLL J Value
        // B0, P0, R7
        // b5-0 = 000100, Set PLL J value to 4
        // PLL_CLK = (PLL_CLKIN x R x J.D)/P
        //
        bRetcode = bRetcode && DACWriteRegister(0x07, 0x04);
    
        //
        // Configure the codec to sample the audio (set SSI clk) at the frequency
        // specified by uiFrequency. Supported sampling frequencies are:
        // 44.1KHz and 48KHz
        //
    
        //
        // 44.1KHz
        //
        if ( uiFrequency == 44100 )
        {
            //
            // Clock Control Register 5, PLL D Value (MSB)
            // B0, P0, R8
            // b5-0 = 0x09, Set PLL D value to 2336
            // Clock Control Register 6, PLL D Value (LSB)
            // B0, P0, R9
            // b7-0 = 0x20, Set PLL D value to 2336
            // PLL_CLK = (PLL_CLKIN x R x J.D)/P, for PRB_R1-R3:
            // 84.672MHz = (20MHz  x 1 x 4.2336)/1 --> For Fs = 44.1KHz
            //
            bRetcode = bRetcode && DACWriteRegister(0x08, 0x09);
            bRetcode = bRetcode && DACWriteRegister(0x09, 0x20);
        }
        //
        // 48KHz
        //
        else if ( uiFrequency == 48000 )
        {
            //
            // Clock Control Register 5, PLL D Value (MSB)
            // B0, P0, R8
            // b5-0 = 0x17, Set PLL D value to 6080
            // Clock Control Register 6, PLL D Value (LSB)
            // B0, P0, R9
            // b7-0 = 0xC0, Set PLL D value to 6080
            // PLL_CLK = (PLL_CLKIN x R x J.D)/P, for PRB_R1-R3:
            // 92.160MHz = (20MHz  x 1 x 4.6080)/1 --> For Fs = 48KHz
            //
            bRetcode = bRetcode && DACWriteRegister(0x08, 0x17);
            bRetcode = bRetcode && DACWriteRegister(0x09, 0xC0);
        }
        //
        // Error - Unsupported sampling rate.
        //
        else
        {
            return(false);
        }
    
        //
        // Clock Control Register 3, PLL P and R Values
        // B0, P0, R6
        // b7 = 1, Power up PLL
        // b6-4 = 001, Set PLL P value to 1
        // b3-0 = 0001, Set PLL R value to 1
        // PLL_CLK = (PLL_CLKIN x R x J.D)/P
        //
        bRetcode = bRetcode && DACWriteRegister(0x06, 0x91);
    
        //
        // Clock Control Register 8, NDAC Divider Values
        // B0, P0, R11
        // b7 = 1, Power up NDAC
        // b5-0 = 000 0011, Set NDAC value to 3
        // DAC_Fs = CODEC_CLK_IN / (NDAC.MDAC.AOSR)
        // 44.1KHz = 84.672MHz / (3.5.128)
        // 48KHz = 92.160 MHz / (3.5.128)
        //
        bRetcode = bRetcode && DACWriteRegister(0x0B, 0x83);
    
        //
        // Clock Control Register 9, MDAC Divider Values
        // B0, P0, R12
        // b7 = 1, Power up MDAC
        // b5-0 = 000 0101, Set NDAC value to 5
        // DAC_Fs = CODEC_CLK_IN / (NDAC.MDAC.DAC_OSR)
        // 44.1KHz = 84.672MHz / (3.5.128)
        // 48KHz = 92.160 MHz / (3.5.128)
        //
        bRetcode = bRetcode && DACWriteRegister(0x0C, 0x85);
    
        //
        // DAC OSR Control Register 1, MSB Value
        // B0, P0, R13
        // b1-0 = 00, Set DAC_OSR value to 128
        // DAC OSR Control Register 2, LSB Value
        // B0, P0, R14
        // b7-0 = 0x80, Set DAC_OSR value to 128
        // DAC_Fs = CODEC_CLK_IN / (NDAC.MDAC.DAC_OSR)
        // 44.1KHz = 84.672MHz / (3.5.128)
        // 48KHz = 92.160 MHz / (3.5.128)
        //
        bRetcode = bRetcode && DACWriteRegister(0x0D, 0x00);
        bRetcode = bRetcode && DACWriteRegister(0x0E, 0x80);
    
        //*************************************************************************
        //
        // Initialize the Codec
        //
        //*************************************************************************
    
        //
        // Page Select Register
        // Bx, Px, R0
        // b0-7 = 0x01, Switch to Page 1
        //
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x01);
    
        //
        // Power Configuration Register
        // B0, P1, R1
        // b3 = 0, Disable weak connection of AVDD with DVDD
        // b2 = 0, All the external analog supplies are available
        //
        bRetcode = bRetcode && DACWriteRegister(0x01, 0x00);
    
        //
        // Reference Powerup Delay Register
        // B0, P1, R122
        // b3 = 0, At the fine charge time
        // b1-0 = 01, VREF Fast Charge, Fine Charge Time = 30ms
        //
        bRetcode = bRetcode && DACWriteRegister(0x7A, 0x01);
    
        //*************************************************************************
        //
        // Audio Serial Interface #1 Configuration
        //
        //*************************************************************************
    
        //
        // Page Select Register
        // Bx, Px, R0
        // b0-7 = 0x04, Switch to Page 4
        //
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x04);
    
        //
        // Audio Serial Interface 1, Audio Bus Format Control Register
        // B0, P4, R1
        // b7-5 = 000, Set I2S Format (011, Set LJF Format)
        // b4-3 = 00, 16 bits data length
        // b0 = 0, DOUT1 will not be high impedance while ASI1 is active
        // See SLAU309 - Figure 2-65 and/or Figure 2-62
        //
        bRetcode = bRetcode && DACWriteRegister(0x01, 0x00);
    
        //
        // Audio Serial Interface 1, WCLK and BCLK Control Register
        // B0, P4, R10
        // b7-5 = 001, WCLK1 pin is output from Audio Serial Interface 1
        // b4-2 = 001, BCLK1 pin is output from Audio Serial Interface 1
        // b1 = 1, Bit Clock Inverted (0, Default Bit Clock polarity)
        // b0 = 0, Primary BCLK and Primary WCLK buffers are powered down when the
        //         codec is powered down or Audio Serial Interface 1 is inactive.
        // See SLAU309 - Figure 2-65 and/or Figure 2-62
        //
        bRetcode = bRetcode && DACWriteRegister(0x0A, 0x26);
    
        //
        // Audio Serial Interface 1, Bit Clock N Divider Input Control Register
        // B0, P4, R11
        // b1-0 = 00, ASI1_BDIV_CLKIN = DAC_CLK
        // DAC_CLK = CODEC_CLK_IN / NDAC
        // 28.224 MHz = 84.672MHz / 3
        // 30.72 MHz = 92.160 MHz / 3
        //
        bRetcode = bRetcode && DACWriteRegister(0x0B, 0x00);
    
        //
        // Audio Serial Interface 1, Bit Clock N Divider Register
        // B0, P4, R12
        // b7 = 1, Power Up BCLK N Divider
        // b6-0 = 0x0A, BCLK N Divider = 20
        //
        bRetcode = bRetcode && DACWriteRegister(0x0C, 0x94); // BCLK_DIV ON and Div = 20
    
        //
        // Audio Serial Interface 1, BCLK and WCLK Output Register
        // B0, P4, R14
        // b6-4 = 000, BCLK_OUT = BCLK_DIV_OUT
        // b2-0 = 000, WCLK_OUT = DAC_Fs
        // BCLK_DIV_OUT = ASI1_BDIV_CLKIN / BCLK N Divider
        // 2.8224 MHz = 28.224 MHz / 10 -> 44.1KHz
        // 3.072 = 30.72 MHz / 10 -> 48KHz
        // DAC_Fs = 44.1 KHz
        // DAC_Fs = 48 KHz
        //
        bRetcode = bRetcode && DACWriteRegister(0x0E, 0x00);
    
        //*************************************************************************
        //
        // Signal Processing
        //
        //*************************************************************************
    
        // Select page 0
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x00);
        // Set DAC PRB mode to PRB_P1
        bRetcode = bRetcode && DACWriteRegister(0x3C, 0x01);
    
        //*************************************************************************
        //
        // DAC Configuration
        //
        //*************************************************************************
    
        // Select page 1
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x01);
        // Set DAC PTM mode to PTM_P3
        bRetcode = bRetcode && DACWriteRegister(0x03, 0x00);
        bRetcode = bRetcode && DACWriteRegister(0x04, 0x00);
        // Route LDAC to HPL and route RDAC to HPR, don't power up HP driver yet
        bRetcode = bRetcode && DACWriteRegister(0x1B, 0x30);
        // Select page 0
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x00);
        // Power up LDAC and RDAC
        bRetcode = bRetcode && DACWriteRegister(0x3F, 0xC0);
        // Select page 0
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x00);
        // Power up LDAC and RDAC
        bRetcode = bRetcode && DACWriteRegister(0x3F, 0xC0);
        // Select page 1
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x01);
        // Set Headphone in Ground-centered Mode, HPL is still muted
        bRetcode = bRetcode && DACWriteRegister(0x1F, 0xB9);
        // HPR has the same gain as HPL, HPR is still muted
        bRetcode = bRetcode && DACWriteRegister(0x20, 0xB9);
        // Charge pump runs of Oscillator clock with divider = 4
        bRetcode = bRetcode && DACWriteRegister(0x21, 0x28);
        // Headphone output offset correction (default setting)
        bRetcode = bRetcode && DACWriteRegister(0x22, 0x3E);
        // Charge pump to power up on the headphone power up in Ground-centered Mode
        bRetcode = bRetcode && DACWriteRegister(0x23, 0x30);
        // Unmute HPL driver, set gain = 0 dB
        bRetcode = bRetcode && DACWriteRegister(0x1F, 0x80);
        // Unmute HPR driver, set gain = 0 dB
        bRetcode = bRetcode && DACWriteRegister(0x20, 0x80);
        // Select page 0
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x00);
        // Unmute LDAC and RDAC digital volume
        bRetcode = bRetcode && DACWriteRegister(0x40, 0x40);
        // Select page 1
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x01);
        // Reduce HP power to 25 percent
        bRetcode = bRetcode && DACWriteRegister(0x09, 0x70);
        // Power up HPL/HPR
        bRetcode = bRetcode && DACWriteRegister(0x1B, 0x33);
    
        // Select page 1
        bRetcode = bRetcode && DACWriteRegister(0x00, 0x01);
        // Increase HP power to 100 percent
        bRetcode = bRetcode && DACWriteRegister(0x09, 0x10);
    */
        return(bRetcode);
    }
    
    //*****************************************************************************
    //
    //! Initializes the TLV320AIC3262 Codec.
    //!
    //! This function initializes the I2C interface and the TLV320AIC3262 Codec. It
    //! must be called prior to any other API in the DAC module.
    //!
    //! \return Returns \b true on success or \b false on failure.
    //
    //*****************************************************************************
    bool
    DACInit(void)
    {
        bool bRetcode = true;
    
        //
        // Enable the GPIO port containing the I2C pins and set the SDA pin as a
        // GPIO input for now and engage a weak pull-down.  If the daughter board
        // is present, the pull-up on the board should easily overwhelm
        // the pull-down and we should read the line state as high.
        //
        //SysCtlPeripheralReset(DAC_I2C_PERIPH);
        ROM_SysCtlPeripheralEnable(DAC_I2C_PERIPH);
    
        //
        // Enable the I2C peripheral.
        //
        //SysCtlPeripheralReset(DAC_I2C_GPIO_PERIPH);
        ROM_SysCtlPeripheralEnable(DAC_I2C_GPIO_PERIPH);
    
        //
        // Configure the pin mux.
        //
        ROM_GPIOPinConfigure(DAC_I2CSCL_GPIO);
        ROM_GPIOPinConfigure(DAC_I2CSDA_GPIO);
    
        //
        // Configure the I2C SCL and SDA pins for I2C operation.
        //
        ROM_GPIOPinTypeI2CSCL(DAC_I2C_BASE, DAC_I2CSCL_PIN);
        ROM_GPIOPinTypeI2C(DAC_I2C_BASE, DAC_I2CSDA_PIN);
    
        //
        // Initialize the I2C master.
        //
        ROM_I2CMasterInitExpClk(DAC_I2C_MASTER_BASE, g_ui32SysClock, true);
    
        //
        // Enable the I2C peripheral.
        //
        ROM_SysCtlPeripheralEnable(DAC_RESET_GPIO_PERIPH);
    
        //
        // Configure the PD0 as a GPIO output.
        //
        ROM_GPIOPinTypeGPIOOutput(DAC_RESET_GPIO_PORT, DAC_RESET_PIN);
    
        //
        // Reset the Codec.
        //
        ROM_GPIOPinWrite(DAC_RESET_GPIO_PORT , DAC_RESET_PIN, 0);
        ROM_GPIOPinWrite(DAC_RESET_GPIO_PORT , DAC_RESET_PIN, DAC_RESET_PIN);
    
        //
        // Delay a while to ensure that the codec is ready. If we read too quickly,
        // the result is unpredictable. This delay is around 10mS.
        //
        SysCtlDelay((10000 * (g_ui32SysClock / 1000000) + 1 ) / 3);
    
        //
        // Select Codec's Page 0.  Check the return code on this call since
        // we use it to indicate whether or not the Codec is present.  If the
        // register write fails, we assume the Codec EVM is not present and
        // return false.
        //
        bRetcode = bRetcode && DACWriteRegister(TI_PAGE_SELECT_R, 0x00);
    
        return(bRetcode);
    }
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    

    //*****************************************************************************
    //
    // sound.c - Functions supporting playback of .wav audio files on LM4F232.
    //
    // Copyright (c) 2012 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    // This is part of revision 8049 of the Stellaris Firmware Development Package.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    //! \addtogroup sound_api
    //! @{
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "inc/hw_ssi.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/ssi.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/udma.h"
    #include "driverlib/timer.h"
    #include "utils/ustdlib.h"
    #include "dac.h"
    #include "sound_ssi.h"
    
    //*****************************************************************************
    //
    // The system clock frequency in Hz. it must be supplied by the application.
    //
    //*****************************************************************************
    extern uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // Configure the Timer5B as a 16-bit PWM with a duty cycle of 50%,
    // 20MHz output, to drive the Codecs's MCLK.
    //
    //*****************************************************************************
    void
    setupCCP()
    {
        unsigned long ulTimerMatchValue;
    
        //
        // Enable the Timer5 peripheral for use.
        //
        ROM_SysCtlPeripheralEnable(I2S_MASTERCLK_PERIPH);
    
        //
        // Timer CCP5 uses GPIO port S, pin 7.
        // GPIO port S needs to be enabled so these pins can be used.
        //
        ROM_SysCtlPeripheralEnable(I2S_MASTERCLK_GPIO);
    
        //
        // Configure the GPIO pin muxing for the Timer/CCP function.
        //
        ROM_GPIOPinConfigure(I2S_MASTERCLK_PORT);
    
        //
        // Configure the CCP settings for the CCP pin. This function also gives
        // control of these pins to the SSI hardware.
        //
        ROM_GPIOPinTypeTimer(I2S_MASTERCLK_BASE, I2S_MASTERCLK_PIN);
    
        //
        // Configure Timer5B as a 16-bit periodic timer.
        //
        ROM_TimerConfigure(I2S_MASTERCLK_TMR_B, (TIMER_CFG_SPLIT_PAIR |
                        TIMER_CFG_A_PERIODIC | TIMER_CFG_B_PWM));
    
        //
        // Set the Timer5B Frequency to a divisor to generate 20MHz.
        // Set the Timer5B duty cycle to 50%.
        // TM4C129x DS - Figure 16-7
        //
    
        ulTimerMatchValue = (g_ui32SysClock / 20000000) - 1;
    
        ROM_TimerLoadSet(I2S_MASTERCLK_TMR_B, I2S_MASTERCLK_TMR, ulTimerMatchValue);
        ROM_TimerMatchSet(I2S_MASTERCLK_TMR_B, I2S_MASTERCLK_TMR, 1);
    
        ROM_TimerEnable(I2S_MASTERCLK_TMR_B, I2S_MASTERCLK_TMR);
    }
    
    //*****************************************************************************
    //
    //! Initialize the sound driver.
    //!
    //! This function initializes the hardware components of the LM4F board,
    //! necessary for audio playback.
    //!
    //! \return None.
    //
    //*****************************************************************************
    bool
    SoundInit(void)
    {
    /*
        bool bRetcode;
    
        //
        // Enable and reset the necessary peripherals.
        //
        SysCtlPeripheralEnable(I2S_CHAN1_PERIPH);
        SysCtlPeripheralEnable(I2S_CHAN0_PERIPH);
        SysCtlPeripheralEnable(I2S_UDMA_PERIPH);
        SysCtlPeripheralEnable(I2S_CHAN0_GPIO_C);
        SysCtlPeripheralEnable(I2S_CHAN0_GPIO_D);
        SysCtlPeripheralEnable(I2S_CHAN1_GPIO);
    
        //
        // Set up the pin mux for  both SSI ports.
        //
        GPIOPinConfigure(I2S_CHAN1_CLK);
        GPIOPinConfigure(I2S_CHAN1_FSS);
        GPIOPinConfigure(I2S_CHAN1_RX);
        GPIOPinConfigure(I2S_CHAN1_TX);
        GPIOPinConfigure(I2S_CHAN0_RX);
        GPIOPinConfigure(I2S_CHAN0_TX);
        GPIOPinConfigure(I2S_CHAN0_CLK);
        GPIOPinConfigure(I2S_CHAN0_FSS);
    
        //
        // Select alternate functions for all of the SSI pins.
        //
        GPIOPinTypeSSI(I2S_CHAN0_PORT_C, GPIO_PIN_4 | GPIO_PIN_5);
        GPIOPinTypeSSI(I2S_CHAN0_PORT_D, GPIO_PIN_4 | GPIO_PIN_5);
        GPIOPinTypeSSI(I2S_CHAN1_PORT, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 |
                       GPIO_PIN_7);
    
        //
        // Initialize the DAC.
        //
        bRetcode = DACInit();
    
        //
        // Configure the SSI clock (CCP timer).
        //
        setupCCP();
    
        //
        // Clear out all pending interrupts.
        // SSI_TXFF: TX FIFO half full or less
        //
        SSIIntClear(I2S_CHAN0_BASE, SSI_TXFF);
        SSIIntClear(I2S_CHAN1_BASE, SSI_TXFF);
    
        //
        // Enables individual SSI interrupt source.
        // We'll use SSI1's empty interrupt status to drive the FIFO transfers
        // for both SSI1 and SSI3. This interrupt occurs whenever the TX FIFO
        // is half full or less.
        //
        SSIIntEnable(I2S_CHAN0_BASE, SSI_TXFF);
    
        //
        // Configure the synchronous serial interfaces, SSI1 and SSI3.
        // Clock each at the system clock rate of 80MHz.
        // Use the Motorola Mode 2 protocol.
        // As the DAC is the master, set the SSI as a slave device.
        // Set the bit rate to 1.4112 MHz -> 44.1KHz
        // Set the width of the data transfers to the maximum : 16bits.
        //
        SSIConfigSetExpClk(I2S_CHAN0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_2,
                           SSI_MODE_SLAVE, 44100 * 32, 16);
        SSIConfigSetExpClk(I2S_CHAN1_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_2,
                           SSI_MODE_SLAVE, 44100 * 32, 16);
    
        //
        // Enable the SSI controller.
        //
        SSIEnable(I2S_CHAN0_BASE);
        SSIEnable(I2S_CHAN1_BASE);
    
        return(bRetcode);
    */
        return(true);
    }
    
    //*****************************************************************************
    //
    // Configures the SSI peripheral to play audio in a given format.
    //
    // ulSampleRate is the sample rate of the audio to be played in
    // samples per second.
    // usBitsPerSample is the number of bits in each audio sample.
    // usChannels is the number of audio channels, 1 for mono, 2 for
    // stereo.
    //
    // This function configures the SSI peripheral in preparation for playing
    // or recording audio data in a particular format.
    //
    //*****************************************************************************
    bool
    SoundSetFormat(unsigned long ulSampleRate, unsigned short usBitsPerSample, unsigned short usChannels)
    {
        unsigned long ulBitClockRate;
        bool          bRetcode;
    /*
        //
        // Configure for Mono or Stereo, 16 bit formats.
        // Determine the MCLK rate & DAC PLL for each format.
        //
    
        if((usBitsPerSample == 16) && ((ulSampleRate == 44100) || (ulSampleRate == 48000)))
        {
            ulBitClockRate = ulSampleRate * 32;
    
            SSIDisable(I2S_CHAN0_BASE);
            SSIDisable(I2S_CHAN1_BASE);
    
            SSIConfigSetExpClk(I2S_CHAN0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_2,
                               SSI_MODE_SLAVE, ulBitClockRate, 16);
    
            SSIConfigSetExpClk(I2S_CHAN1_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_2,
                               SSI_MODE_SLAVE, ulBitClockRate, 16);
    
            SSIEnable(I2S_CHAN0_BASE);
    
            if(usChannels == 2)
                SSIEnable(I2S_CHAN1_BASE);
    
            bRetcode = DACConfigure(ulSampleRate);
        }
        else
            bRetcode = false;
    
        return(bRetcode);
    */
        return(true);
    }
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    

    Customer observed below behavior with updated code.
    a) iPhone XR with iOS 12.3.1: Audio data are decoded in buffer (data periodically updated). It seems an expected behavior.
    b) iPhone 7 with iOS 12.4.1: Audio data are decoded in buffer are all zero. It is strange as the data before decode show some values, but after SBC_Decode_Data() function, all data are turned zero.

    I tried the same codes with iPhone XR and iPhone 7 here at TIJ, but both seem work fine.
    Do you have any idea why the same smartphone (iPhone7) shows different results?
    Could you replace these two files on your side and try?

    Thanks and regards,
    Koichiro Tashiro

  • Hello Koichiro,

    I'm getting differently behavior like I described before. I am currently out of office for the next two day. As soon as I get back I will review and test the code you sent and get back to you.

    Jesu

  • Hi Koichiro,

    I tested the code with the modifications the customer made and I am seeing updates on the left and right channel buffer which tells me the data is being decoded. I tested it with both a Samsung s10e and an iPhone 8 running iOS 12.4.1. Please have the customer try again to make sure and have them send their console log.

    Jesu

  • Hi Jesu,

    The console log is attached.
    As you can see, the console output “AUD Encoded Audio Data Indication, Length 953” is periodically shown.
    But the decoded data are all zero for specific iPhone.

    OpenStack().
    HCI_VS_InitializeAfterHCIReset
    VS_Update_UART_Baud_Rate success.
    HCI_VS_InitializeAfterHCIReset Success
    Bluetooth Stack ID: 1
    Device Chipset: 4.1
    BD_ADDR: 0xa434f1801129
    
    ******************************************************************
    * Command Options: Source, Sink, Help                            *
    ******************************************************************
    
    Choose Mode> sink
    
    AUD_Initialize() Sink success.
    
    ******************************************************************
    * Command Options: Inquiry, DisplayInquiryList, Pair,            *
    *                  EndPairing, PINCodeResponse, PassKeyResponse, *
    *                  UserConfirmationResponse,                     *
    *                  SetDiscoverabilityMode, SetConnectabilityMode,*
    *                  SetPairabilityMode,                           *
    *                  ChangeSimplePairingParameters,                *
    *                  GetLocalAddress, GetLocalName, SetLocalName,  *
    *                  GetClassOfDevice, SetClassOfDevice,           *
    *                  GetRemoteName, ServiceDiscovery,              *
    *                  OpenRequestResponse, OpenRemoteStream,        *
    *                  CloseStream, OpenRemoteControl,               *
    *                  CloseRemoteControl, ChangeStreamState,        *
    *                  QueryStreamState, ChangeStreamFormat,         *
    *                  QueryStreamFormat, QuerySupportedFormats,     *
    *                  QueryStreamConfig, ChangeConnectionMode,      *
    *                  QueryConnectionMode, SendPassThroughCommand,  *
    *                  Help, Quit                                    *
    ******************************************************************
    
    Sink> setclassofdevice 0x040424
    Class of Device: 0x040424.
    
    Sink> 
    atIOCapabilityResponse: 0x40831d8a0d32
    Capabilities: Display Yes/No
    
    Sink> 
    atIOCapabilityRequest: 0x40831d8a0d32
    
    Auth success.
    
    Sink> 
    atUserConfirmationRequest: 0x40831d8a0d32
    
    Auto Accepting: 989455
    
    GAP_Authentication_Response success.
    
    Sink> 
    atSecureSimplePairingComplete: 0x40831d8a0d32
    
    Sink> 
    atLinkKeyCreation: 0x40831d8a0d32
    Link Key Stored.
    
    Sink> 
    Unknown/Unhandled Audio Event: 14.
    
    Sink> 
    AUD Stream Open Indication, Type: Sink.
    BD_ADDR:  0x40831d8a0d32.
    MediaMTU: 1004.
    Format:   44100, 2.
    
    Sink> 
    AUD Open Remote Control Indication: 0x40831d8a0d32.
    
    Sink> 
    HCI Mode Change Event, Status: 0x00, Connection Handle: 1, Mode: Sniff, Interval: 384
    
    Sink> 
    HCI Mode Change Event, Status: 0x00, Connection Handle: 1, Mode: Active, Interval: 0
    
    Sink> 
    AUD Stream State Change Indication, Type: Sink.
    BD_ADDR: 0x40831d8a0d32.
    State:   Started.
    
    Sink> Buffer High Limit: 4608
    Buffer Low Limit : 3072
    Frame Length     : 119
    Bit Pool         : 53
    Bit Rate         : 327993
    Buffer Length    : 128
    Frames/GAVD      : 16
    
    AUD Encoded Audio Data Indication, Length 953.
    
    AUD Encoded Audio Data Indication, Length 953.
    
    AUD Encoded Audio Data Indication, Length 953.
    
    AUD Encoded Audio Data Indication, Length 953.
    
    AUD Encoded Audio Data Indication, Length 953.
    
    AUD Encoded Audio Data Indication, Length 953.
    
    AUD Stream State Change Indication, Type: Sink.
    BD_ADDR: 0x40831d8a0d32.
    State:   Stopped.
    Shutting down audio decoder.
    
    Sink> 

    Thanks and regards,
    Koichiro Tashiro

  • Hi Koichiro,

    To make sure we on the same page I'm looking at left and right channels mentioned earlier in the post for decoded data. Could you check if the audio data is 0 before decoding? I don't have access to the code right now but it should be easy to find by tracing from whatever function updates left and right channels back to the received encoded data. Let me know if you cannot find it.

    Jesu

  • Hi Jesu,

    The issue was gone after customer updated iOS to iOS13.
    So I guess it was an issue on iOS side.
    I close this item for now.
    Thank you for your support on this.

    Thanks and regards,
    Koichiro Tashiro