My purpose is to test SPI with 2 IWR6843 EVMs. I need to de target tracking demo to customers. I modified xwr68xx demo code in SDK. I see original demo code do UART_write() with input data: header, tl. As my understanding, those data are header and TLV data frame.
Slave: do SPI_write with same input as UART_write in original demo code.
Need to do settings:
SPI_Params spiParams; SPI_Params_init(&spiParams); spiParams.mode = SPI_SLAVE;
Master: do SPI_read to get data and store into a buffer (rxBuf).
Settings as a Master
spiParams.mode = SPI_MASTER;
I wanna ask: In order to read TLV header and data frame, what size of rxBuf I need to set to get full package? How to ensure that I get TLV data by SPI_read in correct sequence to write them into UART_write? I think it's not good if I only read all at once, so I need you explain more about principle and sample code for this task is really helpful. Thank you.
In case I want to transfer TLV data from Slave to Master, should I use a fixed size array as a buffer for SPI_write? I think I only need to write head, TLV index into SPI_write. Is it correct? Besides, I don't know whether the Master can read data from Slave all at once or not.
1. Do I need some delay (i don't know what delay function in TI SDK) or something else in Master device code?
2. How to arrange the data reading on Master by SPI_read in a correct sequence? I'm concerned that header and TLV frame data can be mixed up.
Below is my code of Master and Slave.
Master code for SPI_read and UART_write to GUI
static void SPI_to_UART ( SPI_Handle spiHandle, UART_Handle uartHandle, DPC_ObjectDetection_ExecuteResult *result, MmwDemo_output_message_stats *timingInfo ) { //Read data from slave spi_Read(spiHandle, (void *)rxBuf, SPI_DATA_BLOCK_SIZE); ....// UART_write(uartHandle, (void *)rxBuf, SPI_DATA_BLOCK_SIZE); }
I don't know how to handle rxBuf and transfer TLV tracking data to GUI via UART_write in correct sequence (header, data frame TLV index...). Please tell me how to make it work.
Slave code for SPI_write. I modified original demo code. I replaced UART_write by SPI_write with the same input buffer. So I don't declare a txBuf here.
If you don't want to look at the huge code of MmwDemo_transmitProcessedOutput() below, here's my brief idea. Please confirm if my method for Master & Slave write/read is correct.
//UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); // original demo code used this line //UART_writePolling (uartHandle,(uint8_t*)&header, sizeof(MmwDemo_output_message_header)); // original demo code used this line //SPI write head and TLV index from Slave to Master spi_Write (spiHandle, (uint8_t*)&header, sizeof(MmwDemo_output_message_header)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl));
static void MmwDemo_transmitProcessedOutput (
SPI_Handle spiHandle, UART_Handle uartHandle, DPC_ObjectDetection_ExecuteResult *result, MmwDemo_output_message_stats *timingInfo ) { SPI_Handle spiHandle; MmwDemo_output_message_header header; MmwDemo_GuiMonSel *pGuiMonSel; MmwDemo_SubFrameCfg *subFrameCfg; uint32_t tlvIdx = 0; //uint32_t tlvIdx_spi = 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; //spiDataMsg *pTestMsgOut; //uint16_t seqNo; //uint16_t dc_offset; //int rangeLength,i; /* 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)); //Read data from slave //spi_Read(spiHandle, (void *)rxBuf, SPI_DATA_BLOCK_SIZE); //pTestMsgOut = (spiDataMsg *)&rxBuf[0]; /****************************************************************** 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 = 0xA6843; 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) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP; 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++; } 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)); //SPI write from Slave to Master //spi_Write (spiHandle, (uint8_t*)pTestMsgOut, SPI_DATA_BLOCK_SIZE); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); /*Send array of objects */ //UART_writePolling (uartHandle, (uint8_t*)objOut, sizeof(DPIF_PointCloudCartesian) * result->numObjOut); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); //UART_writePolling (uartHandle, (uint8_t*)objOutSideInfo, sizeof(DPIF_PointCloudSideInfo) * result->numObjOut); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); //UART_writePolling (uartHandle,(uint8_t *)azimuthStaticHeatMap,result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t)); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); //UART_writePolling (uartHandle,(uint8_t*)detMatrix,tl[tlvIdx].length); spi_Write (spiHandle, (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)); spi_Write (spiHandle, (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); spi_Write (spiHandle, (uint8_t*)timingInfo,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); spi_Write (spiHandle, (uint8_t*)padding,numPaddingBytes); } }