AWR1843BOOST: Out_Of_Box demo_AWR1843 with CAN functionality

Part Number: AWR1843BOOST
Other Parts Discussed in Thread: AWR1843, , AWR1642

Tool/software:

Hai.......,

We was trying to adding the functionality of CAN in Out_of_Demo _1843 from Radar Toolbox-2.10.00.04. 

I followed the document " Adding CAN-FD Tx and Rx to an Existing mmWave Project" but still it is not working.....when i went through the mmw_cli,c in OOB demo I found UART_writePolling function there.

In the main.c file i have done all the procedures done as the document.....when it was not working i deeped dived into Out_of_Demo _1843 and I found in mmw_cli.c file UART_writePolling function is called. 

So should i aslo call Can_Transmit_Schedule function in mmw_cli.c .

Thanks,

Rehman

  • Please check this demo

    It is based on the 1642 device but it has the can functionality you are trying to implement

    C:\data-nobackup\radar_toolbox_2_10_00_04\source\ti\examples\object_data_over_can

    Thank you

    Cesar

  • Hi Rehman,

    In addition to the demo above, please also refer to the AWR1843 Medium Range Radar demo in the Radar Toolbox: ($TOOLBOX_INSTALL_DIR\source\ti\examples\ADAS\medium_range_radar)

    This demo implements CAN Tx, as well as the basic callback to handle CAN Rx in mss_main.c.

    Please note that the CLI is used to configure, start, and stop the sensor. If the goal is the have CAN communication while the sensor is running, Can_Transmit_Schedule should be called in the mailbox read task.

    Thank you,

    Jin

  • Hai Jin, 

    The point is.., in Out_of_box demo there is no mailbox read task. I am also familiar with medium range radar.....In medium range radar demo as you mentioned the CAN_Transmit_Schedule as well as UART_writePolling function is called in the mailbox read task..... .

    But in Out_Of_Box demo the UART_writePolling function is called in , "static void MmwDemo_transmitProcessedOutput() " , so i thought of adding the CAN_Transmit_Schedule function in "static void MmwDemo_transmitProcessedOutput() " .

  • Hai Cesar...,

    The point is.., in Out_of_box demo there is no mailbox read task. I am also familiar with object_data_over_can.....In mobject_data_over_can demo as you mentioned the CAN_Transmit_Schedule function is called in the mailbox read task..... .

    But in Out_Of_Box demo the UART_writePolling function is called in , "static void MmwDemo_transmitProcessedOutput() " , so i thought of adding

    the CAN_Transmit_Schedule function in "static void MmwDemo_transmitProcessedOutput() " .

    I am also attaching the " static void MmwDemo_transmitProcessedOutput() " function.

    static void MmwDemo_transmitProcessedOutput
    (
        UART_Handle     uartHandle,
        DPC_ObjectDetection_ExecuteResult   *result,
        MmwDemo_output_message_stats        *timingInfo
    )
    {
        MmwDemo_output_message_header header;
        MmwDemo_GuiMonSel   *pGuiMonSel;
        MmwDemo_SubFrameCfg *subFrameCfg;
        uint32_t tlvIdx = 0;
        uint32_t index;
        uint32_t numPaddingBytes;
        uint32_t packetLen;
        uint8_t padding[MMWDEMO_OUTPUT_MSG_SEGMENT_LEN];
        MmwDemo_output_message_tl   tl[MMWDEMO_OUTPUT_MSG_MAX];
        int32_t errCode;
        uint16_t *detMatrix = (uint16_t *)result->detMatrix.data;
        DPIF_PointCloudCartesian *objOut;
        cmplx16ImRe_t *azimuthStaticHeatMap;
        DPIF_PointCloudSideInfo *objOutSideInfo;
        DPC_ObjectDetection_Stats *stats;
        
        /* Get subframe configuration */
        subFrameCfg = &gMmwMssMCB.subFrameCfg[result->subFrameIdx];
    
        /* Get Gui Monitor configuration */
        pGuiMonSel = &subFrameCfg->guiMonSel;
    
        /* Clear message header */
        memset((void *)&header, 0, sizeof(MmwDemo_output_message_header));
    
        /******************************************************************
           Send out data that is enabled, Since processing results are from DSP,
           address translation is needed for buffer pointers
        *******************************************************************/
        {
            detMatrix = (uint16_t *) SOC_translateAddress((uint32_t)detMatrix,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)detMatrix!= SOC_TRANSLATEADDR_INVALID);
    
            objOut = (DPIF_PointCloudCartesian *) SOC_translateAddress((uint32_t)result->objOut,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)objOut != SOC_TRANSLATEADDR_INVALID);
    
            objOutSideInfo = (DPIF_PointCloudSideInfo *) SOC_translateAddress((uint32_t)result->objOutSideInfo,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)objOutSideInfo != SOC_TRANSLATEADDR_INVALID);
    
            stats = (DPC_ObjectDetection_Stats *) SOC_translateAddress((uint32_t)result->stats,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)stats != SOC_TRANSLATEADDR_INVALID);
    
    
            result->radarCube.data = (void *) SOC_translateAddress((uint32_t) result->radarCube.data,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t) result->radarCube.data!= SOC_TRANSLATEADDR_INVALID);
        }
    
        /* Header: */
        header.platform =  0xA1843;
        header.magicWord[0] = 0x0102;
        header.magicWord[1] = 0x0304;
        header.magicWord[2] = 0x0506;
        header.magicWord[3] = 0x0708;
        header.numDetectedObj = result->numObjOut;
        header.version =    MMWAVE_SDK_VERSION_BUILD |
                            (MMWAVE_SDK_VERSION_BUGFIX << 8) |
                            (MMWAVE_SDK_VERSION_MINOR << 16) |
                            (MMWAVE_SDK_VERSION_MAJOR << 24);
    
        packetLen = sizeof(MmwDemo_output_message_header);
        if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) &&
             (result->numObjOut > 0))
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS;
            tl[tlvIdx].length = sizeof(DPIF_PointCloudCartesian) * result->numObjOut;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        /* Side info */
        if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0))
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS_SIDE_INFO;
            tl[tlvIdx].length = sizeof(DPIF_PointCloudSideInfo) * result->numObjOut;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->logMagRange)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_PROFILE;
            tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->noiseProfile)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_NOISE_PROFILE;
            tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->rangeAzimuthHeatMap)
        {
    #if defined(USE_2D_AOA_DPU)
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_ELEVATION_STATIC_HEAT_MAP;
    #else
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP;
    #endif
            tl[tlvIdx].length = result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t);
            packetLen += sizeof(MmwDemo_output_message_tl) +  tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->rangeDopplerHeatMap)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_DOPPLER_HEAT_MAP;
            tl[tlvIdx].length = subFrameCfg->numRangeBins * subFrameCfg->numDopplerBins * sizeof(uint16_t);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->statsInfo)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_STATS;
            tl[tlvIdx].length = sizeof(MmwDemo_output_message_stats);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
    
            MmwDemo_getTemperatureReport();
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_TEMPERATURE_STATS;
            tl[tlvIdx].length = sizeof(MmwDemo_temperatureStats);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
    
        header.numTLVs = tlvIdx;
        /* Round up packet length to multiple of MMWDEMO_OUTPUT_MSG_SEGMENT_LEN */
        header.totalPacketLen = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN *
                ((packetLen + (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1))/MMWDEMO_OUTPUT_MSG_SEGMENT_LEN);
        header.timeCpuCycles = Pmu_getCount(0);
        header.frameNumber = stats->frameStartIntCounter;
        header.subFrameNumber = result->subFrameIdx;
    
        UART_writePolling (uartHandle,
                           (uint8_t*)&header,
                           sizeof(MmwDemo_output_message_header));
        txMsgObjectParams.msgIdentifier = 0xB1;//Get_CanMessageIdentifier((MmwDemo_output_message_type)MMWDEMO_OUTPUT_MSG_DETECTED_POINTS);
        Can_Transmit_Schedule(txMsgObjectParams.msgIdentifier,(uint8_t*)&header,
                              sizeof(MmwDemo_output_message_header));
    
        tlvIdx = 0;
        /* Send detected Objects */
        if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) &&
            (result->numObjOut > 0))
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            /*Send array of objects */
            UART_writePolling (uartHandle, (uint8_t*)objOut,
                               sizeof(DPIF_PointCloudCartesian) * result->numObjOut);
    
            txMsgObjectParams.msgIdentifier = 0xD1;//Get_CanMessageIdentifier((MmwDemo_output_message_type)MMWDEMO_OUTPUT_MSG_DETECTED_POINTS);
            Can_Transmit_Schedule(txMsgObjectParams.msgIdentifier,(uint8_t*)objOut, sizeof(DPIF_PointCloudCartesian) * result->numObjOut);
            tlvIdx++;
        }
    
        /* Send detected Objects Side Info */
        if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0))
        {
    
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            UART_writePolling (uartHandle, (uint8_t*)objOutSideInfo,
                               sizeof(DPIF_PointCloudSideInfo) * result->numObjOut);
            txMsgObjectParams.msgIdentifier = 0xD2;//Get_CanMessageIdentifier((MmwDemo_output_message_type)MMWDEMO_OUTPUT_MSG_DETECTED_POINTS);
            Can_Transmit_Schedule(txMsgObjectParams.msgIdentifier,(uint8_t*)objOutSideInfo,
                                  sizeof(DPIF_PointCloudSideInfo) * result->numObjOut);
            tlvIdx++;
        }
    
        /* Send Range profile */
        if (pGuiMonSel->logMagRange)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            for(index = 0; index < subFrameCfg->numRangeBins; index++)
            {
                UART_writePolling (uartHandle,
                        (uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins],
                        sizeof(uint16_t));
            }
            tlvIdx++;
        }
    
        /* Send noise profile */
        if (pGuiMonSel->noiseProfile)
        {
            uint32_t maxDopIdx = subFrameCfg->numDopplerBins/2 -1;
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            for(index = 0; index < subFrameCfg->numRangeBins; index++)
            {
                UART_writePolling (uartHandle,
                        (uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins + maxDopIdx],
                        sizeof(uint16_t));
            }
            tlvIdx++;
        }
    
        /* Send data for static azimuth heatmap */
        if (pGuiMonSel->rangeAzimuthHeatMap)
        {
            azimuthStaticHeatMap = (cmplx16ImRe_t *) SOC_translateAddress((uint32_t)result->azimuthStaticHeatMap,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)azimuthStaticHeatMap!= SOC_TRANSLATEADDR_INVALID);
    
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            UART_writePolling (uartHandle,
                    (uint8_t *)azimuthStaticHeatMap,
                    result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t));
    
            tlvIdx++;
        }
    
        /* Send data for range/Doppler heatmap */
        if (pGuiMonSel->rangeDopplerHeatMap == 1)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            UART_writePolling (uartHandle,
                    (uint8_t*)detMatrix,
                    tl[tlvIdx].length);
            tlvIdx++;
        }
    
        /* Send stats information */
        if (pGuiMonSel->statsInfo == 1)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            /* Address translation is done when buffer is received*/
            UART_writePolling (uartHandle,
                               (uint8_t*)timingInfo,
                               tl[tlvIdx].length);
            tlvIdx++;
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
            UART_writePolling (uartHandle,
                               (uint8_t*)&gMmwMssMCB.temperatureStats,
                               tl[tlvIdx].length);
            tlvIdx++;
        }
    
        /* Send padding bytes */
        numPaddingBytes = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN - (packetLen & (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1));
        if (numPaddingBytes<MMWDEMO_OUTPUT_MSG_SEGMENT_LEN)
        {
            UART_writePolling (uartHandle,
                                (uint8_t*)padding,
                                numPaddingBytes);
        }
    
    }

  • Hi Rehman,

    Thanks for the clarification. Yes, the Can_Transmit_Schedule should be called in the MmwDemo_transmitProcessedOut() in the OOB demo. It shouldn't need to be added in mmw_cli.c.

    Thank you,

    Jin

  • In addition, please ensure that the EVM is configured to provide CAN-FD output as described in the EVM user guide. 

  • Hi Jin....,

    I have called Can_Transmit_Schedule in the MmwDemo_transmitProcessedOut()  only...but still not working...., don't know what is wrong.....

    What do mean by EVM should be configured to provide CAN-FD......The board i am using is AWR1843BOOST....I am able to get CANFD output when using Medium Range radar(MRR) demo...., so I guess there shouldn't be nothing to be done in the hardware side right...?.

    I am attaching the mss_main.c file of OOB demo....I have also added the drivers in the file search path in ARM linker....

    /**************************************************************************
     *************************** Include Files ********************************
     **************************************************************************/
    
    /* Standard Include Files. */
    #include <stdint.h>
    #include <stdlib.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    #include <math.h>
    
    
    /* BIOS/XDC Include Files. */
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/IHeap.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/Memory.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/heaps/HeapBuf.h>
    #include <ti/sysbios/heaps/HeapMem.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/family/arm/v7a/Pmu.h>
    #include <ti/sysbios/family/arm/v7r/vim/Hwi.h>
    #include <ti/sysbios/utils/Load.h>
    
    /* mmWave SDK Include Files: */
    #include <ti/common/sys_common.h>
    #include <ti/common/mmwave_sdk_version.h>
    #include <ti/drivers/soc/soc.h>
    #include <ti/drivers/esm/esm.h>
    #include <ti/drivers/crc/crc.h>
    #include <ti/drivers/gpio/gpio.h>
    #include <ti/drivers/mailbox/mailbox.h>
    #include <ti/drivers/pinmux/pinmux.h>
    #include <ti/control/mmwave/mmwave.h>
    #include <ti/control/dpm/dpm.h>
    #include <ti/drivers/osal/DebugP.h>
    #include <ti/drivers/uart/UART.h>
    #include <ti/utils/cli/cli.h>
    #include <ti/utils/mathutils/mathutils.h>
    
    #include<ti/drivers/canfd/canfd.h> // i added for CANFD
    
    /* Demo Include Files */
    #include <ti/demo/xwr18xx/mmw/include/mmw_config.h>
    #include <ti/demo/utils/mmwdemo_rfparser.h>
    #include <ti/demo/utils/mmwdemo_adcconfig.h>
    #include <ti/demo/utils/mmwdemo_monitor.h>
    #include <ti/demo/xwr18xx/mmw/include/mmw_output.h>
    #include <ti/demo/xwr18xx/mmw/mmw_res.h>
    #include <ti/demo/xwr18xx/mmw/mss/mmw_mss.h>
    #include <ti/board/antenna_geometry.h>
    #include <ti/demo/utils/mmwdemo_flash.h>
    
    /* Profiler Include Files */
    #include <ti/utils/cycleprofiler/cycle_profiler.h>
    
    #ifdef SYS_COMMON_RTRIM_MODIFY_EN
    #include <ti/utils/rtrim/rtrimutils.h>
    #endif
    
    
    
    
    /**************************************************************************
     *************************** Global Definitions ***************************
     **************************************************************************/
    volatile uint32_t       gTxDoneFlag = 0, gRxDoneFlag = 0, gParityErrFlag = 0;
    volatile uint32_t       gTxPkts = 0, gRxPkts = 0, gErrStatusInt = 0;
    volatile uint32_t                iterationCount = 0U;
    uint32_t                dataLength = 0U;
    uint32_t                msgLstErrCnt = 0U;
    uint32_t                gDisplayStats = 0;
    
    uint8_t                 rxData[64U];
    uint32_t                txDataLength, rxDataLength;
    CANFD_MCANFrameType     frameType = CANFD_MCANFrameType_FD;
    
    
    /**
     * @brief Task Priority settings:
     * Mmwave task is at higher priority because of potential async messages from BSS
     * that need quick action in real-time.
     *
     * CLI task must be at a lower priority than object detection
     * dpm task priority because the dynamic CLI command handling in the objection detection
     * dpm task assumes CLI task is held back during this processing. The alternative
     * is to use a semaphore between the two tasks.
     */
    #define MMWDEMO_CLI_TASK_PRIORITY                 3
    #define MMWDEMO_DPC_OBJDET_DPM_TASK_PRIORITY      4
    #define MMWDEMO_MMWAVE_CTRL_TASK_PRIORITY         5
    
    #define CAN_MESSAGE_PARK_SENS_POS 0x00
    #define MMWDEMO_HEADER              0x5U
    #define CAN_MESSAGE_PARK_SENS_POS 0x00
    #define CAN_MESSAGE_MMWDEMO_MAX     0x6U  /*(messge type (4) + header (1) + padding(1))*/
    
    
    #if (MMWDEMO_CLI_TASK_PRIORITY >= MMWDEMO_DPC_OBJDET_DPM_TASK_PRIORITY)
    #error CLI task priority must be < Object Detection DPM task priority
    #endif
    
    #define DPC_OBJDET_INSTANCEID       (0xFEEDFEED)
    
    /* These address offsets are in bytes, when configure address offset in hardware,
       these values will be converted to number of 128bits
       Buffer at offset 0x0U is reserved by BSS, hence offset starts from 0x800
     */
    #define MMW_DEMO_CQ_SIGIMG_ADDR_OFFSET          0x800U
    #define MMW_DEMO_CQ_RXSAT_ADDR_OFFSET           0x1000U
    
    /* CQ data is at 16 bytes alignment for mulitple chirps */
    #define MMW_DEMO_CQ_DATA_ALIGNMENT            16U
    
    
    
    typedef enum mmwDemo_can_message_type_e
    {
        /*! @brief   List of detected points */
        CAN_MESSAGE_MMWDEMO_DETECTED_POINTS = 0xD1,
    
        /*! @brief   CLUSTERS */
        CAN_MESSAGE_MMWDEMO_CLUSTERS,
    
        /*! @brief   TRACKED OBJECTS */
        CAN_MESSAGE_MMWDEMO_TRACKED_OBJECTS,
    
        /*! @brief   PARK ASSIST */
        CAN_MESSAGE_MMWDEMO_PARKING_ASSIST,
    
    } mmwDemo_can_message_type;
    
    
    
    static void MCANAppInitParams(CANFD_MCANInitParams* mcanCfgParams);
    
    
    CANFD_Handle                canHandle;
    CANFD_MsgObjHandle          txMsgObjHandle;
    CANFD_MCANMsgObjCfgParams   txMsgObjectParams;
    
    /**************************************************************************
     *************************** Global Definitions ***************************
     **************************************************************************/
    
    /**
     * @brief
     *  Global Variable for tracking information required by the mmw Demo
     */
    MmwDemo_MSS_MCB    gMmwMssMCB;
    
    /**
     * @brief
     *  Global Variable for HSRAM buffer used to share results to remote
     */
    MmwDemo_HSRAM gHSRAM;
    
    /**
     * @brief
     *  Global Variable for LDO BYPASS config   
     **********************************************************
      AS PER RECOMMENDATION FROM THE xWR1843BOOST EVM User guide
     **********************************************************
       set LDO bypass since the board has 1.0V RF supply 1 
       and 1.0V RF supply 2. Please update this API if this 
       assumption is not valid else it may DAMAGE your board!
     **********************************************************
     **********************************************************
     */
    rlRfLdoBypassCfg_t gRFLdoBypassCfg =
    {
        .ldoBypassEnable   = 3, /* 1.0V RF supply 1 and 1.0V RF supply 2 */
        .supplyMonIrDrop   = 1, /* IR drop of 3% */
        .ioSupplyIndicator = 0, /* 3.3 V IO supply */
    };
    
    
    /*! HSRAM for processing results */
    #pragma DATA_SECTION(gHSRAM, ".demoSharedMem");
    #pragma DATA_ALIGN(gHSRAM, 4);
    
    
    /* Calibration Data Save/Restore defines */
    #define MMWDEMO_CALIB_FLASH_SIZE	              4096
    #define MMWDEMO_CALIB_STORE_MAGIC            (0x7CB28DF9U)
    
    MmwDemo_calibData gCalibDataStorage;
    #pragma DATA_ALIGN(gCalibDataStorage, 8);
    
    /**************************************************************************
     *************************** Extern Definitions ***************************
     **************************************************************************/
    
    extern void MmwDemo_CLIInit(uint8_t taskPriority);
    
    /**************************************************************************
     ************************* Millimeter Wave Demo Functions prototype *************
     **************************************************************************/
    
    /* MMW demo functions for datapath operation */
    static void MmwDemo_dataPathOpen(void);
    static int32_t MmwDemo_dataPathConfig (void);
    static void MmwDemo_dataPathStart (void);
    static void MmwDemo_dataPathStop (void);
    static void MmwDemo_handleObjectDetResult(DPM_Buffer  *ptrResult);
    static void MmwDemo_DPC_ObjectDetection_reportFxn
    (
        DPM_Report  reportType,
        uint32_t    instanceId,
        int32_t     errCode,
        uint32_t    arg0,
        uint32_t    arg1
    );
    static void MmwDemo_transmitProcessedOutput
    (
        UART_Handle     uartHandle,
        DPC_ObjectDetection_ExecuteResult   *result,
        MmwDemo_output_message_stats        *timingInfo
    );
    static void MmwDemo_measurementResultOutput(DPU_AoAProc_compRxChannelBiasCfg *compRxChanCfg);
    static int32_t MmwDemo_DPM_ioctl_blocking
    (
        DPM_Handle handle,
        uint32_t cmd,
        void* arg,
        uint32_t argLen
    );
    static int32_t MmwDemo_processPendingDynamicCfgCommands(uint8_t subFrameIndx);
    
    static void MmwDemo_initTask(UArg arg0, UArg arg1);
    static void MmwDemo_platformInit(MmwDemo_platformCfg *config);
    
    /* Mmwave control functions */
    static void MmwDemo_mmWaveCtrlTask(UArg arg0, UArg arg1);
    static int32_t MmwDemo_mmWaveCtrlStop (void);
    static int32_t MmwDemo_eventCallbackFxn(uint16_t msgId, uint16_t sbId, uint16_t sbLen, uint8_t *payload);
    
    /* external sleep function when in idle (used in .cfg file) */
    void MmwDemo_sleep(void);
    
    /* Edma related functions */
    static void MmwDemo_edmaInit(void);
    static void MmwDemo_edmaOpen(void);
    static void MmwDemo_EDMA_transferControllerErrorCallbackFxn(EDMA_Handle handle,
                    EDMA_transferControllerErrorInfo_t *errorInfo);
    static void MmwDemo_EDMA_errorCallbackFxn(EDMA_Handle handle, EDMA_errorInfo_t *errorInfo);
    static void MmwDemo_checkEdmaErrors(void);
    
    static int32_t MmwDemo_configCQ(MmwDemo_SubFrameCfg *subFrameCfg,
                                               uint8_t numChirpsPerChirpEvent,
                                               uint8_t validProfileIdx);
    
    /* Calibration save/restore APIs */
    static int32_t MmwDemo_calibInit(void);
    static int32_t MmwDemo_calibSave(MmwDemo_calibDataHeader *ptrCalibDataHdr, MmwDemo_calibData  *ptrCalibrationData);
    static int32_t MmwDemo_calibRestore(MmwDemo_calibData  *calibrationData);
    
    /**************************************************************************
     ************************* Millimeter Wave Demo Functions **********************
     **************************************************************************/
    /**
     *  @b Description
     *  @n
     *      Send assert information through CLI.
     */
    void _MmwDemo_debugAssert(int32_t expression, const char *file, int32_t line)
    {
        if (!expression) {
            CLI_write ("Exception: %s, line %d.\n",file,line);
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to set the pending state of configuration.
     *
     *  @param[in] subFrameCfg Pointer to Sub-frame specific configuration
     *  @param[in] offset Configuration structure offset that uniquely identifies the
     *                    configuration to set to the pending state.
     *
     *  @retval None
     */
    static void MmwDemo_setSubFramePendingState(MmwDemo_SubFrameCfg *subFrameCfg, uint32_t offset)
    {
        switch (offset)
        {
            case MMWDEMO_GUIMONSEL_OFFSET:
                subFrameCfg->objDetDynCfg.isPrepareRangeAzimuthHeatMapPending = 1;
            break;
            case MMWDEMO_CFARCFGRANGE_OFFSET:
                subFrameCfg->objDetDynCfg.isCfarCfgRangePending = 1;
            break;
            case MMWDEMO_CFARCFGDOPPLER_OFFSET:
                subFrameCfg->objDetDynCfg.isCfarCfgDopplerPending = 1;
            break;
            case MMWDEMO_FOVRANGE_OFFSET:
                subFrameCfg->objDetDynCfg.isFovRangePending = 1;
            break;
            case MMWDEMO_FOVDOPPLER_OFFSET:
                subFrameCfg->objDetDynCfg.isFovDopplerPending = 1;
            break;
            case MMWDEMO_FOVAOA_OFFSET:
                subFrameCfg->objDetDynCfg.isFovAoaCfgPending = 1;
            break;
            case MMWDEMO_MULTIOBJBEAMFORMING_OFFSET:
                subFrameCfg->objDetDynCfg.isMultiObjBeamFormingCfgPending = 1;
            break;
            case MMWDEMO_CALIBDCRANGESIG_OFFSET:
                subFrameCfg->objDetDynCfg.isCalibDcRangeSigCfg = 1;
            break;
            case MMWDEMO_STATICCLUTTERREMOFVAL_OFFSET:
                subFrameCfg->objDetDynCfg.isStaticClutterRemovalCfgPending = 1;
            break;
            case MMWDEMO_EXTMAXVEL_OFFSET:
                subFrameCfg->objDetDynCfg.isExtMaxVelCfgPending = 1;
            break;
            case MMWDEMO_ADCBUFCFG_OFFSET:
                subFrameCfg->isAdcBufCfgPending = 1;
            break;
            case MMWDEMO_LVDSSTREAMCFG_OFFSET:
                subFrameCfg->isLvdsStreamCfgPending = 1;
            break;
            default:
                MmwDemo_debugAssert(0);
            break;
        }
    }
    
    
    /**
     *  @b Description
     *  @n
     *      Utility function to find out if all common configuration is pending
     *
     *  @param[in] cfg Pointer to Common configuration
     *
     *  @retval 1 if all common configuration is pending, else return 0.
     */
    static uint8_t MmwDemo_isDynObjDetCommonCfgPendingState(MmwDemo_DPC_ObjDet_CommonCfg *cfg)
    {
        uint8_t retVal;
    
        retVal = (cfg->isCompRxChannelBiasCfgPending    == 1) &&
                 (cfg->isMeasureRxChannelBiasCfgPending == 1);
    
        return(retVal);
    }
    
    
    /**
     *  @b Description
     *  @n
     *      Utility function to find out if all sub-frame specific dynamic
     *      configuration is pending
     *
     *  @param[in] cfg Pointer to sub-frame specific configuration
     *
     *  @retval 1 if all sub-frame specific dynamic configuration is pending, else return 0
     */
    static uint8_t MmwDemo_isDynObjDetCfgPendingState(MmwDemo_DPC_ObjDet_DynCfg *cfg)
    {
        uint8_t retVal;
    
        retVal = (cfg->isCalibDcRangeSigCfg    == 1) &&
                 (cfg->isCfarCfgDopplerPending == 1) &&
                 (cfg->isCfarCfgRangePending   == 1) &&
                 (cfg->isFovDopplerPending     == 1) &&
                 (cfg->isFovRangePending       == 1) &&
                 (cfg->isMultiObjBeamFormingCfgPending     == 1) &&
                 (cfg->isPrepareRangeAzimuthHeatMapPending == 1) &&
                 (cfg->isStaticClutterRemovalCfgPending    == 1) &&
                 (cfg->isFovAoaCfgPending                  == 1) &&
                 (cfg->isExtMaxVelCfgPending               == 1);
    
        return(retVal);
    }
    
    
    
    
    int32_t Can_Transmit_Schedule( uint32_t msg_id,
                uint8_t *txmsg, uint32_t len)
    {
    
        volatile uint32_t                   index = 0;
        int32_t                     retVal = 0;
        int32_t                     errCode = 0;
    
        //System_printf ("MEssage %x  len %d\n", msg_id, len);
        if(frameType == CANFD_MCANFrameType_FD)
        {
            Task_sleep(1);
    
            while(len > 64U)
            {
                retVal = CANFD_transmitData (txMsgObjHandle, msg_id, CANFD_MCANFrameType_FD, 64U, &txmsg[index], &errCode);
                index = index + 64U;
                len = len - 64U;
    
                Task_sleep(1);
            }
            retVal = CANFD_transmitData (txMsgObjHandle, msg_id, CANFD_MCANFrameType_FD, len, &txmsg[index], &errCode);
        }
        else
        {
            while(len > 8U)
            {
                retVal = CANFD_transmitData (txMsgObjHandle, msg_id, CANFD_MCANFrameType_CLASSIC, 8U, &txmsg[index], &errCode);
                if (retVal < 0)
                {
    
                    continue;
                }
                index = index + 8U;
                len = len - 8U;
    
            }
    
            retVal = CANFD_transmitData (txMsgObjHandle, msg_id, CANFD_MCANFrameType_CLASSIC, len, &txmsg[index], &errCode);
    
            while(retVal < 0)
            {
                //System_printf("Debug: Error transmitting CAN data %x , Errcode %x\n", retVal, errCode);
                retVal = CANFD_transmitData (txMsgObjHandle, msg_id, CANFD_MCANFrameType_CLASSIC, len, &txmsg[index], &errCode);
    
            }
    
        }
    
    
        return retVal;
    
    }
    
    
    uint32_t Get_CanMessageIdentifier(MmwDemo_output_message_type type)
    {
        uint32_t can_msgId;
    
        if(type == MMWDEMO_OUTPUT_MSG_DETECTED_POINTS)
        {
            can_msgId = (mmwDemo_can_message_type)CAN_MESSAGE_MMWDEMO_DETECTED_POINTS;
        }
    //    else if(type == MMWDEMO_OUTPUT_MSG_CLUSTERS)
    //    {
    //        can_msgId = (mmwDemo_can_message_type)CAN_MESSAGE_MMWDEMO_CLUSTERS;
    //    }
    //    else if(type == MMWDEMO_OUTPUT_MSG_TRACKED_OBJECTS)
    //    {
    //        can_msgId = (mmwDemo_can_message_type)CAN_MESSAGE_MMWDEMO_TRACKED_OBJECTS;
    //    }
    //    else if(type == MMWDEMO_OUTPUT_MSG_PARKING_ASSIST)
    //    {
    //        can_msgId = (mmwDemo_can_message_type)CAN_MESSAGE_MMWDEMO_PARKING_ASSIST;
    //    }
    //    else if (type == MMWDEMO_HEADER)
    //    {
    //        can_msgId = (mmwDemo_can_message_type)CAN_MESSAGE_MMWDEMO_HEADER;
    //    }
    //    else if (type == MMWDEMO_PADDING)
    //    {
    //        can_msgId = (mmwDemo_can_message_type)CAN_MESSAGE_MMWDEMO_PADDING;
    //    }
        else
        {
            can_msgId = (mmwDemo_can_message_type)CAN_MESSAGE_MMWDEMO_MAX;
        }
        if(txMsgObjectParams.msgIdType == CANFD_MCANXidType_29_BIT)
        {
            can_msgId |= ~(0xFFFFFFFF);
        }
        return (uint32_t)(can_msgId | CAN_MESSAGE_PARK_SENS_POS);
    }
    
    
    
    static void MCANAppErrStatusCallback(CANFD_Handle handle, CANFD_Reason reason, CANFD_ErrStatusResp* errStatusResp)
    {
        gErrStatusInt++;
    
        return;
    }
    
    
    
    
    static void MCANAppCallback(CANFD_MsgObjHandle handle, CANFD_Reason reason)
    {
        int32_t                 errCode, retVal;
        uint32_t                id;
        CANFD_MCANFrameType     rxFrameType;
        CANFD_MCANXidType       rxIdType;
    
        if (reason == CANFD_Reason_TX_COMPLETION)
        {
            {
                gTxPkts++;
                gTxDoneFlag = 1;
                return;
            }
        }
        if (reason == CANFD_Reason_RX)
        {
            {
                /* Reset the receive buffer */
                memset(&rxData, 0, sizeof (rxData));
                dataLength = 0;
    
                retVal = CANFD_getData (handle, &id, &rxFrameType, &rxIdType, &rxDataLength, &rxData[0], &errCode);
                if (retVal < 0)
                {
                    //System_printf ("Error: CAN receive data for iteration %d failed [Error code %d]\n", iterationCount, errCode);
                    return;
                }
    
                if (rxFrameType != frameType)
                {
                    System_printf ("Error: CAN received incorrect frame type Sent %d Received %d for iteration %d failed\n", frameType, rxFrameType, iterationCount);
                    return;
                }
    
    
                /* Validate the data */
    
                gRxPkts++;
                gRxDoneFlag = 1;
                return;
            }
        }
        if (reason == CANFD_Reason_TX_CANCELED)
        {
            {
                gTxPkts++;
                gTxDoneFlag = 1;
                gRxDoneFlag = 1;
                return;
            }
        }
    
    }
    
    
    
    static void MCANAppInitParams(CANFD_MCANInitParams* mcanCfgParams)
    {
        /*Intialize MCAN Config Params*/
        memset (mcanCfgParams, sizeof (CANFD_MCANInitParams), 0);
    
        mcanCfgParams->fdMode          = 0x1U;
        mcanCfgParams->brsEnable       = 0x1U;
        mcanCfgParams->txpEnable       = 0x0U;
        mcanCfgParams->efbi            = 0x0U;
        mcanCfgParams->pxhddisable     = 0x0U;
        mcanCfgParams->darEnable       = 0x1U;
        mcanCfgParams->wkupReqEnable   = 0x1U;
        mcanCfgParams->autoWkupEnable  = 0x1U;
        mcanCfgParams->emulationEnable = 0x0U;
        mcanCfgParams->emulationFAck   = 0x0U;
        mcanCfgParams->clkStopFAck     = 0x0U;
        mcanCfgParams->wdcPreload      = 0x0U;
        mcanCfgParams->tdcEnable       = 0x1U;
        mcanCfgParams->tdcConfig.tdcf  = 0U;
        mcanCfgParams->tdcConfig.tdco  = 8U;
        mcanCfgParams->monEnable       = 0x0U;
        mcanCfgParams->asmEnable       = 0x0U;
        mcanCfgParams->tsPrescalar     = 0x0U;
        mcanCfgParams->tsSelect        = 0x0U;
        mcanCfgParams->timeoutSelect   = CANFD_MCANTimeOutSelect_CONT;
        mcanCfgParams->timeoutPreload  = 0x0U;
        mcanCfgParams->timeoutCntEnable= 0x0U;
        mcanCfgParams->filterConfig.rrfe        = 0x1U;
        mcanCfgParams->filterConfig.rrfs        = 0x1U;
        mcanCfgParams->filterConfig.anfe        = 0x1U;
        mcanCfgParams->filterConfig.anfs        = 0x1U;
        mcanCfgParams->msgRAMConfig.lss         = 127U;
        mcanCfgParams->msgRAMConfig.lse         = 64U;
        mcanCfgParams->msgRAMConfig.txBufNum    = 32U;
        mcanCfgParams->msgRAMConfig.txFIFOSize  = 0U;
        mcanCfgParams->msgRAMConfig.txBufMode   = 0U;
        mcanCfgParams->msgRAMConfig.txEventFIFOSize         = 0U;
        mcanCfgParams->msgRAMConfig.txEventFIFOWaterMark    = 0U;
        mcanCfgParams->msgRAMConfig.rxFIFO0size             = 0U;
        mcanCfgParams->msgRAMConfig.rxFIFO0OpMode           = 0U;
        mcanCfgParams->msgRAMConfig.rxFIFO0waterMark        = 0U;
        mcanCfgParams->msgRAMConfig.rxFIFO1size             = 64U;
        mcanCfgParams->msgRAMConfig.rxFIFO1waterMark        = 64U;
        mcanCfgParams->msgRAMConfig.rxFIFO1OpMode           = 64U;
    
    
        mcanCfgParams->eccConfig.enable         = 1;
        mcanCfgParams->eccConfig.enableChk      = 1;
        mcanCfgParams->eccConfig.enableRdModWr  = 1;
    
        mcanCfgParams->errInterruptEnable   = 1U;
        mcanCfgParams->dataInterruptEnable  = 1U;
        mcanCfgParams->appErrCallBack       = MCANAppErrStatusCallback;
        mcanCfgParams->appDataCallBack      = MCANAppCallback;
    }
    
    
    
    void Can_Initialize(void)
    {
    
        int32_t                     errCode = 0;
         int32_t                     retVal = 0;
        // int32_t j = 0;
        //CANFD_OptionTLV             optionTLV;
        CANFD_MCANInitParams        mcanCfgParams;
        CANFD_MCANBitTimingParams   mcanBitTimingParams;
        #if 0
        CANFD_MCANMsgObjectStats    msgObjStats;
        CANFD_MCANErrCntStatus      errCounter;
        CANFD_MCANProtocolStatus    protoStatus;
        #endif
        CANFD_MCANMsgObjCfgParams   rxMsgObjectParams;
        CANFD_MsgObjHandle          rxMsgObjHandle;
    
        gTxDoneFlag = 0;
        gRxDoneFlag = 0;
    
    
        /* Setup the PINMUX to bring out the XWR16xx CAN pins */
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINE14_PADAE, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINE14_PADAE, SOC_XWR18XX_PINE14_PADAE_CANFD_TX);
    
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PIND13_PADAD, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PIND13_PADAD, SOC_XWR18XX_PIND13_PADAD_CANFD_RX);
    
         /* Configure the divide value for MCAN source clock */
        SOC_setPeripheralClock(gMmwMssMCB.socHandle, SOC_MODULE_MCAN, SOC_CLKSOURCE_VCLK, 4U, &errCode);
    
        /* Initialize peripheral memory */
        SOC_initPeripheralRam(gMmwMssMCB.socHandle, SOC_MODULE_MCAN, &errCode);
    
    
        CSL_FINSR(0x43201450, 22, 22, 0x1U);
        CSL_FINSR(0x4320140C, 26, 16, 0x23U);
    
    
        MCANAppInitParams (&mcanCfgParams);
    
        /* Initialize the CANFD driver */
        canHandle = CANFD_init(0, &mcanCfgParams, &errCode);
        if (canHandle == NULL)
        {
            System_printf ("Error: CANFD Module Initialization failed [Error code %d]\n", errCode);
            return ;
        }
    
        /* Configuring 1Mbps and 5Mbps as nominal and data bit-rate respectively
            Prop seg: 8
            Ph seg 1: 6
            Ph Seg2 : 5
            Sync jump: 1
            BRP(Baud rate Prescaler): 2
    
            Nominal Bit rate = (40)/(((8+6+5)+1)*BRP) = 1Mhz
    
            Timing Params for Data Bit rate:
            Prop seg: 2
            Ph seg 1: 2
            Ph Seg2 : 3
            Sync jump: 1
            BRP(Baud rate Prescaler): 1
    
            Nominal Bit rate = (40)/(((2+2+3)+1)*BRP) = 5Mhz
        */
    #if 1
        mcanBitTimingParams.nomBrp      = 0x2U;
        mcanBitTimingParams.nomPropSeg  = 0x8U;
        mcanBitTimingParams.nomPseg1    = 0x6U;
        mcanBitTimingParams.nomPseg2    = 0x5U;
        mcanBitTimingParams.nomSjw      = 0x1U;
    #else
        /*500Kbps NomBitRate: (40)/(((6+5+4)+1)*5)*/
        mcanBitTimingParams.nomBrp      = 0x5U;
        mcanBitTimingParams.nomPropSeg  = 0x6U;
        mcanBitTimingParams.nomPseg1    = 0x5U;
        mcanBitTimingParams.nomPseg2    = 0x4U;
        mcanBitTimingParams.nomSjw      = 0x1U;
    #endif
    
    #if 1 //5 Mbps
        mcanBitTimingParams.dataBrp     = 0x1U;
        mcanBitTimingParams.dataPropSeg = 0x2U;
        mcanBitTimingParams.dataPseg1   = 0x2U;
        mcanBitTimingParams.dataPseg2   = 0x3U;
        mcanBitTimingParams.dataSjw     = 0x1U;
    #else //2 Mbps
        mcanBitTimingParams.dataBrp     = 0x4U;
        mcanBitTimingParams.dataPropSeg = 01U;
        mcanBitTimingParams.dataPseg1   = 0x2U;
        mcanBitTimingParams.dataPseg2   = 0x1U;
        mcanBitTimingParams.dataSjw     = 0x1U;
    
    #endif
        /* Configure the CAN driver */
        retVal = CANFD_configBitTime (canHandle, &mcanBitTimingParams, &errCode);
        if (retVal < 0)
        {
            System_printf ("Error: CANFD Module configure bit time failed [Error code %d]\n", errCode);
            return ;
        }
    
        /* Setup the transmit message object */
        txMsgObjectParams.direction = CANFD_Direction_TX;
        txMsgObjectParams.msgIdType = CANFD_MCANXidType_29_BIT;
        txMsgObjectParams.msgIdentifier = 0xD1 | CAN_MESSAGE_PARK_SENS_POS;
    
    
        txMsgObjHandle = CANFD_createMsgObject (canHandle, &txMsgObjectParams, &errCode);
        if (txMsgObjHandle == NULL)
        {
            System_printf ("Error: CANFD create Tx message object failed [Error code %d]\n", errCode);
            return ;
        }
    
    
        /* Setup the receive message object */
        rxMsgObjectParams.direction = CANFD_Direction_RX;
        rxMsgObjectParams.msgIdType = CANFD_MCANXidType_29_BIT;
        rxMsgObjectParams.msgIdentifier = 0xA1 | CAN_MESSAGE_PARK_SENS_POS;
    
        rxMsgObjHandle = CANFD_createMsgObject (canHandle, &rxMsgObjectParams, &errCode);
        if (rxMsgObjHandle == NULL)
        {
            System_printf ("Error: CANFD create Rx message object failed [Error code %d]\n", errCode);
            return ;
        }
    
    
    }
    
    
    
    
    /**
     *  @b Description
     *  @n
     *      Utility function to find out if all common configuration is in non-pending (cleared)
     *      state.
     *
     *  @param[in] cfg Pointer to common specific configuration
     *
     *  @retval 1 if all common configuration is in non-pending state, else return 0
     */
    static uint8_t MmwDemo_isDynObjDetCommonCfgInNonPendingState(MmwDemo_DPC_ObjDet_CommonCfg *cfg)
    {
        uint8_t retVal;
    
        retVal = (cfg->isCompRxChannelBiasCfgPending    == 0) &&
                 (cfg->isMeasureRxChannelBiasCfgPending == 0);
    
        return(retVal);
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to find out if all sub-frame specific dynamic configuration
     *      is in non-pending (cleared) state.
     *
     *  @param[in] cfg Pointer to common specific configuration
     *
     *  @retval 1 if all sub-frame specific dynamic configuration is in non-pending
     *          state, else return 0
     */
    static uint8_t MmwDemo_isDynObjDetCfgInNonPendingState(MmwDemo_DPC_ObjDet_DynCfg *cfg)
    {
        uint8_t retVal;
    
        retVal = (cfg->isCalibDcRangeSigCfg    == 0) &&
                 (cfg->isCfarCfgDopplerPending == 0) &&
                 (cfg->isCfarCfgRangePending   == 0) &&
                 (cfg->isFovDopplerPending     == 0) &&
                 (cfg->isFovRangePending       == 0) &&
                 (cfg->isMultiObjBeamFormingCfgPending     == 0) &&
                 (cfg->isPrepareRangeAzimuthHeatMapPending == 0) &&
                 (cfg->isStaticClutterRemovalCfgPending    == 0) &&
                 (cfg->isFovAoaCfgPending                  == 0) &&
                 (cfg->isExtMaxVelCfgPending               == 0);
    
        return(retVal);
    }
    
    /**
     *  @b Description
     *  @n
     *      Resets (clears) all pending common configuration of Object Detection DPC
     *
     *  @param[in] cfg Object Detection DPC common configuration
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_resetDynObjDetCommonCfgPendingState(MmwDemo_DPC_ObjDet_CommonCfg *cfg)
    {
        cfg->isCompRxChannelBiasCfgPending = 0;
        cfg->isMeasureRxChannelBiasCfgPending = 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      Resets (clears) all pending sub-frame specific dynamic configuration
     *      of Object Detection DPC
     *
     *  @param[in] cfg Object Detection DPC sub-frame dynamic configuration
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_resetDynObjDetCfgPendingState(MmwDemo_DPC_ObjDet_DynCfg *cfg)
    {
        cfg->isCalibDcRangeSigCfg    = 0;
        cfg->isCfarCfgDopplerPending = 0;
        cfg->isCfarCfgRangePending   = 0;
        cfg->isFovDopplerPending     = 0;
        cfg->isFovRangePending       = 0;
        cfg->isMultiObjBeamFormingCfgPending = 0;
        cfg->isPrepareRangeAzimuthHeatMapPending = 0;
        cfg->isStaticClutterRemovalCfgPending = 0;
        cfg->isFovAoaCfgPending = 0;
    	cfg->isExtMaxVelCfgPending = 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      Resets (clears) all pending static (non-dynamic) configuration
     *
     */
    void MmwDemo_resetStaticCfgPendingState(void)
    {
        uint8_t indx;
    
        for(indx = 0; indx < gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames; indx++)
        {
            gMmwMssMCB.subFrameCfg[indx].isAdcBufCfgPending = 0;
            gMmwMssMCB.subFrameCfg[indx].isLvdsStreamCfgPending = 0;
        }
    
        gMmwMssMCB.isAnaMonCfgPending = 0;
        gMmwMssMCB.isCalibCfgPending = 0;
    
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to find out if all configuration (common and sub-frame
     *      specific dynamic config) is in pending state.
     *
     *  @retval 1 if all configuration (common and sub-frame specific dynamic config)
     *            is in pending state, else return 0
     */
    uint8_t MmwDemo_isAllCfgInPendingState(void)
    {
        uint8_t indx, flag = 1;
    
        for(indx = 0; indx < gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames; indx++)
        {
            flag = flag && MmwDemo_isDynObjDetCfgPendingState(&gMmwMssMCB.subFrameCfg[indx].objDetDynCfg);
            flag = flag && (gMmwMssMCB.subFrameCfg[indx].isAdcBufCfgPending == 1);
            flag = flag && (gMmwMssMCB.subFrameCfg[indx].isLvdsStreamCfgPending == 1);
        }
    
        flag = flag && MmwDemo_isDynObjDetCommonCfgPendingState(&gMmwMssMCB.objDetCommonCfg);
        flag = flag && (gMmwMssMCB.isAnaMonCfgPending == 1);
        flag = flag && (gMmwMssMCB.isCalibCfgPending == 1);
    
        return(flag);
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to find out if all configuration (common and sub-frame
     *      specific dynamic config) is in non-pending (cleared) state.
     *
     *  @retval 1 if all configuration (common and sub-frame specific dynamic config)
     *            is in non-pending state, else return 0
     */
    uint8_t MmwDemo_isAllCfgInNonPendingState(void)
    {
        uint8_t indx, flag = 1;
    
        for(indx = 0; indx < gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames; indx++)
        {
            flag = flag && MmwDemo_isDynObjDetCfgInNonPendingState(&gMmwMssMCB.subFrameCfg[indx].objDetDynCfg);
            flag = flag && (gMmwMssMCB.subFrameCfg[indx].isAdcBufCfgPending == 0);
            flag = flag && (gMmwMssMCB.subFrameCfg[indx].isLvdsStreamCfgPending == 0);
        }
    
        flag = flag && (MmwDemo_isDynObjDetCommonCfgInNonPendingState(&gMmwMssMCB.objDetCommonCfg) && flag);
        flag = flag && (gMmwMssMCB.isAnaMonCfgPending == 0);
        flag = flag && (gMmwMssMCB.isCalibCfgPending == 0);
    
        return(flag);
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to apply configuration to specified sub-frame
     *
     *  @param[in] srcPtr Pointer to configuration
     *  @param[in] offset Offset of configuration within the parent structure
     *  @param[in] size   Size of configuration
     *  @param[in] subFrameNum Sub-frame Number (0 based) to apply to, broadcast to
     *                         all sub-frames if special code MMWDEMO_SUBFRAME_NUM_FRAME_LEVEL_CONFIG
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    void MmwDemo_CfgUpdate(void *srcPtr, uint32_t offset, uint32_t size, int8_t subFrameNum)
    {    
        /* if subFrameNum undefined, broadcast to all sub-frames */
        if(subFrameNum == MMWDEMO_SUBFRAME_NUM_FRAME_LEVEL_CONFIG)
        {
            uint8_t  indx;
            for(indx = 0; indx < RL_MAX_SUBFRAMES; indx++)
            {
                memcpy((void *)((uint32_t) &gMmwMssMCB.subFrameCfg[indx] + offset), srcPtr, size);
                MmwDemo_setSubFramePendingState(&gMmwMssMCB.subFrameCfg[indx], offset);
            }
        }
        else
        {
            /* Apply configuration to specific subframe (or to position zero for the legacy case
               where there is no advanced frame config) */
            memcpy((void *)((uint32_t) &gMmwMssMCB.subFrameCfg[subFrameNum] + offset), srcPtr, size);
            MmwDemo_setSubFramePendingState(&gMmwMssMCB.subFrameCfg[subFrameNum], offset);
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to get temperature report from front end and
     *      save it in global structure.
     *
     *  @retval None
     */
    void MmwDemo_getTemperatureReport()
    {
        /* Get Temerature report */
        gMmwMssMCB.temperatureStats.tempReportValid = rlRfGetTemperatureReport(RL_DEVICE_MAP_INTERNAL_BSS, 
                            (rlRfTempData_t*)&gMmwMssMCB.temperatureStats.temperatureReport);
    }
    
    
    
    /**************************************************************************
     ******************** Millimeter Wave Demo Results Transmit Functions *************
     **************************************************************************/
    static void MmwDemo_measurementResultOutput(DPU_AoAProc_compRxChannelBiasCfg *compRxChanCfg)
    {
        /* Send the received DSS calibration info through CLI */
        CLI_write ("compRangeBiasAndRxChanPhase");
        CLI_write (" %.7f", compRxChanCfg->rangeBias);
        int32_t i;
        for (i = 0; i < SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL; i++)
        {
            CLI_write (" %.5f", (float) compRxChanCfg->rxChPhaseComp[i].real/32768.);
            CLI_write (" %.5f", (float) compRxChanCfg->rxChPhaseComp[i].imag/32768.);
        }
        CLI_write ("\n");
    }
    
    /** @brief Transmits detection data over UART
    *
    *    The following data is transmitted:
    *    1. Header (size = 32bytes), including "Magic word", (size = 8 bytes)
    *       and including the number of TLV items
    *    TLV Items:
    *    2. If detectedObjects flag is 1 or 2, DPIF_PointCloudCartesian structure containing
    *       X,Y,Z location and velocity for detected objects,
    *       size = sizeof(DPIF_PointCloudCartesian) * number of detected objects
    *    3. If detectedObjects flag is 1, DPIF_PointCloudSideInfo structure containing SNR
    *       and noise for detected objects,
    *       size = sizeof(DPIF_PointCloudCartesian) * number of detected objects
    *    4. If logMagRange flag is set,  rangeProfile,
    *       size = number of range bins * sizeof(uint16_t)
    *    5. If noiseProfile flag is set,  noiseProfile,
    *       size = number of range bins * sizeof(uint16_t)
    *    6. If rangeAzimuthHeatMap flag is set, the zero Doppler column of the
    *       range cubed matrix, size = number of Rx Azimuth virtual antennas *
    *       number of chirps per frame * sizeof(uint32_t)
    *    7. If rangeDopplerHeatMap flag is set, the log magnitude range-Doppler matrix,
    *       size = number of range bins * number of Doppler bins * sizeof(uint16_t)
    *    8. If statsInfo flag is set, the stats information
    *   @param[in] uartHandle   UART driver handle
    *   @param[in] result       Pointer to result from object detection DPC processing
    *   @param[in] timingInfo   Pointer to timing information provided from core that runs data path
    */
    static void MmwDemo_transmitProcessedOutput
    (
        UART_Handle     uartHandle,
        DPC_ObjectDetection_ExecuteResult   *result,
        MmwDemo_output_message_stats        *timingInfo
    )
    {
        MmwDemo_output_message_header header;
        MmwDemo_GuiMonSel   *pGuiMonSel;
        MmwDemo_SubFrameCfg *subFrameCfg;
        uint32_t tlvIdx = 0;
        uint32_t index;
        uint32_t numPaddingBytes;
        uint32_t packetLen;
        uint8_t padding[MMWDEMO_OUTPUT_MSG_SEGMENT_LEN];
        MmwDemo_output_message_tl   tl[MMWDEMO_OUTPUT_MSG_MAX];
        int32_t errCode;
        uint16_t *detMatrix = (uint16_t *)result->detMatrix.data;
        DPIF_PointCloudCartesian *objOut;
        cmplx16ImRe_t *azimuthStaticHeatMap;
        DPIF_PointCloudSideInfo *objOutSideInfo;
        DPC_ObjectDetection_Stats *stats;
        
        /* Get subframe configuration */
        subFrameCfg = &gMmwMssMCB.subFrameCfg[result->subFrameIdx];
    
        /* Get Gui Monitor configuration */
        pGuiMonSel = &subFrameCfg->guiMonSel;
    
        /* Clear message header */
        memset((void *)&header, 0, sizeof(MmwDemo_output_message_header));
    
        /******************************************************************
           Send out data that is enabled, Since processing results are from DSP,
           address translation is needed for buffer pointers
        *******************************************************************/
        {
            detMatrix = (uint16_t *) SOC_translateAddress((uint32_t)detMatrix,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)detMatrix!= SOC_TRANSLATEADDR_INVALID);
    
            objOut = (DPIF_PointCloudCartesian *) SOC_translateAddress((uint32_t)result->objOut,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)objOut != SOC_TRANSLATEADDR_INVALID);
    
            objOutSideInfo = (DPIF_PointCloudSideInfo *) SOC_translateAddress((uint32_t)result->objOutSideInfo,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)objOutSideInfo != SOC_TRANSLATEADDR_INVALID);
    
            stats = (DPC_ObjectDetection_Stats *) SOC_translateAddress((uint32_t)result->stats,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)stats != SOC_TRANSLATEADDR_INVALID);
    
    
            result->radarCube.data = (void *) SOC_translateAddress((uint32_t) result->radarCube.data,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t) result->radarCube.data!= SOC_TRANSLATEADDR_INVALID);
        }
    
        /* Header: */
        header.platform =  0xA1843;
        header.magicWord[0] = 0x0102;
        header.magicWord[1] = 0x0304;
        header.magicWord[2] = 0x0506;
        header.magicWord[3] = 0x0708;
        header.numDetectedObj = result->numObjOut;
        header.version =    MMWAVE_SDK_VERSION_BUILD |
                            (MMWAVE_SDK_VERSION_BUGFIX << 8) |
                            (MMWAVE_SDK_VERSION_MINOR << 16) |
                            (MMWAVE_SDK_VERSION_MAJOR << 24);
    
        packetLen = sizeof(MmwDemo_output_message_header);
        if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) &&
             (result->numObjOut > 0))
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS;
            tl[tlvIdx].length = sizeof(DPIF_PointCloudCartesian) * result->numObjOut;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        /* Side info */
        if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0))
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS_SIDE_INFO;
            tl[tlvIdx].length = sizeof(DPIF_PointCloudSideInfo) * result->numObjOut;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->logMagRange)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_PROFILE;
            tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->noiseProfile)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_NOISE_PROFILE;
            tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->rangeAzimuthHeatMap)
        {
    #if defined(USE_2D_AOA_DPU)
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_ELEVATION_STATIC_HEAT_MAP;
    #else
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP;
    #endif
            tl[tlvIdx].length = result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t);
            packetLen += sizeof(MmwDemo_output_message_tl) +  tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->rangeDopplerHeatMap)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_DOPPLER_HEAT_MAP;
            tl[tlvIdx].length = subFrameCfg->numRangeBins * subFrameCfg->numDopplerBins * sizeof(uint16_t);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->statsInfo)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_STATS;
            tl[tlvIdx].length = sizeof(MmwDemo_output_message_stats);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
    
            MmwDemo_getTemperatureReport();
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_TEMPERATURE_STATS;
            tl[tlvIdx].length = sizeof(MmwDemo_temperatureStats);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
    
        header.numTLVs = tlvIdx;
        /* Round up packet length to multiple of MMWDEMO_OUTPUT_MSG_SEGMENT_LEN */
        header.totalPacketLen = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN *
                ((packetLen + (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1))/MMWDEMO_OUTPUT_MSG_SEGMENT_LEN);
        header.timeCpuCycles = Pmu_getCount(0);
        header.frameNumber = stats->frameStartIntCounter;
        header.subFrameNumber = result->subFrameIdx;
    
        UART_writePolling (uartHandle,
                           (uint8_t*)&header,
                           sizeof(MmwDemo_output_message_header));
        txMsgObjectParams.msgIdentifier = 0xB1;//Get_CanMessageIdentifier((MmwDemo_output_message_type)MMWDEMO_OUTPUT_MSG_DETECTED_POINTS);
        Can_Transmit_Schedule(txMsgObjectParams.msgIdentifier,(uint8_t*)&header,
                              sizeof(MmwDemo_output_message_header));
    
        tlvIdx = 0;
        /* Send detected Objects */
        if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) &&
            (result->numObjOut > 0))
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            /*Send array of objects */
            UART_writePolling (uartHandle, (uint8_t*)objOut,
                               sizeof(DPIF_PointCloudCartesian) * result->numObjOut);
    
            txMsgObjectParams.msgIdentifier = 0xD1;//Get_CanMessageIdentifier((MmwDemo_output_message_type)MMWDEMO_OUTPUT_MSG_DETECTED_POINTS);
            Can_Transmit_Schedule(txMsgObjectParams.msgIdentifier,(uint8_t*)objOut, sizeof(DPIF_PointCloudCartesian) * result->numObjOut);
            tlvIdx++;
        }
    
        /* Send detected Objects Side Info */
        if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0))
        {
    
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            UART_writePolling (uartHandle, (uint8_t*)objOutSideInfo,
                               sizeof(DPIF_PointCloudSideInfo) * result->numObjOut);
            txMsgObjectParams.msgIdentifier = 0xD2;//Get_CanMessageIdentifier((MmwDemo_output_message_type)MMWDEMO_OUTPUT_MSG_DETECTED_POINTS);
            Can_Transmit_Schedule(txMsgObjectParams.msgIdentifier,(uint8_t*)objOutSideInfo,
                                  sizeof(DPIF_PointCloudSideInfo) * result->numObjOut);
            tlvIdx++;
        }
    
        /* Send Range profile */
        if (pGuiMonSel->logMagRange)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            for(index = 0; index < subFrameCfg->numRangeBins; index++)
            {
                UART_writePolling (uartHandle,
                        (uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins],
                        sizeof(uint16_t));
            }
            tlvIdx++;
        }
    
        /* Send noise profile */
        if (pGuiMonSel->noiseProfile)
        {
            uint32_t maxDopIdx = subFrameCfg->numDopplerBins/2 -1;
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            for(index = 0; index < subFrameCfg->numRangeBins; index++)
            {
                UART_writePolling (uartHandle,
                        (uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins + maxDopIdx],
                        sizeof(uint16_t));
            }
            tlvIdx++;
        }
    
        /* Send data for static azimuth heatmap */
        if (pGuiMonSel->rangeAzimuthHeatMap)
        {
            azimuthStaticHeatMap = (cmplx16ImRe_t *) SOC_translateAddress((uint32_t)result->azimuthStaticHeatMap,
                                                         SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                         &errCode);
            DebugP_assert ((uint32_t)azimuthStaticHeatMap!= SOC_TRANSLATEADDR_INVALID);
    
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            UART_writePolling (uartHandle,
                    (uint8_t *)azimuthStaticHeatMap,
                    result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t));
    
            tlvIdx++;
        }
    
        /* Send data for range/Doppler heatmap */
        if (pGuiMonSel->rangeDopplerHeatMap == 1)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            UART_writePolling (uartHandle,
                    (uint8_t*)detMatrix,
                    tl[tlvIdx].length);
            tlvIdx++;
        }
    
        /* Send stats information */
        if (pGuiMonSel->statsInfo == 1)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            /* Address translation is done when buffer is received*/
            UART_writePolling (uartHandle,
                               (uint8_t*)timingInfo,
                               tl[tlvIdx].length);
            tlvIdx++;
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
            UART_writePolling (uartHandle,
                               (uint8_t*)&gMmwMssMCB.temperatureStats,
                               tl[tlvIdx].length);
            tlvIdx++;
        }
    
        /* Send padding bytes */
        numPaddingBytes = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN - (packetLen & (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1));
        if (numPaddingBytes<MMWDEMO_OUTPUT_MSG_SEGMENT_LEN)
        {
            UART_writePolling (uartHandle,
                                (uint8_t*)padding,
                                numPaddingBytes);
        }
    
    }
    
    /**************************************************************************
     ******************** Millimeter Wave Demo control path Functions *****************
     **************************************************************************/
    /**
     *  @b Description
     *  @n
     *      The function is used to trigger the Front end to stop generating chirps.
     *
     *  @retval
     *      Not Applicable.
     */
    static int32_t MmwDemo_mmWaveCtrlStop (void)
    {
        int32_t                 errCode = 0;
    
        DebugP_log0("App: Issuing MMWave_stop\n");
    
        /* Stop the mmWave module: */
        if (MMWave_stop (gMmwMssMCB.ctrlHandle, &errCode) < 0)
        {
            MMWave_ErrorLevel   errorLevel;
            int16_t             mmWaveErrorCode;
            int16_t             subsysErrorCode;
    
            /* Error/Warning: Unable to stop the mmWave module */
            MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
            if (errorLevel == MMWave_ErrorLevel_ERROR)
            {
                /* Error: Display the error message: */
                System_printf ("Error: mmWave Stop failed [Error code: %d Subsystem: %d]\n",
                                mmWaveErrorCode, subsysErrorCode);
    
                /* Not expected */
                MmwDemo_debugAssert(0);
            }
            else
            {
                /* Warning: This is treated as a successful stop. */
                System_printf ("mmWave Stop error ignored [Error code: %d Subsystem: %d]\n",
                                mmWaveErrorCode, subsysErrorCode);
            }
        }
    
        return errCode;
    }
    
    /**
     *  @b Description
     *  @n
     *      The task is used to provide an execution context for the mmWave
     *      control task
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_mmWaveCtrlTask(UArg arg0, UArg arg1)
    {
        int32_t errCode;
    
        while (1)
        {
            /* Execute the mmWave control module: */
            if (MMWave_execute (gMmwMssMCB.ctrlHandle, &errCode) < 0)
            {
                //System_printf ("Error: mmWave control execution failed [Error code %d]\n", errCode);
                MmwDemo_debugAssert (0);
            }
        }
    }
    
    /**************************************************************************
     ******************** Millimeter Wave Demo data path Functions *******************
     **************************************************************************/
    
    /**
     *  @b Description
     *  @n
     *      Help function to make DPM_ioctl blocking until response is reported
     *
     *  @retval
     *      Success         -0
     *      Failed          <0
     */
    static int32_t MmwDemo_DPM_ioctl_blocking
    (
        DPM_Handle handle,
        uint32_t cmd,
        void* arg,
        uint32_t argLen
    )
    {
        int32_t retVal = 0;
    
        retVal = DPM_ioctl(handle,
                         cmd,
                         arg,
                         argLen);
    
        if(retVal == 0)
        {
            /* Wait until ioctl completed */
            Semaphore_pend(gMmwMssMCB.DPMioctlSemHandle, BIOS_WAIT_FOREVER);
        }
    
        return(retVal);
    }
    
    /**
     *  @b Description
     *  @n
     *      Perform Data path driver open 
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_dataPathOpen(void)
    {
        gMmwMssMCB.adcBufHandle = MmwDemo_ADCBufOpen(gMmwMssMCB.socHandle);
        if(gMmwMssMCB.adcBufHandle == NULL)
        {
            MmwDemo_debugAssert(0);
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      Function to configure CQ.
     *
     *  @param[in] subFrameCfg Pointer to sub-frame config
     *  @param[in] numChirpsPerChirpEvent number of chirps per chirp event
     *  @param[in] validProfileIdx valid profile index
     *
     *  @retval
     *      0 if no error, else error (there will be system prints for these).
     */
    static int32_t MmwDemo_configCQ(MmwDemo_SubFrameCfg *subFrameCfg,
                                    uint8_t numChirpsPerChirpEvent,
                                    uint8_t validProfileIdx)
    {
        MmwDemo_AnaMonitorCfg*      ptrAnaMonitorCfg;
        ADCBuf_CQConf               cqConfig;
        rlRxSatMonConf_t*           ptrSatMonCfg;
        rlSigImgMonConf_t*          ptrSigImgMonCfg;
        int32_t                     retVal;
        uint16_t                    cqChirpSize;
    
        /* Get analog monitor configuration */
        ptrAnaMonitorCfg = &gMmwMssMCB.anaMonCfg;
    
        /* Config mmwaveLink to enable Saturation monitor - CQ2 */
        ptrSatMonCfg = &gMmwMssMCB.cqSatMonCfg[validProfileIdx];
    
        if (ptrAnaMonitorCfg->rxSatMonEn)
        {
            if (ptrSatMonCfg->profileIndx != validProfileIdx)
            {
                System_printf ("Error: Saturation monitoring (globally) enabled but not configured for profile(%d)\n",
                               validProfileIdx);
                MmwDemo_debugAssert(0);
            }
    
            retVal = mmwDemo_cfgRxSaturationMonitor(ptrSatMonCfg);
            if(retVal != 0)
            {
                System_printf ("Error: rlRfRxIfSatMonConfig returns error = %d for profile(%d)\n",
                               retVal, ptrSatMonCfg->profileIndx);
                goto exit;
            }
        }
    
        /* Config mmwaveLink to enable Saturation monitor - CQ1 */
        ptrSigImgMonCfg = &gMmwMssMCB.cqSigImgMonCfg[validProfileIdx];
    
        if (ptrAnaMonitorCfg->sigImgMonEn)
        {
            if (ptrSigImgMonCfg->profileIndx != validProfileIdx)
            {
                System_printf ("Error: Sig/Image monitoring (globally) enabled but not configured for profile(%d)\n",
                               validProfileIdx);
                MmwDemo_debugAssert(0);
            }
    
            retVal = mmwDemo_cfgRxSigImgMonitor(ptrSigImgMonCfg);
            if(retVal != 0)
            {
                System_printf ("Error: rlRfRxSigImgMonConfig returns error = %d for profile(%d)\n",
                               retVal, ptrSigImgMonCfg->profileIndx);
                goto exit;
            }
        }
    
        retVal = mmwDemo_cfgAnalogMonitor(ptrAnaMonitorCfg);
        if (retVal != 0)
        {
            System_printf ("Error: rlRfAnaMonConfig returns error = %d\n", retVal);
            goto exit;
        }
    
        if(ptrAnaMonitorCfg->rxSatMonEn || ptrAnaMonitorCfg->sigImgMonEn)
        {
            /* CQ driver config */
            memset((void *)&cqConfig, 0, sizeof(ADCBuf_CQConf));
            cqConfig.cqDataWidth = 0; /* 16bit for mmw demo */
            cqConfig.cq1AddrOffset = MMW_DEMO_CQ_SIGIMG_ADDR_OFFSET; /* CQ1 starts from the beginning of the buffer */
            cqConfig.cq2AddrOffset = MMW_DEMO_CQ_RXSAT_ADDR_OFFSET;  /* Address should be 16 bytes aligned */
    
            retVal = ADCBuf_control(gMmwMssMCB.adcBufHandle, ADCBufMMWave_CMD_CONF_CQ, (void *)&cqConfig);
            if (retVal < 0)
            {
                System_printf ("Error: MMWDemoDSS Unable to configure the CQ\n");
                MmwDemo_debugAssert(0);
            }
        }
    
        if (ptrAnaMonitorCfg->sigImgMonEn)
        {
            /* This is for 16bit format in mmw demo, signal/image band data has 2 bytes/slice
               For other format, please check DFP interface document
             */
            cqChirpSize = (ptrSigImgMonCfg->numSlices + 1) * sizeof(uint16_t);
            cqChirpSize = MATHUTILS_ROUND_UP_UNSIGNED(cqChirpSize, MMW_DEMO_CQ_DATA_ALIGNMENT);
            subFrameCfg->sigImgMonTotalSize = cqChirpSize * numChirpsPerChirpEvent;
        }
    
        if (ptrAnaMonitorCfg->rxSatMonEn)
        {
            /* This is for 16bit format in mmw demo, saturation data has one byte/slice
               For other format, please check DFP interface document
             */
            cqChirpSize = (ptrSatMonCfg->numSlices + 1) * sizeof(uint8_t);
            cqChirpSize = MATHUTILS_ROUND_UP_UNSIGNED(cqChirpSize, MMW_DEMO_CQ_DATA_ALIGNMENT);
            subFrameCfg->satMonTotalSize = cqChirpSize * numChirpsPerChirpEvent;
        }
    
    exit:
        return(retVal);
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to convert the CFAR threshold
     *      from a CLI encoded dB value to a linear value
     *      as expected by the CFAR DPU
     *
     *  @param[in] codedCfarVal CFAR threshold in dB as encoded in the CLI 
     *  @param[in] numVirtualAntennas Number of virtual antennas
     *
     *  @retval
     *      CFAR threshold in linear format
     */
    static uint16_t MmwDemo_convertCfarToLinear(uint16_t codedCfarVal, uint8_t numVirtualAntennas)
    {
        uint16_t linearVal;
        float    dbVal, linVal;   
    
        /* dbVal is a float value from 0-100dB. It needs to
        be converted to linear scale..
        First, recover float dbVal that was encoded in CLI. */
        dbVal = (float)(codedCfarVal / MMWDEMO_CFAR_THRESHOLD_ENCODING_FACTOR);
        
        /* Now convert it to linear value according to the following:
        linear_value = dB_value * (256 / 6) * (numVirtualAntennas / (2^ ceil(log2(numVirtualAntennas)))) .
        */
        linVal = dbVal * (256.0 / 6.0) * ((float)numVirtualAntennas / (float)(1 << mathUtils_ceilLog2(numVirtualAntennas)));
        
        linearVal = (uint16_t) linVal;
        return (linearVal);
    }
    
    
    /**
     *  @b Description
     *  @n
     *      The function is used to configure the data path based on the chirp profile.
     *      After this function is executed, the data path processing will ready to go
     *      when the ADC buffer starts receiving samples corresponding to the chirps.
     *
     *  @retval
     *      Success     - 0
     *  @retval
     *      Error       - <0
     */
    static int32_t MmwDemo_dataPathConfig (void)
    {
        int32_t                         errCode;
        MMWave_CtrlCfg                  *ptrCtrlCfg;
        MmwDemo_DPC_ObjDet_CommonCfg *objDetCommonCfg;
        MmwDemo_SubFrameCfg             *subFrameCfg;
        int8_t                          subFrameIndx;
        MmwDemo_RFParserOutParams       RFparserOutParams;
        DPC_ObjectDetection_PreStartCfg  objDetPreStartCfg;
        DPC_ObjectDetection_StaticCfg   *staticCfg;
    
        /* Get data path object and control configuration */
        ptrCtrlCfg = &gMmwMssMCB.cfg.ctrlCfg;
    
        objDetCommonCfg = &gMmwMssMCB.objDetCommonCfg;
        staticCfg = &objDetPreStartCfg.staticCfg;
    
        gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames =
            MmwDemo_RFParser_getNumSubFrames(ptrCtrlCfg);
    
        DebugP_log0("App: Issuing Pre-start Common Config IOCTL\n");
    
        /* Get RF frequency scale factor */
        gMmwMssMCB.rfFreqScaleFactor = SOC_getDeviceRFFreqScaleFactor(gMmwMssMCB.socHandle, &errCode);
        if (errCode < 0)
        {
            System_printf ("Error: Unable to get RF scale factor [Error:%d]\n", errCode);
            MmwDemo_debugAssert(0);
        }
    
        /* Copy antenna geometry definition */
    #if defined(XWR18XX_AOP_ANTENNA_PATTERN)
        extern ANTDEF_AntGeometry gAntDef_AWR1843AOP;
        objDetCommonCfg->preStartCommonCfg.antDef = gAntDef_AWR1843AOP;
    #endif
    
        /* DPC pre-start common config */
        errCode = MmwDemo_DPM_ioctl_blocking (gMmwMssMCB.objDetDpmHandle,
                             DPC_OBJDET_IOCTL__STATIC_PRE_START_COMMON_CFG,
                             &objDetCommonCfg->preStartCommonCfg,
                             sizeof (DPC_ObjectDetection_PreStartCommonCfg));
    
        if (errCode < 0)
        {
            System_printf ("Error: Unable to send DPC_OBJDET_IOCTL__STATIC_PRE_START_COMMON_CFG [Error:%d]\n", errCode);
            goto exit;
        }
    
        MmwDemo_resetDynObjDetCommonCfgPendingState(&gMmwMssMCB.objDetCommonCfg);
    
        /* Reason for reverse loop is that when sensor is started, the first sub-frame
         * will be active and the ADC configuration needs to be done for that sub-frame
         * before starting (ADC buf hardware does not have notion of sub-frame, it will
         * be reconfigured every sub-frame). This cannot be alternatively done by calling
         * the MmwDemo_ADCBufConfig function only for the first sub-frame because this is
         * a utility API that computes the rxChanOffset that is part of ADC dataProperty
         * which will be used by range DPU and therefore this computation is required for
         * all sub-frames.
         */
        for(subFrameIndx = gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames -1; subFrameIndx >= 0;
            subFrameIndx--)
        {
            subFrameCfg  = &gMmwMssMCB.subFrameCfg[subFrameIndx];
    
            /*****************************************************************************
             * Data path :: Algorithm Configuration
             *****************************************************************************/
    
            /* Parse the profile and chirp configs and get the valid number of TX Antennas */
            errCode = MmwDemo_RFParser_parseConfig(&RFparserOutParams, subFrameIndx,
                                             &gMmwMssMCB.cfg.openCfg, ptrCtrlCfg,
                                             &subFrameCfg->adcBufCfg,
                                             gMmwMssMCB.rfFreqScaleFactor,
                                             false/* no BPM in 18xx demo */);
    
            /* if number of doppler chirps is too low, interpolate to be able to detect
             * better with CFAR tuning. E.g. a 2-pt FFT will be problematic in terms
             * of distinguishing direction of motion */
            if (RFparserOutParams.numDopplerChirps <= 4)
            {
                RFparserOutParams.dopplerStep = RFparserOutParams.dopplerStep / (8 / RFparserOutParams.numDopplerBins);
                RFparserOutParams.numDopplerBins = 8;
            }
    
            if (errCode != 0)
            {
                System_printf ("Error: MmwDemo_RFParser_parseConfig [Error:%d]\n", errCode);
                goto exit;
            }
    
            subFrameCfg->numRangeBins = RFparserOutParams.numRangeBins;
            /* Workaround for range DPU limitation for FFT size 1024 and 12 virtual antennas case*/
            if ((RFparserOutParams.numVirtualAntennas == 12) && (RFparserOutParams.numRangeBins == 1024))
            {
                subFrameCfg->numRangeBins = 1022;
                RFparserOutParams.numRangeBins = 1022;
            }
    
            subFrameCfg->numDopplerBins = RFparserOutParams.numDopplerBins;
            subFrameCfg->numChirpsPerChirpEvent = RFparserOutParams.numChirpsPerChirpEvent;
            subFrameCfg->adcBufChanDataSize = RFparserOutParams.adcBufChanDataSize;
            subFrameCfg->objDetDynCfg.dynCfg.prepareRangeAzimuthHeatMap = subFrameCfg->guiMonSel.rangeAzimuthHeatMap;
            subFrameCfg->numAdcSamples = RFparserOutParams.numAdcSamples;
            subFrameCfg->numChirpsPerSubFrame = RFparserOutParams.numChirpsPerFrame;
            subFrameCfg->numVirtualAntennas = RFparserOutParams.numVirtualAntennas;
    
            errCode = MmwDemo_ADCBufConfig(gMmwMssMCB.adcBufHandle,
                                     gMmwMssMCB.cfg.openCfg.chCfg.rxChannelEn,
                                     subFrameCfg->numChirpsPerChirpEvent,
                                     subFrameCfg->adcBufChanDataSize,
                                     &subFrameCfg->adcBufCfg,
                                     &staticCfg->ADCBufData.dataProperty.rxChanOffset[0]);
            if (errCode < 0)
            {
                System_printf("Error: ADCBuf config failed with error[%d]\n", errCode);
                MmwDemo_debugAssert (0);
            }
    
            errCode = MmwDemo_configCQ(subFrameCfg, RFparserOutParams.numChirpsPerChirpEvent,
                                       RFparserOutParams.validProfileIdx);
    
            if (errCode < 0)
            {
                goto exit;
            }
    
            /* DPC pre-start config */
            {
                int32_t idx;
    
                objDetPreStartCfg.subFrameNum = subFrameIndx;
    
                /* Fill static configuration */
                staticCfg->ADCBufData.data = (void *)SOC_XWR18XX_MSS_ADCBUF_BASE_ADDRESS;
                staticCfg->ADCBufData.dataProperty.adcBits = 2; /* 16-bit */
    
                /* only complex format supported */
                MmwDemo_debugAssert(subFrameCfg->adcBufCfg.adcFmt == 0);
    
                if (subFrameCfg->adcBufCfg.iqSwapSel == 1)
                {
                    staticCfg->ADCBufData.dataProperty.dataFmt = DPIF_DATAFORMAT_COMPLEX16_IMRE;
                }
                else
                {
                    staticCfg->ADCBufData.dataProperty.dataFmt = DPIF_DATAFORMAT_COMPLEX16_REIM;
                }
                if (subFrameCfg->adcBufCfg.chInterleave == 0)
                {
                    staticCfg->ADCBufData.dataProperty.interleave = DPIF_RXCHAN_INTERLEAVE_MODE;
                }
                else
                {
                    staticCfg->ADCBufData.dataProperty.interleave = DPIF_RXCHAN_NON_INTERLEAVE_MODE;
                }
                staticCfg->ADCBufData.dataProperty.numAdcSamples = RFparserOutParams.numAdcSamples;
                staticCfg->ADCBufData.dataProperty.numChirpsPerChirpEvent = RFparserOutParams.numChirpsPerChirpEvent;
                staticCfg->ADCBufData.dataProperty.numRxAntennas = RFparserOutParams.numRxAntennas;
                staticCfg->ADCBufData.dataSize = RFparserOutParams.numRxAntennas * RFparserOutParams.numAdcSamples * sizeof(cmplx16ImRe_t);
                staticCfg->dopplerStep = RFparserOutParams.dopplerStep;
                staticCfg->isValidProfileHasOneTxPerChirp = RFparserOutParams.validProfileHasOneTxPerChirp;
                staticCfg->numChirpsPerFrame = RFparserOutParams.numChirpsPerFrame;
                staticCfg->numDopplerBins = RFparserOutParams.numDopplerBins;
                staticCfg->numDopplerChirps = RFparserOutParams.numDopplerChirps;
                staticCfg->numRangeBins = RFparserOutParams.numRangeBins;
                staticCfg->numTxAntennas = RFparserOutParams.numTxAntennas;
                staticCfg->numVirtualAntAzim = RFparserOutParams.numVirtualAntAzim;
                staticCfg->numVirtualAntElev = RFparserOutParams.numVirtualAntElev;
                staticCfg->numVirtualAntennas = RFparserOutParams.numVirtualAntennas;
                staticCfg->rangeStep = RFparserOutParams.rangeStep;
    
                if (RFparserOutParams.numRangeBins >= 1022) 
                {        
                    staticCfg->rangeFFTtuning.fftOutputDivShift = 0;
                    /* scale only 2 stages */
                    staticCfg->rangeFFTtuning.numLastButterflyStagesToScale = 2; 
                } 
                else if (RFparserOutParams.numRangeBins==512)
                {        
                    staticCfg->rangeFFTtuning.fftOutputDivShift = 1;
                    /* scale last stage */
                    staticCfg->rangeFFTtuning.numLastButterflyStagesToScale = 1; 
                } 
                else    
                {        
                    staticCfg->rangeFFTtuning.fftOutputDivShift = 2;
                    /* no scaling needed as ADC data is 16-bit and we have 8 bits to grow */
                    staticCfg->rangeFFTtuning.numLastButterflyStagesToScale = 0; 
                }
    
                for (idx = 0; idx < RFparserOutParams.numRxAntennas; idx++)
                {
                    staticCfg->rxAntOrder[idx] = RFparserOutParams.rxAntOrder[idx];
                }
                for (idx = 0; idx < RFparserOutParams.numTxAntennas; idx++)
                {
                    staticCfg->txAntOrder[idx] = RFparserOutParams.txAntOrder[idx];
                }
    
                /* Convert CFAR threshold value */
                subFrameCfg->objDetDynCfg.dynCfg.cfarCfgRange.thresholdScale = 
                    MmwDemo_convertCfarToLinear(subFrameCfg->objDetDynCfg.dynCfg.cfarCfgRange.thresholdScale, 
                                                staticCfg->numVirtualAntennas);
    
                subFrameCfg->objDetDynCfg.dynCfg.cfarCfgDoppler.thresholdScale = 
                    MmwDemo_convertCfarToLinear(subFrameCfg->objDetDynCfg.dynCfg.cfarCfgDoppler.thresholdScale, 
                                                staticCfg->numVirtualAntennas);
                                            
                /* Fill dynamic configuration for the sub-frame */
                objDetPreStartCfg.dynCfg = subFrameCfg->objDetDynCfg.dynCfg;           
    
                DebugP_log1("App: Issuing Pre-start Config IOCTL (subFrameIndx = %d)\n", subFrameIndx);
    
                /* DPC running on remote core, address need to be converted */
                staticCfg->ADCBufData.data = (void *) SOC_translateAddress((uint32_t)staticCfg->ADCBufData.data,
                                                     SOC_TranslateAddr_Dir_TO_OTHER_CPU,
                                                     &errCode);
                DebugP_assert ((uint32_t)staticCfg->ADCBufData.data != SOC_TRANSLATEADDR_INVALID);
    
                /* send pre-start config */
                errCode = MmwDemo_DPM_ioctl_blocking (gMmwMssMCB.objDetDpmHandle,
                                     DPC_OBJDET_IOCTL__STATIC_PRE_START_CFG,
                                     &objDetPreStartCfg,
                                     sizeof (DPC_ObjectDetection_PreStartCfg));
    
                MmwDemo_resetDynObjDetCfgPendingState(&subFrameCfg->objDetDynCfg);
    
                if (errCode < 0)
                {
                    System_printf ("Error: Unable to send DPC_OBJDET_IOCTL__STATIC_PRE_START_CFG [Error:%d]\n", errCode);
                    goto exit;
                }
            }
        }
    exit:
        return errCode;
    }
    
    /**
     *  @b Description
     *  @n
     *      The function is used to Start data path to handle chirps from front end.
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_dataPathStart (void)
    {
        int32_t retVal;
    
        DebugP_log0("App: Issuing DPM_start\n");
        
        /* Configure HW LVDS stream for the first sub-frame that will start upon
         * start of frame */
        if (gMmwMssMCB.subFrameCfg[0].lvdsStreamCfg.dataFmt != MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_DISABLED)
        {
            MmwDemo_configLVDSHwData(0);
        }
    
        /* Start the DPM Profile: */
        if ((retVal = DPM_start(gMmwMssMCB.objDetDpmHandle)) < 0)
        {
            /* Error: Unable to start the profile */
            System_printf("Error: Unable to start the DPM [Error: %d]\n", retVal);
            MmwDemo_debugAssert(0);
        }
    
        /* Wait until start completed */
        Semaphore_pend(gMmwMssMCB.DPMstartSemHandle, BIOS_WAIT_FOREVER);
    
        DebugP_log0("App: DPM_start Done (post Semaphore_pend on reportFxn reporting start)\n");
    }
    
    /**
     *  @b Description
     *  @n
     *      The function is used to stop data path.
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_dataPathStop (void)
    {
        int32_t retVal;
    
        DebugP_log0("App: Issuing DPM_stop\n");
    
        retVal = DPM_stop (gMmwMssMCB.objDetDpmHandle);
        if (retVal < 0)
        {
            System_printf ("DPM_stop failed[Error code %d]\n", retVal);
            MmwDemo_debugAssert(0);
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      Registered event function to mmwave which is invoked when an event from the
     *      BSS is received.
     *
     *  @param[in]  msgId
     *      Message Identifier
     *  @param[in]  sbId
     *      Subblock identifier
     *  @param[in]  sbLen
     *      Length of the subblock
     *  @param[in]  payload
     *      Pointer to the payload buffer
     *
     *  @retval
     *      Always return 0
     */
    static int32_t MmwDemo_eventCallbackFxn(uint16_t msgId, uint16_t sbId, uint16_t sbLen, uint8_t *payload)
    {
        uint16_t asyncSB = RL_GET_SBID_FROM_UNIQ_SBID(sbId);
    
        /* Process the received message: */
        switch (msgId)
        {
            case RL_RF_ASYNC_EVENT_MSG:
            {
                /* Received Asychronous Message: */
                switch (asyncSB)
                {
                    case RL_RF_AE_CPUFAULT_SB:
                    {
                        MmwDemo_debugAssert(0);
                        break;
                    }
                    case RL_RF_AE_ESMFAULT_SB:
                    {
                        MmwDemo_debugAssert(0);
                        break;
                    }
                    case RL_RF_AE_ANALOG_FAULT_SB:
                    {
                        MmwDemo_debugAssert(0);
                        break;
                    }
                    case RL_RF_AE_INITCALIBSTATUS_SB:
                    {
                        rlRfInitComplete_t*  ptrRFInitCompleteMessage;
                        uint32_t            calibrationStatus;
    
                        /* Get the RF-Init completion message: */
                        ptrRFInitCompleteMessage = (rlRfInitComplete_t*)payload;
                        calibrationStatus = ptrRFInitCompleteMessage->calibStatus & 0x1FFFU;
    
                        /* Display the calibration status: */
                        CLI_write ("Debug: Init Calibration Status = 0x%x\n", calibrationStatus);
                        break;
                    }
                    case RL_RF_AE_FRAME_TRIGGER_RDY_SB:
                    {
                        gMmwMssMCB.stats.frameTriggerReady++;
                        break;
                    }
                    case RL_RF_AE_MON_TIMING_FAIL_REPORT_SB:
                    {
                        gMmwMssMCB.stats.failedTimingReports++;
                        break;
                    }
                    case RL_RF_AE_RUN_TIME_CALIB_REPORT_SB:
                    {
                        gMmwMssMCB.stats.calibrationReports++;
                        break;
                    }
                    case RL_RF_AE_FRAME_END_SB:
                    {
                        gMmwMssMCB.stats.sensorStopped++;
                        DebugP_log0("App: BSS stop (frame end) received\n");
    
                        MmwDemo_dataPathStop();
                        break;
                    }
                    default:
                    {
                        System_printf ("Error: Asynchronous Event SB Id %d not handled\n", asyncSB);
                        break;
                    }
                }
                break;
            }
            /* Async Event from MMWL */
            case RL_MMWL_ASYNC_EVENT_MSG:
            {
                switch (asyncSB)
                {
                    case RL_MMWL_AE_MISMATCH_REPORT:
                    {
                        /* link reports protocol error in the async report from BSS */
                        MmwDemo_debugAssert(0);
                        break;
                    }            
                    case RL_MMWL_AE_INTERNALERR_REPORT:
                    {
                        /* link reports internal error during BSS communication */
                        MmwDemo_debugAssert(0);
                        break;
                    }
                }
                break;
            }
            default:
            {
                System_printf ("Error: Asynchronous message %d is NOT handled\n", msgId);
                break;
            }
        }
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      DPM Registered Report Handler. The DPM Module uses this registered function to notify
     *      the application about DPM reports.
     *
     *  @param[in]  reportType
     *      Report Type
     *  @param[in]  instanceId
     *      Instance Identifier which generated the report
     *  @param[in]  errCode
     *      Error code if any.
     *  @param[in] arg0
     *      Argument 0 interpreted with the report type
     *  @param[in] arg1
     *      Argument 1 interpreted with the report type
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_DPC_ObjectDetection_reportFxn
    (
        DPM_Report  reportType,
        uint32_t    instanceId,
        int32_t     errCode,
        uint32_t    arg0,
        uint32_t    arg1
    )
    {
        /* Only errors are logged on the console: */
        if ((errCode != 0) || (instanceId != DPC_OBJDET_INSTANCEID))
        {
            /* Error: Detected log on the console and die all errors are FATAL currently. */
            System_printf ("Error: DPM Report %d received with error:%d arg0:0x%x arg1:0x%x\n",
                            reportType, errCode, arg0, arg1);
            DebugP_assert (0);
        }
    
        /* Processing further is based on the reports received: This is the control of the profile
         * state machine: */
        switch (reportType)
        {
            case DPM_Report_IOCTL:
            {
                
                /*****************************************************************
                 * DPC has been configured without an error:
                 * - This is an indication that the profile configuration commands
                 *   went through without any issues.
                 *****************************************************************/
                DebugP_log1("App: DPM Report IOCTL, command = %d\n", arg0);
    
                if (arg0 == DPC_OBJDET_IOCTL__STATIC_PRE_START_CFG)
                {
                    DPC_ObjectDetection_PreStartCfg *cfg;
                    DPC_ObjectDetection_DPC_IOCTL_preStartCfg_memUsage *memUsage;
    
                    cfg = (DPC_ObjectDetection_PreStartCfg*)arg1;
    
                    memUsage = &cfg->memUsage;
    
                    System_printf("============ Heap Memory Stats ============\n");
                    System_printf("%20s %12s %12s %12s %12s\n", " ", "Size", "Used", "Free", "DPCUsed");
                    System_printf("%20s %12d %12d %12d %12d\n", "System Heap(L2)",
                                  memUsage->SystemHeapTotal, memUsage->SystemHeapUsed,
                                  memUsage->SystemHeapTotal - memUsage->SystemHeapUsed,
                                  memUsage->SystemHeapDPCUsed);
    
                    System_printf("%20s %12d %12d %12d\n", "L3",
                                  memUsage->L3RamTotal,
                                  memUsage->L3RamUsage,
                                  memUsage->L3RamTotal - memUsage->L3RamUsage);
    
                    System_printf("%20s %12d %12d %12d\n", "localRam(L2)",
                                  memUsage->CoreLocalRamTotal,
                                  memUsage->CoreLocalRamUsage,
                                  memUsage->CoreLocalRamTotal - memUsage->CoreLocalRamUsage);
                }
    
                switch(arg0)
                {
                    /* The following ioctls take longer time to finish. It causes DPM to queue IOCTL requests on DSS before
                     * they are handled. However DPM has limited pipe queues, hence adding sync points in demo to avoid 
                     * sending too many such ioctls to DSS at a time.
                     * The semaphore blocks CLI task to wait for the response from DSS before sending the next ioctl.
                     */
                    case DPC_OBJDET_IOCTL__STATIC_PRE_START_CFG:
                    case DPC_OBJDET_IOCTL__STATIC_PRE_START_COMMON_CFG:
                        Semaphore_post(gMmwMssMCB.DPMioctlSemHandle);
                        break;
                    default:
                        break;
                }
                break;
            }
            case DPM_Report_DPC_STARTED:
            {
                /*****************************************************************
                 * DPC has been started without an error:
                 * - notify sensor management task that DPC is started.
                 *****************************************************************/
                DebugP_log0("App: DPM Report DPC Started\n");
                Semaphore_post(gMmwMssMCB.DPMstartSemHandle);
                break;
            }
            case DPM_Report_NOTIFY_DPC_RESULT:
            {
                /*****************************************************************
                 * datapath has finished frame processing, results are reported
                 *****************************************************************/
                DPM_Buffer*     ptrResult;
    
                /* Get the result: */
                ptrResult = (DPM_Buffer*)arg0;
    
                MmwDemo_handleObjectDetResult(ptrResult);
                break;
            }
            case DPM_Report_DPC_ASSERT:
            {
                DPM_DPCAssert*  ptrAssert;
    
                /*****************************************************************
                 * DPC Fault has been detected:
                 * - This implies that the DPC has crashed.
                 * - The argument0 points to the DPC assertion information
                 *****************************************************************/
                ptrAssert = (DPM_DPCAssert*)arg0;
                CLI_write("Obj Det DPC Exception: %s, line %d.\n", ptrAssert->fileName,
                           ptrAssert->lineNum);
                break;
            }
            case DPM_Report_DPC_STOPPED:
            {
                /*****************************************************************
                 * DPC has been stopped without an error:
                 * - This implies that the DPC can either be reconfigured or
                 *   restarted.
                 *****************************************************************/
                DebugP_log0("App: DPM Report DPC Stopped\n");
                Semaphore_post(gMmwMssMCB.DPMstopSemHandle);
                break;
            }
            case DPM_Report_DPC_INFO:
            case DPM_Report_NOTIFY_DPC_RESULT_ACKED:
            {
                /* Currently objDetHwa does not use this feature. */
                break;
            }
            default:
            {
                DebugP_assert (0);
                break;
            }
        }
        return;
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to get next sub-frame index
     *
     *  @param[in] currentIndx Current sub-frame index
     *  @param[in] numSubFrames Number of sub-frames
     *
     *  @retval
     *      Index of next sub-frame.
     */
    static uint8_t MmwDemo_getNextSubFrameIndx(uint8_t currentIndx, uint8_t numSubFrames)
    {
        uint8_t nextIndx;
    
        if (currentIndx == (numSubFrames - 1))
        {
            nextIndx = 0;
        }
        else
        {
            nextIndx = currentIndx + 1;
        }
        return(nextIndx);
    }
    
    /**
     *  @b Description
     *  @n
     *      Utility function to get previous sub-frame index
     *
     *  @param[in] currentIndx Current sub-frame index
     *  @param[in] numSubFrames Number of sub-frames
     *
     *  @retval
     *      Index of previous sub-frame
     */
    static uint8_t MmwDemo_getPrevSubFrameIndx(uint8_t currentIndx, uint8_t numSubFrames)
    {
        uint8_t prevIndx;
    
        if (currentIndx == 0)
        {
            prevIndx = numSubFrames - 1;
        }
        else
        {
            prevIndx = currentIndx - 1;
        }
        return(prevIndx);
    }
    
    /**
     *  @b Description
     *  @n
     *      Processes any pending dynamic configuration commands for the specified
     *      sub-frame by fanning out to the respective DPUs using IOCTL interface, and
     *      resets (clears) the pending state after processing.
     *
     *  @param[in] subFrameIndx Sub-frame index of desired sub-frame to process
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_processPendingDynamicCfgCommands(uint8_t subFrameIndx)
    {
        int32_t retVal =0;
    
        MmwDemo_DPC_ObjDet_CommonCfg *commonCfg = &gMmwMssMCB.objDetCommonCfg;
        MmwDemo_DPC_ObjDet_DynCfg *subFrameCfg = &gMmwMssMCB.subFrameCfg[subFrameIndx].objDetDynCfg;
        uint8_t numVirtualAntennas = gMmwMssMCB.subFrameCfg[subFrameIndx].numVirtualAntennas;
    
        /* perform globals ones if first sub-frame */
        if (subFrameIndx == 0)
        {
            if (commonCfg->isMeasureRxChannelBiasCfgPending == 1)
            {
                retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                     DPC_OBJDET_IOCTL__DYNAMIC_MEASURE_RANGE_BIAS_AND_RX_CHAN_PHASE,
                                     &commonCfg->preStartCommonCfg.measureRxChannelBiasCfg,
                                     sizeof (DPC_ObjectDetection_MeasureRxChannelBiasCfg));
                if (retVal != 0)
                {
                    goto exit;
                }
                commonCfg->isMeasureRxChannelBiasCfgPending = 0;
            }
            if (commonCfg->isCompRxChannelBiasCfgPending == 1)
            {
                retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                     DPC_OBJDET_IOCTL__DYNAMIC_COMP_RANGE_BIAS_AND_RX_CHAN_PHASE,
                                     &commonCfg->preStartCommonCfg.compRxChanCfg,
                                     sizeof (DPU_AoAProc_compRxChannelBiasCfg));
                if (retVal != 0)
                {
                    goto exit;
                }
                commonCfg->isCompRxChannelBiasCfgPending = 0;
            }
        }
    
        /* Perform sub-frame specific ones */
        if (subFrameCfg->isCalibDcRangeSigCfg == 1)
        {
            DPC_ObjectDetection_CalibDcRangeSigCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.cfg = subFrameCfg->dynCfg.calibDcRangeSigCfg;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_CALIB_DC_RANGE_SIG_CFG,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_CalibDcRangeSigCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isCalibDcRangeSigCfg = 0;
        }
        if (subFrameCfg->isCfarCfgDopplerPending == 1)
        {
            DPC_ObjectDetection_CfarCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            /* Update with correct threshold value based on number of virtual antennas */
            subFrameCfg->dynCfg.cfarCfgDoppler.thresholdScale = 
                MmwDemo_convertCfarToLinear(subFrameCfg->dynCfg.cfarCfgDoppler.thresholdScale, 
                                            numVirtualAntennas);
    
            cfg.cfg = subFrameCfg->dynCfg.cfarCfgDoppler;
            
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_CFAR_DOPPLER_CFG,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_CfarCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isCfarCfgDopplerPending = 0;
        }
        if (subFrameCfg->isCfarCfgRangePending == 1)
        {
            DPC_ObjectDetection_CfarCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            /* Update with correct threshold value based on number of virtual antennas */
            subFrameCfg->dynCfg.cfarCfgRange.thresholdScale = 
                MmwDemo_convertCfarToLinear(subFrameCfg->dynCfg.cfarCfgRange.thresholdScale, 
                                            numVirtualAntennas);
            
            cfg.cfg = subFrameCfg->dynCfg.cfarCfgRange;
            
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_CFAR_RANGE_CFG,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_CfarCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isCfarCfgRangePending = 0;
        }
        if (subFrameCfg->isFovDopplerPending == 1)
        {
            DPC_ObjectDetection_fovDopplerCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.cfg = subFrameCfg->dynCfg.fovDoppler;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_FOV_DOPPLER,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_fovDopplerCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isFovDopplerPending = 0;
        }
        if (subFrameCfg->isFovRangePending == 1)
        {
            DPC_ObjectDetection_fovRangeCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.cfg = subFrameCfg->dynCfg.fovRange;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_FOV_RANGE,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_fovRangeCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isFovRangePending = 0;
        }
        if (subFrameCfg->isMultiObjBeamFormingCfgPending == 1)
        {
            DPC_ObjectDetection_MultiObjBeamFormingCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.cfg = subFrameCfg->dynCfg.multiObjBeamFormingCfg;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_MULTI_OBJ_BEAM_FORM_CFG,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_MultiObjBeamFormingCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isMultiObjBeamFormingCfgPending = 0;
        }
        if (subFrameCfg->isPrepareRangeAzimuthHeatMapPending == 1)
        {
            DPC_ObjectDetection_RangeAzimuthHeatMapCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.prepareRangeAzimuthHeatMap = subFrameCfg->dynCfg.prepareRangeAzimuthHeatMap;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_RANGE_AZIMUTH_HEAT_MAP,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_RangeAzimuthHeatMapCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isPrepareRangeAzimuthHeatMapPending = 0;
        }
        if (subFrameCfg->isStaticClutterRemovalCfgPending == 1)
        {
            DPC_ObjectDetection_StaticClutterRemovalCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.cfg = subFrameCfg->dynCfg.staticClutterRemovalCfg;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_STATICCLUTTER_REMOVAL_CFG,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_StaticClutterRemovalCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isStaticClutterRemovalCfgPending = 0;
        }
        if (subFrameCfg->isFovAoaCfgPending == 1)
        {
            DPC_ObjectDetection_fovAoaCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.cfg = subFrameCfg->dynCfg.fovAoaCfg;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                 DPC_OBJDET_IOCTL__DYNAMIC_FOV_AOA,
                                 &cfg,
                                 sizeof (DPC_ObjectDetection_fovAoaCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isFovAoaCfgPending = 0;
        }
        if (subFrameCfg->isExtMaxVelCfgPending == 1)
        {
            DPC_ObjectDetection_extMaxVelCfg cfg;
    
            cfg.subFrameNum = subFrameIndx;
            cfg.cfg = subFrameCfg->dynCfg.extMaxVelCfg;
            retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                                DPC_OBJDET_IOCTL__DYNAMIC_EXT_MAX_VELOCITY,
                                &cfg,
                                sizeof (DPC_ObjectDetection_extMaxVelCfg));
            if (retVal != 0)
            {
                goto exit;
            }
            subFrameCfg->isExtMaxVelCfgPending = 0;
        }
    
    exit:
        return(retVal);
    }
    
    /**
     *  @b Description
     *  @n
     *      Transmit user data over LVDS interface.
     *
     *  @param[in]  subFrameIndx Sub-frame index
     *  @param[in]  dpcResults   pointer to DPC result
     *
     */
    void MmwDemo_transferLVDSUserData(uint8_t subFrameIndx,
                                      DPC_ObjectDetection_ExecuteResult *dpcResults)
    {
        int32_t errCode;
        DPC_ObjectDetection_Stats *stats;
        DPIF_PointCloudCartesian *objOut;
        DPIF_PointCloudSideInfo *objOutSideInfo;
    
        stats = (DPC_ObjectDetection_Stats *) SOC_translateAddress((uint32_t)dpcResults->stats,
                                                     SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                     &errCode);
        DebugP_assert ((uint32_t)stats != SOC_TRANSLATEADDR_INVALID);
    
        objOut = (DPIF_PointCloudCartesian *) SOC_translateAddress((uint32_t)dpcResults->objOut,
                                                     SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                     &errCode);
        DebugP_assert ((uint32_t)objOut != SOC_TRANSLATEADDR_INVALID);
    
        objOutSideInfo = (DPIF_PointCloudSideInfo *) SOC_translateAddress((uint32_t)dpcResults->objOutSideInfo,
                                                     SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                     &errCode);
        DebugP_assert ((uint32_t)objOutSideInfo != SOC_TRANSLATEADDR_INVALID);
    
        /* Delete previous SW session if it exists. SW session is being
           reconfigured every frame because number of detected objects
           may change from frame to frame which implies that the size of
           the streamed data may change. */
        if(gMmwMssMCB.lvdsStream.swSessionHandle != NULL)
        {
            MmwDemo_LVDSStreamDeleteSwSession();
        }
    
        /* Configure SW session for this subframe */
        if (MmwDemo_LVDSStreamSwConfig(dpcResults->numObjOut,
                                       objOut,
                                       objOutSideInfo) < 0)
        {
            System_printf("Failed LVDS stream SW configuration for sub-frame %d\n", subFrameIndx);
            MmwDemo_debugAssert(0);
            return;
        }
    
        /* Populate user data header that will be streamed out*/
        gMmwMssMCB.lvdsStream.userDataHeader->frameNum  = stats->frameStartIntCounter;
        gMmwMssMCB.lvdsStream.userDataHeader->detObjNum = dpcResults->numObjOut;
        gMmwMssMCB.lvdsStream.userDataHeader->subFrameNum  = (uint16_t) dpcResults->subFrameIdx;
    
        /* If SW LVDS stream is enabled, start the session here. User data will immediately
           start to stream over LVDS.*/
        if(CBUFF_activateSession (gMmwMssMCB.lvdsStream.swSessionHandle, &errCode) < 0)
        {
            System_printf("Failed to activate CBUFF session for LVDS stream SW. errCode=%d\n",errCode);
            MmwDemo_debugAssert(0);
            return;
        }
    }
    
    
    /**
     *  @b Description
     *  @n
     *      Function to handle frame processing results from DPC
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_handleObjectDetResult
    (
        DPM_Buffer  *ptrResult
    )
    {
        int32_t     retVal;
        DPC_ObjectDetection_ExecuteResultExportedInfo exportInfo;
        DPC_ObjectDetection_ExecuteResult        *dpcResults;
        MmwDemo_output_message_stats            *frameStats;
        volatile uint32_t                        startTime;
        uint8_t                                  nextSubFrameIdx;
        uint8_t                                  numSubFrames;
        uint8_t                                  currSubFrameIdx;
        uint8_t                                  prevSubFrameIdx;
        MmwDemo_SubFrameStats                    *currSubFrameStats;
        MmwDemo_SubFrameStats                    *prevSubFrameStats;
    
        /*****************************************************************
         * datapath has finished frame processing, results are reported
         *****************************************************************/
    
        /* Validate DPC results buffer */
        DebugP_assert (ptrResult->size[0] == sizeof(DPC_ObjectDetection_ExecuteResult));
    
        /* Translate the address: */
        dpcResults = (DPC_ObjectDetection_ExecuteResult *)SOC_translateAddress((uint32_t)ptrResult->ptrBuffer[0],
                                                 SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                 &retVal);
        DebugP_assert ((uint32_t)dpcResults != SOC_TRANSLATEADDR_INVALID);
    
        /* Validate timing Info buffer */
        DebugP_assert (ptrResult->size[1] == sizeof(MmwDemo_output_message_stats));
    
        numSubFrames = gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames;
        currSubFrameIdx = dpcResults->subFrameIdx;
        prevSubFrameIdx = MmwDemo_getPrevSubFrameIndx(currSubFrameIdx, numSubFrames);
        currSubFrameStats = &gMmwMssMCB.subFrameStats[currSubFrameIdx];
        prevSubFrameStats = &gMmwMssMCB.subFrameStats[prevSubFrameIdx];
    
        /*****************************************************************
         * Transmit results
         *****************************************************************/
        startTime = Cycleprofiler_getTimeStamp();
    
        /* Send out of CLI the range bias and phase config measurement if it was enabled. */
        if (gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.measureRxChannelBiasCfg.enabled == 1)
        {
            if(dpcResults->compRxChanBiasMeasurement != NULL)
            {
                dpcResults->compRxChanBiasMeasurement =
                    (DPU_AoAProc_compRxChannelBiasCfg *)SOC_translateAddress((uint32_t)dpcResults->compRxChanBiasMeasurement,
                    SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                    &retVal);
                DebugP_assert ((uint32_t)dpcResults->compRxChanBiasMeasurement != SOC_TRANSLATEADDR_INVALID);
    
                MmwDemo_measurementResultOutput(dpcResults->compRxChanBiasMeasurement);
            }
            else
            {
                /* DPC is not ready to ship the measurement results */
            }
        }
    
    
        /* Translate the address: */
        frameStats = (MmwDemo_output_message_stats *)SOC_translateAddress((uint32_t)ptrResult->ptrBuffer[1],
                                                 SOC_TranslateAddr_Dir_FROM_OTHER_CPU,
                                                 &retVal);
        DebugP_assert ((uint32_t)frameStats != SOC_TRANSLATEADDR_INVALID);
    
        /* Update current frame stats */
        currSubFrameStats->outputStats.interFrameCPULoad = frameStats->interFrameCPULoad;
        currSubFrameStats->outputStats.activeFrameCPULoad= frameStats->activeFrameCPULoad;
        currSubFrameStats->outputStats.interChirpProcessingMargin = frameStats->interChirpProcessingMargin;
        currSubFrameStats->outputStats.interFrameProcessingTime = frameStats->interFrameProcessingTime;
        prevSubFrameStats->outputStats.interFrameProcessingMargin = frameStats->interFrameProcessingMargin;
        currSubFrameStats->outputStats.interFrameProcessingMargin = currSubFrameStats->outputStats.interFrameProcessingMargin -
                                                             (currSubFrameStats->pendingConfigProcTime + currSubFrameStats->subFramePreparationTime);
    
        if (gMmwMssMCB.subFrameCfg[currSubFrameIdx].lvdsStreamCfg.dataFmt !=
                 MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_DISABLED)
        {
            /* check Edma errors (which are considered fatal) for the current sub-frame's
             * h/w session that is expected to be completed by now */
            MmwDemo_checkEdmaErrors();
    
            /* Pend for completion of h/w session, generally this will not wait
             * because of time spent doing inter-frame processing is expected to
             * be bigger than the transmission of the h/w session */
            Semaphore_pend(gMmwMssMCB.lvdsStream.hwFrameDoneSemHandle, BIOS_WAIT_FOREVER);
        }
    
        /* Transfer data on LVDS if s/w session is enabled for the current sub-frame */
        if(gMmwMssMCB.subFrameCfg[currSubFrameIdx].lvdsStreamCfg.isSwEnabled == 1)
        {
            MmwDemo_transferLVDSUserData(currSubFrameIdx, dpcResults);
        }
    
        /* Transmit processing results for the frame */
        MmwDemo_transmitProcessedOutput(gMmwMssMCB.loggingUartHandle,  
                                        dpcResults,
                                        &currSubFrameStats->outputStats);
    
        /* Wait until s/w session is complete. We expect the LVDS transmission of
         * s/w session to be completed by now because the UART transmission above is slower.
         * Doing the wait immediately after starting the transmission above MmwDemo_transferLVDSUserData
         * will serialize the LVDS and UART transfers so it is better to do after UART
         * transmission (which is blocking call i.e UART transmission is completed when we exit
         * out of above MmwDemo_transmitProcessedOutput). Note we cannot replace below code
         * with check for previous sub-frame s/w session completion before the
         * MmwDemo_transferLVDSUserData above because we need to ensure that
         * current sub-frame/frame's contents are not being read during the
         * next sub-frame/frame transmission, presently the data that is being
         * transmitted is not double buffered to allow this */
        if(gMmwMssMCB.subFrameCfg[currSubFrameIdx].lvdsStreamCfg.isSwEnabled == 1)
        {
            /* check Edma errors (which are considered fatal) for the s/w session
             * that is expected to be completed by now */
            MmwDemo_checkEdmaErrors();
    
            /* Pend completion of s/w session, no wait is expected here */
            Semaphore_pend(gMmwMssMCB.lvdsStream.swFrameDoneSemHandle, BIOS_WAIT_FOREVER);
        }
    
        /* Update current frame transmit time */
        currSubFrameStats->outputStats.transmitOutputTime = (Cycleprofiler_getTimeStamp() - startTime)/R4F_CLOCK_MHZ; /* In micro seconds */
    
    
        /*****************************************************************
         * Handle dynamic pending configuration
         * For non-advanced frame case:
         *   process all pending dynamic config commands.
         * For advanced-frame case:
         *  Process next sub-frame related pending dynamic config commands.
         *  If the next sub-frame was the first sub-frame of the frame,
         *  then process common (sub-frame independent) pending dynamic config
         *  commands.
         *****************************************************************/
        startTime = Cycleprofiler_getTimeStamp();
    
        nextSubFrameIdx = MmwDemo_getNextSubFrameIndx(currSubFrameIdx,   numSubFrames);
        retVal = MmwDemo_processPendingDynamicCfgCommands(nextSubFrameIdx);
        if (retVal != 0)
        {
            System_printf ("Error: Executing Pending Dynamic Configuration Commands [Error code %d]\n",
                           retVal);
            MmwDemo_debugAssert(0);
        }
        currSubFrameStats->pendingConfigProcTime = (Cycleprofiler_getTimeStamp() - startTime)/R4F_CLOCK_MHZ;
    
        /*****************************************************************
         * Prepare for subFrame switch
         *****************************************************************/
        if(numSubFrames > 1)
        {
            MmwDemo_SubFrameCfg  *nextSubFrameCfg;
            uint16_t dummyRxChanOffset[SYS_COMMON_NUM_RX_CHANNEL];
    
            startTime = Cycleprofiler_getTimeStamp();
    
            nextSubFrameCfg = &gMmwMssMCB.subFrameCfg[nextSubFrameIdx];
    
            /* Configure ADC for next sub-frame */
            retVal = MmwDemo_ADCBufConfig(gMmwMssMCB.adcBufHandle,
                                     gMmwMssMCB.cfg.openCfg.chCfg.rxChannelEn,
                                     nextSubFrameCfg->numChirpsPerChirpEvent,
                                     nextSubFrameCfg->adcBufChanDataSize,
                                     &nextSubFrameCfg->adcBufCfg,
                                     &dummyRxChanOffset[0]);
            if(retVal < 0)
            {
                System_printf("Error: ADCBuf config failed with error[%d]\n", retVal);
                MmwDemo_debugAssert(0);
            }
    
            /* Configure HW LVDS stream for this subframe? */
            if(nextSubFrameCfg->lvdsStreamCfg.dataFmt != MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_DISABLED)
            {
                /* check Edma errors (which are considered fatal) for any previous session, even
                 * though we have checked for a previous s/w session, if s/w session weren't
                 * enabled, then this will check for previous h/w session related Edma errors */
                MmwDemo_checkEdmaErrors();
    
                MmwDemo_configLVDSHwData(nextSubFrameIdx);
            }
    
            currSubFrameStats->subFramePreparationTime = (Cycleprofiler_getTimeStamp() - startTime)/R4F_CLOCK_MHZ;
        }
        else
        {
            currSubFrameStats->subFramePreparationTime = 0;
        }
    
        /*****************************************************************
         * Send notification to data path after results are handled
         *****************************************************************/
        /* Indicate result consumed and end of frame/sub-frame processing */
        exportInfo.subFrameIdx = currSubFrameIdx;
        retVal = DPM_ioctl (gMmwMssMCB.objDetDpmHandle,
                             DPC_OBJDET_IOCTL__DYNAMIC_EXECUTE_RESULT_EXPORTED,
                             &exportInfo,
                             sizeof (DPC_ObjectDetection_ExecuteResultExportedInfo));
        if (retVal < 0) {
            System_printf ("Error: DPM DPC_OBJDET_IOCTL__DYNAMIC_EXECUTE_RESULT_EXPORTED failed [Error code %d]\n",
                           retVal);
            MmwDemo_debugAssert(0);
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      DPM Execution Task which executes the DPM Instance which manages the
     *      HL Profiles executing on the MSS.
     *
     *  @retval
     *      Not Applicable.
     */
    static void mmwDemo_mssDPMTask(UArg arg0, UArg arg1)
    {
        int32_t     errCode;
        DPM_Buffer  result;
    
        while (1)
        {
            /* Execute the DPM module: */
            errCode = DPM_execute (gMmwMssMCB.objDetDpmHandle, &result);
            if (errCode < 0)
            {
                System_printf ("Error: DPM execution failed [Error code %d]\n", errCode);
            }
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      Function to Setup the HSI Clock. Required for LVDS streaming.
     *
     *  @retval
     *      0  - Success.
     *      <0 - Failed with errors
     */
    int32_t MmwDemo_mssSetHsiClk(void)
    {
        rlDevHsiClk_t                           hsiClkgs;
        int32_t                                 retVal;
    
        /*************************************************************************************
         * Setup the HSI Clock through the mmWave Link:
         *************************************************************************************/
        memset ((void*)&hsiClkgs, 0, sizeof(rlDevHsiClk_t));
    
        /* Setup the HSI Clock as per the Radar Interface Document:
         * - This is set to 600Mhz DDR Mode */
        hsiClkgs.hsiClk = 0x9;
    
        /* Setup the HSI in the radar link: */
        retVal = rlDeviceSetHsiClk(RL_DEVICE_MAP_CASCADED_1, &hsiClkgs);
        if (retVal != RL_RET_CODE_OK)
        {
            /* Error: Unable to set the HSI clock */
            System_printf ("Error: Setting up the HSI Clock Failed [Error %d]\n", retVal);
            return -1;
        }
    
        /*The delay below is needed only if the DCA1000EVM is being used to capture the data traces.
          This is needed because the DCA1000EVM FPGA needs the delay to lock to the
          bit clock before they can start capturing the data correctly. */
        Task_sleep(HSI_DCA_MIN_DELAY_MSEC);
    
        return 0;
    }
    
    /**************************************************************************
     ******************** Millimeter Wave Demo sensor management Functions **********
     **************************************************************************/
    
    /**
     *  @b Description
     *  @n
     *      mmw demo helper Function to do one time sensor initialization. 
     *      User need to fill gMmwMssMCB.cfg.openCfg before calling this function
     *
     *  @param[in]  isFirstTimeOpen     If true then issues MMwave_open
     *
     *  @retval
     *      Success     - 0
     *  @retval
     *      Error       - <0
     */
    int32_t MmwDemo_openSensor(bool isFirstTimeOpen)
    {
        int32_t             errCode;
        MMWave_ErrorLevel   errorLevel;
        int16_t             mmWaveErrorCode;
        int16_t             subsysErrorCode;    
        int32_t             retVal;
        MMWave_CalibrationData     calibrationDataCfg;
        MMWave_CalibrationData     *ptrCalibrationDataCfg;
    
        /*  Open mmWave module, this is only done once */
        if (isFirstTimeOpen == true)
        {
    
            System_printf ("Debug: Sending rlRfSetLdoBypassConfig with %d %d %d\n",
                                                gRFLdoBypassCfg.ldoBypassEnable,
                                                gRFLdoBypassCfg.supplyMonIrDrop,
                                                gRFLdoBypassCfg.ioSupplyIndicator);
    
            retVal = rlRfSetLdoBypassConfig(RL_DEVICE_MAP_INTERNAL_BSS, (rlRfLdoBypassCfg_t*)&gRFLdoBypassCfg);        
            if(retVal != 0)
            {            
                System_printf("Error: rlRfSetLdoBypassConfig retVal=%d\n", retVal);
                return -1;
            }
    
            /**********************************************************
             **********************************************************/         
    
            /* Open mmWave module, this is only done once */
            /* Setup the calibration frequency:*/
            gMmwMssMCB.cfg.openCfg.freqLimitLow  = 760U;
            gMmwMssMCB.cfg.openCfg.freqLimitHigh = 810U;
    
            /* start/stop async events */
            gMmwMssMCB.cfg.openCfg.disableFrameStartAsyncEvent = false;
            gMmwMssMCB.cfg.openCfg.disableFrameStopAsyncEvent  = false;
    
            /* No custom calibration: */
            gMmwMssMCB.cfg.openCfg.useCustomCalibration        = false;
            gMmwMssMCB.cfg.openCfg.customCalibrationEnableMask = 0x0;
    
            /* calibration monitoring base time unit
             * setting it to one frame duration as the demo doesnt support any 
             * monitoring related functionality
             */
            gMmwMssMCB.cfg.openCfg.calibMonTimeUnit            = 1;
    
            if( (gMmwMssMCB.calibCfg.saveEnable != 0) &&
    		(gMmwMssMCB.calibCfg.restoreEnable != 0) )
            {
                /* Error: only one can be enabled at at time */
                System_printf ("Error: MmwDemo failed with both save and restore enabled.\n");
                return -1;
    	 }
    
            if(gMmwMssMCB.calibCfg.restoreEnable != 0)
            {
                if(MmwDemo_calibRestore(&gCalibDataStorage) < 0)
                {
    	            System_printf ("Error: MmwDemo failed restoring calibration data from flash.\n");
    	            return -1;
                }
    
                /*  Boot calibration during restore: Disable calibration for:
                     - Rx gain,
                     - Rx IQMM,
                     - Tx phase shifer,
                     - Tx Power
    
                     The above calibration data will be restored from flash. Since they are calibrated in a control
                     way to avoid interfaerence and spec violations.
                     In this demo, other bit fields(except the above) are enabled as indicated in customCalibrationEnableMask to perform boot time
                     calibration. The boot time calibration will overwrite the restored calibration data from flash.
                     However other bit fields can be disabled and calibration data can be restored from flash as well.
    
                     Note: In this demo, calibration masks are enabled for all bit fields when "saving" the data.
                */
                gMmwMssMCB.cfg.openCfg.useCustomCalibration        = true;
                gMmwMssMCB.cfg.openCfg.customCalibrationEnableMask = 0x1F0U;
    
                calibrationDataCfg.ptrCalibData = &gCalibDataStorage.calibData;
                calibrationDataCfg.ptrPhaseShiftCalibData = &gCalibDataStorage.phaseShiftCalibData;
                ptrCalibrationDataCfg = &calibrationDataCfg;
            }
            else
            {
                ptrCalibrationDataCfg = NULL;
            }
    
            /* Open the mmWave module: */
            if (MMWave_open (gMmwMssMCB.ctrlHandle, &gMmwMssMCB.cfg.openCfg, ptrCalibrationDataCfg, &errCode) < 0)
            {
                /* Error: decode and Report the error */
                MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
                System_printf ("Error: mmWave Open failed [Error code: %d Subsystem: %d]\n",
                                mmWaveErrorCode, subsysErrorCode);
                return -1;
            }
    
    	 /* Save calibration data in flash */
    	 if(gMmwMssMCB.calibCfg.saveEnable != 0)
            {
    
                retVal = rlRfCalibDataStore(RL_DEVICE_MAP_INTERNAL_BSS, &gCalibDataStorage.calibData);
                if(retVal != RL_RET_CODE_OK)
                {
                    /* Error: Calibration data restore failed */
    	         System_printf("MSS demo failed rlRfCalibDataStore with Error[%d]\n", retVal);
                    return -1;
                }
    
    #if (defined(SOC_XWR18XX) || defined(SOC_XWR68XX))
    
            /* update txIndex in all chunks to get data from all Tx.
               This should be done regardless of num TX channels enabled in MMWave_OpenCfg_t::chCfg or number of Tx
               application is interested in. Data for all existing Tx channels should be retrieved
               from RadarSS and in the order as shown below.
               RadarSS will return non-zero phase shift values for all the channels enabled via
               MMWave_OpenCfg_t::chCfg and zero phase shift values for channels disabled in MMWave_OpenCfg_t::chCfg */
                gCalibDataStorage.phaseShiftCalibData.PhShiftcalibChunk[0].txIndex = 0;
                gCalibDataStorage.phaseShiftCalibData.PhShiftcalibChunk[1].txIndex = 1;
                gCalibDataStorage.phaseShiftCalibData.PhShiftcalibChunk[2].txIndex = 2;
    
                /* Basic validation passed: Restore the phase shift calibration data */
                retVal = rlRfPhShiftCalibDataStore(RL_DEVICE_MAP_INTERNAL_BSS, &(gCalibDataStorage.phaseShiftCalibData));
                if (retVal != RL_RET_CODE_OK)
                {
                    /* Error: Phase shift Calibration data restore failed */
    	         System_printf("MSS demo failed rlRfPhShiftCalibDataStore with Error[%d]\n", retVal);
                    return retVal;
                }
    #endif
                /* Save data in flash */
                retVal = MmwDemo_calibSave(&gMmwMssMCB.calibCfg.calibDataHdr, &gCalibDataStorage);
                if(retVal < 0)
                {
                    return retVal;
                }
            }
    
            /*Set up HSI clock*/
            if(MmwDemo_mssSetHsiClk() < 0)
            {
                System_printf ("Error: MmwDemo_mssSetHsiClk failed.\n");
                return -1;
            }
    
            /* Open the datapath modules that runs on MSS */
            MmwDemo_dataPathOpen();
        }
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      MMW demo helper Function to configure sensor. User need to fill gMmwMssMCB.cfg.ctrlCfg and
     *      add profiles/chirp to mmWave before calling this function
     *
     *  @retval
     *      Success     - 0
     *  @retval
     *      Error       - <0
     */
    int32_t MmwDemo_configSensor(void)
    {
        int32_t     errCode = 0;
    
        /* Configure the mmWave module: */
        if (MMWave_config (gMmwMssMCB.ctrlHandle, &gMmwMssMCB.cfg.ctrlCfg, &errCode) < 0)
        {
            MMWave_ErrorLevel   errorLevel;
            int16_t             mmWaveErrorCode;
            int16_t             subsysErrorCode;
    
            /* Error: Report the error */
            MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
            System_printf ("Error: mmWave Config failed [Error code: %d Subsystem: %d]\n",
                            mmWaveErrorCode, subsysErrorCode);
        }
        else
        {
            errCode = MmwDemo_dataPathConfig();
        }
    
        return errCode;
    }
    
    /**
     *  @b Description
     *  @n
     *      mmw demo helper Function to start sensor.
     *
     *  @retval
     *      Success     - 0
     *  @retval
     *      Error       - <0
     */
    int32_t MmwDemo_startSensor(void)
    {
        int32_t     errCode;
        MMWave_CalibrationCfg   calibrationCfg;
    
        /*****************************************************************************
         * Data path :: start data path first - this will pend for DPC to ack
         *****************************************************************************/
        MmwDemo_dataPathStart();
    
        /*****************************************************************************
         * RF :: now start the RF and the real time ticking
         *****************************************************************************/
        /* Initialize the calibration configuration: */
        memset ((void *)&calibrationCfg, 0, sizeof(MMWave_CalibrationCfg));
        /* Populate the calibration configuration: */
        calibrationCfg.dfeDataOutputMode = gMmwMssMCB.cfg.ctrlCfg.dfeDataOutputMode;
        calibrationCfg.u.chirpCalibrationCfg.enableCalibration    = true;
        calibrationCfg.u.chirpCalibrationCfg.enablePeriodicity    = true;
        calibrationCfg.u.chirpCalibrationCfg.periodicTimeInFrames = 10U;
    
        DebugP_log0("App: MMWave_start Issued\n");
    
        System_printf("Starting Sensor (issuing MMWave_start)\n");
    
        /* Start the mmWave module: The configuration has been applied successfully. */
        if (MMWave_start(gMmwMssMCB.ctrlHandle, &calibrationCfg, &errCode) < 0)
        {
            MMWave_ErrorLevel   errorLevel;
            int16_t             mmWaveErrorCode;
            int16_t             subsysErrorCode;
    
            /* Error/Warning: Unable to start the mmWave module */
            MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
            System_printf ("Error: mmWave Start failed [mmWave Error: %d Subsys: %d]\n", mmWaveErrorCode, subsysErrorCode);
            /* datapath has already been moved to start state; so either we initiate a cleanup of start sequence or
               assert here and re-start from the beginning. For now, choosing the latter path */ 
            MmwDemo_debugAssert(0);
            return -1;
        }
    
        /*****************************************************************************
         * The sensor has been started successfully. Switch on the LED 
         *****************************************************************************/
        GPIO_write (gMmwMssMCB.cfg.platformCfg.SensorStatusGPIO, 1U);
    
        gMmwMssMCB.sensorStartCount++;
        return 0;
    }
    
    /**
     *  @b Description
     *  @n
     *      Epilog processing after sensor has stopped
     *
     *  @retval None
     */
    static void MmwDemo_sensorStopEpilog(void)
    {
        Task_Stat stat;
        Hwi_StackInfo stackInfo;
        Bool stackOverflow;
    
        /* Print task statistics, note data path has completely stopped due to
         * end of frame, so we can do non-real time processing like prints on
         * console */
        System_printf("Data Path Stopped (last frame processing done)\n");
    
        System_printf("============================================\n");
        System_printf("MSS Task Stack Usage (Note: Task Stack Usage) ==========\n");
        System_printf("%20s %12s %12s %12s\n", "Task Name", "Size", "Used", "Free");
    
    
        Task_stat(gMmwMssMCB.taskHandles.initTask, &stat);
        System_printf("%20s %12d %12d %12d\n", "Init",
                      stat.stackSize, stat.used, stat.stackSize - stat.used);
    
        Task_stat(gMmwMssMCB.taskHandles.mmwaveCtrl, &stat);
        System_printf("%20s %12d %12d %12d\n", "Mmwave Control",
                      stat.stackSize, stat.used, stat.stackSize - stat.used);
    
        Task_stat(gMmwMssMCB.taskHandles.objDetDpmTask, &stat);
        System_printf("%20s %12d %12d %12d\n", "ObjDet DPM",
                      stat.stackSize, stat.used, stat.stackSize - stat.used);
    
        System_printf("HWI Stack (same as System Stack) Usage ============\n");
        stackOverflow = Hwi_getStackInfo(&stackInfo, TRUE);
        if (stackOverflow == TRUE)
        {
            System_printf("HWI Stack overflowed\n");
            MmwDemo_debugAssert(0);
        }
        else
        {
            System_printf("%20s %12s %12s %12s\n", " ", "Size", "Used", "Free");
            System_printf("%20s %12d %12d %12d\n", " ",
                          stackInfo.hwiStackSize, stackInfo.hwiStackPeak,
                          stackInfo.hwiStackSize - stackInfo.hwiStackPeak);
        }
    }
    
    
    /**
     *  @b Description
     *  @n
     *      Stops the RF and datapath for the sensor. Blocks until both operation are completed.
     *      Prints epilog at the end.
     *
     *  @retval  None
     */
    void MmwDemo_stopSensor(void)
    {
        int32_t errCode;
    
        /* Stop sensor RF , data path will be stopped after RF stop is completed */
        MmwDemo_mmWaveCtrlStop();
    
        /* Wait until DPM_stop is completed */
        Semaphore_pend(gMmwMssMCB.DPMstopSemHandle, BIOS_WAIT_FOREVER);
    
        /* Delete any active streaming session */
        if(gMmwMssMCB.lvdsStream.hwSessionHandle != NULL)
        {
            /* Evaluate need to deactivate h/w session:
             * One sub-frame case:
             *   if h/w only enabled, deactivation never happened, hence need to deactivate
             *   if h/w and s/w both enabled, then s/w would leave h/w activated when it is done
             *   so need to deactivate
             *   (only s/w enabled cannot be the case here because we are checking for non-null h/w session)
             * Multi sub-frame case:
             *   Given stop, we must have re-configured the next sub-frame by now which is next of the
             *   last sub-frame i.e we must have re-configured sub-frame 0. So if sub-frame 0 had
             *   h/w enabled, then it is left in active state and need to deactivate. For all
             *   other cases, h/w was already deactivated when done.
             */
            if ((gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames == 1) ||
                ((gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames > 1) &&
                 (gMmwMssMCB.subFrameCfg[0].lvdsStreamCfg.dataFmt != MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_DISABLED))
               )
            {
                if (CBUFF_deactivateSession(gMmwMssMCB.lvdsStream.hwSessionHandle, &errCode) < 0)
                {
                    System_printf("CBUFF_deactivateSession failed with errorCode = %d\n", errCode);
                    MmwDemo_debugAssert(0);
                }
            }
            MmwDemo_LVDSStreamDeleteHwSession();
        }
    
        /* Delete s/w session if it exists. S/w session never needs to be deactivated in stop because
         * it always (unconditionally) deactivates itself upon completion.
         */
        if(gMmwMssMCB.lvdsStream.swSessionHandle != NULL)
        {
            MmwDemo_LVDSStreamDeleteSwSession();
        }
    
        /* Print epilog */
        MmwDemo_sensorStopEpilog();
    
        /* The sensor has been stopped successfully. Switch off the LED */
        GPIO_write (gMmwMssMCB.cfg.platformCfg.SensorStatusGPIO, 0U);
    
        gMmwMssMCB.sensorStopCount++;
    
        /* print for user */
        System_printf("Sensor has been stopped: startCount: %d stopCount %d\n",
                      gMmwMssMCB.sensorStartCount,gMmwMssMCB.sensorStopCount);
    }
    
    /**************************************************************************
     ******************** Millimeter Wave Demo init Functions ************************
     **************************************************************************/
    
    /**
     *  @b Description
     *  @n
     *      Platform specific hardware initialization.
     *
     *  @param[in]  config     Platform initialization configuraiton
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_platformInit(MmwDemo_platformCfg *config)
    {
        /* Setup the PINMUX to bring out the UART-1 */
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINN5_PADBE, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);    
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINN5_PADBE, SOC_XWR18XX_PINN5_PADBE_MSS_UARTA_TX);
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINN4_PADBD, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);    
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINN4_PADBD, SOC_XWR18XX_PINN4_PADBD_MSS_UARTA_RX);
    
        /* Setup the PINMUX to bring out the UART-3 */
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINF14_PADAJ, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINF14_PADAJ, SOC_XWR18XX_PINF14_PADAJ_MSS_UARTB_TX);
    
        /**********************************************************************
         * Setup the PINMUX:
         * - GPIO Output: Configure pin K13 as GPIO_2 output
         **********************************************************************/
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINK13_PADAZ, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINK13_PADAZ, SOC_XWR18XX_PINK13_PADAZ_GPIO_2);
    
        /**********************************************************************
         * Setup the PINMUX:
         * - for QSPI Flash
         **********************************************************************/
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINR12_PADAP, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINR12_PADAP, SOC_XWR18XX_PINR12_PADAP_QSPI_CLK);
    
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINP11_PADAQ, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINP11_PADAQ, SOC_XWR18XX_PINP11_PADAQ_QSPI_CSN);
    
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINR13_PADAL, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINR13_PADAL, SOC_XWR18XX_PINR13_PADAL_QSPI_D0);
    
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINN12_PADAM, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINN12_PADAM, SOC_XWR18XX_PINN12_PADAM_QSPI_D1);
    
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINR14_PADAN, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINR14_PADAN, SOC_XWR18XX_PINR14_PADAN_QSPI_D2);
    
        Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINP12_PADAO, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
        Pinmux_Set_FuncSel(SOC_XWR18XX_PINP12_PADAO, SOC_XWR18XX_PINP12_PADAO_QSPI_D3);
    
        /**********************************************************************
         * Setup the GPIO:
         * - GPIO Output: Configure pin K13 as GPIO_2 output
         **********************************************************************/
        config->SensorStatusGPIO    = SOC_XWR18XX_GPIO_2;
    
        /* Initialize the DEMO configuration: */
        config->sysClockFrequency   = MSS_SYS_VCLK;
        config->loggingBaudRate     = 921600;
        config->commandBaudRate     = 115200;
    
        /**********************************************************************
         * Setup the DS3 LED on the EVM connected to GPIO_2
         **********************************************************************/
        GPIO_setConfig (config->SensorStatusGPIO, GPIO_CFG_OUTPUT);
    }
    
    /**
     *  @b Description
     *  @n
     *      Init EDMA.
     */
    static void MmwDemo_edmaInit(void)
    {
        int32_t errorCode;
    
        errorCode = EDMA_init(MMW_LVDS_STREAM_EDMA_INSTANCE);
        if (errorCode != EDMA_NO_ERROR)
        {
            System_printf ("Debug: EDMA instance %d initialization returned error %d\n", errorCode);
            MmwDemo_debugAssert (0);
            return;
        }
    
        memset(&gMmwMssMCB.EDMA_errorInfo, 0, sizeof(gMmwMssMCB.EDMA_errorInfo));
        memset(&gMmwMssMCB.EDMA_transferControllerErrorInfo, 0, sizeof(gMmwMssMCB.EDMA_transferControllerErrorInfo));
    }
    
    /**
     *  @b Description
     *  @n
     *      Call back function for EDMA CC (Channel controller) error as per EDMA API.
     *      Declare fatal error if happens, the output errorInfo can be examined if code
     *      gets trapped here.
     */
    static void MmwDemo_EDMA_errorCallbackFxn(EDMA_Handle handle, EDMA_errorInfo_t *errorInfo)
    {
        gMmwMssMCB.EDMA_errorInfo = *errorInfo;
        MmwDemo_debugAssert(0);
    }
    
    /**
     *  @b Description
     *  @n
     *      Call back function for EDMA transfer controller error as per EDMA API.
     *      Declare fatal error if happens, the output errorInfo can be examined if code
     *      gets trapped here.
     */
    static void MmwDemo_EDMA_transferControllerErrorCallbackFxn(EDMA_Handle handle,
                    EDMA_transferControllerErrorInfo_t *errorInfo)
    {
        gMmwMssMCB.EDMA_transferControllerErrorInfo = *errorInfo;
        MmwDemo_debugAssert(0);
    }
    
    /**
     *  @b Description
     *  @n
     *      Open EDMA.
     */
    static void MmwDemo_edmaOpen(void)
    {
        int32_t             errCode;
        EDMA_instanceInfo_t edmaInstanceInfo;
        EDMA_errorConfig_t  errorConfig;
        uint8_t             tc;
    
        gMmwMssMCB.edmaHandle = EDMA_open(MMW_LVDS_STREAM_EDMA_INSTANCE, &errCode, &edmaInstanceInfo);
        gMmwMssMCB.numEdmaEventQueues = edmaInstanceInfo.numEventQueues;
    
        if (gMmwMssMCB.edmaHandle == NULL)
        {
            System_printf("Error: Unable to open the EDMA Instance err:%d\n",errCode);
            MmwDemo_debugAssert (0);
            return;
        }
    
        errorConfig.isConfigAllEventQueues = true;
        errorConfig.isConfigAllTransferControllers = true;
        errorConfig.isEventQueueThresholdingEnabled = true;
        errorConfig.eventQueueThreshold = EDMA_EVENT_QUEUE_THRESHOLD_MAX;
        errorConfig.isEnableAllTransferControllerErrors = true;
    
        gMmwMssMCB.isPollEdmaError = false;
        if (edmaInstanceInfo.isErrorInterruptConnected == true)
        {
            errorConfig.callbackFxn = MmwDemo_EDMA_errorCallbackFxn;
        }
        else
        {
            errorConfig.callbackFxn = NULL;
            gMmwMssMCB.isPollEdmaError = true;
        }
    
        errorConfig.transferControllerCallbackFxn = MmwDemo_EDMA_transferControllerErrorCallbackFxn;
        gMmwMssMCB.isPollEdmaTransferControllerError = false;
    
        for(tc = 0; tc < edmaInstanceInfo.numEventQueues; tc++)
        {
            if (edmaInstanceInfo.isTransferControllerErrorInterruptConnected[tc] == false)
            {
                errorConfig.transferControllerCallbackFxn = NULL;
                gMmwMssMCB.isPollEdmaTransferControllerError = true;
                break;
            }
        }
    
        if ((errCode = EDMA_configErrorMonitoring(gMmwMssMCB.edmaHandle, &errorConfig)) != EDMA_NO_ERROR)
        {
            //System_printf("Error: EDMA_configErrorMonitoring() failed with errorCode = %d\n", errCode);
            MmwDemo_debugAssert (0);
            return;
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      Checks for EDMA errors, used on devices where error interrupts are not connected
     *      to the CPU. Current use case is for LVDS, note it is not very useful to
     *      check for edma errors within the CBUFF session completion interrupts
     *      because they will not happen if edma had errors. So this API should be
     *      called at opportune places in the application code, typically at some time
     *      later than the triggering of the session when it is roughly expected that
     *      the session would have completed by that time.
     */
    static void MmwDemo_checkEdmaErrors(void)
    {
        int32_t     errCode;
        bool        isAnyError;
    
        if (gMmwMssMCB.isPollEdmaError == true)
        {
            errCode = EDMA_getErrorStatus(gMmwMssMCB.edmaHandle, &isAnyError, &gMmwMssMCB.EDMA_errorInfo);
            if (errCode != EDMA_NO_ERROR)
            {
                System_printf("Error: EDMA_getErrorStatus() failed with error code = %d\n", errCode);
                MmwDemo_debugAssert(0);
            }
    
            if (isAnyError == true)
            {
                System_printf("EDMA channel controller has errors, see gMmwMssMCB.EDMA_errorInfo\n");
                MmwDemo_debugAssert(0);
            }
        }
    
        if (gMmwMssMCB.isPollEdmaTransferControllerError == true)
        {
            uint8_t tc;
    
            for(tc = 0; tc < gMmwMssMCB.numEdmaEventQueues; tc++)
            {
                errCode = EDMA_getTransferControllerErrorStatus(gMmwMssMCB.edmaHandle, tc,
                               &isAnyError, &gMmwMssMCB.EDMA_transferControllerErrorInfo);
                if (errCode != EDMA_NO_ERROR)
                {
                    System_printf("Error: EDMA_getTransferControllerErrorStatus() failed with error code = %d\n", errCode);
                    MmwDemo_debugAssert(0);
                }
    
                if (isAnyError == true)
                {
                    System_printf("EDMA Transfer Controller instance %d has errors, see gMmwMssMCB.EDMA_transferControllerErrorInfo\n", tc);
                    MmwDemo_debugAssert(0);
                }
            }
        }
    }
    
    /**
     *  @b Description
     *  @n
     *      Calibration save/restore initialization
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_calibInit(void)
    {
        int32_t          retVal = 0;
        rlVersion_t    verArgs;
    
        /* Initialize verArgs */
        memset((void *)&verArgs, 0, sizeof(rlVersion_t));
    
        /* Get the version string: */
        retVal = rlDeviceGetVersion(RL_DEVICE_MAP_INTERNAL_BSS, &verArgs);
        if (retVal < 0)
        {
            System_printf ("Error: Unable to get the device version from mmWave link [Error %d]\n", retVal);
            return -1;
        }
    
        /* Calibration save/restore init */
        gMmwMssMCB.calibCfg.sizeOfCalibDataStorage = sizeof(MmwDemo_calibData);
        gMmwMssMCB.calibCfg.calibDataHdr.magic = MMWDEMO_CALIB_STORE_MAGIC;
        memcpy((void *)& gMmwMssMCB.calibCfg.calibDataHdr.linkVer, (void *)&verArgs.mmWaveLink, sizeof(rlSwVersionParam_t));
        memcpy((void *)& gMmwMssMCB.calibCfg.calibDataHdr.radarSSVer, (void *)&verArgs.rf, sizeof(rlFwVersionParam_t));
    
        /* Check if Calibration data is over the Reserved storage */
        if(gMmwMssMCB.calibCfg.sizeOfCalibDataStorage   <= MMWDEMO_CALIB_FLASH_SIZE)
        {
    	    gMmwMssMCB.calibCfg.calibDataHdr.hdrLen = sizeof(MmwDemo_calibDataHeader);
    	    gMmwMssMCB.calibCfg.calibDataHdr.dataLen= sizeof(MmwDemo_calibData) - sizeof(MmwDemo_calibDataHeader);
    
               /* Resets calibration data */
               memset((void *)&gCalibDataStorage, 0, sizeof(MmwDemo_calibData));
    
    	    retVal = mmwDemo_flashInit();
        }
        else
        {
            System_printf ("Error: Calibration data size is bigger than reserved size\n");
            retVal = -1;
        }
    
        return retVal;
    
    }
    
    /**
     *  @b Description
     *  @n
     *      This function retrieves the calibration data from front end and saves it in flash.
     *
     *  @param[in]  ptrCalibDataHdr     	Pointer to Calibration data header
     *  @param[in]  ptrCalibrationData      Pointer to Calibration data
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_calibSave(MmwDemo_calibDataHeader *ptrCalibDataHdr, MmwDemo_calibData  *ptrCalibrationData)
    {
        uint32_t				flashOffset;
        int32_t 				retVal = 0;
    
        /* Calculate the read size in bytes */
        flashOffset = gMmwMssMCB.calibCfg.flashOffset;
    
        /* Copy header  */
        memcpy((void *)&(ptrCalibrationData->calibDataHdr), ptrCalibDataHdr, sizeof(MmwDemo_calibDataHeader));
    
        /* Flash calibration data */
        retVal = mmwDemo_flashWrite(flashOffset, (uint32_t *)ptrCalibrationData, sizeof(MmwDemo_calibData));
        if(retVal < 0)
        {
            /* Flash Header failed */
            System_printf ("Error: MmwDemo failed flashing calibration data with error[%d].\n", retVal);
        }
    
        return(retVal);
    }
    
    /**
     *  @b Description
     *  @n
     *      This function reads calibration data from flash and send it to front end through MMWave_open()
     *
     *  @param[in]  ptrCalibData     	Pointer to Calibration data
     *
     *  @retval
     *      Success -   0
     *  @retval
     *      Error   -   <0
     */
    static int32_t MmwDemo_calibRestore(MmwDemo_calibData  *ptrCalibData)
    {
        MmwDemo_calibDataHeader    *pDataHdr;
        int32_t 				retVal = 0;
        uint32_t				flashOffset;
    
        pDataHdr = &(ptrCalibData->calibDataHdr);
    
        /* Calculate the read size in bytes */
        flashOffset = gMmwMssMCB.calibCfg.flashOffset;
    
        /* Read calibration data header */
        if(mmwDemo_flashRead(flashOffset, (uint32_t *)pDataHdr, sizeof(MmwDemo_calibData) )< 0)
        {
            /* Error: only one can be enable at at time */
            System_printf ("Error: MmwDemo failed when reading calibration data from flash.\n");
            return -1;
        }
    
        /* Validate data header */
        if( (pDataHdr->magic != MMWDEMO_CALIB_STORE_MAGIC) ||
             (pDataHdr->hdrLen != gMmwMssMCB.calibCfg.calibDataHdr.hdrLen) ||
             (pDataHdr->dataLen != gMmwMssMCB.calibCfg.calibDataHdr.dataLen) )
        {
            /* Header validation failed */
            System_printf ("Error: MmwDemo calibration data header validation failed.\n");
            retVal = -1;
        }
        /* Matching mmwLink version:
             In this demo, we would like to save/restore with the matching mmwLink and RF FW version.
             However, this logic can be changed to use data saved from previous mmwLink and FW releases,
             as long as the data format of the calibration data matches.
         */
        else if(memcmp((void *)&pDataHdr->linkVer, (void *)&gMmwMssMCB.calibCfg.calibDataHdr.linkVer, sizeof(rlSwVersionParam_t)) != 0)
        {
            System_printf ("Error: MmwDemo failed mmwLink version validation when restoring calibration data.\n");
            retVal = -1;
        }
        else if(memcmp((void *)&pDataHdr->radarSSVer, (void *)&gMmwMssMCB.calibCfg.calibDataHdr.radarSSVer, sizeof(rlFwVersionParam_t)) != 0)
        {
            System_printf ("Error: MmwDemo failed RF FW version validation when restoring calibration data.\n");
            retVal = -1;
        }
        return(retVal);
    }
    /**
     *  @b Description
     *  @n
     *      System Initialization Task which initializes the various
     *      components in the system.
     *
     *  @retval
     *      Not Applicable.
     */
    static void MmwDemo_initTask(UArg arg0, UArg arg1)
    {
        int32_t             errCode;
        MMWave_InitCfg      initCfg;
        UART_Params         uartParams;
        Task_Params         taskParams;
        Semaphore_Params    semParams;
        DPM_InitCfg         dpmInitCfg;
        DPC_ObjectDetection_InitParams      objDetInitParams;
        int32_t             i;
    
        /* Debug Message: */
        System_printf("Debug: Launched the Initialization Task\n");
    
        /*****************************************************************************
         * Initialize the mmWave SDK components:
         *****************************************************************************/
        /* Initialize the UART */
        UART_init();
    
        /* Initialize the GPIO */
        GPIO_init();
    
        /* Initialize the Mailbox */
        Mailbox_init(MAILBOX_TYPE_MSS);
    
        MmwDemo_edmaInit();
    
        MmwDemo_edmaOpen();
    
        /* Initialize LVDS streaming components */
        if ((errCode = MmwDemo_LVDSStreamInit()) < 0 )
        {
            System_printf ("Error: MMWDemoDSS LVDS stream init failed with Error[%d]\n",errCode);
            return;
        }
    
        /* initialize cq configs to invalid profile index to be able to detect
         * unconfigured state of these when monitors for them are enabled.
         */
        for(i = 0; i < RL_MAX_PROFILES_CNT; i++)
        {
            gMmwMssMCB.cqSatMonCfg[i].profileIndx    = (RL_MAX_PROFILES_CNT + 1);
            gMmwMssMCB.cqSigImgMonCfg[i].profileIndx = (RL_MAX_PROFILES_CNT + 1);
        }
    
        /* Platform specific configuration */
        MmwDemo_platformInit(&gMmwMssMCB.cfg.platformCfg);
    
        /*****************************************************************************
         * Open the mmWave SDK components:
         *****************************************************************************/
        /* Setup the default UART Parameters */
        UART_Params_init(&uartParams);
        uartParams.clockFrequency = gMmwMssMCB.cfg.platformCfg.sysClockFrequency;
        uartParams.baudRate       = gMmwMssMCB.cfg.platformCfg.commandBaudRate;
        uartParams.isPinMuxDone   = 1;
    
        /* Open the UART Instance */
        gMmwMssMCB.commandUartHandle = UART_open(0, &uartParams);
        if (gMmwMssMCB.commandUartHandle == NULL)
        {
            //System_printf("Error: Unable to open the Command UART Instance\n");
            MmwDemo_debugAssert (0);
            return;
        }
        //System_printf("Debug: UART Instance %p has been opened successfully\n", gMmwMssMCB.commandUartHandle);
    
        /* 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       = gMmwMssMCB.cfg.platformCfg.loggingBaudRate;
        uartParams.isPinMuxDone   = 1U;
    
        /* Open the Logging UART Instance: */
        gMmwMssMCB.loggingUartHandle = UART_open(1, &uartParams);
        if (gMmwMssMCB.loggingUartHandle == NULL)
        {
            System_printf("Error: Unable to open the Logging UART Instance\n");
            MmwDemo_debugAssert (0);
            return;
        }
    
        /* Create binary semaphores which is used to signal DPM_start/DPM_stop/DPM_ioctl is done
         * to the sensor management task. The signalling (Semaphore_post) will be done
         * from DPM registered report function (which will execute in the DPM execute task context). */
        Semaphore_Params_init(&semParams);
        semParams.mode              = Semaphore_Mode_BINARY;
        gMmwMssMCB.DPMstartSemHandle   = Semaphore_create(0, &semParams, NULL);
        gMmwMssMCB.DPMstopSemHandle   = Semaphore_create(0, &semParams, NULL);
        gMmwMssMCB.DPMioctlSemHandle   = Semaphore_create(0, &semParams, NULL);
    
        /*****************************************************************************
         * mmWave: Initialization of the high level module
         *****************************************************************************/
    
        /* Initialize the mmWave control init configuration */
        memset ((void*)&initCfg, 0 , sizeof(MMWave_InitCfg));
    
        /* Populate the init configuration: */
        initCfg.domain                  = MMWave_Domain_MSS;
        initCfg.socHandle               = gMmwMssMCB.socHandle;
        initCfg.eventFxn                = MmwDemo_eventCallbackFxn;
        initCfg.linkCRCCfg.useCRCDriver = 1U;
        initCfg.linkCRCCfg.crcChannel   = CRC_Channel_CH1;
        initCfg.cfgMode                 = MMWave_ConfigurationMode_FULL;
        initCfg.executionMode           = MMWave_ExecutionMode_ISOLATION;
    
        /* Initialize and setup the mmWave Control module */
        gMmwMssMCB.ctrlHandle = MMWave_init (&initCfg, &errCode);
        if (gMmwMssMCB.ctrlHandle == NULL)
        {
            /* Error: Unable to initialize the mmWave control module */
            System_printf ("Error: mmWave Control Initialization failed [Error code %d]\n", errCode);
            MmwDemo_debugAssert (0);
            return;
        }
        System_printf ("Debug: mmWave Control Initialization was successful\n");
    
        /* Synchronization: This will synchronize the execution of the control module
         * between the domains. This is a prerequiste and always needs to be invoked. */
        if (MMWave_sync (gMmwMssMCB.ctrlHandle, &errCode) < 0)
        {
            /* Error: Unable to synchronize the mmWave control module */
            System_printf ("Error: mmWave Control Synchronization failed [Error code %d]\n", errCode);
            MmwDemo_debugAssert (0);
            return;
        }
        System_printf ("Debug: mmWave Control Synchronization was successful\n");
    
    #ifdef SYS_COMMON_RTRIM_MODIFY_EN
        /* Only when RTRIM MODIFICATION enabled for customer certification purpose */
        /* Read RTRIM, changing the default RTRIM value 12 to 6 */
        System_printf ("Trim Value: %d\n", rtrim_get());
        rtrim_set(6U);
        System_printf ("Trim Value: %d\n", rtrim_get());
    #endif
    
        /*****************************************************************************
         * Launch the mmWave control execution task
         * - This should have a higher priroity than any other task which uses the
         *   mmWave control API
         *****************************************************************************/
        Task_Params_init(&taskParams);
        taskParams.priority  = MMWDEMO_MMWAVE_CTRL_TASK_PRIORITY;
        taskParams.stackSize = 3*1024;
        gMmwMssMCB.taskHandles.mmwaveCtrl = Task_create(MmwDemo_mmWaveCtrlTask, &taskParams, NULL);
    
        /*****************************************************************************
         * Initialization of the DPM Module:
         *****************************************************************************/
        memset ((void *)&dpmInitCfg, 0, sizeof(DPM_InitCfg));
    
        /* Setup the configuration: */
        dpmInitCfg.socHandle        = gMmwMssMCB.socHandle;
        dpmInitCfg.ptrProcChainCfg  = NULL;
        dpmInitCfg.instanceId       = DPC_OBJDET_INSTANCEID;
        dpmInitCfg.domain           = DPM_Domain_REMOTE;
        dpmInitCfg.reportFxn        = MmwDemo_DPC_ObjectDetection_reportFxn;
        dpmInitCfg.arg              = &objDetInitParams;
        dpmInitCfg.argSize          = sizeof(DPC_ObjectDetection_InitParams);
    
        /* Initialize the DPM Module: */
        gMmwMssMCB.objDetDpmHandle = DPM_init (&dpmInitCfg, &errCode);
        if (gMmwMssMCB.objDetDpmHandle == NULL)
        {
            System_printf ("Error: Unable to initialize the DPM Module [Error: %d]\n", errCode);
            MmwDemo_debugAssert (0);
            return;
        }
    
        /* Synchronization: This will synchronize the execution of the datapath module
         * between the domains. This is a prerequiste and always needs to be invoked. */
        while (1)
        {
            int32_t syncStatus;
    
            /* Get the synchronization status: */
            syncStatus = DPM_synch (gMmwMssMCB.objDetDpmHandle, &errCode);
            if (syncStatus < 0)
            {
                /* Error: Unable to synchronize the framework */
                System_printf ("Error: DPM Synchronization failed [Error code %d]\n", errCode);
                MmwDemo_debugAssert (0);
                return;
            }
            if (syncStatus == 1)
            {
                /* Synchronization acheived: */
                break;
            }
            /* Sleep and poll again: */
            Task_sleep(1);
        }
    
        /* Launch the DPM Task */
        Task_Params_init(&taskParams);
        taskParams.priority  = MMWDEMO_DPC_OBJDET_DPM_TASK_PRIORITY;
        taskParams.stackSize = 4*1024;
        gMmwMssMCB.taskHandles.objDetDpmTask = Task_create(mmwDemo_mssDPMTask, &taskParams, NULL);
    
        /* Calibration save/restore initialization */
        if(MmwDemo_calibInit()<0)
        {
            System_printf("Error: Calibration data initialization failed \n");
            MmwDemo_debugAssert (0);
        }
    
        /*****************************************************************************
         * Initialize the Profiler
         *****************************************************************************/
        Cycleprofiler_init();
    
        /*****************************************************************************
         * Initialize the CLI Module:
         *****************************************************************************/
        MmwDemo_CLIInit(MMWDEMO_CLI_TASK_PRIORITY);
    
        return;
    }
    
    /**
     *  @b Description
     *  @n
     *     Function to sleep the R4F using WFI (Wait For Interrupt) instruction.
     *     When R4F has no work left to do,
     *     the BIOS will be in Idle thread and will call this function. The R4F will
     *     wake-up on any interrupt (e.g chirp interrupt).
     *
     *  @retval
     *      Not Applicable.
     */
    void MmwDemo_sleep(void)
    {
        /* issue WFI (Wait For Interrupt) instruction */
        asm(" WFI ");
    }
    
    /**
     *  @b Description
     *  @n
     *      Entry point into the Millimeter Wave Demo
     *
     *  @retval
     *      Not Applicable.
     */
    int main (void)
    {
        Task_Params     taskParams;
        int32_t         errCode;
        SOC_Handle      socHandle;
        SOC_Cfg         socCfg;
    
        /* Initialize the ESM: Dont clear errors as TI RTOS does it */
        ESM_init(0U);
    
        /* Initialize the SOC confiugration: */
        memset ((void *)&socCfg, 0, sizeof(SOC_Cfg));
    
        /* Populate the SOC configuration: */
        socCfg.clockCfg = SOC_SysClock_INIT;
        socCfg.mpuCfg = SOC_MPUCfg_CONFIG;
        socCfg.dssCfg = SOC_DSSCfg_UNHALT;
    
        /* Initialize the SOC Module: This is done as soon as the application is started
         * to ensure that the MPU is correctly configured. */
        socHandle = SOC_init (&socCfg, &errCode);
        if (socHandle == NULL)
        {
            System_printf ("Error: SOC Module Initialization failed [Error code %d]\n", errCode);
            MmwDemo_debugAssert (0);
            return -1;
        }    
        
        /* Wait for BSS powerup */
        if (SOC_waitBSSPowerUp(socHandle, &errCode) < 0)
        {
            /* Debug Message: */
            System_printf ("Debug: SOC_waitBSSPowerUp failed with Error [%d]\n", errCode);
            return 0;
        }
    
        /* Check if the SOC is a secure device */
        if (SOC_isSecureDevice(socHandle, &errCode))
        {
            /* Disable firewall for JTAG and LOGGER (UART) which is needed by all unit tests */
            SOC_controlSecureFirewall(socHandle, 
                                      (uint32_t)(SOC_SECURE_FIREWALL_JTAG | SOC_SECURE_FIREWALL_LOGGER),
                                      SOC_SECURE_FIREWALL_DISABLE,
                                      &errCode);
        }
    
        /* Initialize and populate the demo MCB */
        memset ((void*)&gMmwMssMCB, 0, sizeof(MmwDemo_MSS_MCB));
    
        gMmwMssMCB.socHandle = socHandle;
    
        /* Debug Message: */
        System_printf ("**********************************************\n");
        System_printf ("Debug: Launching the MMW Demo on MSS\n");
        System_printf ("**********************************************\n");
    
        /* Initialize the Task Parameters. */
        Task_Params_init(&taskParams);
        gMmwMssMCB.taskHandles.initTask = Task_create(MmwDemo_initTask, &taskParams, NULL);
    
        /* Start BIOS */
        BIOS_start();
        return 0;
    }

  • Hi Rehman,

    If the MRR demo is outputting CAN-FD, the switch configurations should be correct. 

    Could you step through Can_Initialize() to ensure that the params and message RAM are being properly initialized?

    Afterwards, please step through the Can_Transmit_Schedule to confirm that the message is being correctly written to the message RAM. The Memory Browser can be used to view the RAM directly.

    Thank you,

    Jin

  • Hai JIN,

    The both functions mentioned above are all OK....but one doubt I have is...in the given document nothing has been specified of how to link the CAN-FD driver...only given info is a figure...

    So i just copied the file mentioned in the figure and pasted in the FILE SEARCH of ARM LINKER.....

    It would be great if TI elaboarte the steps instead of giving a figure.

    "Linking the CAN-FD Driver :- The final step is to build the executable by linking with the CAN-FD drivers. If using a CCS project, the CAN-FD drivers can be added to the project’s linker properties, as shown in Figure 1" 

  • Hi Rehman,

    The figure in reference ("Figure 1. CCS Project Linker Properties") shows the CAN-FD library file for the AWR1642 device. Please ensure that the canfd driver is included in the library search path, and that libcanfd_xwr18xx.aer4f is included. Please also confirm you are using the latest version of SDK3.

    To confirm the last question, you are able to see the message RAM properly initialized in memory, and see the message being written when CANFD_transmitData is called?

    Thank you,

    Jin

  • So I can just copy it form MRR demo right....which uses AWR1843 board only....

    The memory thing i should run it in debug mode right....when I checked all the registers was 0s...........

    Is there any document which specifies how to access RAM...since i am first into CCS i am not much aware of how to access .

    Thanks ,

    Rehman

  • Hi Rehman, 

    Copying the search paths and library files from the MRR demo is a starting point - please check that the paths are correct, and that the latest SDK3 is used.

    For information on using the Memory Browser view, please refer to the help document included in CCS:

    Help->Help Contents->Code Composer Studio User's Guide->Debug->Debugging the Application->Memory Browser view. 

    Please check where the message RAM for CAN-FD is being initialized, and that the transmitted message is written into the message RAM  when CANFD_transmitData() is called.

    Thank you,

    Jin

  • Hi Jin.....,

    I have done all the required for the paths and library files. 

    I also viewed the memory browser and found that RAM for CAN-FD is initialised......still CAN is not coming up.....

    i will share the photos of all below.

    1) - Paths and files 

    2) - CANFD Registers - 0xFFFFEA10 and 0xFFFFEA0C (pins - E14 and D13 resp)

  • Hi Rehman, 

    Thank you for update. Paths and files look fine to me. 

    Some notes regarding the Memory browser and debugging:

    • In R4F, 0xFFFF_EA00 to 0xFFFF_EBFF in memory are used for the I/O pinmux registers, not for CAN data config/RAM. 
    • In C66, 0x5600_0000 to 0xFFFF_FFFF are reserved and shouldn't be used. 

    In R4F, 0xFF50_0000 to 0xFF9F_FFFF are reserved for MCAN RAM memory space - the MCAN RAM address should be within those bounds. 

    Please refer to section 3.2 in the AWR18xx TRM (https://www.ti.com/lit/pdf/swru520) for more details. 

    Also, I recommend you use breakpoints to step through the CAN-FD functions so you can see the variables/memory browser update values. Continuous refresh (yellow icon in the top right of the Memory Browser window) might be another option, but it would be less helpful for debugging. 

    Thank you,

    Jin

  • If using the AWR1843BOOST, there is a switch that must be set in SPI position. Please check EVM UG for more details.

    Thank you

    Cesar

  • I meant from SPI to CAN position