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.

CCS/AWR1642BOOST: MSS stand alone for mmw demo

Part Number: AWR1642BOOST
Other Parts Discussed in Thread: AWR1642

Tool/software: Code Composer Studio

Hi there,

I notice in the SDK, TI documents that the control path can run on the MSS entirely on its own (without running the DSS in the "co-operative" mode) to configure the RADARSS (RF). The mmWave unit tests provide sample implementations. 

1) Is there a way to disable the DSS entirely and solely run on MSS to configure RADARSS in the mmwdemo version?

2) If not, where are the sample implementations that the SDK mentions? And are those BIN files that I can flash on to the AWR?

Thanks!

George

  • Hell George,

    Please refer the mmwavelink test application where it does all the BSS configuration from MSS only.

    And for Generating metaImage you need to provide NULL instead of DSS image path in the metaImage script (in ccs project properties).

     

    Regards,

    Jitendra

  • Hi Jitendra,

    Great, thank you for the references. In order to apply BPM to a random sequence of chirps (not BPM MIMO), would this be necessary or could I do so from the mmwave demo flash that I have on my board now? What do you recommend?

    George

  • Hello George,

    Yes, you can implement and flash the mmwave demo based on BPM random sequence.

    Regards,

    Jitendra

  • Hi Jitendra,

    Since you say that I can use the SDK OOB demo to implement random BPM sequence on Tx0 (for instance), what are the steps you would take to implement it? Would you use the bpmCfg API in the CLI script? If not, what would you use?

    Since I thought that was the way to communicate it with the AWR, I ONLY changed the following documents of the flash and kept everything else the same:

    mmw_config.h: 169-208 (** Added 2 more indexes for the MmwDemo_Bpm_Cfg_t structure)

    cli.c: 935-977 // 1305 – 1308 (** Referenced where to get the values I inputted through the CLI script/cmd line).

    mss_main.c: 1511-1586 (** Increased the number of chirps to the BPM structure. I checked this with you E2E before)

    dss_main.c: 1872-1878 (** Commented out the logic check in code that looks to see if both Tx antennas are enabled since I only want one enabled.)

    You mention in this other thread about calling rlSetBpmChirpConfig and rlSetBpmCommonConfig "outside of mmwave, directly from application". Does that play a role in your idea of an implementation? e2e.ti.com/.../3459844

    Thank you!

    George

  • Hello George,

    These code changes should be enough to make ti work.

    On the other hand, default mmw demo from mmwave sdk works for BPM ( 2 unique chirps): bpmCfg CLI cmd. I hope you know this already.

     

    Regards,

    Jitendra

  • Hi Jitendra,

    Thank you for checking the code.

    Agreed, I know what the bpmCfg CLI cmd is. My question was more pointed at how would I configure the BSS to transmit certain 0/180 phase shifted chirps by one transmitter in the CLI script? The only command remotely close to what I want to do is bpmCfg CLI cmd, but like you mentioned, it does 2 chirps ([0 0] and [0 1]) with 2 transmitters, where I need a random sequence and length with one transmitter.

    Is there another CLI API you would recommend creating?

    Thank you!

    George

  • Hello George,

    There is no other CLI API for BPM.

    I may have mentioned earlier in other reply. CLI API is defined by user, new CLI API can be written and at the API handler mmwavelink API can be implementation which configures the BSS for any specific feature (like BPM feature here).

    MSS application can directly call mmwavelink API to configure BSS independent of MMWAVE library. Like mentioned earlier, mmwavelink test application in mmwave SDK does this part of calling mmwavelink API directly to BSS.

     And could you please discuss further BPM related question on single thread, I could see multiple thread by you on the same topic. It will ease our task and save time.

    Thanks & Regards,

    Jitendra

  • Hi Jitendra,

    Yes, my apologies for the many threads. There have been many different questions that I thought might of been easier through individual threads. If you would like me to start an entirely new thread solely for all of my questions, I can do that - just let me know!

    You mention how there is not another CLI API for BPM beside bpmCfg. What about the CLI_MMWaveBPMCfgAdvanced() API? Is there a way to do all of this through the mmwavelink test binary flash file that you are talking about?

    Thanks

  • Hello George,

    As you are trying a custom application that is available in bit an pieces in mmwave SDK application or test app. You need to combine those into a single application to fulfill your requirement.

    You need to understand that there are mmWave and mmwavelink modules where mmwave module is nothing but a combination of multiple mmwavelink APIs to ease the application call load.

    Many of CLI APIs are implmeneted in cli_mmave.c use mmwave module APIs only.

    Like: CLI_MMWaveBPMCfgAdvanced uses MMWave_addBpmChirp which even normal mmw demo uses (mss_main.c  : MmwDemo_bpmConfig)

    As I recollect your main purpose is to configure the device and stream the ADC data over LVDS not doing any DSP processing.

    Then you can directly use mwmavelink APIs to configure the BSS (mmwavelink Test application for reference) and use mmw_lvds_stream.c for setting up the LVDS streaming part of it (take reference from mmw demo to implement the LVDS streaming at your application).

    Now to create metaimage with MSS and BSS (without DSS application) you can use these post-build step in CCS project properties (change the name or device type as required). This is based on mmwave SDK 3.4-

    ${COM_TI_MMWAVE_SDK_INSTALL_DIR}/packages/scripts/ImageCreator/out2rprc/out2rprc.exe xwr18xx_mmw_demo_mss.xer4f xwr18xx_mmw_demo_mss.tmp
    ${COM_TI_MMWAVE_SDK_INSTALL_DIR}/packages/scripts/ImageCreator/multicore_image_generator/MulticoreImageGen.exe LE 37 0x02000006 xwr18xx_mmw_demo.bin 0x35510000 xwr18xx_mmw_demo_mss.tmp 0xb5510000 ${COM_TI_MMWAVE_SDK_INSTALL_DIR}/firmware/radarss/xwr18xx_radarss_rprc.bin
    ${COM_TI_MMWAVE_SDK_INSTALL_DIR}/packages/scripts/ImageCreator/crc_multicore_image/crc_multicore_image.exe xwr18xx_mmw_demo.bin xwr18xx_mmw_demo.tmp
    ${COM_TI_MMWAVE_SDK_INSTALL_DIR}/packages/scripts/ImageCreator/append_bin_crc/gen_bincrc32.exe xwr18xx_mmw_demo.bin

    Refer this FAQ page to create the CCS project for your application.

    https://e2e.ti.com/support/sensors/f/1023/t/856028 

  • Hi Jitendra,

    Thank you for the info. I spent all day today trying to figure out how to do this, but I was not able to get it. Could you help me with the steps (on how you see yourself accomplishing something like this) before doing the build steps that you recommended at the bottom of your last post?

    I have CCS downloaded and I know where to find the MSS and DSS in the automotive toolbox, but I do not think I want this. I think I want to start a new project. But when I start a new project, it is a completely clean slate.

    How do you import the necessary documents (to build the project) for the mmwave link Test application? I think I found the SDK by going to Project properties and then adding in the file directory for the SDK, if that is correct? Would you recommend going off of this test application and then dragging over the lvds c file from the mmwave demo into this project?

    And your understanding of my project is correct. I just need to configure the front end of the radar (BSS) and send the received data to the DCA1000 to my Raspberry which is ready and configured to write down the raw ADC data. Also, if there is a way to do this for the AWR1642, could you tailor the steps to the AWR1642? I have a 502AC version of the chirp with 2.0 SDK currently flashed on it, but I think 3.4 could work? Right? 

    Any more direction would be really really appreciated!

    George

  • Hello George,

    I have attached the CCS project for mmwavelink_test application where it includes only MSS part of the test application.

    And it generates the MetaImage containing MSS and BSS firmware in it.

    5074.ccs.zip

    This CCS project uses SDK 3.4 version.

    Now on top of this CCS project you can add UART CLI feature and LVDS streaming features.

    Regards,

    Jitendra

  • Hi Jitendra,

    Thanks for sending the project, that is really helpful. I was able to load in the project, fix all of the errors, and clear all the warnings. I did receive some optimization advice notes as seen below with the exact project you sent me... Are they necessary? What would you recommend doing, if anything?

    Also, since I do not have a debugger or anything to use to make sure my code runs as desired, is there anyway you could provide me some exact steps on how to add in the UART CLI and LVDS feature? Also, since I want to configure a [0 0 1 1] BPM scheme, should I also include the Advanced BPM CFG API as well? Should I just take the necessary c files from the sdk? Then what? Do they have to be included into the mss_main.c file in this test project? Laying out the steps would be so appreciated! 

    Thank you so much! Almost there!!

    George

  • Hello George,

    As I mentioned eralier, for CLI and LVDS streaming implementation, please refer mmw demo which has these two features.

    And now you are using mmwavelink so you don't need to use mmwave library functions, rather call all the mmwavelink directly.

     

    Regards,

    Jitendra

  • Hi Jitendra,

    I understand that the mmw demo has the two features and I think I found where they are implemented. I am struggling with how to exactly call them in the mmwavelink directly and what that looks like. For example, below are some of the c codes I found for LVDS streaming and CLI in the "demo" folder at large. How would I integrate these features with the "test" project that I showed in my screenshot of the CCS above? Do I call something in the mmwavelink test's mss_main.c? If so, what exactly? Certain order? Do I bring certain .c and .h files from demo to that project? 

    Some of the files in the demo folder regarding LVDS and CLI:

    /**
     *   @file  mmw_lvds_stream.c
     *
     *   @brief
     *      Implements LVDS stream functionality.
     *
     *  \par
     *  NOTE:
     *      (C) Copyright 2019 Texas Instruments, Inc.
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
     
    /**************************************************************************
     *************************** Include Files ********************************
     **************************************************************************/
    #include <stdint.h>
    #include <string.h>
    #include <stdio.h>
    
    /* BIOS/XDC Include Files. */
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Memory.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* MMWSDK Include Files. */
    #include <ti/drivers/soc/soc.h>
    #include <ti/common/sys_common.h>
    #include <ti/drivers/osal/DebugP.h>
    #include <ti/drivers/adcbuf/ADCBuf.h>
    #include <ti/drivers/edma/edma.h>
    #include <ti/drivers/cbuff/cbuff.h>
    #include <ti/utils/hsiheader/hsiheader.h>
    
    /* MMWAVE Demo Include Files */
    #include <ti/demo/xwr16xx/mmw/mss/mmw_mss.h>
    #include <ti/demo/xwr16xx/mmw/mmw_res.h>
    
    extern MmwDemo_MSS_MCB    gMmwMssMCB;
    
     /**
     *  @b Description
     *  @n
     *      This function initializes/configures the LVDS
     *      streaming EDMA resources.
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    void MmwDemo_LVDSStream_EDMAInit (void)
    {
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelAllocatorIndex = 0;
        gMmwMssMCB.lvdsStream.swSessionEDMAChannelAllocatorIndex = 0;
     
        /* Populate the LVDS Stream HW Session EDMA Channel Table: */              
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[0].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_0;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[0].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_0;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[1].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_1;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[1].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_1;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[2].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_2;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[2].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_2;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[3].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_3;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[3].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_3;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[4].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_4;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[4].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_4;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[5].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_5;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[5].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_5;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[6].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_6;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[6].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_6;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[7].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_7;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[7].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_7;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[8].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_8;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[8].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_8;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[9].chainChannelsId       = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_9;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[9].shadowLinkChannelsId  = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_9;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[10].chainChannelsId      = MMW_LVDS_STREAM_HW_SESSION_EDMA_CH_10;
        gMmwMssMCB.lvdsStream.hwSessionEDMAChannelTable[10].shadowLinkChannelsId = MMW_LVDS_STREAM_HW_SESSION_EDMA_SHADOW_CH_10;
    
        /* Populate the LVDS Stream SW Session EDMA Channel Table: */
        gMmwMssMCB.lvdsStream.swSessionEDMAChannelTable[0].chainChannelsId       = MMW_LVDS_STREAM_SW_SESSION_EDMA_CH_0;
        gMmwMssMCB.lvdsStream.swSessionEDMAChannelTable[0].shadowLinkChannelsId  = MMW_LVDS_STREAM_SW_SESSION_EDMA_SHADOW_CH_0;
        gMmwMssMCB.lvdsStream.swSessionEDMAChannelTable[1].chainChannelsId       = MMW_LVDS_STREAM_SW_SESSION_EDMA_CH_1;
        gMmwMssMCB.lvdsStream.swSessionEDMAChannelTable[1].shadowLinkChannelsId  = MMW_LVDS_STREAM_SW_SESSION_EDMA_SHADOW_CH_1;
        gMmwMssMCB.lvdsStream.swSessionEDMAChannelTable[2].chainChannelsId       = MMW_LVDS_STREAM_SW_SESSION_EDMA_CH_2;
        gMmwMssMCB.lvdsStream.swSessionEDMAChannelTable[2].shadowLinkChannelsId  = MMW_LVDS_STREAM_SW_SESSION_EDMA_SHADOW_CH_2;
    } 
     
     /**
     *  @b Description
     *  @n
     *      This is the LVDS streaming init function. 
     *      It initializes the necessary modules
     *      that implement the streaming.
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    int32_t MmwDemo_LVDSStreamInit (void)
    {
        CBUFF_InitCfg           initCfg;
        int32_t                 retVal = MINUS_ONE;
        int32_t                 errCode;
        Semaphore_Params        semParams;
    
        /*************************************************************************************
         * Open the CBUFF Driver:
         *************************************************************************************/
        memset ((void *)&initCfg, 0, sizeof(CBUFF_InitCfg));
    
        /* Populate the configuration: */
        initCfg.socHandle                 = gMmwMssMCB.socHandle;
        initCfg.enableECC                 = 0U;
        initCfg.crcEnable                 = 1U;
        /* Up to 1 SW session + 1 HW session can be configured for each frame. Therefore max session is 2. */
        initCfg.maxSessions               = 2U;
        initCfg.enableDebugMode           = false;
        initCfg.interface                 = CBUFF_Interface_LVDS;
        initCfg.outputDataFmt             = CBUFF_OutputDataFmt_16bit;
        initCfg.u.lvdsCfg.crcEnable       = 0U;
        initCfg.u.lvdsCfg.msbFirst        = 1U;
        /* Enable all lanes available on the platform*/
        initCfg.u.lvdsCfg.lvdsLaneEnable  = 0x3U;
        initCfg.u.lvdsCfg.ddrClockMode    = 1U;
        initCfg.u.lvdsCfg.ddrClockModeMux = 1U;
    
        /* Initialize the CBUFF Driver: */
        gMmwMssMCB.lvdsStream.cbuffHandle = CBUFF_init (&initCfg, &errCode);
        if (gMmwMssMCB.lvdsStream.cbuffHandle == NULL)
        {
            /* Error: Unable to initialize the CBUFF Driver */
            System_printf("Error: CBUFF_init failed with [Error=%d]\n", errCode);
            goto exit;
        }
    
    
        /* User data buffer is involved in LVDS streaming.
         * The 64 byte alignment is a speculative workaround for an issue where
         * EDMA is not completing transfer. */
        gMmwMssMCB.lvdsStream.userDataHeader = Memory_alloc(NULL,
                                                            sizeof(MmwDemo_LVDSUserDataHeader_t),
                                                            64U, /* alignment */
                                                            NULL);
    
        /* Initialize the HSI Header Module: */
        if (HSIHeader_init (&initCfg, &errCode) < 0)
        {
            /* Error: Unable to initialize the HSI Header Module */
            System_printf("Error: HSIHeader_init failed with [Error=%d]\n", errCode);
            goto exit;
        }
    
        /* Populate EDMA resources */
        MmwDemo_LVDSStream_EDMAInit();
        
        /* Initialize semaphores */
        Semaphore_Params_init(&semParams);
        semParams.mode = Semaphore_Mode_BINARY;
        gMmwMssMCB.lvdsStream.hwFrameDoneSemHandle = Semaphore_create(0, &semParams, NULL);
        gMmwMssMCB.lvdsStream.swFrameDoneSemHandle = Semaphore_create(0, &semParams, NULL);
    
        /* Check some assumptions about s/w session regarding sizes for user buffer which
         * are going to stream out in CBUFF units so must be even number of bytes */
        MmwDemo_debugAssert((sizeof(MmwDemo_LVDSUserDataHeader_t) & 1) == 0);
        MmwDemo_debugAssert((sizeof(DPIF_PointCloudCartesian) & 1) == 0);
        MmwDemo_debugAssert((sizeof(DPIF_PointCloudSideInfo) & 1) == 0);
    
        retVal = 0;
    
    exit:
        return retVal;
    }
    
    /**
     *  @b Description
     *  @n
     *      Function that allocates CBUFF-EDMA channel
     *
     *  @param[in]  ptrEDMAInfo
     *      Pointer to the EDMA Information
     *  @param[out]  ptrEDMACfg
     *      Populated EDMA channel configuration
     *
     */
    static void MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel
    (
        CBUFF_EDMAInfo*         ptrEDMAInfo,
        CBUFF_EDMAChannelCfg*   ptrEDMACfg
    )
    {
        if(ptrEDMAInfo->dmaNum == 0)
        {
            ptrEDMACfg->chainChannelsId      = MMW_LVDS_STREAM_CBUFF_EDMA_CH_0;
            ptrEDMACfg->shadowLinkChannelsId = MMW_LVDS_STREAM_CBUFF_EDMA_SHADOW_CH_0;        
        }
        else if(ptrEDMAInfo->dmaNum == 1)
        {
            ptrEDMACfg->chainChannelsId      = MMW_LVDS_STREAM_CBUFF_EDMA_CH_1;
            ptrEDMACfg->shadowLinkChannelsId = MMW_LVDS_STREAM_CBUFF_EDMA_SHADOW_CH_1;        
        }    
        else
        {
            /* Max of 2 CBUFF sessions can be configured*/
            MmwDemo_debugAssert (0);
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the registered CBUFF EDMA channel allocation function
     *      which allocates EDMA channels for CBUFF HW Session
     *
     *  @param[in]  ptrEDMAInfo
     *      Pointer to the EDMA Information
     *  @param[out]  ptrEDMACfg
     *      Populated EDMA channel configuration
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_LVDSStream_EDMAAllocateCBUFFHwChannel
    (
        CBUFF_EDMAInfo*         ptrEDMAInfo,
        CBUFF_EDMAChannelCfg*   ptrEDMACfg
    )
    {
        int32_t         retVal = MINUS_ONE;
        MmwDemo_LVDSStream_MCB_t *streamMCBPtr =  &gMmwMssMCB.lvdsStream;
    
        if(ptrEDMAInfo->isFirstEDMAChannel)
        {
            MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel(ptrEDMAInfo, ptrEDMACfg);
            retVal = 0;
        }
        else
        {
    
            /* Sanity Check: Are there sufficient EDMA channels? */
            if (streamMCBPtr->hwSessionEDMAChannelAllocatorIndex >= MMWDEMO_LVDS_STREAM_HW_SESSION_MAX_EDMA_CHANNEL)
            {
                /* Error: All the EDMA channels are allocated */
                System_printf ("Error: MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel failed. HW channel index=%d\n", 
                                streamMCBPtr->hwSessionEDMAChannelAllocatorIndex);
                goto exit;
            }
    
            /* Copy over the allocated EDMA configuration. */
            memcpy ((void *)ptrEDMACfg,
                    (void*)&streamMCBPtr->hwSessionEDMAChannelTable[streamMCBPtr->hwSessionEDMAChannelAllocatorIndex],
                    sizeof(CBUFF_EDMAChannelCfg));
    
            /* Increment the allocator index: */
            streamMCBPtr->hwSessionEDMAChannelAllocatorIndex++;
    
            /* EDMA Channel allocated successfully */
            retVal = 0;
        }    
    
    exit:
        return retVal;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the registered CBUFF EDMA channel allocation function
     *      which allocates EDMA channels for CBUFF SW Session
     *
     *  @param[in]  ptrEDMAInfo
     *      Pointer to the EDMA Information
     *  @param[out]  ptrEDMACfg
     *      Populated EDMA channel configuration
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_LVDSStream_EDMAAllocateCBUFFSwChannel
    (
        CBUFF_EDMAInfo*         ptrEDMAInfo,
        CBUFF_EDMAChannelCfg*   ptrEDMACfg
    )
    {
        int32_t         retVal = MINUS_ONE;
        MmwDemo_LVDSStream_MCB_t *streamMCBPtr =  &gMmwMssMCB.lvdsStream;
    
        if(ptrEDMAInfo->isFirstEDMAChannel)
        {
            MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel(ptrEDMAInfo,ptrEDMACfg);
            retVal = 0;
        }
        else
        {
            /* Sanity Check: Are there sufficient EDMA channels? */
            if (streamMCBPtr->swSessionEDMAChannelAllocatorIndex >= MMWDEMO_LVDS_STREAM_SW_SESSION_MAX_EDMA_CHANNEL)
            {
                /* Error: All the EDMA channels are allocated */
                System_printf ("Error: MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel failed. SW channel index=%d\n", 
                                streamMCBPtr->swSessionEDMAChannelAllocatorIndex);
                goto exit;
            }
            
            /* Copy over the allocated EDMA configuration. */
            memcpy ((void *)ptrEDMACfg,
                    (void*)&streamMCBPtr->swSessionEDMAChannelTable[streamMCBPtr->swSessionEDMAChannelAllocatorIndex],
                    sizeof(CBUFF_EDMAChannelCfg));
            
            /* Increment the allocator index: */
            streamMCBPtr->swSessionEDMAChannelAllocatorIndex++;
            
            /* EDMA Channel allocated successfully */
            retVal = 0;
        }    
    
    exit:
        return retVal;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the registered CBUFF EDMA channel free function which frees EDMA channels
     *      which had been allocated for use by a CBUFF HW Session
     *
     *  @retval
     *      Not applicable
     */
    static void MmwDemo_LVDSStream_EDMAFreeCBUFFHwChannel (CBUFF_EDMAChannelCfg* ptrEDMACfg)
    {
        uint8_t    index;
        MmwDemo_LVDSStream_MCB_t *streamMCBPtr =  &gMmwMssMCB.lvdsStream;
    
        if((ptrEDMACfg->chainChannelsId == MMW_LVDS_STREAM_CBUFF_EDMA_CH_0) ||
           (ptrEDMACfg->chainChannelsId == MMW_LVDS_STREAM_CBUFF_EDMA_CH_1))
        {
            /*This is the CBUFF trigger channel. It is not part of the resource table so
              nothing needs to be done*/
            goto exit;  
        }
    
        for (index = 0U; index < MMWDEMO_LVDS_STREAM_HW_SESSION_MAX_EDMA_CHANNEL; index++) 
        {
            /* Do we have a match? */
            if (memcmp ((void*)ptrEDMACfg,
                        (void*)&streamMCBPtr->hwSessionEDMAChannelTable[index],
                        sizeof(CBUFF_EDMAChannelCfg)) == 0)
            {
                /* Yes: Decrement the HW Session index */
                streamMCBPtr->hwSessionEDMAChannelAllocatorIndex--;
                goto exit;
            }
        }
    
        /* Sanity Check: We should have had a match. An assertion is thrown to indicate that the EDMA channel
         * being cleaned up does not belong to the table*/
        MmwDemo_debugAssert (0);
    
    exit:
        return;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the registered CBUFF EDMA channel free function which frees EDMA channels
     *      which had been allocated for use by a CBUFF SW Session
     *
     *  @retval
     *      Not applicable
     */
    static void MmwDemo_LVDSStream_EDMAFreeCBUFFSwChannel (CBUFF_EDMAChannelCfg* ptrEDMACfg)
    {
        uint8_t    index;
        MmwDemo_LVDSStream_MCB_t *streamMCBPtr =  &gMmwMssMCB.lvdsStream;
    
        if((ptrEDMACfg->chainChannelsId == MMW_LVDS_STREAM_CBUFF_EDMA_CH_0) ||
           (ptrEDMACfg->chainChannelsId == MMW_LVDS_STREAM_CBUFF_EDMA_CH_1))
        {
            /*This is the CBUFF trigger channel. It is not part of the resource table so
              nothing needs to be done*/
            goto exit;  
        }
    
        for (index = 0U; index < MMWDEMO_LVDS_STREAM_SW_SESSION_MAX_EDMA_CHANNEL; index++)
        {
            /* Do we have a match? */
            if (memcmp ((void*)ptrEDMACfg,
                        (void*)&streamMCBPtr->swSessionEDMAChannelTable[index],
                        sizeof(CBUFF_EDMAChannelCfg)) == 0)
            {
                /* Yes: Decrement the SW Session index */
                streamMCBPtr->swSessionEDMAChannelAllocatorIndex--;
                goto exit;
            }
        }
    
        /* Sanity Check: We should have had a match. An assertion is thrown to indicate that the EDMA channel
         * being cleaned up does not belong to the table*/
        MmwDemo_debugAssert (0);
    
    exit:
        return;
    }
    
    
    /**
     *  @b Description
     *  @n
     *      This function deletes the hardware session and any HSI
     *      header associated with it. 
     *
     *  @retval
     *      Not applicable
     */
    void MmwDemo_LVDSStreamDeleteHwSession (void)
    {
        int32_t     errCode;
        MmwDemo_LVDSStream_MCB_t* streamMcb = &gMmwMssMCB.lvdsStream;
        
        /* Delete session*/
        if (CBUFF_deleteSession (streamMcb->hwSessionHandle, &errCode) < 0)
        {
            /* Error: Unable to delete the session. */
            System_printf ("Error: MmwDemo_LVDSStreamDeleteHwSession CBUFF_deleteSession failed. Error code %d\n", errCode);
            MmwDemo_debugAssert(0);
            return;
        }
        
        streamMcb->hwSessionHandle = NULL;
        
        /* Did we stream out with the HSI Header? */
        if (streamMcb->isHwSessionHSIHeaderAllocated == true)
        {
            /* Delete the HSI Header: */
            if (HSIHeader_deleteHeader (&streamMcb->hwSessionHSIHeader, &errCode) < 0)
            {
                /* Error: Unable to delete the HSI Header */
                System_printf ("Error: MmwDemo_LVDSStreamDeleteHwSession HSIHeader_deleteHeader failed. Error code %d\n", errCode);
                MmwDemo_debugAssert(0);
                return;
            }
    
            streamMcb->isHwSessionHSIHeaderAllocated = false;
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      This function deletes the SW session and any HSI
     *      header associated with it. 
     *
     *  @retval
     *      Not applicable
     */
    void MmwDemo_LVDSStreamDeleteSwSession (void)
    {
        int32_t     errCode;
        MmwDemo_LVDSStream_MCB_t* streamMcb = &gMmwMssMCB.lvdsStream;
        
        /* Delete session*/
        if (CBUFF_deleteSession (streamMcb->swSessionHandle, &errCode) < 0)
        {
            /* Error: Unable to delete the session. */
            System_printf ("Error: MmwDemo_LVDSStreamDeleteSwSession CBUFF_deleteSession failed. Error code %d\n", errCode);
            MmwDemo_debugAssert(0);
            return;
        }
        
        streamMcb->swSessionHandle = NULL;
        
        /* Delete the HSI Header: */
        if (HSIHeader_deleteHeader (&streamMcb->swSessionHSIHeader, &errCode) < 0)
        {
            /* Error: Unable to delete the HSI Header */
            System_printf ("Error: MmwDemo_LVDSStreamDeleteSwSession HSIHeader_deleteHeader failed. Error code %d\n", errCode);
            MmwDemo_debugAssert(0);
            return;
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the registered callback function which is invoked after the
     *      frame done interrupt is received for the hardware session.
     *
     *  @param[in]  sessionHandle
     *      Handle to the session
     *
     *  @retval
     *      Not applicable
     */
    static void MmwDemo_LVDSStream_HwTriggerFrameDone (CBUFF_SessionHandle sessionHandle)
    {
        int32_t     errCode;
    
        /* Increment stats*/
        gMmwMssMCB.lvdsStream.hwFrameDoneCount++;
    
        if(sessionHandle != NULL)
        {
            /* There are 2 cases to consider:
               Only one subframe configured (legacy frame):
               If there is a software session configured for this subframe, we need to 
               deactivate the HW session here. 
               
               More than one subframe configured:
               If there is more than one subframe we need to deactivate the HW
               session here as other subframes may have configured a HW session.
               In this case (more than one subframe), the HW session is always created
               and activated in the application code */
            if((gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames > 1) ||
                (gMmwMssMCB.subFrameCfg[0].lvdsStreamCfg.isSwEnabled == 1))
            {
                if(CBUFF_deactivateSession (sessionHandle, &errCode) < 0)
                {
                    /* Error: Unable to deactivate the session. */
                    DebugP_assert(0);
                    return;
                }
            }    
        }
        else
        {
            DebugP_assert(0);
        }
    
        Semaphore_post(gMmwMssMCB.lvdsStream.hwFrameDoneSemHandle);
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the registered callback function which is invoked after the
     *      frame done interrupt is received for the SW session.
     *
     *  @param[in]  sessionHandle
     *      Handle to the session
     *
     *  @retval
     *      Not applicable
     */
    static void MmwDemo_LVDSStream_SwTriggerFrameDone (CBUFF_SessionHandle sessionHandle)
    {    
        int32_t     errCode;
    
        /* Increment stats*/
        gMmwMssMCB.lvdsStream.swFrameDoneCount++;
        
        if(sessionHandle != NULL)
        {
            if(CBUFF_deactivateSession (sessionHandle, &errCode) < 0)
            {
                /* Error: Unable to deactivate the session. */
                DebugP_assert(0);
                return;
            }
            
            /*If only one subframe has been configured (legacy frame) and
              a HW session has been configured for that subframe, we need to
              enable it here as for the legacy frame the HW is NOT reconfigured
              every frame. 
              If more than one subframe is configured, the HW
              session is reconfigured and activated every subframe
              in the application code, not here.*/
            if((gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames == 1) &&
               (gMmwMssMCB.lvdsStream.hwSessionHandle != NULL))
            {        
                if(CBUFF_activateSession (gMmwMssMCB.lvdsStream.hwSessionHandle, &errCode) < 0)
                {
                    DebugP_assert(0);
                }
            }        
        }
        else
        {
            DebugP_assert(0);
        }    
        
        Semaphore_post(gMmwMssMCB.lvdsStream.swFrameDoneSemHandle);
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the LVDS streaming config function. 
     *      It configures the sessions for the LVDS streaming.
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    int32_t MmwDemo_LVDSStreamHwConfig (uint8_t subFrameIndx)
    {
        CBUFF_SessionCfg          sessionCfg;
        MmwDemo_LVDSStream_MCB_t* streamMcb = &gMmwMssMCB.lvdsStream;
        int32_t                   errCode;
        int32_t                   retVal = MINUS_ONE;
        MmwDemo_SubFrameCfg       *subFrameCfg = &gMmwMssMCB.subFrameCfg[subFrameIndx];
    
        memset ((void*)&sessionCfg, 0, sizeof(CBUFF_SessionCfg));
        
        /* Populate the configuration: */
        sessionCfg.executionMode          = CBUFF_SessionExecuteMode_HW;
        sessionCfg.edmaHandle             = gMmwMssMCB.edmaHandle;
        sessionCfg.allocateEDMAChannelFxn = MmwDemo_LVDSStream_EDMAAllocateCBUFFHwChannel;
        sessionCfg.freeEDMAChannelFxn     = MmwDemo_LVDSStream_EDMAFreeCBUFFHwChannel;
        sessionCfg.frameDoneCallbackFxn   = MmwDemo_LVDSStream_HwTriggerFrameDone;
        sessionCfg.dataType               = CBUFF_DataType_COMPLEX;
        sessionCfg.u.hwCfg.dataMode       = (CBUFF_DataMode)subFrameCfg->adcBufCfg.chInterleave;
        
        /* Populate the HW Session configuration: */
        sessionCfg.u.hwCfg.adcBufHandle      = gMmwMssMCB.adcBufHandle;
        sessionCfg.u.hwCfg.numADCSamples     = subFrameCfg->numAdcSamples;
        sessionCfg.u.hwCfg.numChirpsPerFrame = subFrameCfg->numChirpsPerSubFrame;
        sessionCfg.u.hwCfg.chirpMode         = subFrameCfg->adcBufCfg.chirpThreshold;
        sessionCfg.u.hwCfg.opMode            = CBUFF_OperationalMode_CHIRP;
        
        switch(subFrameCfg->lvdsStreamCfg.dataFmt)
        {
            case MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_ADC:
                sessionCfg.u.hwCfg.dataFormat = CBUFF_DataFmt_ADC_DATA;
            break;
            case MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_CP_ADC_CQ:
                sessionCfg.u.hwCfg.dataFormat = CBUFF_DataFmt_CP_ADC_CQ;
                sessionCfg.u.hwCfg.cqSize[0] = 0;
                sessionCfg.u.hwCfg.cqSize[1] = HSIHeader_toCBUFFUnits(subFrameCfg->sigImgMonTotalSize);
                sessionCfg.u.hwCfg.cqSize[2] = HSIHeader_toCBUFFUnits(subFrameCfg->satMonTotalSize);
            break;
            default:
                System_printf ("Error: lvdsStreamCfg dataFmt %d is invalid\n", subFrameCfg->lvdsStreamCfg.dataFmt);
                MmwDemo_debugAssert(0);
            break;
        }    
            
        if(subFrameCfg->lvdsStreamCfg.isHeaderEnabled)
        {    
            MmwDemo_debugAssert(streamMcb->isHwSessionHSIHeaderAllocated == false);
    
            /* Create the HSI Header to be used for the HW Session: */ 
            if (HSIHeader_createHeader (&sessionCfg, false, &(streamMcb->hwSessionHSIHeader), &errCode) < 0)
            {
                /* Error: Unable to create the HSI Header; report the error */
                System_printf("Error: MmwDemo_LVDSStream_config unable to create HW HSI header with [Error=%d]\n", errCode);
                goto exit;
            }
            
            streamMcb->isHwSessionHSIHeaderAllocated = true;
    
            /* Setup the header in the CBUFF session configuration: */
            sessionCfg.header.size    = HSIHeader_getHeaderSize(&streamMcb->hwSessionHSIHeader);
            sessionCfg.header.address = (uint32_t)&(streamMcb->hwSessionHSIHeader);
        }    
           
        /* Create the HW Session: */
        streamMcb->hwSessionHandle = CBUFF_createSession (gMmwMssMCB.lvdsStream.cbuffHandle, &sessionCfg, &errCode);
                                                          
        if (streamMcb->hwSessionHandle == NULL)
        {
            /* Error: Unable to create the CBUFF hardware session */
            System_printf("Error: MmwDemo_LVDSStream_config unable to create the CBUFF hardware session with [Error=%d]\n", errCode);
            goto exit;
        }
    
        /* Control comes here implies that the LVDS Stream has been configured successfully */
        retVal = 0;
    
    exit:
        return retVal;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the LVDS sw streaming config function.
     *      It configures the sw session for the LVDS streaming.
     *
     *  @param[in]  numObjOut      Number of detected objects to stream out
     *  @param[in]  objOut         Pointer to detected objects point cloud
     *  @param[in]  objOutSideInfo Pointer to detected objects side information
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    int32_t MmwDemo_LVDSStreamSwConfig (uint32_t numObjOut,
                                        DPIF_PointCloudCartesian *objOut,
                                        DPIF_PointCloudSideInfo *objOutSideInfo)
    {
        CBUFF_SessionCfg          sessionCfg;
        MmwDemo_LVDSStream_MCB_t* streamMcb = &gMmwMssMCB.lvdsStream;
        int32_t                   errCode;
        int32_t                   retVal = MINUS_ONE;
    
        memset ((void*)&sessionCfg, 0, sizeof(CBUFF_SessionCfg));
        
        /* Populate the configuration: */
        sessionCfg.executionMode                     = CBUFF_SessionExecuteMode_SW;
        sessionCfg.edmaHandle                        = gMmwMssMCB.edmaHandle;
        sessionCfg.allocateEDMAChannelFxn            = MmwDemo_LVDSStream_EDMAAllocateCBUFFSwChannel;
        sessionCfg.freeEDMAChannelFxn                = MmwDemo_LVDSStream_EDMAFreeCBUFFSwChannel;
        sessionCfg.frameDoneCallbackFxn              = MmwDemo_LVDSStream_SwTriggerFrameDone;
        sessionCfg.dataType                          = CBUFF_DataType_COMPLEX; 
        sessionCfg.u.swCfg.userBufferInfo[0].size    = HSIHeader_toCBUFFUnits(sizeof(MmwDemo_LVDSUserDataHeader_t));
        sessionCfg.u.swCfg.userBufferInfo[0].address = (uint32_t)(streamMcb->userDataHeader);
    
        /* Note size and addresses have defaulted to 0 due to memset zero initialization above */
        if(numObjOut != 0)
        {
            sessionCfg.u.swCfg.userBufferInfo[1].size    = HSIHeader_toCBUFFUnits(numObjOut * sizeof(DPIF_PointCloudCartesian));
            sessionCfg.u.swCfg.userBufferInfo[1].address = (uint32_t)objOut;
    
            sessionCfg.u.swCfg.userBufferInfo[2].size    = HSIHeader_toCBUFFUnits(numObjOut * sizeof(DPIF_PointCloudSideInfo));
            sessionCfg.u.swCfg.userBufferInfo[2].address = (uint32_t)objOutSideInfo;
        }
    
        /* Create the HSI Header to be used for the SW Session: */
        if (HSIHeader_createHeader (&sessionCfg, true, &(streamMcb->swSessionHSIHeader), &errCode) < 0)
        {
            /* Error: Unable to create the HSI Header; report the error */
            System_printf("Error: MmwDemo_LVDSStream_config unable to create HW HSI header with [Error=%d]\n", errCode);
            goto exit;
        }
        
        /* Setup the header in the CBUFF session configuration: */
        sessionCfg.header.size    = HSIHeader_getHeaderSize(&streamMcb->swSessionHSIHeader);
        sessionCfg.header.address = (uint32_t)&(streamMcb->swSessionHSIHeader);
    
        /* Create the SW Session. */
        streamMcb->swSessionHandle = CBUFF_createSession (gMmwMssMCB.lvdsStream.cbuffHandle, &sessionCfg, &errCode);
        
        if (streamMcb->swSessionHandle == NULL)
        {
            /* Error: Unable to create the CBUFF SW session */
            System_printf("Error: MmwDemo_LVDSStream_config unable to create the CBUFF SW session with [Error=%d]\n", errCode);
            goto exit;
        }
    
        /* Control comes here implies that the LVDS Stream has been configured successfully */
        retVal = 0;
    
    exit:
        return retVal;
    }
    
    /**
    *  @b Description
    *  @n
    *      High level API for configuring Hw session. Deletes h/w session if it exists,
    *      configures desired configuration input and activates the h/w session
    *  @param[in]  subFrameIndx Index of sub-frame
    *
    *  @retval
    *      None
    */
    void MmwDemo_configLVDSHwData(uint8_t subFrameIndx)
    {
        int32_t retVal;
    
        /* Delete previous CBUFF HW session if one was configured */
        if(gMmwMssMCB.lvdsStream.hwSessionHandle != NULL)
        {
            MmwDemo_LVDSStreamDeleteHwSession();
        }
    
        /* Configure HW session */
        if (MmwDemo_LVDSStreamHwConfig(subFrameIndx) < 0)
        {
            System_printf("Failed LVDS stream HW configuration\n");
            MmwDemo_debugAssert(0);
        }
    
        /* If HW LVDS stream is enabled, start the session here so that ADC samples will be
        streamed out as soon as the first chirp samples land on ADC*/
        if(CBUFF_activateSession(gMmwMssMCB.lvdsStream.hwSessionHandle, &retVal) < 0)
        {
            System_printf("Failed to activate CBUFF session for LVDS stream HW. errCode=%d\n",retVal);
            MmwDemo_debugAssert(0);
        }
    }
    

    mmw_lvds_stream.h

    mmw_mss.h

    0513.mss_main.c

    /*
     *   @file  mmw_cli.c
     *
     *   @brief
     *      Mmw (Milli-meter wave) DEMO CLI Implementation
     *
     *  \par
     *  NOTE:
     *      (C) Copyright 2018 Texas Instruments, Inc.
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**************************************************************************
     *************************** Include Files ********************************
     **************************************************************************/
    
    /* Standard Include Files. */
    #include <stdint.h>
    #include <stdlib.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    
    /* BIOS/XDC Include Files. */
    #include <xdc/runtime/System.h>
    
    /* mmWave SDK Include Files: */
    #include <ti/common/sys_common.h>
    #include <ti/common/mmwave_sdk_version.h>
    #include <ti/drivers/uart/UART.h>
    #include <ti/control/mmwavelink/mmwavelink.h>
    #include <ti/utils/cli/cli.h>
    #include <ti/utils/mathutils/mathutils.h>
    
    /* Demo Include Files */
    #include <ti/demo/xwr16xx/mmw/include/mmw_config.h>
    #include <ti/demo/xwr16xx/mmw/mss/mmw_mss.h>
    #include <ti/demo/utils/mmwdemo_adcconfig.h>
    #include <ti/demo/utils/mmwdemo_rfparser.h>
    
    /**************************************************************************
     *************************** Local function prototype****************************
     **************************************************************************/
    
    /* CLI Extended Command Functions */
    static int32_t MmwDemo_CLICfarCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIMultiObjBeamForming (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLICalibDcRangeSig (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIClutterRemoval (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLISensorStart (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLISensorStop (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIGuiMonSel (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIADCBufCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLICompRangeBiasAndRxChanPhaseCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIMeasureRangeBiasAndRxChanPhaseCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLICfarFovCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIAoAFovCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIExtendedMaxVelocity (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIBpmCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIChirpQualityRxSatMonCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIChirpQualitySigImgMonCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIAnalogMonitorCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLILvdsStreamCfg (int32_t argc, char* argv[]);
    static int32_t MmwDemo_CLIConfigDataPort (int32_t argc, char* argv[]);
    
    /**************************************************************************
     *************************** Extern Definitions *******************************
     **************************************************************************/
    
    extern MmwDemo_MSS_MCB    gMmwMssMCB;
    
    /**************************************************************************
     *************************** Local Definitions ****************************
     **************************************************************************/
    
    #define MMWDEMO_DATAUART_MAX_BAUDRATE_SUPPORTED 3125000
    
    /**************************************************************************
     *************************** CLI  Function Definitions **************************
     **************************************************************************/
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the sensor start command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLISensorStart (int32_t argc, char* argv[])
    {
        bool        doReconfig = true;
        int32_t     retVal = 0;
    
        /*  Only following command syntax will be supported 
            sensorStart
            sensorStart 0
        */
        if (argc == 2)
        {
            doReconfig = (bool) atoi (argv[1]);
    
            if (doReconfig == true)
            {
                CLI_write ("Error: Reconfig is not supported, only argument of 0 is\n"
                           "(do not reconfig, just re-start the sensor) valid\n");
                return -1;
            }
        }
        else
        {
            /* In case there is no argument for sensorStart, always do reconfig */
            doReconfig = true;
        }
    
        /***********************************************************************************
         * Do sensor state management to influence the sensor actions
         ***********************************************************************************/
    
        /* Error checking initial state: no partial config is allowed 
           until the first sucessful sensor start state */
        if ((gMmwMssMCB.sensorState == MmwDemo_SensorState_INIT) || 
             (gMmwMssMCB.sensorState == MmwDemo_SensorState_OPENED))
        {
            MMWave_CtrlCfg ctrlCfg;
    
            /* need to get number of sub-frames so that next function to check
             * pending state can work */
            CLI_getMMWaveExtensionConfig (&ctrlCfg);
            gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames =
                MmwDemo_RFParser_getNumSubFrames(&ctrlCfg);
    
            if (MmwDemo_isAllCfgInPendingState() == 0)
            {
                CLI_write ("Error: Full configuration must be provided before sensor can be started "
                           "the first time\n");
    
                /* Although not strictly needed, bring back to the initial value since we
                 * are rejecting this first time configuration, prevents misleading debug. */
                gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames = 0;
    
                return -1;
            }
        }
    
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: Sensor is already started\n");
            return 0;
        }
    
        if (doReconfig == false)
        {
             /* User intends to issue sensor start without config, check if no
                config was issued after stop and generate error if this is the case. */
             if (MmwDemo_isAllCfgInNonPendingState() == 0)
             {
                 /* Message user differently if all config was issued or partial config was
                    issued. */
                 if (MmwDemo_isAllCfgInPendingState())
                 {
                     CLI_write ("Error: You have provided complete new configuration, "
                                "issue \"sensorStart\" (without argument) if you want it to "
                                "take effect\n");
                 }
                 else
                 {
                     CLI_write ("Error: You have provided partial configuration between stop and this "
                                "command and partial configuration cannot be undone."
                                "Issue the full configuration and do \"sensorStart\" \n");
                 }
                 return -1;
             }
        }
        else
        {
            /* User intends to issue sensor start with full config, check if all config
               was issued after stop and generate error if  is the case. */
            MMWave_CtrlCfg ctrlCfg;
    
            /* need to get number of sub-frames so that next function to check
             * pending state can work */
            CLI_getMMWaveExtensionConfig (&ctrlCfg);
            gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames =
                MmwDemo_RFParser_getNumSubFrames(&ctrlCfg);
            
            if (MmwDemo_isAllCfgInPendingState() == 0)
            {
                /* Message user differently if no config was issued or partial config was
                   issued. */
                if (MmwDemo_isAllCfgInNonPendingState())
                {
                    CLI_write ("Error: You have provided no configuration, "
                               "issue \"sensorStart 0\" OR provide "
                               "full configuration and issue \"sensorStart\"\n");
                }
                else
                {
                    CLI_write ("Error: You have provided partial configuration between stop and this "
                               "command and partial configuration cannot be undone."
                               "Issue the full configuration and do \"sensorStart\" \n");
                }
                /* Although not strictly needed, bring back to the initial value since we
                 * are rejecting this first time configuration, prevents misleading debug. */
                gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames = 0;
                return -1;
            }
        }
    
        /***********************************************************************************
         * Retreive and check mmwave Open related config before calling openSensor
         ***********************************************************************************/
    
        /*  Fill demo's MCB mmWave openCfg structure from the CLI configs*/
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_INIT)
        {
            /* Get the open configuration: */
            CLI_getMMWaveExtensionOpenConfig (&gMmwMssMCB.cfg.openCfg);
            /* call sensor open */
            retVal = MmwDemo_openSensor(true);
            if(retVal != 0)
            {
                return -1;
            }
            gMmwMssMCB.sensorState = MmwDemo_SensorState_OPENED;    
        }
        else
        {
            /* openCfg related configurations like chCfg, lowPowerMode, adcCfg
             * are only used on the first sensor start. If they are different
             * on a subsequent sensor start, then generate a fatal error
             * so the user does not think that the new (changed) configuration
             * takes effect, the board needs to be reboot for the new
             * configuration to be applied.
             */
            MMWave_OpenCfg openCfg;
            CLI_getMMWaveExtensionOpenConfig (&openCfg);
            /* Compare openCfg->chCfg*/
            if(memcmp((void *)&gMmwMssMCB.cfg.openCfg.chCfg, (void *)&openCfg.chCfg,
                              sizeof(rlChanCfg_t)) != 0)
            {
                MmwDemo_debugAssert(0);
            }
            
            /* Compare openCfg->lowPowerMode*/
            if(memcmp((void *)&gMmwMssMCB.cfg.openCfg.lowPowerMode, (void *)&openCfg.lowPowerMode,
                              sizeof(rlLowPowerModeCfg_t)) != 0)
            {
                MmwDemo_debugAssert(0);
            }
            /* Compare openCfg->adcOutCfg*/
            if(memcmp((void *)&gMmwMssMCB.cfg.openCfg.adcOutCfg, (void *)&openCfg.adcOutCfg,
                              sizeof(rlAdcOutCfg_t)) != 0)
            {
                MmwDemo_debugAssert(0);
            }
        }
    
        
    
        /***********************************************************************************
         * Retrieve mmwave Control related config before calling startSensor
         ***********************************************************************************/
        /* Get the mmWave ctrlCfg from the CLI mmWave Extension */
        if(doReconfig)
        {
            /* if MmwDemo_openSensor has non-first time related processing, call here again*/
            /* call sensor config */
            CLI_getMMWaveExtensionConfig (&gMmwMssMCB.cfg.ctrlCfg);
            retVal = MmwDemo_configSensor();
            if(retVal != 0)
            {
                return -1;
            }
        }
        retVal = MmwDemo_startSensor();
        if(retVal != 0)
        {
            return -1;
        }
    
        /***********************************************************************************
         * Set the state
         ***********************************************************************************/
        gMmwMssMCB.sensorState = MmwDemo_SensorState_STARTED;
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the sensor stop command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLISensorStop (int32_t argc, char* argv[])
    {
        if ((gMmwMssMCB.sensorState == MmwDemo_SensorState_STOPPED) ||
            (gMmwMssMCB.sensorState == MmwDemo_SensorState_INIT) ||
            (gMmwMssMCB.sensorState == MmwDemo_SensorState_OPENED))
        {
            CLI_write ("Ignored: Sensor is already stopped\n");
            return 0;
        }
    
        MmwDemo_stopSensor();
    
        MmwDemo_resetStaticCfgPendingState();
    
        gMmwMssMCB.sensorState = MmwDemo_SensorState_STOPPED;
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to get sub-frame number
     *
     *  @param[in] argc  Number of arguments
     *  @param[in] argv  Arguments
     *  @param[in] expectedArgc Expected number of arguments
     *  @param[out] subFrameNum Sub-frame Number (0 based)
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIGetSubframe (int32_t argc, char* argv[], int32_t expectedArgc,
                                           int8_t* subFrameNum)
    {
        int8_t subframe;
        
        /* Sanity Check: Minimum argument check */
        if (argc != expectedArgc)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /*Subframe info is always in position 1*/
        subframe = (int8_t) atoi(argv[1]);
    
        if(subframe >= (int8_t)RL_MAX_SUBFRAMES)
        {
            CLI_write ("Error: Subframe number is invalid\n");
            return -1;
        }
    
        *subFrameNum = (int8_t)subframe;
    
        return 0;
    }
    
    
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for gui monitoring configuration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIGuiMonSel (int32_t argc, char* argv[])
    {
        MmwDemo_GuiMonSel   guiMonSel;
        int8_t              subFrameNum;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 8, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize the guiMonSel configuration: */
        memset ((void *)&guiMonSel, 0, sizeof(MmwDemo_GuiMonSel));
    
        /* Populate configuration: */
        guiMonSel.detectedObjects           = atoi (argv[2]);
        guiMonSel.logMagRange               = atoi (argv[3]);
        guiMonSel.noiseProfile              = atoi (argv[4]);
        guiMonSel.rangeAzimuthHeatMap       = atoi (argv[5]);
        guiMonSel.rangeDopplerHeatMap       = atoi (argv[6]);
        guiMonSel.statsInfo                 = atoi (argv[7]);
    
        MmwDemo_CfgUpdate((void *)&guiMonSel, MMWDEMO_GUIMONSEL_OFFSET,
            sizeof(MmwDemo_GuiMonSel), subFrameNum);
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for CFAR configuration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLICfarCfg (int32_t argc, char* argv[])
    {
        DPU_CFARCAProc_CfarCfg   cfarCfg;
        uint32_t            procDirection;
        int8_t              subFrameNum;
        float               threshold;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 10, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&cfarCfg, 0, sizeof(cfarCfg));
    
        /* Populate configuration: */
        procDirection             = (uint32_t) atoi (argv[2]);
        cfarCfg.averageMode       = (uint8_t) atoi (argv[3]);
        cfarCfg.winLen            = (uint8_t) atoi (argv[4]);
        cfarCfg.guardLen          = (uint8_t) atoi (argv[5]);
        cfarCfg.noiseDivShift     = (uint8_t) atoi (argv[6]);
        cfarCfg.cyclicMode        = (uint8_t) atoi (argv[7]);
        threshold                 = (float) atof (argv[8]);
        cfarCfg.peakGroupingEn    = (uint8_t) atoi (argv[9]);
    
        if (threshold > 100.0)
        {
            CLI_write("Error: Maximum value for CFAR thresholdScale is 100.0 dB.\n");
            return -1;
        }   
        
        /* threshold is a float value from 0-100dB. It needs to
           be later converted to linear scale (conversion can only be done
           when the number of virtual antennas is known) before passing it
           to CFAR DPU.
           For now, the threshold will be coded in a 16bit integer in the following
           way:
           suppose threshold is a float represented as XYZ.ABC
           it will be saved as a 16bit integer XYZAB       
           that is, 2 decimal cases are saved.*/
        threshold = threshold * MMWDEMO_CFAR_THRESHOLD_ENCODING_FACTOR;   
        cfarCfg.thresholdScale    = (uint16_t) threshold;
        
        /* Save Configuration to use later */     
        if (procDirection == 0)
        {
            MmwDemo_CfgUpdate((void *)&cfarCfg, MMWDEMO_CFARCFGRANGE_OFFSET,
                              sizeof(cfarCfg), subFrameNum);
        }
        else
        {
            MmwDemo_CfgUpdate((void *)&cfarCfg, MMWDEMO_CFARCFGDOPPLER_OFFSET,
                              sizeof(cfarCfg), subFrameNum);
        }
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for CFAR FOV (Field Of View) configuration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLICfarFovCfg (int32_t argc, char* argv[])
    {
        DPU_CFARCAProc_FovCfg   fovCfg;
        uint32_t            procDirection;
        int8_t              subFrameNum;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 5, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&fovCfg, 0, sizeof(fovCfg));
    
        /* Populate configuration: */
        procDirection             = (uint32_t) atoi (argv[2]);
        fovCfg.min                = (float) atof (argv[3]);
        fovCfg.max                = (float) atof (argv[4]);
    
        /* Save Configuration to use later */
        if (procDirection == 0)
        {
            MmwDemo_CfgUpdate((void *)&fovCfg, MMWDEMO_FOVRANGE_OFFSET,
                              sizeof(fovCfg), subFrameNum);
        }
        else
        {
            MmwDemo_CfgUpdate((void *)&fovCfg, MMWDEMO_FOVDOPPLER_OFFSET,
                              sizeof(fovCfg), subFrameNum);
        }
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for AoA FOV (Field Of View) configuration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIAoAFovCfg (int32_t argc, char* argv[])
    {
        DPU_AoAProc_FovAoaCfg   fovCfg;
        int8_t              subFrameNum;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 6, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&fovCfg, 0, sizeof(fovCfg));
    
        /* Populate configuration: */
        fovCfg.minAzimuthDeg      = (float) atoi (argv[2]);
        fovCfg.maxAzimuthDeg      = (float) atoi (argv[3]);
        fovCfg.minElevationDeg    = (float) atoi (argv[4]);
        fovCfg.maxElevationDeg    = (float) atoi (argv[5]);
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&fovCfg, MMWDEMO_FOVAOA_OFFSET,
                          sizeof(fovCfg), subFrameNum);
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for extended maximum velocity configuration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIExtendedMaxVelocity (int32_t argc, char* argv[])
    {
        DPU_AoAProc_ExtendedMaxVelocityCfg   cfg;
        int8_t              subFrameNum;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 3, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&cfg, 0, sizeof(cfg));
    
        /* Populate configuration: */
        cfg.enabled      = (uint8_t) atoi (argv[2]);
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&cfg, MMWDEMO_EXTMAXVEL_OFFSET,
                          sizeof(cfg), subFrameNum);
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for multi object beam forming configuration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIMultiObjBeamForming (int32_t argc, char* argv[])
    {
        DPU_AoAProc_MultiObjBeamFormingCfg cfg;
        int8_t              subFrameNum;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 4, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&cfg, 0, sizeof(cfg));
    
        /* Populate configuration: */
        cfg.enabled                     = (uint8_t) atoi (argv[2]);
        cfg.multiPeakThrsScal           = (float) atof (argv[3]);
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&cfg, MMWDEMO_MULTIOBJBEAMFORMING_OFFSET,
                          sizeof(cfg), subFrameNum);
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for DC range calibration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLICalibDcRangeSig (int32_t argc, char* argv[])
    {
        DPU_RangeProc_CalibDcRangeSigCfg cfg;
        uint32_t                   log2NumAvgChirps;
        int8_t                     subFrameNum;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 6, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration for DC range signature calibration */
        memset ((void *)&cfg, 0, sizeof(cfg));
    
        /* Populate configuration: */
        cfg.enabled          = (uint16_t) atoi (argv[2]);
        cfg.negativeBinIdx   = (int16_t)  atoi (argv[3]);
        cfg.positiveBinIdx   = (int16_t)  atoi (argv[4]);
        cfg.numAvgChirps     = (uint16_t) atoi (argv[5]);
    
        if (cfg.negativeBinIdx > 0)
        {
            CLI_write ("Error: Invalid negative bin index\n");
            return -1;
        }
        if ((cfg.positiveBinIdx - cfg.negativeBinIdx + 1) > DPU_RANGEPROC_SIGNATURE_COMP_MAX_BIN_SIZE)
        {
            CLI_write ("Error: Number of bins exceeds the limit\n");
            return -1;
        }
        log2NumAvgChirps = (uint32_t) mathUtils_ceilLog2(cfg.numAvgChirps);
        if (cfg.numAvgChirps != (1U << log2NumAvgChirps))
        {
            CLI_write ("Error: Number of averaged chirps is not power of two\n");
            return -1;
        }
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&cfg, MMWDEMO_CALIBDCRANGESIG_OFFSET,
                          sizeof(cfg), subFrameNum);
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      Clutter removal Configuration
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIClutterRemoval (int32_t argc, char* argv[])
    {
        DPC_ObjectDetection_StaticClutterRemovalCfg_Base cfg;
        int8_t              subFrameNum;
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 3, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration for clutter removal */
        memset ((void *)&cfg, 0, sizeof(cfg));
    
        /* Populate configuration: */
        cfg.enabled          = (uint16_t) atoi (argv[2]);
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&cfg, MMWDEMO_STATICCLUTTERREMOFVAL_OFFSET,
                          sizeof(cfg), subFrameNum);
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for data logger set command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIADCBufCfg (int32_t argc, char* argv[])
    {
        MmwDemo_ADCBufCfg   adcBufCfg;
        int8_t              subFrameNum;
    
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: This command is not allowed after sensor has started\n");
            return 0;
        }
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 6, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize the ADC Output configuration: */
        memset ((void *)&adcBufCfg, 0, sizeof(adcBufCfg));
    
        /* Populate configuration: */
        adcBufCfg.adcFmt          = (uint8_t) atoi (argv[2]);
        adcBufCfg.iqSwapSel       = (uint8_t) atoi (argv[3]);
        adcBufCfg.chInterleave    = (uint8_t) atoi (argv[4]);
        adcBufCfg.chirpThreshold  = (uint8_t) atoi (argv[5]);
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&adcBufCfg,
                          MMWDEMO_ADCBUFCFG_OFFSET,
                          sizeof(MmwDemo_ADCBufCfg), subFrameNum);
        return 0;
    }
    
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for compensation of range bias and channel phase offsets
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLICompRangeBiasAndRxChanPhaseCfg (int32_t argc, char* argv[])
    {
        DPU_AoAProc_compRxChannelBiasCfg   cfg;
        int32_t Re, Im;
        int32_t argInd;
        int32_t i;
    
        /* Sanity Check: Minimum argument check */
        if (argc != (1+1+SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2))
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&cfg, 0, sizeof(cfg));
    
        /* Populate configuration: */
        cfg.rangeBias          = (float) atof (argv[1]);
    
        argInd = 2;
        for (i=0; i < SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL; i++)
        {
            Re = (int32_t) (atof (argv[argInd++]) * 32768.);
            MATHUTILS_SATURATE16(Re);
            cfg.rxChPhaseComp[i].real = (int16_t) Re;
    
            Im = (int32_t) (atof (argv[argInd++]) * 32768.);
            MATHUTILS_SATURATE16(Im);
            cfg.rxChPhaseComp[i].imag = (int16_t) Im;
    
        }
        /* Save Configuration to use later */
        memcpy((void *) &gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.compRxChanCfg,
               &cfg, sizeof(cfg));
    
        gMmwMssMCB.objDetCommonCfg.isCompRxChannelBiasCfgPending = 1;
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for measurement configuration of range bias
     *      and channel phase offsets
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIMeasureRangeBiasAndRxChanPhaseCfg (int32_t argc, char* argv[])
    {
        DPC_ObjectDetection_MeasureRxChannelBiasCfg   cfg;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 4)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&cfg, 0, sizeof(cfg));
    
        /* Populate configuration: */
        cfg.enabled          = (uint8_t) atoi (argv[1]);
        cfg.targetDistance   = (float) atof (argv[2]);
        cfg.searchWinSize   = (float) atof (argv[3]);
    
        /* Save Configuration to use later */
        memcpy((void *) &gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.measureRxChannelBiasCfg,
               &cfg, sizeof(cfg));
    
        gMmwMssMCB.objDetCommonCfg.isMeasureRxChannelBiasCfgPending = 1;
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for BPM configuration supported by the mmw Demo
     *      Note that there is a generic BPM configuration command supported by
     *      utils/cli and mmwave. The generic BPM command is not supported by the
     *      demo as the mmw demo assumes a specific BPM pattern for the TX antennas.
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIBpmCfg (int32_t argc, char* argv[])
    {
        int8_t              subFrameNum;
        MmwDemo_BpmCfg      bpmCfg;
    
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: This command is not allowed after sensor has started\n");
            return 0;
        }
    
        /* Sanity Check: Minimum argument check */
        if (argc != 5)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 5, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration for DC range signature calibration */
        memset ((void *)&bpmCfg, 0, sizeof(MmwDemo_BpmCfg));
    
        /* Populate configuration: */
        bpmCfg.isEnabled = (bool) atoi(argv[2]) ;
        bpmCfg.chirp0Idx = (uint16_t) atoi(argv[3]) ;
        bpmCfg.chirp1Idx = (uint16_t) atoi(argv[4]) ;
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&bpmCfg, MMWDEMO_BPMCFG_OFFSET,
                          sizeof(MmwDemo_BpmCfg), subFrameNum);
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for configuring CQ RX Saturation monitor
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIChirpQualityRxSatMonCfg (int32_t argc, char* argv[])
    {
        rlRxSatMonConf_t        cqSatMonCfg;
    
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: This command is not allowed after sensor has started\n");
            return 0;
        }
    
        /* Sanity Check: Minimum argument check */
        if (argc != 6)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&cqSatMonCfg, 0, sizeof(rlRxSatMonConf_t));
    
        /* Populate configuration: */
        cqSatMonCfg.profileIndx                 = (uint8_t) atoi (argv[1]);
    
        if(cqSatMonCfg.profileIndx < RL_MAX_PROFILES_CNT)
        {
    
            cqSatMonCfg.satMonSel                   = (uint8_t) atoi (argv[2]);
            cqSatMonCfg.primarySliceDuration        = (uint16_t) atoi (argv[3]);
            cqSatMonCfg.numSlices                   = (uint16_t) atoi (argv[4]);
            cqSatMonCfg.rxChannelMask               = (uint8_t) atoi (argv[5]);
    
            /* Save Configuration to use later */
            gMmwMssMCB.cqSatMonCfg[cqSatMonCfg.profileIndx] = cqSatMonCfg;
    
            return 0;
        }
        else
        {
            return -1;
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for configuring CQ Signal & Image band monitor
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIChirpQualitySigImgMonCfg (int32_t argc, char* argv[])
    {
        rlSigImgMonConf_t       cqSigImgMonCfg;
    
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: This command is not allowed after sensor has started\n");
            return 0;
        }
    
        /* Sanity Check: Minimum argument check */
        if (argc != 4)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Initialize configuration: */
        memset ((void *)&cqSigImgMonCfg, 0, sizeof(rlSigImgMonConf_t));
    
        /* Populate configuration: */
        cqSigImgMonCfg.profileIndx              = (uint8_t) atoi (argv[1]);
    
        if(cqSigImgMonCfg.profileIndx < RL_MAX_PROFILES_CNT)
        {
            cqSigImgMonCfg.numSlices            = (uint8_t) atoi (argv[2]);
            cqSigImgMonCfg.timeSliceNumSamples  = (uint16_t) atoi (argv[3]);
    
            /* Save Configuration to use later */
            gMmwMssMCB.cqSigImgMonCfg[cqSigImgMonCfg.profileIndx] = cqSigImgMonCfg;
    
            return 0;
        }
        else
        {
            return -1;
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for enabling analog monitors
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIAnalogMonitorCfg (int32_t argc, char* argv[])
    {
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: This command is not allowed after sensor has started\n");
            return 0;
        }
    
        /* Sanity Check: Minimum argument check */
        if (argc != 3)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Save Configuration to use later */
        gMmwMssMCB.anaMonCfg.rxSatMonEn = atoi (argv[1]);
        gMmwMssMCB.anaMonCfg.sigImgMonEn = atoi (argv[2]);
    
        gMmwMssMCB.isAnaMonCfgPending = 1;
    
        return 0;
    }
    
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the High Speed Interface
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLILvdsStreamCfg (int32_t argc, char* argv[])
    {
        MmwDemo_LvdsStreamCfg   cfg;
        int8_t                  subFrameNum;
    
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: This command is not allowed after sensor has started\n");
            return 0;
        }
    
        if(MmwDemo_CLIGetSubframe(argc, argv, 5, &subFrameNum) < 0)
        {
            return -1;
        }
    
        /* Initialize configuration for DC range signature calibration */
        memset ((void *)&cfg, 0, sizeof(MmwDemo_LvdsStreamCfg));
    
        /* Populate configuration: */
        cfg.isHeaderEnabled = (bool)    atoi(argv[2]);
        cfg.dataFmt         = (uint8_t) atoi(argv[3]);
        cfg.isSwEnabled     = (bool)    atoi(argv[4]);
    
        /* If both h/w and s/w are enabled, HSI header must be enabled, because
         * we don't allow mixed h/w session without HSI header
         * simultaneously with s/w session with HSI header (s/w session always
         * streams HSI header) */
        if ((cfg.isSwEnabled == true) && (cfg.dataFmt != MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_DISABLED))
        {
            if (cfg.isHeaderEnabled == false)
            {
                CLI_write("Error: header must be enabled when both h/w and s/w streaming are enabled\n");
                return -1;
            }
        }
    
        /* Save Configuration to use later */
        MmwDemo_CfgUpdate((void *)&cfg,
                          MMWDEMO_LVDSSTREAMCFG_OFFSET,
                          sizeof(MmwDemo_LvdsStreamCfg), subFrameNum);
    
        return 0;
    }
    
    
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for configuring the data port
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIConfigDataPort (int32_t argc, char* argv[])
    {
        uint32_t baudrate;
        bool  ackPing;
        UART_Params uartParams;
        uint8_t ackData[16];
        
    
        if (gMmwMssMCB.sensorState == MmwDemo_SensorState_STARTED)
        {
            CLI_write ("Ignored: This command is not allowed after sensor has started\n");
            return 0;
        }
    
        /* Populate configuration: */
        baudrate = (uint32_t) atoi(argv[1]);
        ackPing = (bool) atoi(argv[2]);
    
        /* check if requested value is less than max supported value */
        if (baudrate > MMWDEMO_DATAUART_MAX_BAUDRATE_SUPPORTED)
        {
            CLI_write ("Ignored: Invalid baud rate (%d) specified\n",baudrate);
            return 0;
        }
    
        /* re-open UART port if requested baud rate is different than current */
        if (gMmwMssMCB.cfg.platformCfg.loggingBaudRate != baudrate)
        {
            /* close previous opened handle */
            /* since the sensor is not running at this time, it is safe to close
               the existing port */
            if (gMmwMssMCB.loggingUartHandle != NULL)
            {
                UART_close(gMmwMssMCB.loggingUartHandle);
                gMmwMssMCB.loggingUartHandle = NULL;
            }   
            
            /* Setup the default UART Parameters */
            UART_Params_init(&uartParams);
            uartParams.writeDataMode  = UART_DATA_BINARY;
            uartParams.readDataMode   = UART_DATA_BINARY;
            uartParams.clockFrequency = gMmwMssMCB.cfg.platformCfg.sysClockFrequency;
            uartParams.baudRate       = baudrate;
            uartParams.isPinMuxDone   = 1U;
    
            /* Open the Logging UART Instance: */
            gMmwMssMCB.loggingUartHandle = UART_open(1, &uartParams);
            if (gMmwMssMCB.loggingUartHandle == NULL)
            {
                CLI_write ("Error: Unable to open the Logging UART Instance\n");
                return -1;
            }
            gMmwMssMCB.cfg.platformCfg.loggingBaudRate = baudrate;
            CLI_write ("Data port baud rate changed to %d\n",baudrate);
        }
    
        /* regardless of baud rate update, ack back to the host over this UART 
           port if handle is valid and user has requested the ack back */
        if ((gMmwMssMCB.loggingUartHandle != NULL) && (ackPing == true))
        {
            memset(ackData,0xFF,sizeof(ackData));
            UART_writePolling (gMmwMssMCB.loggingUartHandle,
                               (uint8_t*)ackData,
                               sizeof(ackData));
        }
    
        return 0;
    }
    
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for querying Demo status
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_CLIQueryDemoStatus (int32_t argc, char* argv[])
    {
        CLI_write ("Sensor State: %d\n",gMmwMssMCB.sensorState);
        CLI_write ("Data port baud rate: %d\n",gMmwMssMCB.cfg.platformCfg.loggingBaudRate);
    
        return 0;
    }
    
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Execution Task
     *
     *  @retval
     *      Not Applicable.
     */
    void MmwDemo_CLIInit (uint8_t taskPriority)
    {
        CLI_Cfg     cliCfg;
        char        demoBanner[256];
        uint32_t    cnt;
    
        /* Create Demo Banner to be printed out by CLI */
        sprintf(&demoBanner[0], 
                           "******************************************\n" \
                           "xWR16xx MMW Demo %02d.%02d.%02d.%02d\n"  \
                           "******************************************\n", 
                            MMWAVE_SDK_VERSION_MAJOR,
                            MMWAVE_SDK_VERSION_MINOR,
                            MMWAVE_SDK_VERSION_BUGFIX,
                            MMWAVE_SDK_VERSION_BUILD
                );
    
        /* Initialize the CLI configuration: */
        memset ((void *)&cliCfg, 0, sizeof(CLI_Cfg));
    
        /* Populate the CLI configuration: */
        cliCfg.cliPrompt                    = "mmwDemo:/>";
        cliCfg.cliBanner                    = demoBanner;
        cliCfg.cliUartHandle                = gMmwMssMCB.commandUartHandle;
        cliCfg.taskPriority                 = taskPriority;
        cliCfg.socHandle                    = gMmwMssMCB.socHandle;
        cliCfg.mmWaveHandle                 = gMmwMssMCB.ctrlHandle;
        cliCfg.enableMMWaveExtension        = 1U;
        cliCfg.usePolledMode                = true;
        cliCfg.overridePlatform             = false;
        cliCfg.overridePlatformString       = NULL;
        
        cnt=0;
        cliCfg.tableEntry[cnt].cmd            = "sensorStart";
        cliCfg.tableEntry[cnt].helpString     = "[doReconfig(optional, default:enabled)]";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLISensorStart;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "sensorStop";
        cliCfg.tableEntry[cnt].helpString     = "No arguments";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLISensorStop;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "guiMonitor";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <detectedObjects> <logMagRange> <noiseProfile> <rangeAzimuthHeatMap> <rangeDopplerHeatMap> <statsInfo>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIGuiMonSel;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "cfarCfg";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <procDirection> <averageMode> <winLen> <guardLen> <noiseDiv> <cyclicMode> <thresholdScale> <peakGroupingEn>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLICfarCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "multiObjBeamForming";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <enabled> <threshold>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIMultiObjBeamForming;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "calibDcRangeSig";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <enabled> <negativeBinIdx> <positiveBinIdx> <numAvgFrames>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLICalibDcRangeSig;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "clutterRemoval";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <enabled>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIClutterRemoval;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "adcbufCfg";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <adcOutputFmt> <SampleSwap> <ChanInterleave> <ChirpThreshold>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIADCBufCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "compRangeBiasAndRxChanPhase";
        cliCfg.tableEntry[cnt].helpString     = "<rangeBias> <Re00> <Im00> <Re01> <Im01> <Re02> <Im02> <Re03> <Im03> <Re10> <Im10> <Re11> <Im11> <Re12> <Im12> <Re13> <Im13> ";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLICompRangeBiasAndRxChanPhaseCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "measureRangeBiasAndRxChanPhase";
        cliCfg.tableEntry[cnt].helpString     = "<enabled> <targetDistance> <searchWin>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIMeasureRangeBiasAndRxChanPhaseCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "aoaFovCfg";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <minAzimuthDeg> <maxAzimuthDeg> <minElevationDeg> <maxElevationDeg>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIAoAFovCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "cfarFovCfg";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <procDirection> <min (meters or m/s)> <max (meters or m/s)>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLICfarFovCfg;
        cnt++;
        cliCfg.tableEntry[cnt].cmd            = "extendedMaxVelocity";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <enabled>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIExtendedMaxVelocity;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "bpmCfg";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <enabled> <chirp0Idx> <chirp1Idx>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIBpmCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "CQRxSatMonitor";
        cliCfg.tableEntry[cnt].helpString     = "<profile> <satMonSel> <priSliceDuration> <numSlices> <rxChanMask>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIChirpQualityRxSatMonCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "CQSigImgMonitor";
        cliCfg.tableEntry[cnt].helpString     = "<profile> <numSlices> <numSamplePerSlice>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIChirpQualitySigImgMonCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "analogMonitor";
        cliCfg.tableEntry[cnt].helpString     = "<rxSaturation> <sigImgBand>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIAnalogMonitorCfg;
        cnt++;
    
        cliCfg.tableEntry[cnt].cmd            = "lvdsStreamCfg";
        cliCfg.tableEntry[cnt].helpString     = "<subFrameIdx> <enableHeader> <dataFmt> <enableSW>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLILvdsStreamCfg;
        cnt++;
        
        cliCfg.tableEntry[cnt].cmd            = "configDataPort";
        cliCfg.tableEntry[cnt].helpString     = "<baudrate> <ackPing>";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIConfigDataPort;
        cnt++;
        
        cliCfg.tableEntry[cnt].cmd            = "queryDemoStatus";
        cliCfg.tableEntry[cnt].helpString     = "";
        cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIQueryDemoStatus;
        cnt++;
    
        /* Open the CLI: */
        if (CLI_open (&cliCfg) < 0)
        {
            System_printf ("Error: Unable to open the CLI\n");
            return;
        }
        System_printf ("Debug: CLI is operational\n");
        return;
    }
    
    
    

    CLI file for SDK 3.4 is not even in mmwave demo folder, but is used to configure the radar in the demo...do I bring this file over too?

    /*
     *   @file  cli_mmwave.c
     *
     *   @brief
     *      CLI Extension which handles the mmWave configuration
     *
     *  \par
     *  NOTE:
     *      (C) Copyright 2016 Texas Instruments, Inc.
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**************************************************************************
     *************************** Include Files ********************************
     **************************************************************************/
    
    /* Standard Include Files. */
    #include <stdint.h>
    #include <stdlib.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    
    /* mmWave SDK Include Files: */
    #include <ti/common/sys_common.h>
    #include <ti/common/mmwave_sdk_version.h>
    #include <ti/drivers/uart/UART.h>
    #include <ti/control/mmwavelink/mmwavelink.h>
    #include <ti/control/mmwave/mmwave.h>
    #include <ti/utils/cli/cli.h>
    #include <ti/utils/cli/include/cli_internal.h>
    
    /**************************************************************************
     ******************* CLI mmWave Extension Local Definitions****************
     **************************************************************************/
    
    /*This is used in several formulas that translate CLI input to mmwavelink units.
      It must be defined as double to achieve the correct precision
      on the formulas (if defined as float there will be small precision errors
      that may result in the computed value being out of mmwavelink range if the 
      CLI input is a borderline value).
    
      The vaiable is initialized in @ref CLI_MMWaveExtensionInit() */
    double gCLI_mmwave_freq_scale_factor;
    
    
    /**************************************************************************
     ******************* CLI mmWave Extension Local Functions *****************
     **************************************************************************/
    
    /* CLI Command Functions */
    static int32_t CLI_MMWaveVersion (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveFlushCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveDataOutputMode (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveChannelCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveADCCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveProfileCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveChirpCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveFrameCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveAdvFrameCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveSubFrameCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveLowPowerCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveContModeCfg (int32_t argc, char* argv[]);
    static int32_t CLI_MMWaveBPMCfgAdvanced (int32_t argc, char* argv[]);
    
    #undef CLI_MMWAVE_HELP_SUPPORT
    
    /**************************************************************************
     ************************ CLI mmWave Extension Globals ********************
     **************************************************************************/
    
    /**
     * @brief
     *  This is the mmWave extension table added to the CLI.
     */
    CLI_CmdTableEntry gCLIMMWaveExtensionTable[] =
    {
        {
            "version",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "No arguments",
    #else
            NULL,
    #endif
            CLI_MMWaveVersion
        },
        {
            "flushCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "No arguments",
    #else
            NULL,
    #endif
            CLI_MMWaveFlushCfg
        },
        {
            "dfeDataOutputMode",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<modeType>   1-Chirp and 2-Continuous",
    #else
            NULL,
    #endif
            CLI_MMWaveDataOutputMode
        },
        {
            "channelCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<rxChannelEn> <txChannelEn> <cascading>",
    #else
            NULL,
    #endif
            CLI_MMWaveChannelCfg
        },
        {
            "adcCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<numADCBits> <adcOutputFmt>",
    #else
            NULL,
    #endif
            CLI_MMWaveADCCfg
        },
        {
            "profileCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<profileId> <startFreq> <idleTime> <adcStartTime> <rampEndTime> <txOutPower> <txPhaseShifter> <freqSlopeConst> <txStartTime> <numAdcSamples> <digOutSampleRate> <hpfCornerFreq1> <hpfCornerFreq2> <rxGain>",
    #else
            NULL,
    #endif
            CLI_MMWaveProfileCfg
        },
        {
            "chirpCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<startIdx> <endIdx> <profileId> <startFreqVar> <freqSlopeVar> <idleTimeVar> <adcStartTimeVar> <txEnable>",
    #else
            NULL,
    #endif
            CLI_MMWaveChirpCfg
        },
        {
            "frameCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<chirpStartIdx> <chirpEndIdx> <numLoops> <numFrames> <framePeriodicity> <triggerSelect> <frameTriggerDelay>",
    #else
            NULL,
    #endif
            CLI_MMWaveFrameCfg
        },
        {
            "advFrameCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<numOfSubFrames> <forceProfile> <numFrames> <triggerSelect> <frameTrigDelay>",
    #else
            NULL,
    #endif
            CLI_MMWaveAdvFrameCfg
        },
        {
            "subFrameCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<subFrameNum> <forceProfileIdx> <chirpStartIdx> <numOfChirps> <numLoops> <burstPeriodicity> <chirpStartIdxOffset> <numOfBurst> <numOfBurstLoops> <subFramePeriodicity>",
    #else
            NULL,
    #endif
            CLI_MMWaveSubFrameCfg
        },
        {
            "lowPower",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<reserved> <lpAdcMode>",
    #else
            NULL,
    #endif
            CLI_MMWaveLowPowerCfg
        },
        {
            "contModeCfg",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<startFreq> <txOutPower> <txPhaseShifter> <digOutSampleRate> <hpfCornerFreq1> <hpfCornerFreq2> <rxGain> <reserved> <numSamples>",
    #else
            NULL,
    #endif
            CLI_MMWaveContModeCfg,
        },
        {
            "bpmCfgAdvanced",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<chirpStartIdx> <chirpEndIdx> <constBpmVal>",
    #else
            NULL,
    #endif
            CLI_MMWaveBPMCfgAdvanced
        },
        {
            NULL,
            NULL,
            NULL
        }
    };
    
    /**
     * @brief
     *  Global MMWave configuration tracked by the module.
     */
    MMWave_CtrlCfg      gCLIMMWaveControlCfg;
    
    /**
     * @brief
     *  Global MMWave open configuration tracked by the module.
     */
    MMWave_OpenCfg      gCLIMMWaveOpenCfg;
    
    /**
     * @brief
     *  Global mmwave device part number and string table
     */
    CLI_partInfoString partInfoStringArray[] =
    {
        /* Maximum part number string size is CLI_MAX_PARTNO_STRING_LEN */
    #ifdef SOC_XWR14XX
        {SOC_AWR14XX_nonSecure_PartNumber,  "AWR14xx non-secure"},
        {SOC_IWR14XX_nonSecure_PartNumber,  "IWR14xx non-secure"},
    #endif
    
    #ifdef SOC_XWR16XX
        {SOC_AWR16XX_nonSecure_PartNumber,  "AWR16xx non-secure"},
        {SOC_IWR16XX_nonSecure_PartNumber,  "IWR16xx non-secure"},
        {SOC_AWR16XX_Secure_PartNumber,     "AWR16xx secure"},
        {SOC_IWR16XX_Secure_PartNumber,     "IWR16xx secure"},
    #endif
    
    #ifdef SOC_XWR18XX
        {SOC_AWR18XX_nonSecure_PartNumber,  "AWR18xx non-secure"},
        {SOC_IWR18XX_nonSecure_PartNumber,  "IWR18xx non-secure"},
        {SOC_AWR18XX_Secure_PartNumber,     "AWR18xx secure"},
    #endif
    
    #ifdef SOC_XWR68XX
        {SOC_IWR64XX_nonSecure_PartNumber,  "IWR64xx non-secure"},    
        {SOC_IWR68XX_nonSecure_PartNumber,  "IWR68xx non-secure"},    
        {SOC_IWR68XX_Secure_PartNumber,     "IWR68xx secure"},   
        {SOC_AWR64XX_nonSecure_PartNumber,  "AWR64xx non-secure"},
        {SOC_AWR68XX_nonSecure_PartNumber,  "AWR68xx non-secure"},
        {SOC_IWR68XX_AOP_nonSecure_PartNumber,  "IWR68xx AOP non-secure"},
        {SOC_IWR68XX_AOP_Secure_PartNumber, "IWR68xx AOP secure"},
    #endif
    
        /* last entry of the table */
        {0U,                                "Not Supported"}
    };
    
    /**************************************************************************
     ********************** CLI mmWave Extension Functions ********************
     **************************************************************************/
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the version command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveVersion (int32_t argc, char* argv[])
    {
        rlVersion_t    verArgs;
        int32_t        retVal;
        uint8_t        rfPatchBuildVer, rfPatchDebugVer;
        rlRfDieIdCfg_t  dieId = { 0 };
        SOC_PartNumber  devicePartNumber;
        uint8_t         index;
        int32_t         errCode;
    
        if(gCLI.cfg.overridePlatform == false)
        {
            /* print the platform */
    #ifdef SOC_XWR14XX
            CLI_write ("Platform                : xWR14xx\n");
    #elif defined(SOC_XWR16XX)              
            CLI_write ("Platform                : xWR16xx\n");
    #elif defined(SOC_XWR18XX)              
            CLI_write ("Platform                : xWR18xx\n");
    #elif defined(SOC_XWR68XX)
            CLI_write ("Platform                : xWR68xx\n");
    #else                                   
            CLI_write ("Platform                : unknown\n");
    #endif
        }
        else
        {
            CLI_write ("Platform                : %s\n", gCLI.cfg.overridePlatformString);
        }
    
        /* Get the version string: */
        retVal = SOC_getDevicePartNumber(gCLI.cfg.socHandle, &devicePartNumber, &errCode);
        if (retVal < 0)
        {
            CLI_write ("Error: Unable to get the device version from SOC[Error %d]\n", errCode);
            return -1;
        }
    
        /* Get the version string: */
        retVal = rlDeviceGetVersion(RL_DEVICE_MAP_INTERNAL_BSS, &verArgs);
        if (retVal < 0)
        {
            CLI_write ("Error: Unable to get the device version from mmWave link [Error %d]\n", retVal);
            return -1;
        }
    
        /* Display the version information on the CLI Console: */
        CLI_write ("mmWave SDK Version      : %02d.%02d.%02d.%02d\n",
                                MMWAVE_SDK_VERSION_MAJOR,
                                MMWAVE_SDK_VERSION_MINOR,
                                MMWAVE_SDK_VERSION_BUGFIX,
                                MMWAVE_SDK_VERSION_BUILD);
        index = 0;
        while(partInfoStringArray[index].partNumber !=0U)
        {
            if(devicePartNumber == partInfoStringArray[index].partNumber)
            {
                /* found device in supported list */
                break;
            }
            index++;
        }
        if(partInfoStringArray[index].partNumber ==0U)
        {
            /* Device is not found in the list: */
            /* Display the device information on the CLI Console: */
            CLI_write ("Device Info             : Device#%x ES %02d.%02d\n",
                       devicePartNumber,verArgs.rf.hwMajor, verArgs.rf.hwMinor);
        }
        else
        {
            /* Display the device information on the CLI Console: */
            CLI_write ("Device Info             : %s ES %02d.%02d\n",
                       partInfoStringArray[index].partNumString,verArgs.rf.hwMajor, verArgs.rf.hwMinor);
        }
    
        CLI_write ("RF F/W Version          : %02d.%02d.%02d.%02d.%02d.%02d.%02d\n",
                    verArgs.rf.fwMajor, verArgs.rf.fwMinor, verArgs.rf.fwBuild, verArgs.rf.fwDebug,
                    verArgs.rf.fwYear, verArgs.rf.fwMonth, verArgs.rf.fwDay);
                                    
        rfPatchDebugVer = ((verArgs.rf.patchBuildDebug) & 0x0F);
        rfPatchBuildVer = (((verArgs.rf.patchBuildDebug) & 0xF0) >> 4);
        
        CLI_write ("RF F/W Patch            : %02d.%02d.%02d.%02d.%02d.%02d.%02d\n",
                    verArgs.rf.patchMajor, verArgs.rf.patchMinor, rfPatchBuildVer, rfPatchDebugVer,
                    verArgs.rf.patchYear, verArgs.rf.patchMonth, verArgs.rf.patchDay);            
        CLI_write ("mmWaveLink Version      : %02d.%02d.%02d.%02d\n",
                    verArgs.mmWaveLink.major, verArgs.mmWaveLink.minor,
                    verArgs.mmWaveLink.build, verArgs.mmWaveLink.debug);
                    
        /* Get the die ID: */
        retVal = rlGetRfDieId(RL_DEVICE_MAP_INTERNAL_BSS, &dieId);
        if (retVal < 0)
        {
            CLI_write ("Error: Unable to get the device die ID from mmWave link [Error %d]\n", retVal);
            return 0;
        }
    
        CLI_write ("Lot number              : %d\n", dieId.lotNo);
        CLI_write ("Wafer number            : %d\n", dieId.waferNo);
        CLI_write ("Die coordinates in wafer: X = %d, Y = %d\n",
                   dieId.devX, dieId.devY);
    
        /* Version string has been formatted successfully. */
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the flush configuration command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveFlushCfg (int32_t argc, char* argv[])
    {
        int32_t errCode;
    
        /* Flush the configuration in the MMWave */
        if (MMWave_flushCfg (gCLI.cfg.mmWaveHandle, &errCode) < 0)
        {
            /* Error: Flushing the configuration failed. Return the error code back to the callee */
            return errCode;
        }
    
        /* Reset the global configuration: */
        memset ((void*)&gCLIMMWaveControlCfg, 0, sizeof(MMWave_CtrlCfg));
    
        /* Reset the open configuration: */
        memset ((void*)&gCLIMMWaveOpenCfg, 0, sizeof(MMWave_OpenCfg));
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the DFE Data Output mode.
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveDataOutputMode (int32_t argc, char* argv[])
    {
        uint32_t cfgMode;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 2)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Get the configuration mode: */
        cfgMode = atoi (argv[1]);
        switch (cfgMode)
        {
            case 1U:
            {
                gCLIMMWaveControlCfg.dfeDataOutputMode = MMWave_DFEDataOutputMode_FRAME;
                break;
            }
            case 2U:
            {
                gCLIMMWaveControlCfg.dfeDataOutputMode = MMWave_DFEDataOutputMode_CONTINUOUS;
                break;
            }
            case 3U:
            {
                gCLIMMWaveControlCfg.dfeDataOutputMode = MMWave_DFEDataOutputMode_ADVANCED_FRAME;
                break;
            }
            default:
            {
                /* Error: Invalid argument. */
                CLI_write ("Error: Invalid mode.\n");
                return -1;
            }
        }
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the channel configuration command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveChannelCfg (int32_t argc, char* argv[])
    {
        rlChanCfg_t     chCfg;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 4)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Initialize the channel configuration: */
        memset ((void *)&chCfg, 0, sizeof(rlChanCfg_t));
    
        /* Populate the channel configuration: */
        chCfg.rxChannelEn = atoi (argv[1]);
        chCfg.txChannelEn = atoi (argv[2]);
        chCfg.cascading   = atoi (argv[3]);
    
        /* Save Configuration to use later */
        memcpy((void *)&gCLIMMWaveOpenCfg.chCfg, (void *)&chCfg, sizeof(rlChanCfg_t));
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the ADC configuration command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveADCCfg (int32_t argc, char* argv[])
    {
        rlAdcOutCfg_t   adcOutCfg;
        int32_t         retVal = 0;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 3)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Initialize the ADC Output configuration: */
        memset ((void *)&adcOutCfg, 0, sizeof(rlAdcOutCfg_t));
    
        /* Populate the ADC Output configuration: */
        adcOutCfg.fmt.b2AdcBits   = atoi (argv[1]);
        adcOutCfg.fmt.b2AdcOutFmt = atoi (argv[2]);
    
        /* Save Configuration to use later */
        memcpy((void *)&gCLIMMWaveOpenCfg.adcOutCfg, (void *)&adcOutCfg, sizeof(rlAdcOutCfg_t));
        return retVal;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the profile configuration command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveProfileCfg (int32_t argc, char* argv[])
    {
        rlProfileCfg_t          profileCfg;
        uint8_t                 index;
        int32_t                 errCode;
        MMWave_ProfileHandle    profileHandle;
        MMWave_ProfileHandle*   ptrBaseCfgProfileHandle;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 15)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Sanity Check: Profile configuration is valid only for the Frame or 
                         Advanced Frame Mode: */
        if ((gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_FRAME) &&
            (gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_ADVANCED_FRAME))
        {
            CLI_write ("Error: Configuration is valid only if the DFE Output Mode is Frame or Advanced Frame\n");
            return -1;
        }
        
        if (gCLIMMWaveControlCfg.dfeDataOutputMode == MMWave_DFEDataOutputMode_FRAME)
        {
            ptrBaseCfgProfileHandle = &gCLIMMWaveControlCfg.u.frameCfg.profileHandle[0U];
        }
        else
        {
            ptrBaseCfgProfileHandle = &gCLIMMWaveControlCfg.u.advancedFrameCfg.profileHandle[0U];
        }
    
        /* Initialize the profile configuration: */
        memset ((void *)&profileCfg, 0, sizeof(rlProfileCfg_t));
    
        /* Populate the profile configuration: */
        profileCfg.profileId             = atoi (argv[1]);
    
        /* Translate from GHz to [1 LSB = gCLI_mmwave_freq_scale_factor * 1e9 / 2^26 Hz] units
         * of mmwavelink format */
        profileCfg.startFreqConst        = (uint32_t) (atof(argv[2]) * (1U << 26) /
                                                       gCLI_mmwave_freq_scale_factor);
    
        /* Translate below times from us to [1 LSB = 10 ns] units of mmwavelink format */
        profileCfg.idleTimeConst         = (uint32_t)((float)atof(argv[3]) * 1000 / 10);
        profileCfg.adcStartTimeConst     = (uint32_t)((float)atof(argv[4]) * 1000 / 10);
        profileCfg.rampEndTime           = (uint32_t)((float)atof(argv[5]) * 1000 / 10);
    
        profileCfg.txOutPowerBackoffCode = atoi (argv[6]);
        profileCfg.txPhaseShifter        = atoi (argv[7]);
    
        /* Translate from MHz/us to [1 LSB = (gCLI_mmwave_freq_scale_factor * 1e6 * 900) / 2^26 kHz/uS]
         * units of mmwavelink format */
        profileCfg.freqSlopeConst        = (int16_t)(atof(argv[8]) * (1U << 26) /
                                                     ((gCLI_mmwave_freq_scale_factor * 1e3) * 900.0));
    
        /* Translate from us to [1 LSB = 10 ns] units of mmwavelink format */
        profileCfg.txStartTime           = (int32_t)((float)atof(argv[9]) * 1000 / 10);
    
        profileCfg.numAdcSamples         = atoi (argv[10]);
        profileCfg.digOutSampleRate      = atoi (argv[11]);
        profileCfg.hpfCornerFreq1        = atoi (argv[12]);
        profileCfg.hpfCornerFreq2        = atoi (argv[13]);
        profileCfg.rxGain                = atoi (argv[14]);
    
        /* Search for a free space in the mmWave configuration block: */
        for (index = 0U; index < MMWAVE_MAX_PROFILE; index++)
        {
            /* Did we get a free entry? */
            if (ptrBaseCfgProfileHandle[index] == NULL)
            {
                /* YES: We can add the profile. */
                break;
            }
        }
        if (index == MMWAVE_MAX_PROFILE)
        {
            /* Error: All the profiles have been exhausted */
            return -1;
        }
    
        /* Add the profile to the mmWave module: */
        profileHandle = MMWave_addProfile (gCLI.cfg.mmWaveHandle, &profileCfg, &errCode);
        if (profileHandle == NULL)
        {
            /* Error: Unable to add the profile. Return the error code back */
            return errCode;
        }
    
        /* Record the profile: */
        ptrBaseCfgProfileHandle[index] = profileHandle;
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the chirp configuration command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveChirpCfg (int32_t argc, char* argv[])
    {
        rlChirpCfg_t            chirpCfg;
        MMWave_ProfileHandle    profileHandle;
        int32_t                 errCode;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 9)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Sanity Check: Chirp configuration is valid only for the Frame or
                         Advanced Frame Mode: */
        if ((gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_FRAME) &&
            (gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_ADVANCED_FRAME))
        {
            CLI_write ("Error: Configuration is valid only if the DFE Output Mode is Chirp\n");
            return -1;
        }
    
        /* Initialize the chirp configuration: */
        memset ((void *)&chirpCfg, 0, sizeof(rlChirpCfg_t));
    
        /* Populate the chirp configuration: */
        chirpCfg.chirpStartIdx   = atoi (argv[1]);
        chirpCfg.chirpEndIdx     = atoi (argv[2]);
        chirpCfg.profileId       = atoi (argv[3]);
    
        /* Translate from Hz to number of [1 LSB = (gCLI_mmwave_freq_scale_factor * 1e9) / 2^26 Hz]
         * units of mmwavelink format */
        chirpCfg.startFreqVar    = (uint32_t) ((float)atof(argv[4]) * (1U << 26) /
                                                (gCLI_mmwave_freq_scale_factor * 1e9));
    
        /* Translate from KHz/us to number of [1 LSB = (gCLI_mmwave_freq_scale_factor * 1e6) * 900 /2^26 KHz/us]
         * units of mmwavelink format */
        chirpCfg.freqSlopeVar    = (uint16_t) ((float)atof(argv[5]) * (1U << 26) /
                                               ((gCLI_mmwave_freq_scale_factor * 1e6) * 900.0));
    
        /* Translate from us to [1 LSB = 10ns] units of mmwavelink format */
        chirpCfg.idleTimeVar     = (uint32_t)((float)atof (argv[6]) * 1000.0 / 10.0);
    
        /* Translate from us to [1 LSB = 10ns] units of mmwavelink format */
        chirpCfg.adcStartTimeVar = (uint32_t)((float)atof (argv[7]) * 1000.0 / 10.0);
    
        chirpCfg.txEnable        = atoi (argv[8]);
    
        /* Get the profile handle to which the chirp is to be added: */
        if (MMWave_getProfileHandle (gCLI.cfg.mmWaveHandle, chirpCfg.profileId,
                                     &profileHandle, &errCode) < 0)
        {
            /* Error: Unable to get the profile handle. Return the error code */
            return errCode;
        }
    
        /* Add the chirp to the profile */
        if (MMWave_addChirp (profileHandle, &chirpCfg, &errCode) == NULL)
        {
            /* Error: Unable to add the chirp. Return the error code. */
            return errCode;
        }
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the frame configuration command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveFrameCfg (int32_t argc, char* argv[])
    {
        rlFrameCfg_t    frameCfg;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 8)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Sanity Check: Frame configuration is valid only for the Frame or
                         Advanced Frame Mode: */
        if (gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_FRAME)
        {
            CLI_write ("Error: Configuration is valid only if the DFE Output Mode is Chirp\n");
            return -1;
        }
    
        /* Initialize the frame configuration: */
        memset ((void *)&frameCfg, 0, sizeof(rlFrameCfg_t));
    
        /* Populate the frame configuration: */
        frameCfg.chirpStartIdx      = atoi (argv[1]);
        frameCfg.chirpEndIdx        = atoi (argv[2]);
        frameCfg.numLoops           = atoi (argv[3]);
        frameCfg.numFrames          = atoi (argv[4]);
        frameCfg.framePeriodicity   = (uint32_t)((float)atof(argv[5]) * 1000000 / 5);
        frameCfg.triggerSelect      = atoi (argv[6]);
        frameCfg.frameTriggerDelay  = (uint32_t)((float)atof(argv[7]) * 1000000 / 5);
    
        /* Save Configuration to use later */
        memcpy((void *)&gCLIMMWaveControlCfg.u.frameCfg.frameCfg, (void *)&frameCfg, sizeof(rlFrameCfg_t));
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the advanced frame configuration command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveAdvFrameCfg (int32_t argc, char* argv[])
    {
        rlAdvFrameCfg_t  advFrameCfg;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 6)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
        
        /* Sanity Check: Frame configuration is valid only for the Frame or
                         Advanced Frame Mode: */
        if (gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_ADVANCED_FRAME)
        {
            CLI_write ("Error: Configuration is valid only if the DFE Output Mode is Advanced Frame\n");
            return -1;
        }
    
        /* Initialize the frame configuration: */
        memset ((void *)&advFrameCfg, 0, sizeof(rlAdvFrameCfg_t));
    
        /* Populate the frame configuration: */
        advFrameCfg.frameSeq.numOfSubFrames      = atoi (argv[1]);
        advFrameCfg.frameSeq.forceProfile        = atoi (argv[2]);
        advFrameCfg.frameSeq.numFrames           = atoi (argv[3]);
        advFrameCfg.frameSeq.triggerSelect       = atoi (argv[4]);
        advFrameCfg.frameSeq.frameTrigDelay      = (uint32_t)((float)atof(argv[5]) * 1000000 / 5);
    
        /* Save Configuration to use later */
        memcpy ((void *)&gCLIMMWaveControlCfg.u.advancedFrameCfg.frameCfg,
                (void *)&advFrameCfg, sizeof(rlAdvFrameCfg_t));
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the subframe configuration command.
     *      Only valid when used in conjunction with the advanced frame configuration.
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveSubFrameCfg (int32_t argc, char* argv[])
    {
        rlSubFrameCfg_t  subFrameCfg;
        uint8_t          subFrameNum;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 11)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
        
        /* Sanity Check: Sub Frame configuration is valid only for the Advanced Frame Mode: */
        if (gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_ADVANCED_FRAME)
        {
            CLI_write ("Error: Configuration is valid only if the DFE Output Mode is Advanced Frame\n");
            return -1;
        }
    
        /* Initialize the frame configuration: */
        memset ((void *)&subFrameCfg, 0, sizeof(rlSubFrameCfg_t));
    
        /* Populate the frame configuration: */
        subFrameNum                                  = (uint8_t)atoi (argv[1]);
        if (subFrameNum > gCLIMMWaveControlCfg.u.advancedFrameCfg.frameCfg.frameSeq.numOfSubFrames)
        {
            CLI_write ("Error: Invalid subframe number.\n");
            return -1;
        }
        subFrameCfg.forceProfileIdx     = atoi (argv[2]);
        subFrameCfg.chirpStartIdx       = atoi (argv[3]);
        subFrameCfg.numOfChirps         = atoi (argv[4]);
        subFrameCfg.numLoops            = atoi (argv[5]);
        subFrameCfg.burstPeriodicity    = (uint32_t)((float)atof(argv[6]) * 1000000 / 5);
        subFrameCfg.chirpStartIdxOffset = atoi (argv[7]);
        subFrameCfg.numOfBurst          = atoi (argv[8]);
        subFrameCfg.numOfBurstLoops     = atoi (argv[9]);
        subFrameCfg.subFramePeriodicity = (uint32_t)((float)atof(argv[10]) * 1000000 / 5);
        
        /* Save Configuration to use later */
        memcpy((void *)&gCLIMMWaveControlCfg.u.advancedFrameCfg.frameCfg.frameSeq.subFrameCfg[subFrameNum],
            (void *)&subFrameCfg, sizeof(rlSubFrameCfg_t));
        return 0;
        
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the low power command
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveLowPowerCfg (int32_t argc, char* argv[])
    {
        rlLowPowerModeCfg_t     lowPowerCfg;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 3)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Initialize the channel configuration: */
        memset ((void *)&lowPowerCfg, 0, sizeof(rlLowPowerModeCfg_t));
    
        /* Populate the channel configuration: */
        lowPowerCfg.lpAdcMode     = atoi (argv[2]);
    
        /* Save Configuration to use later */
        memcpy((void *)&gCLIMMWaveOpenCfg.lowPowerMode, (void *)&lowPowerCfg, sizeof(rlLowPowerModeCfg_t));
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the continuous mode
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveContModeCfg (int32_t argc, char* argv[])
    {
        MMWave_ContModeCfg *contCfg = &gCLIMMWaveControlCfg.u.continuousModeCfg;
    
        /* Sanity Check: Minimum argument check */
        if (argc != 10)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Sanity Check: Continuous configuration is valid only for the Continuous Mode: */
        if (gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_CONTINUOUS)
        {
            CLI_write ("Error: Configuration is valid only if the DFE Output Mode is Continuous\n");
            return -1;
        }
    
        /* Populate the configuration: */
        contCfg->cfg.startFreqConst        = (uint32_t) (atof(argv[1]) * (1U << 26) /
                                                         gCLI_mmwave_freq_scale_factor);
        contCfg->cfg.txOutPowerBackoffCode = (uint32_t) atoi (argv[2]);
        contCfg->cfg.txPhaseShifter        = (uint32_t) atoi (argv[3]);
        contCfg->cfg.digOutSampleRate      = (uint16_t) atoi (argv[4]);
        contCfg->cfg.hpfCornerFreq1        = (uint8_t)  atoi (argv[5]);
        contCfg->cfg.hpfCornerFreq2        = (uint8_t)  atoi (argv[6]);
        contCfg->cfg.rxGain                = (uint16_t) atoi (argv[7]);
        /*argv[8] is reserved*/
        contCfg->dataTransSize             = (uint16_t) atoi (argv[9]);
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the CLI Handler for the BPM configuration.
     *
     *  @param[in] argc
     *      Number of arguments
     *  @param[in] argv
     *      Arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t CLI_MMWaveBPMCfgAdvanced (int32_t argc, char* argv[])
    {   
        rlBpmChirpCfg_t         bpmChirpCfg;
        int32_t                 errCode;
           
        /* Sanity Check: Minimum argument check */
        if (argc != 4)
        {
            CLI_write ("Error: Invalid usage of the CLI command\n");
            return -1;
        }
    
        /* Sanity Check: BPM Chirp configuration is valid only for the Frame or
                         Advanced Frame Mode: */
        if ((gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_FRAME) &&
            (gCLIMMWaveControlCfg.dfeDataOutputMode != MMWave_DFEDataOutputMode_ADVANCED_FRAME))
        {
            CLI_write ("Error: BPM Configuration is valid only if the DFE Output Mode is frame or advanced frame\n");
            return -1;
        }
    
        /* Initialize the chirp configuration: */
        memset ((void *)&bpmChirpCfg, 0, sizeof(rlBpmChirpCfg_t));
    
        /* Populate the chirp configuration: */
        bpmChirpCfg.chirpStartIdx   = atoi (argv[1]);
        bpmChirpCfg.chirpEndIdx     = atoi (argv[2]);
        bpmChirpCfg.constBpmVal     = atoi (argv[3]);
       
        /* Add the BPM chirp configuration to the list */
        if (MMWave_addBpmChirp (gCLI.cfg.mmWaveHandle, &bpmChirpCfg, &errCode) == NULL)
        {
            /* Error: Unable to add the BPM configuration. Return the error code. */
            return errCode;
        }
    
        return 0;
    
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the mmWave extension initialization API
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    int32_t CLI_MMWaveExtensionInit(CLI_Cfg* ptrCLICfg)
    {
        int32_t         errCode;
    
        /* Sanity Check: We need the mmWave handle to work. */
        if (ptrCLICfg->mmWaveHandle == NULL)
        {
            return -1;
        }
    
        /* Initialize the mmWave control configuration: */
        memset ((void *)&gCLIMMWaveControlCfg, 0, sizeof(MMWave_CtrlCfg));
    
        gCLI_mmwave_freq_scale_factor = SOC_getDeviceRFFreqScaleFactor(ptrCLICfg->socHandle, &errCode);
        if(errCode < 0)
        {
            return -1;
        }
    
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the mmWave extension handler which executes mmWave extension
     *      commands. This is invoked by the main CLI wrapper only if the extension
     *      was enabled.
     *
     *  @param[in]  argc
     *      Number of detected arguments
     *  @param[in] argv
     *      Detected arguments
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      0   -   Matching mmWave extension command found
     *  @retval
     *      -1  -   No Matching mmWave extension command
     */
    int32_t CLI_MMWaveExtensionHandler(int32_t argc, char* argv[])
    {
        CLI_CmdTableEntry*  ptrCLICommandEntry;
        int32_t             cliStatus;
        int32_t             retVal = 0;
    
        /* Get the pointer to the mmWave extension table */
        ptrCLICommandEntry = &gCLIMMWaveExtensionTable[0];
    
        /* Cycle through all the registered externsion CLI commands: */
        while (ptrCLICommandEntry->cmdHandlerFxn != NULL)
        {
            /* Do we have a match? */
            if (strcmp(ptrCLICommandEntry->cmd, argv[0]) == 0)
            {
                /* YES: Pass this to the CLI registered function */
                cliStatus = ptrCLICommandEntry->cmdHandlerFxn (argc, argv);
                if (cliStatus == 0)
                {
                    /* Successfully executed the CLI command: */
                    CLI_write ("Done\n");
                }
                else
                {
                    /* Error: The CLI command failed to execute */
                    CLI_write ("Error %d\n", cliStatus);
                }
                break;
            }
    
            /* Get the next entry: */
            ptrCLICommandEntry++;
        }
    
        /* Was this a valid CLI command? */
        if (ptrCLICommandEntry->cmdHandlerFxn == NULL)
        {
            /* NO: The command was not a valid CLI mmWave extension command. Setup
             * the return value correctly. */
            retVal = -1;
        }
        return retVal;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is the mmWave extension handler which is invoked by the
     *      CLI Help command handler only if the extension was enabled.
     *
     *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
     *
     *  @retval
     *      Not applicable
     */
    void CLI_MMWaveExtensionHelp(void)
    {
        CLI_CmdTableEntry*  ptrCLICommandEntry;
    
        /* Get the pointer to the mmWave extension table */
        ptrCLICommandEntry = &gCLIMMWaveExtensionTable[0];
    
        /* Display the banner: */
        CLI_write ("****************************************************\n");
        CLI_write ("mmWave Extension Help\n");
        CLI_write ("****************************************************\n");
    
        /* Cycle through all the registered externsion CLI commands: */
        while (ptrCLICommandEntry->cmdHandlerFxn != NULL)
        {
            /* Display the help string*/
            CLI_write ("%s: %s\n",
                        ptrCLICommandEntry->cmd,
                       (ptrCLICommandEntry->helpString == NULL) ?
                        "No help available" :
                        ptrCLICommandEntry->helpString);
    
            /* Get the next entry: */
            ptrCLICommandEntry++;
        }
        return;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is an API provided by the CLI mmWave extension handler to get
     *      the mmWave control configuration.
     *
     *  @param[out]  ptrCtrlCfg
     *      Pointer to the control configuration populated by the API
     *
     *  \ingroup CLI_UTIL_EXTERNAL_FUNCTION
     *
     *  @retval
     *      Not applicable
     */
    void CLI_getMMWaveExtensionConfig(MMWave_CtrlCfg* ptrCtrlCfg)
    {
        memcpy ((void*)ptrCtrlCfg, (void*)&gCLIMMWaveControlCfg, sizeof(MMWave_CtrlCfg));
        return;
    }
    
    /**
     *  @b Description
     *  @n
     *      This is an API provided by the CLI mmWave extension handler to get
     *      the mmWave control configuration.
     *
     *  @param[out]  ptrOpenCfg
     *      Pointer to the open configuration populated by the API
     *
     *  \ingroup CLI_UTIL_EXTERNAL_FUNCTION
     *
     *  @retval
     *      Not applicable
     */
    void CLI_getMMWaveExtensionOpenConfig(MMWave_OpenCfg* ptrOpenCfg)
    {
        memcpy ((void*)ptrOpenCfg, (void*)&gCLIMMWaveOpenCfg, sizeof(MMWave_OpenCfg));
        return;
    }
    
    

    Any further guidance would be greatly appreciated since I am unsure exactly on how to carry over the features from mmw demo to the mmwavelink test project. Thanks!

    George

  • Hi Jitendra,

    Any step-by-step guidance on how to integrate those two functions into the CCS mmwavelink test project would be greatly appreciated! Look forward to hearing back from you soon.

    George

  • Hell George,

    There is no step-by-step guidance available but the source code and the Doxygen for those are already available within the SDK which any user can refer and port/integrate into their application as per requirement.

    I would request you to invest time and effort by yourself as high level of integration pieces of information are already provided from our end.

     

    Regards,

    Jitendra

  • Hi Jitendra, 

    Since I am having trouble integrating the CLI and LVDS capabilities from the mmwave demo into the mmwavelink test project you provided, would it be easier/possible for me to include the bpmCfgAdvanced API into the mmwave demo instead? From the documentation, it looks like bpmCfgAdvanced API gives me the flexibility to provide any arbitrary constBpmVal for any set of chirps as seen below. Again, I do not care about DSS since data will immediately be streamed over LVDS.

        {
            "bpmCfgAdvanced",
    #ifdef CLI_MMWAVE_HELP_SUPPORT
            "<chirpStartIdx> <chirpEndIdx> <constBpmVal>",
    #else
            NULL,
    #endif
            CLI_MMWaveBPMCfgAdvanced
        },

    Thoughts? If this is integrated, will the BSS be updated accordingly?

    Thanks!

    George

  • Hello George,

    Main purpose of this bpmCfgAdvanced CLI command is to configure BSS which is being done using API rlSetBpmChirpConfig. And to enable BPM feature you only need to configure the BSS there is nothing required at MSS for that.

    Better to use mmWaveLink Test application where it configures the BSS for BPM

    MmwaveLink_setBpmChirpConfig ()

    rlSetBpmChirpConfig and rlSetMultiBpmChirpConfig APIs are same, first one configures single BPM config whereas using second one you can configure multiple BPM config via single API call.

    If you are already familiar with mmwavelink test application then I would suggest using above mentioned function to configure BSS for BPM.

    Regards,

    JG