This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/AWR1642: Does the fftOut1D store the FFT results of all chirps of one frame in pplcount demo project, how to send out the FFT result of only one chirp of one frame to GUI by UART

Part Number: AWR1642

Tool/software: Code Composer Studio

Hi,

I currently want to send out of the fft result of one of the chirp in a frame in the pplcount demo project. But I found that the sourcing code in pplcount did not have "radarCube" parameter in MmwDemo_DSS_DataPathObj struct, I have try to get the fft result from "fftOut1D", but failed. Could you please tell me how to get the result (not range-fft profile) and send it out to display in GUI by UART. 

Thanks.

  • Hi Genming,

    Our people counting expert should have an answer for you sometime tomorrow.


    Cheers,
    Akash
  • Hello,
    Could you elaborate more on what do you mean by "fftOut1D" failure to get data?
    Since the 1D FFT data is written to L3 memory-radar cube in a transpose form and the same memory is overwritten by further processing in inter-frame time, to pass 1D FFT data over UART, you may need to disable the rest of the processing chain - Angle and Doppler estimation. Also for transferring the data on the UART sufficient inter-frame time needs to be provided by changing the sensor configuration.

    Please help us understand the use scenario or final objective that you intend to achieve by this exercise. We would be happy to assist you with a direction/solution.

    Regards
    AK
  • Abdulraheem Killedar said:
    Hello,
    Could you elaborate more on what do you mean by "fftOut1D" failure to get data?
    Since the 1D FFT data is written to L3 memory-radar cube in a transpose form and the same memory is overwritten by further processing in inter-frame time, to pass 1D FFT data over UART, you may need to disable the rest of the processing chain - Angle and Doppler estimation. Also for transferring the data on the UART sufficient inter-frame time needs to be provided by changing the sensor configuration.

    Please help us understand the use scenario or final objective that you intend to achieve by this exercise. We would be happy to assist you with a direction/solution.

    Regards
    AK

    Hi, AK,

    Thanks for your reply. I want to transfer 1D FFT of only one chirp in one frame by UART. Currently, the configuration of frame is: profileCfg 0 77 7 7 50 0 0 60 1 64 2000 0 0 30. The adcsample number is 64 in our configuration.

    In the project, I first added one variable in the struct: MmwDemo_output_message_pointCloud_t (in mmw_output.h) and radarProcessOutputToTracker (in radarprocess.h), the new structs are as follows:

    typedef struct MmwDemo_output_message_pointCloud_t
    {
    MmwDemo_output_message_tl header;
    MmwDemo_output_message_point point[1];

    int16_t RangefftOut1Chirp[MAX_NUM_RANGE_BINS / 8]; // added by Ding 20180407
    } MmwDemo_output_message_pointCloud;

    typedef struct {
    int32_t object_count; //number of objects (points)

    float range[DOA_OUTPUT_MAXPOINTS];
    float angle[DOA_OUTPUT_MAXPOINTS];
    float doppler[DOA_OUTPUT_MAXPOINTS];
    float snr[DOA_OUTPUT_MAXPOINTS];
    float rangeVar[DOA_OUTPUT_MAXPOINTS];
    float dopplerVar[DOA_OUTPUT_MAXPOINTS];

    int32_t rangebin_cout;
    int16_t RangefftOut1Chirp[MAX_NUM_RANGE_BINS / 8];

    } radarProcessOutputToTracker;

    Then in dss_main.c, we modified the function MmwDemo_dssDataPathProcessEvents  as follows:

    static int32_t MmwDemo_dssDataPathProcessEvents(UInt event)
    {
    MmwDemo_DSS_DataPathObj *dataPathObj;
    volatile uint32_t startTime;

    dataPathObj = &gMmwDssMCB.dataPathObj;

    /* Handle dataPath events */
    switch(event)
    {
    case MMWDEMO_CHIRP_EVT:
    /* Increment event stats */
    gMmwDssMCB.stats.chirpEvt++;

    MmwDemo_processChirp(dataPathObj);
    dataPathObj->chirpProcToken--;
    dataPathObj->chirpEndTimeStamp = Cycleprofiler_getTimeStamp();
    dataPathObj->cycleLog.chirpProcMarginCurrInusec = 1.0e6 * dataPathObj->radarProcConfig.chirpInterval
    - DSP_CLOCK_USEC_PER_CYCLE * (float)(dataPathObj->chirpEndTimeStamp - dataPathObj->chirpStartTimeStamp);

    if (gMmwDssMCB.stats.chirpIntCounter > 4)
    {
    if (dataPathObj->cycleLog.chirpProcMarginMaxInusec < dataPathObj->cycleLog.chirpProcMarginCurrInusec)
    dataPathObj->cycleLog.chirpProcMarginMaxInusec = dataPathObj->cycleLog.chirpProcMarginCurrInusec;
    if (dataPathObj->cycleLog.chirpProcMarginMinInusec > dataPathObj->cycleLog.chirpProcMarginCurrInusec)
    dataPathObj->cycleLog.chirpProcMarginMinInusec = dataPathObj->cycleLog.chirpProcMarginCurrInusec;
    }

    if (dataPathObj->chirpCount == 0)
    {
    MmwDemo_waitEndOfChirps(dataPathObj);

    #ifdef DEBUG
    glbDebugBuf[glbDebugBufCnt++] = 0xcccc;
    if(glbDebugBufCnt >= GLBDEBUGBUFLEN) glbDebugBufCnt = 0;
    glbDebugBuf[glbDebugBufCnt++] = Cycleprofiler_getTimeStamp();
    if(glbDebugBufCnt >= GLBDEBUGBUFLEN) glbDebugBufCnt = 0;
    #endif
    MmwDemo_interFrameProcessing(dataPathObj);
    #ifdef DEBUG
    glbDebugBuf[glbDebugBufCnt++] = 0xdddd;
    if(glbDebugBufCnt >= GLBDEBUGBUFLEN) glbDebugBufCnt = 0;
    glbDebugBuf[glbDebugBufCnt++] = Cycleprofiler_getTimeStamp();
    if(glbDebugBufCnt >= GLBDEBUGBUFLEN) glbDebugBufCnt = 0;
    #endif
    /* Sending detected objects to logging buffer */

    //-------start of modification By Ding -------

    radarProcessOutputToTracker * outToTrackerRangeFFT;

    outToTrackerRangeFFT = (radarProcessOutputToTracker*) &(dataPathObj->outputDataToArm->outputToTracker);


    outToTrackerRangeFFT->rangebin_cout = dataPathObj->numRangeBins * 2;

    uint32_t i;

    cplx16_t * tempData;

    for(i=0; i<dataPathObj->numRangeBins; i++)
    {

       tempData = (cplx16_t *) &(dataPathObj->fftOut1D[i*dataPathObj->numVirtRxAntennas * dataPathObj->numChirpsPerFrame]);


       outToTrackerRangeFFT->RangefftOut1Chirp[2*i] = tempData->real;
       outToTrackerRangeFFT->RangefftOut1Chirp[2*i+1]= tempData->imag;


    }

    // //--- End of modification ---

    MmwDemo_dssDataPathOutputLogging (dataPathObj); 
    dataPathObj->frameProcDoneTimeStamp = Cycleprofiler_getTimeStamp();

    dataPathObj->cycleLog.frameProcMarginCurrInusec = (float)(dataPathObj->radarProcConfig.framePeriod) * 1000.f - DSP_CLOCK_USEC_PER_CYCLE * (float)((int32_t)(dataPathObj->frameProcDoneTimeStamp) - (int32_t)(dataPathObj->frameStartTimeStamp));
    if(dataPathObj->cycleLog.frameProcMarginCurrInusec > 0.f)
    {
    if (dataPathObj->cycleLog.frameProcMarginMaxInusec < dataPathObj->cycleLog.frameProcMarginCurrInusec)
    dataPathObj->cycleLog.frameProcMarginMaxInusec = dataPathObj->cycleLog.frameProcMarginCurrInusec;
    if (dataPathObj->cycleLog.frameProcMarginMinInusec > dataPathObj->cycleLog.frameProcMarginCurrInusec)
    dataPathObj->cycleLog.frameProcMarginMinInusec = dataPathObj->cycleLog.frameProcMarginCurrInusec;
    }
    dataPathObj->interFrameProcToken--;
    dataPathObj->frameCount++;
    }
    break;

    case MMWDEMO_FRAMESTART_EVT:
    /* Increment event stats */
    gMmwDssMCB.stats.frameStartEvt++;
    DebugP_assert(dataPathObj->chirpCount == 0);
    break;

    case MMWDEMO_BSS_FRAME_TRIGGER_READY_EVT:
    /* Increment event stats */
    gMmwDssMCB.stats.frameTrigEvt++;

    break;

    default:
    break;
    }
    return 0;
    }

    And then in the mss project, I  disable the transfer of pointcloud in MmwDemo_mboxReadTask function in task_mbox.c, and transfer the fft result of one chirp instead, the codes are as follows:

    void MmwDemo_mboxReadTask(UArg arg0, UArg arg1)
    {
    MmwDemo_message message;
    int32_t retVal = 0;
    uint32_t timeStart;
    inputFromDSP *srcAddress;
    uint16_t numPoints, nPoint;
    int n;
    uint16_t *headerPtr;
    uint32_t sum;
    MmwDemo_output_message_header outputMessage;
    _Bool sendDescr;

    outputMessage.magicWord[0] = 0x0102;
    outputMessage.magicWord[1] = 0x0304;
    outputMessage.magicWord[2] = 0x0506;
    outputMessage.magicWord[3] = 0x0708;
    outputMessage.platform = 0xA1642;
    outputMessage.version = MMWAVE_SDK_VERSION_BUILD | //DEBUG_VERSION
    (MMWAVE_SDK_VERSION_BUGFIX << 8) |
    (MMWAVE_SDK_VERSION_MINOR << 16) |
    (MMWAVE_SDK_VERSION_MAJOR << 24);
    outputMessage.subFrameNumber = 0;


    /* wait for new message and process all the messages received from the peer */
    while(1)
    {
         Semaphore_pend(gMmwMssMCB.mboxSemHandle, BIOS_WAIT_FOREVER);

    /* Read the message from the peer mailbox: We are not trying to protect the read
    * from the peer mailbox because this is only being invoked from a single thread */
    retVal = Mailbox_read(gMmwMssMCB.peerMailbox, (uint8_t*)&message, sizeof(MmwDemo_message));
    if (retVal < 0)
    {
    /* Error: Unable to read the message. Setup the error code and return values */
    System_printf ("Error: Mailbox read failed [Error code %d]\n", retVal);
    }
    else if (retVal == 0)
    {
    /* We are done: There are no messages available from the peer execution domain. */
    continue;
    }
    else
    {
    /* Flush out the contents of the mailbox to indicate that we are done with the message. This will
    * allow us to receive another message in the mailbox while we process the received message. */
    Mailbox_readFlush (gMmwMssMCB.peerMailbox);

    /* Process the received message: */
    switch (message.type)
    {
    case MMWDEMO_DSS2MSS_DETOBJ_READY:

    timeStart = Cycleprofiler_getTimeStamp();

    srcAddress = (inputFromDSP *)SOC_translateAddress(message.body.detObj.detObjOutAddress, SOC_TranslateAddr_Dir_FROM_OTHER_CPU,NULL);

    outputMessage.frameNumber = srcAddress->header.frameNumber;
    outputMessage.chirpProcessingMargin = srcAddress->header.chirpProcessingMarginInUsec;
    outputMessage.frameProcessingMargin = srcAddress->header.frameProcessingMarginInUsec;
    outputMessage.trackingProcessingTime = gMmwMssMCB.mssDataPathObj.cycleLog.trackingTimeCurrInusec;
    outputMessage.uartSendingTime = gMmwMssMCB.mssDataPathObj.cycleLog.sendingToUARTTimeCurrInusec;


    numPoints = srcAddress->outputToTracker.object_count;
    if(numPoints > gMmwMssMCB.cfg.trackingCfg.config.maxNumPoints) {
    numPoints = gMmwMssMCB.cfg.trackingCfg.config.maxNumPoints;
    }

    // if(numPoints) { 
    if(0) {

    // for testing of rangefft data output

    gMmwMssMCB.pointCloud->header.length = sizeof(MmwDemo_output_message_tl) + numPoints*sizeof(MmwDemo_output_message_point);

    // --- End ---

    for(nPoint = 0; nPoint < numPoints; nPoint++) {
    gMmwMssMCB.pointCloud->point[nPoint].range = srcAddress->outputToTracker.range[nPoint];
    gMmwMssMCB.pointCloud->point[nPoint].azimuth = srcAddress->outputToTracker.angle[nPoint] + gMmwMssMCB.cfg.applicationCfg.sensorAzimuthTilt;
    gMmwMssMCB.pointCloud->point[nPoint].doppler = srcAddress->outputToTracker.doppler[nPoint];
    gMmwMssMCB.pointCloud->point[nPoint].snr = srcAddress->outputToTracker.snr[nPoint];
    }
    }
    else
    gMmwMssMCB.pointCloud->header.length = 0;

    // --- modified by Ding 20180407
    if(1){

    uint32_t i;
    for(i=0;i<srcAddress->outputToTracker.rangebin_cout;i++)
    {
    gMmwMssMCB.pointCloud->RangefftOut1Chirp[i] = srcAddress->outputToTracker.RangefftOut1Chirp[i];
    }

    gMmwMssMCB.pointCloud->header.length = sizeof(MmwDemo_output_message_tl); 
    gMmwMssMCB.pointCloud->header.length += srcAddress->outputToTracker.rangebin_cout * sizeof(int16_t);
    }


    // --- End ---

    gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec = ((float)(Cycleprofiler_getTimeStamp() - timeStart))/(float)R4F_CLOCK_MHZ;
    if ((gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec > 0) && (gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec > gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeMaxInusec))
    gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeMaxInusec = gMmwMssMCB.mssDataPathObj.cycleLog.copyResultsTimeCurrInusec;

    /* Send a message to MSS to log the output data */
    memset((void *)&message, 0, sizeof(MmwDemo_message));
    message.type = MMWDEMO_MSS2DSS_DETOBJ_SHIPPED;
    if (MmwDemo_mboxWrite(&message) != 0) {
    System_printf ("Error: Mailbox send message id=%d failed \n", message.type);
    }

    /* Post a job for group tracker */
    sendDescr = gMmwMssMCB.targetDescrHandle->currentDescr;
    gMmwMssMCB.targetDescrHandle->currentDescr = !sendDescr;

    if(gMmwMssMCB.mssDataPathObj.groupTrackerEnabled)
    Semaphore_post(gMmwMssMCB.appSemHandle);

    outputMessage.timeStamp = Cycleprofiler_getTimeStamp();
    outputMessage.totalPacketLen = sizeof(MmwDemo_output_message_header);
    outputMessage.numTLVs = 0;
    outputMessage.checksum = 0;

    if(gMmwMssMCB.pointCloud->header.length) {
    /* Add pointCloud TLV length */
    outputMessage.totalPacketLen += gMmwMssMCB.pointCloud->header.length;
    outputMessage.numTLVs += 1;
    }
    if(gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length) {
    /* Add targetList TLV length */
    outputMessage.totalPacketLen += gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length;
    outputMessage.numTLVs += 1;
    }
    if(gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length) {
    /* Add targetIndex TLV length */
    outputMessage.totalPacketLen += gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length;
    outputMessage.numTLVs += 1;
    }

    /* Calculate header checksum */
    headerPtr = (uint16_t *)&outputMessage;
    for(n=0, sum = 0; n < sizeof(MmwDemo_output_message_header)/sizeof(uint16_t); n++)
    sum += *headerPtr++;
    outputMessage.checksum = ~((sum >> 16) + (sum & 0xFFFF));

    /* Always send a packet header */
    UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)&outputMessage, sizeof(MmwDemo_output_message_header));

    if(gMmwMssMCB.pointCloud->header.length) {
    /* If any points detected, send Point Cloud TLV */
    UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)gMmwMssMCB.pointCloud, gMmwMssMCB.pointCloud->header.length);
    }

    if(gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length) {
    /* If any targets tracked, send send target List TLV */
    UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)gMmwMssMCB.targetDescrHandle->tList[sendDescr], gMmwMssMCB.targetDescrHandle->tList[sendDescr]->header.length);
    }

    if(gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length) {
    /* If exists, send target Index TLV */
    UART_write (gMmwMssMCB.loggingUartHandle, (uint8_t *)gMmwMssMCB.targetDescrHandle->tIndex[sendDescr], gMmwMssMCB.targetDescrHandle->tIndex[sendDescr]->header.length);
    }


    gMmwMssMCB.mssDataPathObj.cycleLog.sendingToUARTTimeCurrInusec = ((float)(Cycleprofiler_getTimeStamp() - timeStart))/(float)R4F_CLOCK_MHZ;
    if ((gMmwMssMCB.mssDataPathObj.cycleLog.sendingToUARTTimeCurrInusec > 0) && (gMmwMssMCB.mssDataPathObj.cycleLog.sendingToUARTTimeCurrInusec > gMmwMssMCB.mssDataPathObj.cycleLog.sendingToUARTTimeMaxInusec))
    gMmwMssMCB.mssDataPathObj.cycleLog.sendingToUARTTimeMaxInusec = gMmwMssMCB.mssDataPathObj.cycleLog.sendingToUARTTimeCurrInusec;

    break;

    case MMWDEMO_DSS2MSS_CONFIGDONE:
    gMmwMssMCB.mssDataPathObj.heatmapAddress = (float *)SOC_translateAddress(message.body.dssStaticInfo.heatmapAddress, SOC_TranslateAddr_Dir_FROM_OTHER_CPU,NULL);
    gMmwMssMCB.mssDataPathObj.heatmapRowLen = message.body.dssStaticInfo.heatmapRowLen;
    gMmwMssMCB.mssDataPathObj.heatmapNumRows = message.body.dssStaticInfo.heatmapNumRows;
    break;

    default:
    {
    /* Message not support */
    System_printf ("Error: Unsupported Mailbox message id=%d\n", message.type);
    break;
    }
    }
    }
    }
    }

    In the matlab code for the GUI (pcount_demo_gui.m), the case 6 is changed to:

    case 6

    % Point Cloud TLV

    % added by GDing
    size(rxData)
    rangeProfile = [];
    rangeProfileTemp = [];

    rangeProfileTemp = rxData(offset+1: offset+valueLength);
    rangeProfile = single(typecast(uint8([rangeProfileTemp]),'uint16'));
    rangeProfile(rangeProfile>(2^15)) = rangeProfile(rangeProfile>(2^15)) - 2^16;

    rp_cplx = rangeProfile(1:2:end) + 1j*(rangeProfile(2:2:end));
    rangeFFT = abs(rp_cplx);

    Xaxis=[0:63].*0.078;

    figure(1)
    plot(Xaxis, rangeFFT);




    continue;


    % ---- End ----
    %
    numInputPoints = valueLength/pointLengthInBytes
    if(numInputPoints > 0) 
    % Get Point Cloud from the sensor
    p = typecast(uint8(rxData(offset+1: offset+valueLength)),'single');

    pointCloud = reshape(p,4, numInputPoints); 
    % pointCloud(2,:) = pointCloud(2,:)*pi/180;

    posAll = [pointCloud(1,:).*sin(pointCloud(2,:)); pointCloud(1,:).*cos(pointCloud(2,:))];
    snrAll = pointCloud(4,:);

    % Remove out of Range, Behind the Walls, out of FOV points
    inRangeInd = (pointCloud(1,:) > 1) & (pointCloud(1,:) < 6) & ...
    (pointCloud(2,:) > -50*pi/180) & (pointCloud(2,:) < 50*pi/180) & ...
    (posAll(1,:) > scene.areaBox(1)) & (posAll(1,:) < (scene.areaBox(1) + scene.areaBox(3))) & ...
    (posAll(2,:) > scene.areaBox(2)) & (posAll(2,:) < (scene.areaBox(2) + scene.areaBox(4)));
    pointCloudInRange = pointCloud(:,inRangeInd);
    posInRange = posAll(:,inRangeInd);
    %{
    % Clutter removal
    staticInd = (pointCloud(3,:) == 0); 
    clutterInd = ismember(pointCloud(1:2,:)', clutterPoints', 'rows');
    clutterInd = clutterInd' & staticInd;
    clutterPoints = pointCloud(1:2,staticInd);
    pointCloud = pointCloud(1:3,~clutterInd);
    %}
    numOutputPoints = size(pointCloud,2); 
    end 
    offset = offset + valueLength;

    %--------------

       Could you please help us to find the problem, thanks very much.

    B.R.

    GenmingDing

  • Hello Ming,
    Unfortunately, its very difficult to debug code this way. We don't have a standard solution to what you are trying to achieve. There are two ways I suggest if they are acceptable as solutions to you.
    1. Use the Capture demo with the SDK version 1.1. The Raw data from the first frame is available to be pulled out through the CCS via memory dump. The SDK 1.1 useguide has detailed procedure for the same.
    Once the data is dumped to a file, use the script available with the SDK 1.1 to plot the same.
    2. Use the chirp configuration that you have defined earlier with one frame and one chirp as above. place a breakpoint after the iDFFT processing step. from the 1DFFT output buffer, pullout the data using the CCS memory dump.


    regards
    AK
  • Thanks for your kind help. I will try to use the visualizer Demo to capture the range-fft profile.