TI-radar AWR1843 C674x DSP core  1
dss_data_path.c
Go to the documentation of this file.
1 
40 /**************************************************************************
41 *************************** Include Files ********************************
42 **************************************************************************/
43 
44 /* Standard Include Files. */
45 #include <stdint.h>
46 #include <stdlib.h>
47 #include <stddef.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <math.h>
51 
52 /* BIOS/XDC Include Files. */
53 #include <xdc/std.h>
54 #include <xdc/cfg/global.h>
55 #include <xdc/runtime/IHeap.h>
56 #include <xdc/runtime/System.h>
57 #include <xdc/runtime/Error.h>
58 #include <xdc/runtime/Memory.h>
59 #include <ti/sysbios/BIOS.h>
60 #include <ti/sysbios/knl/Task.h>
61 #include <ti/sysbios/knl/Event.h>
62 #include <ti/sysbios/knl/Semaphore.h>
63 #include <ti/sysbios/knl/Clock.h>
64 #include <ti/sysbios/heaps/HeapBuf.h>
65 #include <ti/sysbios/heaps/HeapMem.h>
66 #include <ti/sysbios/knl/Event.h>
67 #if defined (SUBSYS_DSS)
68 #include <ti/sysbios/family/c64p/Hwi.h>
69 #include <ti/sysbios/family/c64p/EventCombiner.h>
70 #endif
71 #define DebugP_ASSERT_ENABLED 1
72 #include <ti/drivers/osal/DebugP.h>
73 #include <assert.h>
74 #include <ti/common/sys_common.h>
75 #include <ti/drivers/osal/SemaphoreP.h>
76 #include <ti/drivers/edma/edma.h>
77 #include <ti/drivers/esm/esm.h>
78 #include <ti/drivers/soc/soc.h>
79 #include <ti/utils/cycleprofiler/cycle_profiler.h>
80 
81 #include <ti/alg/mmwavelib/mmwavelib.h>
82 /* C64P dsplib (fixed point part for C674X) */
83 #include "gen_twiddle_fft32x32.h"
84 #include "gen_twiddle_fft16x16.h"
85 #include "DSP_fft32x32.h"
86 #include "DSP_fft16x16.h"
87 
88 /* C674x mathlib */
89 /* Suppress the mathlib.h warnings
90  * #48-D: incompatible redefinition of macro "TRUE"
91  * #48-D: incompatible redefinition of macro "FALSE"
92  */
93 #pragma diag_push
94 #pragma diag_suppress 48
95 #include <ti/mathlib/mathlib.h>
96 #pragma diag_pop
97 
98 #include <common/app_cfg.h>
99 #include "dss_data_path.h"
100 #include "dss_config_edma_util.h"
101 
102 /* Clustering library */
103 #include "clusteringDBscan.h"
104 
105 /* Tracking library */
106 #include "EKF_XYZ_Interface.h"
107 #include "common/mmWave_XSS.h"
108 
109 #define ROUND(x) ((x) < 0 ? ((x) - 0.5) : ((x) + 0.5) )
110 
111 #define SOC_XWR18XX_DSS_L3RAM_SIZE 0x100000
112 
113 #define MMW_ADCBUF_SIZE 0x4000U
114 
117 #define MMW_L2_HEAP_SIZE 0x19000U
118 
121 #define MMW_L1_HEAP_SIZE 0x4000U
122 
124 #pragma DATA_SECTION(gMmwL3, ".l3data");
125 #pragma DATA_ALIGN(gMmwL3, 8);
127 
129 #pragma DATA_SECTION(gMmwL2, ".l2data");
130 #pragma DATA_ALIGN(gMmwL2, 8);
132 
134 #pragma DATA_SECTION(gMmwL1, ".l1data");
135 #pragma DATA_ALIGN(gMmwL1, 8);
137 
140 #define FFT_WINDOW_INT16 0
141 
142 #define FFT_WINDOW_INT32 1
143 
144 /* FFT Window */
146 #define MMW_WIN_HAMMING 0
147 
148 #define MMW_WIN_BLACKMAN 1
149 
150 #define MMW_WIN_RECT 2
151 
152 #define MMW_WIN_HANNING_RECT 3
153 
154 #define ROUNDF(x)((x) < 0 ? ((x) - 0.5f) : ((x) + 0.5f) )
155 /* Main control structure. */
156 extern MCB gMCB;
157 /* Local defines. */
158 #define pingPongId(x) ((x) & 0x1U)
159 #define isPong(x) (pingPongId(x))
160 
161 void MmwDemo_genWindow(void *win,
162  uint32_t windowDatumType,
163  uint32_t winLen,
164  uint32_t winGenLen,
165  int32_t oneQformat,
166  uint32_t winType);
167 
168 
169 uint32_t findKLargestPeaks(uint16_t * restrict cfarDetObjIndexBuf,
170  uint16_t * restrict cfarDetObjSNR,
171  uint32_t numDetObjPerCfar,
172  uint16_t * restrict sumAbs,
173  uint16_t numBins,
174  uint16_t K);
175 
176 uint32_t pruneToPeaks(uint16_t* restrict cfarDetObjIndexBuf,
177  uint16_t* restrict cfarDetObjSNR,
178  uint32_t numDetObjPerCfar,
179  uint16_t* restrict sumAbs,
180  uint16_t numBins);
181 
182 uint32_t pruneToPeaksOrNeighbourOfPeaks(uint16_t* restrict cfarDetObjIndexBuf,
183  uint16_t* restrict cfarDetObjSNR,
184  uint32_t numDetObjPerCfar,
185  uint16_t* restrict sumAbs,
186  uint16_t numBins);
187 
189  DSS_DataPathObj * restrict obj,
190  uint32_t numDetObjPerCfar,
191  uint16_t dopplerLine,
192  uint32_t numDetObj2D,
193  uint16_t * restrict sumAbsRange);
194 
195 uint32_t findandPopulateDetectedObjects(DSS_DataPathObj * restrict obj, uint32_t numDetObjPerCfar,
196  uint16_t dopplerLine, uint32_t numDetObj2D, uint16_t * restrict sumAbsRange);
197 
198 uint32_t MmwDemo_cfarPeakGrouping(MmwDemo_detectedObjActual* objOut, uint32_t numDetectedObjects,
199  uint16_t* detMatrix, uint32_t numRangeBins, uint32_t numDopplerBins,
200  uint32_t groupInDopplerDirection, uint32_t groupInRangeDirection);
201 
202 uint32_t secondDimFFTandLog2Computation(DSS_DataPathObj *obj, uint16_t * sumAbs,
203  uint16_t checkDetMatrixTx, uint16_t rangeIdx,
204  uint32_t * pingPongIdxPtr);
205 
206 
207 uint32_t cfarCa_SO_dBwrap_withSNR(const uint16_t inp[restrict],
208  uint16_t out[restrict],
209  uint16_t outSNR[restrict],
210  uint32_t len,
211  uint32_t const1, uint32_t const2,
212  uint32_t guardLen, uint32_t noiseLen);
213 uint32_t cfarCadB_SO_withSNR(const uint16_t inp[restrict],
214  uint16_t out[restrict],
215  uint16_t outSNR[restrict], uint32_t len,
216  uint32_t const1, uint32_t const2,
217  uint32_t guardLen, uint32_t noiseLen,
218  uint32_t minIndxToIgnoreHPF);
219 
220 uint32_t aziEleProcessing(DSS_DataPathObj *obj, uint32_t subframeIndx);
221 
222 uint16_t computeSinAzimSNR(float * azimuthMagSqr, uint16_t azimIdx, uint16_t numVirtualAntAzim, uint16_t numAngleBins, uint16_t xyzOutputQFormat);
223 
224 float antilog2(int32_t inputActual, uint16_t fracBitIn);
225 
226 void associateClustering(clusteringDBscanOutput_t * restrict output,
227  clusteringDBscanReport_t * restrict state,
228  uint16_t maxNumTrackers,
229  int32_t epsilon2,
230  int32_t vFactor);
231 
233  MmwDemo_objRaw2D_t * restrict objOut,
234  uint32_t numDetectedObjects,
235  uint16_t* detMatrix,
236  uint32_t numRangeBins,
237  uint32_t numDopplerBins);
238 
240 uint32_t pruneTrackingInput(trackingInputReport_t * trackingInput, uint32_t numCluster);
241 float quadraticInterpFltPeakLoc(float * restrict y, int32_t len, int32_t indx);
242 float quadraticInterpLog2ShortPeakLoc(uint16_t * restrict y, int32_t len, int32_t indx, uint16_t fracBitIn);
243 void MmwDemo_XYcalc (DSS_DataPathObj *obj, uint32_t objIndex, uint16_t azimIdx, float * azimuthMagSqr);
244 void MmwDemo_addDopplerCompensation(int32_t dopplerIdx,
245  int32_t numDopplerBins,
246  uint32_t *azimuthModCoefs,
247  uint32_t *azimuthModCoefsThirdBin,
248  uint32_t *azimuthModCoefsTwoThirdBin,
249  int64_t *azimuthIn,
250  uint32_t numAnt,
251  uint32_t numTxAnt,
252  uint16_t txAntIdx);
253 
254 static inline void MmwDemo_rxChanPhaseBiasCompensation(uint32_t *rxChComp,
255  int64_t *input,
256  uint32_t numAnt);
257 
258 extern volatile cycleLog_t gCycleLog;
259 
266 uint8_t select_channel(uint8_t subframeIndx,
267  uint8_t pingPongId,
268  uint8_t option0ping,
269  uint8_t option0pong)
270 {
271  uint8_t chId;
272  if (pingPongId == 0)
273  {
274  if (subframeIndx == 0)
275  {
276  chId = option0ping;
277  } /*
278  else
279  {
280  chId = option1ping;
281  } */
282  }
283  else
284  {
285  if (subframeIndx == 0)
286  {
287  chId = option0pong;
288  }
289  /* else
290  {
291  chId = option1pong;
292  } */
293  }
294  return chId;
295 }
296 
303 void MmwDemo_startDmaTransfer(EDMA_Handle handle, uint8_t channelId0, uint8_t subframeIndx)
304 {
305  if (subframeIndx == 0)
306  {
307  EDMA_startDmaTransfer(handle, channelId0);
308  }
309 
310 }
311 
324 {
325  memset((void *)ths->dopplerLineMask, 0, ths->dopplerLineMaskLen * sizeof(uint32_t));
326  ths->currentIndex = 0;
327 }
328 
336 void MmwDemo_setDopplerLine(MmwDemo_1D_DopplerLines_t * ths, uint16_t dopplerIndex)
337 {
338  uint32_t word = dopplerIndex >> 5;
339  uint32_t bit = dopplerIndex & 31;
340 
341  ths->dopplerLineMask[word] |= (0x1 << bit);
342 }
343 
353 {
354  uint32_t dopplerLineStat;
355  uint32_t word = index >> 5;
356  uint32_t bit = index & 31;
357 
358  if (ths->dopplerLineMask[word] & (0x1 << bit))
359  {
360  dopplerLineStat = 1;
361  }
362  else
363  {
364  dopplerLineStat = 0;
365  }
366  return dopplerLineStat;
367 }
368 
378 {
379  uint32_t index = ths->currentIndex;
380  uint32_t word = index >> 5;
381  uint32_t bit = index & 31;
382 
383  while (((ths->dopplerLineMask[word] >> bit) & 0x1) == 0)
384  {
385  index++;
386  bit++;
387  if (bit == 32)
388  {
389  word++;
390  bit = 0;
391 
392  }
393  }
394  ths->currentIndex = index + 1;
395  return index;
396 }
397 
398 
404 uint32_t MmwDemo_pow2roundup(uint32_t x)
405 {
406  uint32_t result = 1;
407  while (x > result)
408  {
409  result <<= 1;
410  }
411  return result;
412 }
413 
431 void MmwDemo_XYestimation(DSS_DataPathObj *obj, uint32_t objIndex)
432 {
433  uint32_t i;
434  float *azimuthMagSqr = obj->azimuthMagSqr;
435  uint32_t xyzOutputQFormat = obj->xyzOutputQFormat;
436  uint32_t oneQFormat = (1 << xyzOutputQFormat);
437  uint32_t numAngleBins = obj->numAngleBins;
438  uint32_t numSearchBins;
439  uint16_t azimIdx = 0;
440  float maxVal = 0;
441 
443  {
444  numSearchBins = numAngleBins*2;
445  }
446  else
447  {
448  numSearchBins = numAngleBins;
449  }
450 
451  /* Find peak position - search in original and flipped output */
452  for (i = 0; i < numSearchBins ; i++)
453  {
454  if (azimuthMagSqr[i] > maxVal)
455  {
456  azimIdx = i;
457  maxVal = azimuthMagSqr[i];
458  }
459  }
460 
462  {
463  if(azimIdx >= numAngleBins)
464  {
465  /* Velocity aliased: |velocity| > Vmax */
466  /* Correct peak index: */
467  azimIdx -= numAngleBins;
468 
469  /* Use the second azimuthMagSqr array for further computation. */
470  azimuthMagSqr += numAngleBins;
471 
472  /* Correct velocity */
473  if (obj->detObj2D[objIndex].speed < 0)
474  {
475  obj->detObj2D[objIndex].speed += (int16_t) (2 * obj->maxUnambiguousVel * (float)oneQFormat);
476  }
477  else
478  {
479  obj->detObj2D[objIndex].speed -= (int16_t) (2 * obj->maxUnambiguousVel * (float)oneQFormat);
480  }
481  }
482  }
483 
484  MmwDemo_XYcalc (obj, objIndex, azimIdx, azimuthMagSqr);
485 
486  /* Check for second peak. */
488  {
489  uint32_t leftSearchIdx;
490  uint32_t rightSearchIdx;
491  uint32_t secondSearchLen;
492  uint32_t iModAzimLen;
493  float maxVal2;
494  int32_t k;
495 
496  /* Find right edge of the first peak. */
497  i = azimIdx;
498  leftSearchIdx = (i + 1) & (numAngleBins - 1);
499  k = numAngleBins;
500  while ((azimuthMagSqr[i] >= azimuthMagSqr[leftSearchIdx]) && (k > 0))
501  {
502  i = (i + 1) & (numAngleBins - 1);
503  leftSearchIdx = (leftSearchIdx + 1) & (numAngleBins - 1);
504  k--;
505  }
506 
507  /* Find left edge of the first peak. */
508  i = azimIdx;
509  rightSearchIdx = (i - 1) & (numAngleBins - 1);
510  k = numAngleBins;
511  while ((azimuthMagSqr[i] >= azimuthMagSqr[rightSearchIdx]) && (k > 0))
512  {
513  i = (i - 1) & (numAngleBins - 1);
514  rightSearchIdx = (rightSearchIdx - 1) & (numAngleBins - 1);
515  k--;
516  }
517 
518  secondSearchLen = ((rightSearchIdx - leftSearchIdx) & (numAngleBins - 1)) + 1;
519  /* Find second peak. */
520  maxVal2 = azimuthMagSqr[leftSearchIdx];
521  azimIdx = leftSearchIdx;
522  for (i = leftSearchIdx; i < (leftSearchIdx + secondSearchLen); i++)
523  {
524  iModAzimLen = i & (numAngleBins - 1);
525  if (azimuthMagSqr[iModAzimLen] > maxVal2)
526  {
527  azimIdx = iModAzimLen;
528  maxVal2 = azimuthMagSqr[iModAzimLen];
529  }
530  }
531 
532  /* Is second peak greater than threshold? */
533  if (maxVal2 > (maxVal * obj->multiObjBeamFormingCfg.multiPeakThrsScal) && (obj->numDetObj < MRR_MAX_OBJ_OUT))
534  {
535  /* Second peak detected! Add it to the end of the list. */
536  obj->detObj2D[obj->numDetObj] = obj->detObj2D[objIndex];
537  objIndex = obj->numDetObj;
538  obj->numDetObj++;
539 
540  MmwDemo_XYcalc (obj, objIndex, azimIdx, azimuthMagSqr);
541  }
542  }
543 }
544 
545 
563 void MmwDemo_XYZestimation(DSS_DataPathObj *obj, uint32_t objIndex)
564 {
565  uint32_t i;
566  float *azimuthMagSqr = obj->azimuthMagSqr;
567  uint32_t xyzOutputQFormat = obj->xyzOutputQFormat;
568  uint32_t oneQFormat = (1 << xyzOutputQFormat);
569  uint32_t numAngleBins = obj->numAngleBins;
570  uint32_t numSearchBins;
571  uint16_t azimIdx = 0;
572  float maxVal = 0;
573 
575  {
577  {
578  numSearchBins = numAngleBins*2;
579  }
580  else
581  {
582  numSearchBins = numAngleBins;
583  }
584  }
585  else
586  {
587  numSearchBins = numAngleBins;
588  }
589  /* Find peak position - search in original and flipped output */
590  for (i = 0; i < numSearchBins ; i++)
591  {
592  if (azimuthMagSqr[i] > maxVal)
593  {
594  azimIdx = i;
595  maxVal = azimuthMagSqr[i];
596  }
597  }
598 
600  {
602  {
603 
604  if(azimIdx >= numAngleBins)
605  {
606  /* Velocity aliased: |velocity| > Vmax */
607  /* Correct peak index: */
608  azimIdx -= numAngleBins;
609 
610  /* Use the second azimuthMagSqr array for further computation. */
611  azimuthMagSqr += numAngleBins;
612 
613  /* Correct velocity */
614  if (obj->detObj2D[objIndex].speed < 0)
615  {
616  obj->detObj2D[objIndex].speed += (int16_t) (2 * obj->maxUnambiguousVel * (float)oneQFormat);
617  }
618  else
619  {
620  obj->detObj2D[objIndex].speed -= (int16_t) (2 * obj->maxUnambiguousVel * (float)oneQFormat);
621  }
622  }
623  }
624  }
625 
626 
627  MmwDemo_XYZcalc (obj, objIndex, azimIdx, azimuthMagSqr);
628 
629  /* Check for second peak. */
630 
632  {
633  uint32_t leftSearchIdx;
634  uint32_t rightSearchIdx;
635  uint32_t secondSearchLen;
636  uint32_t iModAzimLen;
637  float maxVal2;
638  int32_t k;
639 
640  /* Find right edge of the first peak. */
641  i = azimIdx;
642  leftSearchIdx = (i + 1) & (numAngleBins - 1);
643  k = numAngleBins;
644  while ((azimuthMagSqr[i] >= azimuthMagSqr[leftSearchIdx]) && (k > 0))
645  {
646  i = (i + 1) & (numAngleBins - 1);
647  leftSearchIdx = (leftSearchIdx + 1) & (numAngleBins - 1);
648  k--;
649  }
650 
651  /* Find left edge of the first peak. */
652  i = azimIdx;
653  rightSearchIdx = (i - 1) & (numAngleBins - 1);
654  k = numAngleBins;
655  while ((azimuthMagSqr[i] >= azimuthMagSqr[rightSearchIdx]) && (k > 0))
656  {
657  i = (i - 1) & (numAngleBins - 1);
658  rightSearchIdx = (rightSearchIdx - 1) & (numAngleBins - 1);
659  k--;
660  }
661 
662  secondSearchLen = ((rightSearchIdx - leftSearchIdx) & (numAngleBins - 1)) + 1;
663  /* Find second peak. */
664  maxVal2 = azimuthMagSqr[leftSearchIdx];
665  azimIdx = leftSearchIdx;
666  for (i = leftSearchIdx; i < (leftSearchIdx + secondSearchLen); i++)
667  {
668  iModAzimLen = i & (numAngleBins - 1);
669  if (azimuthMagSqr[iModAzimLen] > maxVal2)
670  {
671  azimIdx = iModAzimLen;
672  maxVal2 = azimuthMagSqr[iModAzimLen];
673  }
674  }
675 
676  /* Is second peak greater than threshold? */
677  if (maxVal2 > (maxVal * obj->multiObjBeamFormingCfg.multiPeakThrsScal) && (obj->numDetObj < MRR_MAX_OBJ_OUT))
678  {
679  /* Second peak detected! Add it to the end of the list. */
680  obj->detObj2D[obj->numDetObj] = obj->detObj2D[objIndex];
681  objIndex = obj->numDetObj;
682  obj->numDetObj++;
683 
684  MmwDemo_XYZcalc (obj, objIndex, azimIdx, azimuthMagSqr);
685  }
686  }
687 
688 }
689 
703 void MmwDemo_dataPathWait1DInputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
704 {
705  /* wait until transfer done */
706  volatile bool isTransferDone;
707  uint8_t chId;
708  if (pingPongId == 0)
709  {
710  if (subframeIndx == 0)
711  {
713  } /*
714  else
715  {
716  chId = MRR_SF1_EDMA_CH_1D_IN_PING;
717  }*/
718  }
719  else
720  {
721 
722  if (subframeIndx == 0)
723  {
725  }
726  /* else
727  {
728  chId = MRR_SF1_EDMA_CH_1D_IN_PONG;
729  } */
730 
731  }
732  do {
733  if (EDMA_isTransferComplete(obj->edmaHandle[EDMA_INSTANCE_DSS],
734  chId,
735  (bool *)&isTransferDone) != EDMA_NO_ERROR)
736  {
738  }
739  } while (isTransferDone == false);
740 }
741 
755 void MmwDemo_dataPathWait1DOutputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
756 {
757  volatile bool isTransferDone;
758  /* select the right EDMA channel based on the subframeIndx, and the pinPongId. */
759  uint8_t chId = select_channel(subframeIndx, pingPongId, \
761 
762  /* wait until transfer done */
763  do {
764  if (EDMA_isTransferComplete(obj->edmaHandle[EDMA_INSTANCE_DSS],
765  chId,
766  (bool *)&isTransferDone) != EDMA_NO_ERROR)
767  {
769  }
770  } while (isTransferDone == false);
771 }
772 
786 void MmwDemo_dataPathWait2DInputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
787 {
788  volatile bool isTransferDone;
789 
790  /* select the right EDMA channel based on the subframeIndx, and the pinPongId. */
791  uint8_t chId = select_channel(subframeIndx, pingPongId, \
793 
794  /* wait until transfer done */
795  do {
796  if (EDMA_isTransferComplete(obj->edmaHandle[EDMA_INSTANCE_DSS],
797  chId,
798  (bool *)&isTransferDone) != EDMA_NO_ERROR)
799  {
801  }
802  } while (isTransferDone == false);
803 }
804 
818 void MmwDemo_dataPathWait3DInputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
819 {
820  /* wait until transfer done */
821  volatile bool isTransferDone;
822  uint8_t chId = select_channel(subframeIndx, pingPongId, \
824  do
825  {
826  if (EDMA_isTransferComplete(obj->edmaHandle[EDMA_INSTANCE_DSS],
827  chId,
828  (bool *)&isTransferDone) != EDMA_NO_ERROR)
829  {
831  }
832  } while (isTransferDone == false);
833 }
834 
848 void MmwDemo_dataPathWaitTransDetMatrix(DSS_DataPathObj *obj, uint8_t subframeIndx)
849 {
850  volatile bool isTransferDone;
851  uint8_t chId;
852  if (subframeIndx == 0)
853  {
855  }
856  /* else
857  {
858  chId = MRR_SF1_EDMA_CH_DET_MATRIX;
859  } */
860 
861  do
862  {
863  if (EDMA_isTransferComplete(obj->edmaHandle[EDMA_INSTANCE_DSS],
864  (uint8_t)chId,
865  (bool *)&isTransferDone) != EDMA_NO_ERROR)
866  {
868  }
869  } while (isTransferDone == false);
870 }
871 
885 void MmwDemo_dataPathWaitTransDetMatrix2(DSS_DataPathObj *obj, uint32_t subframeIndx)
886 {
887 
888  /* wait until transfer done */
889  volatile bool isTransferDone;
890  uint8_t chId;
891  if (subframeIndx == 0)
892  {
894  }
895 
896  /*else
897  {
898  chId = MRR_SF1_EDMA_CH_DET_MATRIX2;
899  } */
900 
901  do
902  {
903  if (EDMA_isTransferComplete(obj->edmaHandle[EDMA_INSTANCE_DSS],
904  (uint8_t)chId,
905  (bool *)&isTransferDone) != EDMA_NO_ERROR)
906  {
908  }
909  } while (isTransferDone == false);
910 }
911 
937 {
938  uint32_t eventQueue;
939  uint16_t shadowParam = EDMA_NUM_DMA_CHANNELS;
940  int32_t retVal = 0;
941  uint8_t chId;
942  uint8_t subframeIndx;
943  uint32_t numChirpTypes = 1;
944  uint32_t ADCBufferoffset = (32 * 1024)/4;
945 
946  for (subframeIndx = 0; subframeIndx < NUM_SUBFRAMES; subframeIndx++, obj++)
947  {
948 
949 
950  numChirpTypes = 1;
952  {
953  numChirpTypes = 2;
954  }
955 
956  /*****************************************************
957  * EDMA configuration for getting ADC data from ADC buffer
958  * to L2 (prior to 1D FFT)
959  * For ADC Buffer to L2 use EDMA-A TPTC =1
960  *****************************************************/
961  eventQueue = 0U;
962 
963  /* Ping - copies chirp samples from even antenna numbers (e.g. RxAnt0 and RxAnt2) */
964 
965  if (subframeIndx == 0)
966  {
968  }
969  /* else
970  {
971  chId = MRR_SF1_EDMA_CH_1D_IN_PING;
972  }
973  */
974 
975  retVal =
977  (uint8_t *)(&obj->ADCdataBuf[0]),
978  (uint8_t *)(SOC_translateAddress((uint32_t)&obj->adcDataIn[0], SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
979  chId,
980  false,
981  shadowParam++,
983  MAX(obj->numRxAntennas / 2, 1),
984  ADCBufferoffset * 2,
985  0,
986  eventQueue,
987  NULL,
988  (uintptr_t)obj);
989  if (retVal < 0)
990  {
991  return -1;
992  }
993 
994  if (subframeIndx == 0)
995  {
997  }
998  /* else
999  {
1000  chId = MRR_SF1_EDMA_CH_1D_IN_PONG;
1001  } */
1002 
1003  /* Pong - copies chirp samples from odd antenna numbers (e.g. RxAnt1 and RxAnt3)
1004  * Note that ADCBufferoffset is in bytes, but ADCdataBuf is in cmplx16ReIm_t.
1005  * There are four bytes in one cmplx16ReIm_t*/
1006  retVal =
1007  EDMAutil_configType1(obj->edmaHandle[EDMA_INSTANCE_DSS],
1008  (uint8_t *)(&obj->ADCdataBuf[(ADCBufferoffset>>2)]),
1009  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->adcDataIn[obj->numRangeBins]), SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1010  chId,
1011  false,
1012  shadowParam++,
1013  obj->numAdcSamples * BYTES_PER_SAMP_1D,
1014  MAX(obj->numRxAntennas / 2, 1),
1015  ADCBufferoffset * 2,
1016  0,
1017  eventQueue,
1018  NULL,
1019  (uintptr_t)obj);
1020  if (retVal < 0)
1021  {
1022  return -1;
1023  }
1024 
1025  /* using different event queue between input and output to parallelize better */
1026  eventQueue = 1U;
1027  /*
1028  * EDMA configuration for storing 1d fft output in transposed manner to L3.
1029  * It copies all Rx antennas of the chirp per trigger event.
1030  */
1031 
1032 
1033  /* Ping - Copies from ping FFT output (even chirp indices) to L3 */
1034  if (subframeIndx == 0)
1035  {
1037  }
1038  /*else
1039  {
1040  chId = MRR_SF1_EDMA_CH_1D_OUT_PING;
1041  }*/
1042 
1043 
1044  retVal =
1045  EDMAutil_configType2a(obj->edmaHandle[EDMA_INSTANCE_DSS],
1046  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->fftOut1D[0]), SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1047  (uint8_t *)(&obj->radarCube[0]),
1048  chId,
1049  false,
1050  shadowParam++,
1052  obj->numRangeBins,
1053  obj->numTxAntennas * numChirpTypes,
1054  obj->numRxAntennas,
1055  obj->numDopplerBins,
1056  eventQueue,
1057  NULL,
1058  (uintptr_t)obj);
1059  if (retVal < 0)
1060  {
1061  return -1;
1062  }
1063 
1064  /* Ping - Copies from pong FFT output (odd chirp indices) to L3 */
1065  if (subframeIndx == 0)
1066  {
1068  }
1069  /*else
1070  {
1071  chId = MRR_SF1_EDMA_CH_1D_OUT_PONG;
1072  }*/
1073 
1074  retVal =
1075  EDMAutil_configType2a(obj->edmaHandle[EDMA_INSTANCE_DSS],
1076  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->fftOut1D[obj->numRxAntennas * obj->numRangeBins]),
1077  SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1078  (uint8_t *)(&obj->radarCube[0]),
1079  chId,
1080  false,
1081  shadowParam++,
1083  obj->numRangeBins,
1084  obj->numTxAntennas * numChirpTypes,
1085  obj->numRxAntennas,
1086  obj->numDopplerBins,
1087  eventQueue,
1088  NULL,
1089  (uintptr_t)obj);
1090  if (retVal < 0)
1091  {
1092  return -1;
1093  }
1094 
1095 
1096  /*****************************************
1097  * Interframe processing related EDMA configuration
1098  *****************************************/
1099  eventQueue = 0U;
1100 
1101  /* For the max-vel enh implementation, we pull out twice as much range-gates per range bin.
1102  * Hence EDMA BCNT is multiplied by 2. */
1103 
1104  /* Ping: This DMA channel is programmed to fetch the 1D FFT data from radarCube
1105  * matrix in L3 mem of even antenna rows into the Ping Buffer in L2 mem*/
1106  if (subframeIndx == 0)
1107  {
1109  }
1110  /*else
1111  {
1112  chId = MRR_SF1_EDMA_CH_2D_IN_PING;
1113  }*/
1114 
1115  retVal =
1116  EDMAutil_configType1(obj->edmaHandle[EDMA_INSTANCE_DSS],
1117  (uint8_t *)(&obj->radarCube[0]),
1118  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->dstPingPong[0]), SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1119  chId,
1120  false,
1121  shadowParam++,
1122  obj->numDopplerBins * BYTES_PER_SAMP_1D,
1123  (obj->numRangeBins * obj->numRxAntennas * obj->numTxAntennas * numChirpTypes) / 2,
1124  obj->numDopplerBins * BYTES_PER_SAMP_1D * 2,
1125  0,
1126  eventQueue,
1127  NULL,
1128  (uintptr_t)obj);
1129  if (retVal < 0)
1130  {
1131  return -1;
1132  }
1133 
1134  /* Pong: This DMA channel is programmed to fetch the 1D FFT data from radarCube
1135  * matrix in L3 mem of odd antenna rows into thePong Buffer in L2 mem*/
1136  if (subframeIndx == 0)
1137  {
1139  }
1140 /* else
1141  {
1142  chId = MRR_SF1_EDMA_CH_2D_IN_PONG;
1143  } */
1144 
1145  retVal =
1146  EDMAutil_configType1(obj->edmaHandle[EDMA_INSTANCE_DSS],
1147  (uint8_t *)(&obj->radarCube[obj->numDopplerBins]),
1148  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->dstPingPong[obj->numDopplerBins]),
1149  SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1150  chId,
1151  false,
1152  shadowParam++,
1153  obj->numDopplerBins * BYTES_PER_SAMP_1D,
1154  (obj->numRangeBins * obj->numRxAntennas * obj->numTxAntennas * numChirpTypes) / 2,
1155  obj->numDopplerBins * BYTES_PER_SAMP_1D * 2,
1156  0,
1157  eventQueue,
1158  NULL,
1159  (uintptr_t)obj);
1160  if (retVal < 0)
1161  {
1162  return -1;
1163  }
1164 
1165  eventQueue = 1U;
1166  /* This EDMA channel copies the sum (across virtual antennas) of log2
1167  * magnitude squared of Doppler FFT bins from L2 mem to detection
1168  * matrix in L3 mem. */
1169  if (subframeIndx == 0)
1170  {
1172  }
1173  /*else
1174  {
1175  chId = MRR_SF1_EDMA_CH_DET_MATRIX;
1176  }*/
1177 
1178  retVal =
1179  EDMAutil_configType1(obj->edmaHandle[EDMA_INSTANCE_DSS],
1180  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->sumAbs[0U]), SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1181  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->detMatrix[0U]), SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1182  /* (uint8_t *)(obj->detMatrix),*/
1183  chId,
1184  false,
1185  shadowParam++,
1186  obj->numDopplerBins * BYTES_PER_SAMP_DET,
1187  obj->numRangeBins,
1188  0,
1189  obj->numDopplerBins * BYTES_PER_SAMP_DET,
1190  eventQueue,
1191  NULL,
1192  (uintptr_t)obj);
1193  if (retVal < 0)
1194  {
1195  return -1;
1196  }
1197 
1198  /* This EDMA Channel brings selected range bins from detection matrix in
1199  * L3 mem (reading in transposed manner) into L2 mem for CFAR detection (in
1200  * range direction). */
1201  if (subframeIndx == 0)
1202  {
1204  }
1205 /* else
1206  {
1207  chId = MRR_SF1_EDMA_CH_DET_MATRIX2;
1208  } */
1209 
1210  retVal =
1211  EDMAutil_configType3(obj->edmaHandle[EDMA_INSTANCE_DSS],
1212  (uint8_t *)0,
1213  (uint8_t *)0,
1214  chId,
1215  false,
1216  shadowParam++,
1218  obj->numRangeBins,
1219  (obj->numDopplerBins * BYTES_PER_SAMP_DET),
1221  eventQueue,
1222  NULL,
1223  (uintptr_t)obj);
1224  if (retVal < 0)
1225  {
1226  return -1;
1227  }
1228 
1229  /*********************************************************
1230  * These EDMA Channels are for Azimuth calculation. They bring
1231  * 1D FFT data for 2D DFT and Azimuth FFT calculation.
1232  ********************************************************/
1233  /* Ping: This DMA channel is programmed to fetch the 1D FFT data from radarCube
1234  * matrix in L3 mem of even antenna rows into the Ping Buffer in L2 mem.
1235  */
1236  if (subframeIndx == 0)
1237  {
1239  }
1240 /* else
1241  {
1242  chId = MRR_SF1_EDMA_CH_3D_IN_PING;
1243  } */
1244 
1245  retVal =
1246  EDMAutil_configType1(obj->edmaHandle[EDMA_INSTANCE_DSS],
1247  (uint8_t *)NULL,
1248  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->dstPingPong[0]), SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1249  chId,
1250  false,
1251  shadowParam++,
1252  obj->numDopplerBins * BYTES_PER_SAMP_1D,
1253  MAX((obj->numRxAntennas * obj->numTxAntennas) / 2, 1),
1254  (obj->numDopplerBins * BYTES_PER_SAMP_1D * 2),
1255  0,
1256  eventQueue,
1257  NULL,
1258  (uintptr_t)obj);
1259  if (retVal < 0)
1260  {
1261  return -1;
1262  }
1263 
1264  /* Pong: This DMA channel is programmed to fetch the 1D FFT data from radarCube
1265  * matrix in L3 mem of odd antenna rows into the Pong Buffer in L2 mem*/
1266  if (subframeIndx == 0)
1267  {
1269  }
1270  /* else
1271  {
1272  chId = MRR_SF1_EDMA_CH_3D_IN_PONG;
1273  } */
1274 
1275  retVal =
1276  EDMAutil_configType1(obj->edmaHandle[EDMA_INSTANCE_DSS],
1277  (uint8_t *)NULL,
1278  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->dstPingPong[obj->numDopplerBins]), SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1279  chId,
1280  false,
1281  shadowParam++,
1282  obj->numDopplerBins * BYTES_PER_SAMP_1D,
1283  MAX((obj->numRxAntennas * obj->numTxAntennas) / 2, 1),
1284  obj->numDopplerBins * BYTES_PER_SAMP_1D * 2,
1285  0,
1286  eventQueue,
1287  NULL,
1288  (uintptr_t)obj);
1289  if (retVal < 0)
1290  {
1291  return -1;
1292  }
1293 
1294  }
1295 
1296  return(0);
1297 }
1298 
1320 uint32_t rangeBasedPruning(
1321  MmwDemo_detectedObjActual* restrict objOut,
1322  MmwDemo_objRaw2D_t * restrict objRaw,
1323  RangeDependantThresh_t * restrict SNRThresh,
1324  RangeDependantThresh_t * restrict peakValThresh,
1325  uint32_t numDetectedObjects,
1326  uint32_t numDopplerBins,
1327  uint32_t maxRange,
1328  uint32_t minRange)
1329 {
1330  int32_t i, j, k;
1331  uint32_t numObjOut = 0;
1332  uint32_t searchSNRThresh = 0;
1333  uint32_t searchpeakValThresh = 0;
1334  j = 0;
1335  k = 0;
1336  /* No grouping, copy all detected objects to the output matrix within specified min max range
1337  * with the necessary SNR. */
1338  for (i = 0; i < numDetectedObjects; i++)
1339  {
1340  if ((objRaw[i].range <= maxRange) && ((objRaw[i].range >= minRange)))
1341  {
1342  /* We change the SNR requirement as a function of the range, requiring larger
1343  * SNR for objects closer to the car, and lower SNR for objects farther from
1344  * the car. */
1345  searchSNRThresh = 0;
1346 
1347  /* Check if the range (of the target) lies between SNRThresh[j].rangelim and
1348  * SNRThresh[j-1].rangelim. If it doesn't search for a new SNR threshold. */
1349  if (objRaw[i].range > SNRThresh[j].rangelim)
1350  {
1351  searchSNRThresh = 1;
1352  }
1353  else if (j > 0)
1354  {
1355  if (objRaw[i].range < SNRThresh[j-1].rangelim)
1356  {
1357  searchSNRThresh = 1;
1358  }
1359  }
1360 
1361  if (searchSNRThresh == 1)
1362  {
1363  /* MAX_NUM_SNR_THRESH_LIM is typically 3; A linear search should be fine */
1364  for (j = 0; j < MAX_NUM_RANGE_DEPENDANT_SNR_THRESHOLDS - 1; j++)
1365  {
1366  if (objRaw[i].range < SNRThresh[j].rangelim)
1367  {
1368  break;
1369  }
1370  }
1371  }
1372 
1373  /* Ditto for the peakValThresh. */
1374  searchpeakValThresh = 0;
1375 
1376  if (objRaw[i].range > peakValThresh[k].rangelim)
1377  {
1378  searchpeakValThresh = 1;
1379  }
1380  else if (k > 0)
1381  {
1382  if (objRaw[i].range < peakValThresh[k-1].rangelim)
1383  {
1384  searchpeakValThresh = 1;
1385  }
1386  }
1387 
1388  if (searchpeakValThresh == 1)
1389  {
1390  for (k = 0; k < MAX_NUM_RANGE_DEPENDANT_SNR_THRESHOLDS - 1; k++)
1391  {
1392  if (objRaw[i].range < peakValThresh[k].rangelim)
1393  {
1394  break;
1395  }
1396  }
1397  }
1398 
1399 
1400  if ( (objRaw[i].rangeSNRdB > SNRThresh[j].threshold) &&
1401  (objRaw[i].peakVal > peakValThresh[k].threshold) )
1402  {
1403  objOut[numObjOut].rangeIdx = objRaw[i].rangeIdx;
1404  objOut[numObjOut].dopplerIdx = objRaw[i].dopplerIdx;
1405  objOut[numObjOut].range = objRaw[i].range;
1406  objOut[numObjOut].speed = objRaw[i].speed;
1407  objOut[numObjOut].peakVal = objRaw[i].peakVal;
1408  objOut[numObjOut].rangeSNRdB = objRaw[i].rangeSNRdB;
1409  objOut[numObjOut].dopplerSNRdB = objRaw[i].dopplerSNRdB;
1410  numObjOut++;
1411 
1412  if (numObjOut == MRR_MAX_OBJ_OUT)
1413  {
1414  break;
1415  }
1416  }
1417 
1418  }
1419  }
1420  return numObjOut;
1421 }
1422 
1431 void MmwDemo_magnitudeSquared(cmplx32ReIm_t * restrict inpBuff, float * restrict magSqrdBuff, uint32_t numSamples)
1432 {
1433  uint32_t i;
1434  for (i = 0; i < numSamples; i++)
1435  {
1436  magSqrdBuff[i] = (float)inpBuff[i].real * (float)inpBuff[i].real +
1437  (float)inpBuff[i].imag * (float)inpBuff[i].imag;
1438  }
1439 }
1440 
1450 void MmwDemo_dcRangeSignatureCompensation(DSS_DataPathObj *obj, uint8_t chirpPingPongId)
1451 {
1452  uint32_t rxAntIdx, binIdx;
1453  uint32_t ind;
1454  int32_t chirpPingPongOffs;
1455  int32_t chirpPingPongSize;
1456 
1457  chirpPingPongSize = obj->numRxAntennas * (obj->calibDcRangeSigCfg.positiveBinIdx - obj->calibDcRangeSigCfg.negativeBinIdx + 1);
1458  if (obj->dcRangeSigCalibCntr == 0)
1459  {
1460  memset(obj->dcRangeSigMean, 0, obj->numTxAntennas * chirpPingPongSize * sizeof(cmplx32ImRe_t));
1461  }
1462 
1463  chirpPingPongOffs = chirpPingPongId * chirpPingPongSize;
1464 
1465  /* Calibration */
1467  {
1468  /* Accumulate */
1469  ind = 0;
1470  for (rxAntIdx = 0; rxAntIdx < obj->numRxAntennas; rxAntIdx++)
1471  {
1472  uint32_t chirpInOffs = chirpPingPongId * (obj->numRxAntennas * obj->numRangeBins) + (obj->numRangeBins * rxAntIdx);
1473  int64_t *meanPtr = (int64_t *)&obj->dcRangeSigMean[chirpPingPongOffs];
1474  uint32_t *fftPtr = (uint32_t *)&obj->fftOut1D[chirpInOffs];
1475  int64_t meanBin;
1476  uint32_t fftBin;
1477  int32_t Re, Im;
1478 
1479  for (binIdx = 0; binIdx <= obj->calibDcRangeSigCfg.positiveBinIdx; binIdx++)
1480  {
1481  meanBin = _amem8(&meanPtr[ind]);
1482  fftBin = _amem4(&fftPtr[binIdx]);
1483  Im = _loll(meanBin) + _ext(fftBin, 0, 16);
1484  Re = _hill(meanBin) + _ext(fftBin, 16, 16);
1485  _amem8(&meanPtr[ind]) = _itoll(Re, Im);
1486  ind++;
1487  }
1488 
1489  chirpInOffs = chirpPingPongId * (obj->numRxAntennas * obj->numRangeBins) + (obj->numRangeBins * rxAntIdx) + obj->numRangeBins + obj->calibDcRangeSigCfg.negativeBinIdx;
1490  fftPtr = (uint32_t *)&obj->fftOut1D[chirpInOffs];
1491  for (binIdx = 0; binIdx < -obj->calibDcRangeSigCfg.negativeBinIdx; binIdx++)
1492  {
1493  meanBin = _amem8(&meanPtr[ind]);
1494  fftBin = _amem4(&fftPtr[binIdx]);
1495  Im = _loll(meanBin) + _ext(fftBin, 0, 16);
1496  Re = _hill(meanBin) + _ext(fftBin, 16, 16);
1497  _amem8(&meanPtr[ind]) = _itoll(Re, Im);
1498  ind++;
1499  }
1500  }
1501  obj->dcRangeSigCalibCntr++;
1502 
1504  {
1505  /* Divide */
1506  int64_t *meanPtr = (int64_t *)obj->dcRangeSigMean;
1507  int32_t Re, Im;
1508  int64_t meanBin;
1509  int32_t divShift = obj->log2NumAvgChirps;
1510  for (ind = 0; ind < (obj->numTxAntennas * chirpPingPongSize); ind++)
1511  {
1512  meanBin = _amem8(&meanPtr[ind]);
1513  Im = _sshvr(_loll(meanBin), divShift);
1514  Re = _sshvr(_hill(meanBin), divShift);
1515  _amem8(&meanPtr[ind]) = _itoll(Re, Im);
1516  }
1517  }
1518  }
1519  else
1520  {
1521  /* fftOut1D -= dcRangeSigMean */
1522  ind = 0;
1523  for (rxAntIdx = 0; rxAntIdx < obj->numRxAntennas; rxAntIdx++)
1524  {
1525  uint32_t chirpInOffs = chirpPingPongId * (obj->numRxAntennas * obj->numRangeBins) + (obj->numRangeBins * rxAntIdx);
1526  int64_t *meanPtr = (int64_t *)&obj->dcRangeSigMean[chirpPingPongOffs];
1527  uint32_t *fftPtr = (uint32_t *)&obj->fftOut1D[chirpInOffs];
1528  int64_t meanBin;
1529  uint32_t fftBin;
1530  int32_t Re, Im;
1531  for (binIdx = 0; binIdx <= obj->calibDcRangeSigCfg.positiveBinIdx; binIdx++)
1532  {
1533  meanBin = _amem8(&meanPtr[ind]);
1534  fftBin = _amem4(&fftPtr[binIdx]);
1535  Im = _ext(fftBin, 0, 16) - _loll(meanBin);
1536  Re = _ext(fftBin, 16, 16) - _hill(meanBin);
1537  _amem4(&fftPtr[binIdx]) = _pack2(Im, Re);
1538  ind++;
1539  }
1540 
1541  chirpInOffs = chirpPingPongId * (obj->numRxAntennas * obj->numRangeBins) + (obj->numRangeBins * rxAntIdx) + obj->numRangeBins + obj->calibDcRangeSigCfg.negativeBinIdx;
1542  fftPtr = (uint32_t *)&obj->fftOut1D[chirpInOffs];
1543  for (binIdx = 0; binIdx < -obj->calibDcRangeSigCfg.negativeBinIdx; binIdx++)
1544  {
1545  meanBin = _amem8(&meanPtr[ind]);
1546  fftBin = _amem4(&fftPtr[binIdx]);
1547  Im = _ext(fftBin, 0, 16) - _loll(meanBin);
1548  Re = _ext(fftBin, 16, 16) - _hill(meanBin);
1549  _amem4(&fftPtr[binIdx]) = _pack2(Im, Re);
1550  ind++;
1551  }
1552  }
1553  }
1554 }
1555 
1565 void MmwDemo_interChirpProcessing(DSS_DataPathObj *obj, uint32_t chirpPingPongId, uint8_t subframeIndx)
1566 {
1567  uint32_t antIndx, waitingTime;
1568  volatile uint32_t startTime;
1569  volatile uint32_t startTime1;
1570 
1571  waitingTime = 0;
1572  startTime = Cycleprofiler_getTimeStamp();
1573 
1574  /* Kick off DMA to fetch data from ADC buffer for first channel */
1577  subframeIndx);
1578 
1579  /* 1d fft for first antenna, followed by kicking off the DMA of fft output */
1580  for (antIndx = 0; antIndx < obj->numRxAntennas; antIndx++)
1581  {
1582  /* kick off DMA to fetch data for next antenna */
1583  if (antIndx < (obj->numRxAntennas - 1))
1584  {
1585  if (isPong(antIndx))
1586  {
1589  subframeIndx);
1590  }
1591  else
1592  {
1595  subframeIndx);
1596  }
1597  }
1598 
1599  /* verify if DMA has completed for current antenna */
1600  startTime1 = Cycleprofiler_getTimeStamp();
1601  MmwDemo_dataPathWait1DInputData(obj, pingPongId(antIndx), subframeIndx);
1602  waitingTime += Cycleprofiler_getTimeStamp() - startTime1;
1603 
1604 
1605  mmwavelib_windowing16x16(
1606  (int16_t *)&obj->adcDataIn[pingPongId(antIndx) * obj->numRangeBins],
1607  (int16_t *)obj->window1D,
1608  obj->numAdcSamples);
1609  memset((void *)&obj->adcDataIn[pingPongId(antIndx) * obj->numRangeBins + obj->numAdcSamples],
1610  0, (obj->numRangeBins - obj->numAdcSamples) * sizeof(cmplx16ReIm_t));
1611 
1612 
1613 
1614  DSP_fft16x16(
1615  (int16_t *)obj->twiddle16x16_1D,
1616  obj->numRangeBins,
1617  (int16_t *)&obj->adcDataIn[pingPongId(antIndx) * obj->numRangeBins],
1618  (int16_t *)&obj->fftOut1D[chirpPingPongId * (obj->numRxAntennas * obj->numRangeBins) +
1619  (obj->numRangeBins * antIndx)]);
1620  }
1621 
1622  gCycleLog.interChirpProcessingTime += Cycleprofiler_getTimeStamp() - startTime - waitingTime;
1623  gCycleLog.interChirpWaitTime += waitingTime;
1624 }
1625 
1636 void MmwDemo_interFrameProcessing(DSS_DataPathObj *obj, uint8_t subframeIndx)
1637 {
1638  uint32_t rangeIdx, detIdx1, numDetObjPerCfar, numDetDopplerLine1D, numDetObj1D, numDetObj2D;
1639  volatile uint32_t startTime;
1640  volatile uint32_t startTimeWait;
1641  uint32_t waitingTime = 0;
1642  uint32_t pingPongIdx = 0;
1643  uint32_t dopplerLine, dopplerLineNext;
1644  startTime = Cycleprofiler_getTimeStamp();
1645 
1646  /* Trigger first DMA (Ping) to bring the 1DFFT data out of L3 to dstPingPong buffer */
1649  subframeIndx);
1650 
1651  /* Initialize the variable that keeps track of the number of objects detected */
1652  numDetDopplerLine1D = 0;
1653  numDetObj1D = 0;
1655 
1656  for (rangeIdx = 0; rangeIdx < obj->numRangeBins; rangeIdx++)
1657  {
1658 
1659 
1660  /* Perform the 2nd dimension FFT (doppler-FFT), compute the log2Abs, and provide the
1661  * noncoherently added sum of the log2Abs across antennas as the output (sumAbs). */
1662  waitingTime += secondDimFFTandLog2Computation(obj, obj->sumAbs, CHECK_FOR_DET_MATRIX_TX, rangeIdx, &pingPongIdx);
1663 
1665  {
1666  /* In the subframe for maximum velocity enancement, the second half of the chirps of the
1667  * subframe consists of 'slow chirps', i.e., chirps with larger idle times compared to
1668  * the first set. These have a different (lower) max-unambiguous-velocities, and its
1669  * 2D-FFT output can be used (along with the 2D-FFT output of the 'fast-chirps' of the
1670  * first half of the frame ) with the chinese remainder theorem (or CRT) to increase
1671  * the max-unambiguous velocity. */
1672  waitingTime += secondDimFFTandLog2Computation(obj, obj->sumAbsSlowChirp, DO_NOT_CHECK_FOR_DET_MATRIX_TX, rangeIdx, &pingPongIdx);
1673  }
1674 
1675  /* doppler-CFAR-detecton on the current range gate.*/
1676  numDetObjPerCfar = cfarCa_SO_dBwrap_withSNR(
1677  obj->sumAbs,
1678  obj->cfarDetObjIndexBuf,
1679  obj->cfarDetObjSNR,
1680  obj->numDopplerBins,
1683  obj->cfarCfgDoppler.guardLen,
1684  obj->cfarCfgDoppler.winLen);
1685 
1686  /* Reduce the detected objects to peaks. */
1687  numDetObjPerCfar = pruneToPeaks(obj->cfarDetObjIndexBuf, obj->cfarDetObjSNR,
1688  numDetObjPerCfar, obj->sumAbs, obj->numDopplerBins);
1689 
1690  /* If the chirp design allows, perform the 'maximum velocity enhancement using dissimilar chirps and the chinese remainder theorem'. */
1692  {
1693  uint32_t detObj1DRawIdx;
1694  float interpOffset;
1695  float fastChirpVelIdxFlt, fastChirpVel;
1696  int16_t fastChirpVelIdx;
1697 
1698  /* Prune the list of detected objects to at most MAX_NUM_DET_PER_RANGE_GATE largest peaks. */
1699  numDetObjPerCfar = findKLargestPeaks(obj->cfarDetObjIndexBuf, obj->cfarDetObjSNR,
1700  numDetObjPerCfar, obj->sumAbs, obj->numDopplerBins,
1702 
1703  /* Find the list of doppler gates to perform 2D CFAR on. */
1704  for (detIdx1 = 0; detIdx1 < numDetObjPerCfar; detIdx1++)
1705  {
1706  detObj1DRawIdx = rangeIdx*MAX_NUM_DET_PER_RANGE_GATE + detIdx1;
1707  obj->detObj1DRaw[detObj1DRawIdx].dopplerIdx = obj->cfarDetObjIndexBuf[detIdx1];
1708  obj->detObj1DRaw[detObj1DRawIdx].rangeIdx = rangeIdx;
1709  obj->detObj1DRaw[detObj1DRawIdx].dopplerSNRdB = obj->cfarDetObjSNR[detIdx1] >> obj->log2numVirtAnt;
1710 
1711  /* Estimate the velocity from the 'fast chirps'. Also, perform an interpolation
1712  * operation to get close to the true doppler (to avoid being bounded by the
1713  * doppler resolution) . */
1715 
1716  fastChirpVelIdx = (int16_t) obj->cfarDetObjIndexBuf[detIdx1];
1717  if (fastChirpVelIdx > (obj->numDopplerBins >> 1) - 1)
1718  {
1719  fastChirpVelIdx -= obj->numDopplerBins;
1720  }
1721 
1722  fastChirpVelIdxFlt = ((float)fastChirpVelIdx) + interpOffset;
1723  fastChirpVel = fastChirpVelIdxFlt * ((float)obj->maxVelEnhStruct.velResolutionFastChirp);
1724 
1725 
1726  /* velocity disambiguation using chinese remainder theorem. */
1727  /* Note : 'disambiguateVel' irrevocably alters the sumAbsSlowChirp buffer */
1728  /* obj->detObj1DRaw[detObj1DRawIdx].velDisambFacValidity =
1729  disambiguateVel(
1730  obj->sumAbsSlowChirp,
1731  fastChirpVel,
1732  obj->sumAbs[obj->cfarDetObjIndexBuf[detIdx1]],
1733  obj);
1734 */
1735  numDetObj1D++;
1736  }
1737 
1738  for (detIdx1 = numDetObjPerCfar; detIdx1 < MAX_NUM_DET_PER_RANGE_GATE; detIdx1++)
1739  {
1740  detObj1DRawIdx = ((rangeIdx*MAX_NUM_DET_PER_RANGE_GATE) + detIdx1);
1741  obj->detObj1DRaw[detObj1DRawIdx].velDisambFacValidity = -2;
1742  }
1743  }
1744 
1745  /* Decide which doppler 'gates' are to be subjected to the range-CFAR. We only need to do so
1746  * if a detected object from the doppler-CFAR is detected at that 'doppler gate' . */
1747  if (numDetObjPerCfar > 0)
1748  {
1749  for (detIdx1 = 0; detIdx1 < numDetObjPerCfar; detIdx1++)
1750  {
1751  if (!MmwDemo_isSetDopplerLine(&obj->detDopplerLines, obj->cfarDetObjIndexBuf[detIdx1]))
1752  {
1754  numDetDopplerLine1D++;
1755  }
1756  }
1757  }
1758  /* populate the pre-detection matrix */
1762  subframeIndx);
1763 
1764  }
1765 
1766  startTimeWait = Cycleprofiler_getTimeStamp();
1767  MmwDemo_dataPathWaitTransDetMatrix(obj, subframeIndx);
1768  waitingTime += Cycleprofiler_getTimeStamp() - startTimeWait;
1769 
1770  /*
1771  * Perform CFAR detection along range lines. Only those doppler bins which were
1772  * detected in the earlier CFAR along doppler dimension are considered
1773  */
1774  if (numDetDopplerLine1D > 0)
1775  {
1776  uint8_t chId;
1777  if (subframeIndx == 0)
1778  {
1780  }
1781  /* else
1782  {
1783  chId = MRR_SF1_EDMA_CH_DET_MATRIX2;
1784  } */
1785 
1786  dopplerLine = MmwDemo_getDopplerLine(&obj->detDopplerLines);
1788  /*(uint8_t *)(&obj->detMatrix[dopplerLine]),*/
1789  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->detMatrix[dopplerLine]),
1790  SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1791  (uint8_t *)(SOC_translateAddress((uint32_t)(&obj->sumAbsRange[0]),
1792  SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1793  (uint8_t)chId,
1794  (uint8_t)MRR_EDMA_TRIGGER_ENABLE);
1795  }
1796 
1797  numDetObj2D = 0;
1798  for (detIdx1 = 0; detIdx1 < numDetDopplerLine1D; detIdx1++)
1799  {
1800  /* wait for DMA transfer of current range line to complete */
1801  startTimeWait = Cycleprofiler_getTimeStamp();
1802  MmwDemo_dataPathWaitTransDetMatrix2(obj, subframeIndx);
1803  waitingTime += Cycleprofiler_getTimeStamp() - startTimeWait;
1804 
1805  /* Trigger next DMA */
1806  if (detIdx1 < (numDetDopplerLine1D - 1))
1807  {
1808  uint8_t chId;
1809  dopplerLineNext = MmwDemo_getDopplerLine(&obj->detDopplerLines);
1810 
1811  if (subframeIndx == 0)
1812  {
1814  }
1815  /* else
1816  {
1817  chId = MRR_SF1_EDMA_CH_DET_MATRIX2;
1818  } */
1819 
1821  /*(uint8_t*)(&obj->detMatrix[dopplerLineNext]),*/
1822  (uint8_t*)(SOC_translateAddress(
1823  (uint32_t)(&obj->detMatrix[dopplerLineNext]),
1824  SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1825  (uint8_t*)(SOC_translateAddress(
1826  (uint32_t)(&obj->sumAbsRange[((detIdx1 + 1) & 0x1) * obj->numRangeBins]),
1827  SOC_TranslateAddr_Dir_TO_EDMA, NULL)),
1828  (uint8_t)chId,
1829  (uint8_t)MRR_EDMA_TRIGGER_ENABLE);
1830  }
1831 
1832  /* On the detected doppler line, use CFAR to find range peaks among numRangeBins samples.
1833  * Note : This is a modified version of the mmwavelib CFAR function. We were interested in
1834  * the SNR (as computed by the CFAR) as well for the tracking algorithms */
1835  numDetObjPerCfar = cfarCadB_SO_withSNR(
1836  &obj->sumAbsRange[(detIdx1 & 0x1) * obj->numRangeBins],
1837  obj->cfarDetObjIndexBuf,
1838  obj->cfarDetObjSNR,
1839  obj->numRangeBins,
1842  obj->cfarCfgRange.guardLen,
1843  obj->cfarCfgRange.winLen,
1845 
1846  if (numDetObjPerCfar > 0)
1847  {
1849  {
1850  /*
1851  * Since the point tracker works on strong unambiguous peaks, we
1852  * prune the list of objects further to generate targets that are
1853  * peaks in the range dimension.
1854  *
1855  * Note that we've previously pruned the detected objects to be
1856  * peaks in the doppler dimension. With this next step, the list of
1857  * objects are guaranteed to be peaks in both dimensions */
1858 
1859  numDetObjPerCfar = pruneToPeaks(obj->cfarDetObjIndexBuf,
1860  obj->cfarDetObjSNR,
1861  numDetObjPerCfar,
1862  &obj->sumAbsRange[(detIdx1 & 0x1) * obj->numRangeBins],
1863  obj->numRangeBins);
1864 
1865 
1867  numDetObjPerCfar, dopplerLine, numDetObj2D,
1868  &obj->sumAbsRange[(detIdx1 & 0x1) * obj->numRangeBins]);
1869  }
1870  else
1871  {
1872  if (detIdx1 != 0)
1873  {
1874  /* Prune to only neighbours of peaks (or peaks). This increases the point cloud
1875  * density but helps avoid having too many detections around one object. If this
1876  * condition wasn't added, there would be ~3 detections around every target,
1877  * corresponding to the peak, and the neighbours of the peak.
1878  *
1879  * This is not performed for the zero doppler case because in case the car has
1880  * stopped at an intersection, and there are many cars around it, every detected
1881  * point counts. */
1882  numDetObjPerCfar = pruneToPeaksOrNeighbourOfPeaks(obj->cfarDetObjIndexBuf,
1883  obj->cfarDetObjSNR,
1884  numDetObjPerCfar,
1885  &obj->sumAbsRange[(detIdx1 & 0x1) * obj->numRangeBins],
1886  obj->numRangeBins);
1887  }
1888  numDetObj2D = findandPopulateDetectedObjects(obj, numDetObjPerCfar, dopplerLine,
1889  numDetObj2D, &obj->sumAbsRange[(detIdx1 & 0x1) * obj->numRangeBins]);
1890  }
1891  }
1892  dopplerLine = dopplerLineNext;
1893  }
1894 
1896  {
1897  /* Peak grouping
1898  * Another pruning step for the point cloud because we haven't made
1899  * sure that the objects are peaks in doppler. */
1900  numDetObj2D = cfarPeakGroupingAlongDoppler( obj->detObj2DRaw, numDetObj2D,
1901  obj->detMatrix, obj->numRangeBins,
1902  obj->numDopplerBins);
1903  }
1904 
1905  obj->numDetObjRaw = numDetObj2D;
1906 
1907  /* We would like to modify/prune the detection results to take care of the
1908  * following issues.
1909  * 1. remove objects less than minimum range or greater than maximum range.
1910  * 2. Higher SNR/peakVal requirement for close-by objects - to avoid ground
1911  * clutter
1912  */
1913  numDetObj2D = rangeBasedPruning(obj->detObj2D, obj->detObj2DRaw,
1914  obj->SNRThresholds,obj->peakValThresholds,
1915  numDetObj2D, obj->numDopplerBins, obj->maxRange,
1916  obj->minRange);
1917 
1918  obj->numDetObj = numDetObj2D;
1919 
1920  /* Azimuth Processing. */
1921  waitingTime += aziEleProcessing(obj, subframeIndx);
1922 
1923  /* Clustering. */
1924  clusteringDBscanRun(&(obj->dbScanInstance), obj, obj->numDetObj, &(obj->dbScanReport), obj->trackingInput);
1925 
1926  /* Tracking. */
1928  {
1929  uint32_t numTrackingInput;
1930  /* Remove tracking inputs with poor SNR, and at grazing angles. */
1931  numTrackingInput = pruneTrackingInput(obj->trackingInput, obj->dbScanReport.numCluster);
1932 
1933  ekfRun(numTrackingInput, obj->trackingInput, obj, obj->trackerQvecList, FRAME_PERIODICITY_SEC);
1934 
1935  }
1936 
1937  /* Associate clustering outputs */
1939  {
1940  float thresholdFlt = (2 * obj->dbScanInstance.epsilon * obj->dbScanInstance.fixedPointScale);
1941  int32_t threshold = _spint(thresholdFlt*thresholdFlt);
1942  int32_t vFactorFixed = (int32_t)(obj->dbScanInstance.vFactor * obj->dbScanInstance.fixedPointScale);
1943 
1944  associateClustering(&(obj->dbScanReport), obj->dbScanState, obj->dbScanInstance.maxClusters, threshold, vFactorFixed);
1945  }
1946 
1947  /* Create the smallest meaningful array for the data that being sent out to the PC because
1948  * the UART rate is quite low. */
1949  populateOutputs(obj);
1950 
1951  gCycleLog.interFrameProcessingTime += Cycleprofiler_getTimeStamp() - startTime - waitingTime;
1952  gCycleLog.interFrameWaitTime += waitingTime;
1953 }
1954 
1974 //uint32_t logRadarOffset[128];
1975 //uint32_t idx =0;
1976 //uint32_t logChirpcnt[128];
1977 void MmwDemo_processChirp(DSS_DataPathObj *obj, uint8_t subframeIndx)
1978 {
1979  volatile uint32_t startTime;
1980  uint32_t radarCubeOffset;
1981  uint8_t chId;
1982 
1984  startTime = Cycleprofiler_getTimeStamp();
1985 
1986  if (obj->chirpCount > 1) //verify if ping(or pong) buffer is free for odd(or even) chirps
1987  {
1988  MmwDemo_dataPathWait1DOutputData(obj, pingPongId(obj->chirpCount), subframeIndx);
1989  }
1990  gCycleLog.interChirpWaitTime += Cycleprofiler_getTimeStamp() - startTime;
1991 
1993  MmwDemo_interChirpProcessing(obj, pingPongId(obj->chirpCount), subframeIndx);
1994 
1995  /* Modify destination address in Param set and DMA for sending 1DFFT output (for all antennas) to L3 */
1996  if (isPong(obj->chirpCount))
1997  {
1998  /* select the appropriate channel based on the index of the subframe. */
1999  if (subframeIndx == 0)
2000  {
2002  }
2003  /* else
2004  {
2005  chId = MRR_SF1_EDMA_CH_1D_OUT_PONG;
2006  } */
2007 
2008  radarCubeOffset = (obj->numDopplerBins * obj->numRxAntennas * (obj->txAntennaCount))
2009  + obj->dopplerBinCount
2010  + (obj->numDopplerBins * obj->numRxAntennas * obj->numTxAntennas * obj->chirpTypeCount);
2013  (uint8_t *)NULL,
2014  (uint8_t *)(&obj->radarCube[radarCubeOffset]),
2015  (uint8_t)chId,
2016  (uint8_t)MRR_EDMA_TRIGGER_ENABLE);
2017  }
2018  else
2019  {
2020  if (subframeIndx == 0)
2021  {
2023  }
2024  /* else
2025  {
2026  chId = MRR_SF1_EDMA_CH_1D_OUT_PING;
2027  }*/
2028  radarCubeOffset = (obj->numDopplerBins * obj->numRxAntennas * (obj->txAntennaCount))
2029  + obj->dopplerBinCount
2030  + (obj->numDopplerBins * obj->numRxAntennas * obj->numTxAntennas * obj->chirpTypeCount);
2031 
2034  (uint8_t *)NULL,
2035  (uint8_t *)(&obj->radarCube[radarCubeOffset]),
2036  (uint8_t)chId,
2037  (uint8_t)MRR_EDMA_TRIGGER_ENABLE);
2038  }
2039 
2040  //logRadarOffset[idx] = radarCubeOffset;
2041  //
2042  //logChirpcnt[idx] = obj->chirpCount;
2043  //idx++;
2044 
2045 
2046  obj->chirpCount++;
2047  obj->txAntennaCount++;
2048  if (obj->txAntennaCount == obj->numTxAntennas)
2049  {
2050  obj->txAntennaCount = 0;
2051  obj->dopplerBinCount++;
2052  if (obj->dopplerBinCount == obj->numDopplerBins)
2053  {
2055  {
2056  obj->chirpTypeCount++;
2057  obj->dopplerBinCount = 0;
2058  /* if (obj->chirpTypeCount == SUBFRAME_MRR_NUM_CHIRPTYPES)
2059  {
2060  obj->chirpTypeCount = 0;
2061  obj->chirpCount = 0;
2062  } */
2063  }
2064 // else
2065  {
2066  obj->chirpTypeCount = 0;
2067  obj->dopplerBinCount = 0;
2068  obj->chirpCount = 0;
2069  }
2070  }
2071  }
2072 }
2073 
2082 void MmwDemo_waitEndOfChirps(DSS_DataPathObj *obj, uint8_t subframeIndx)
2083 {
2084  volatile uint32_t startTime;
2085 
2086  startTime = Cycleprofiler_getTimeStamp();
2087  /* Wait for transfer of data corresponding to last 2 chirps (ping/pong) */
2088  MmwDemo_dataPathWait1DOutputData(obj, 0, subframeIndx);
2089  MmwDemo_dataPathWait1DOutputData(obj, 1, subframeIndx);
2091  gCycleLog.interChirpWaitTime += Cycleprofiler_getTimeStamp() - startTime;
2092 }
2093 void calc_cmplx_exp(cmplx16ImRe_t *dftSinCos, float i, uint32_t dftLen)
2094 {
2095  int32_t itemp;
2096  float temp;
2097  temp = ONE_Q15 * -sin(2 * PI_*i / dftLen);
2098  itemp = (int32_t)ROUND(temp);
2099 
2100  if (itemp >= ONE_Q15)
2101  {
2102  itemp = ONE_Q15 - 1;
2103  }
2104  dftSinCos->imag = itemp;
2105 
2106  temp = ONE_Q15 * cos(2 * PI_*i / dftLen);
2107  itemp = (int32_t)ROUND(temp);
2108 
2109  if (itemp >= ONE_Q15)
2110  {
2111  itemp = ONE_Q15 - 1;
2112  }
2113  dftSinCos->real = itemp;
2114 }
2115 
2133 void MmwDemo_genDftSinCosTable(cmplx16ImRe_t *dftSinCosTable,
2134  cmplx16ImRe_t *dftHalfBinVal,
2135  cmplx16ImRe_t *dftThirdBinVal,
2136  cmplx16ImRe_t *dftTwoThirdBinVal,
2137  uint32_t dftLen)
2138 {
2139  uint32_t i;
2140 
2141  for (i = 0; i < dftLen; i++)
2142  {
2143  calc_cmplx_exp(&dftSinCosTable[i], (float)i, dftLen);
2144  }
2145 
2146  /*Calculate half bin value*/
2147  calc_cmplx_exp(dftHalfBinVal, 0.5f, dftLen);
2148  /*Calculate at a third bin value*/
2149  calc_cmplx_exp(dftThirdBinVal, 0.33333333333f, dftLen);
2150  /*Calculate at two third bin value*/
2151  calc_cmplx_exp(dftTwoThirdBinVal, 0.66666666666f, dftLen);
2152 }
2153 
2154 
2155 
2166 void MmwDemo_edmaErrorCallbackFxn(EDMA_Handle handle, EDMA_errorInfo_t *errorInfo)
2167 {
2168  MmwDemo_dssAssert(0);
2169 }
2170 
2181 void MmwDemo_edmaTransferControllerErrorCallbackFxn(EDMA_Handle handle,
2182  EDMA_transferControllerErrorInfo_t *errorInfo)
2183 {
2184  DSS_DataPathObj * dataPathObj;
2185  /* Copy the error into the output structure (for debug) */
2186  dataPathObj = &gMCB.dataPathObj[gMCB.subframeIndx];
2187  dataPathObj->EDMA_transferControllerErrorInfo = *errorInfo;
2188  MmwDemo_dssAssert(0);
2189 }
2190 
2191 
2202 {
2203  int8_t subframeIndx = 0;
2204 
2205  for (subframeIndx = 0; subframeIndx < NUM_SUBFRAMES; subframeIndx++, obj++)
2206  {
2207  obj->chirpCount = 0;
2208  obj->dopplerBinCount = 0;
2209  obj->txAntennaCount = 0;
2210  obj->chirpTypeCount = 0;
2211  }
2212 
2213  /* reset profiling logs before start of frame */
2214  memset((void *)&gCycleLog, 0, sizeof(cycleLog_t));
2215 }
2216 
2227 {
2228  uint8_t numInstances;
2229  int32_t errorCode;
2230  EDMA_Handle handle;
2231  EDMA_errorConfig_t errorConfig;
2232  uint32_t instanceId;
2233  EDMA_instanceInfo_t instanceInfo;
2234 
2235  numInstances = EDMA_getNumInstances();
2236 
2237  /* Initialize the edma instance to be tested */
2238  for (instanceId = 0; instanceId < numInstances; instanceId++)
2239  {
2240  EDMA_init(instanceId);
2241 
2242  handle = EDMA_open(instanceId, &errorCode, &instanceInfo);
2243  if (handle == NULL)
2244  {
2245  // System_printf("Error: Unable to open the edma Instance, erorCode = %d\n", errorCode);
2246  return -1;
2247  }
2248  obj->edmaHandle[instanceId] = handle;
2249 
2250  errorConfig.isConfigAllEventQueues = true;
2251  errorConfig.isConfigAllTransferControllers = true;
2252  errorConfig.isEventQueueThresholdingEnabled = true;
2253  errorConfig.eventQueueThreshold = EDMA_EVENT_QUEUE_THRESHOLD_MAX;
2254  errorConfig.isEnableAllTransferControllerErrors = true;
2255  errorConfig.callbackFxn = MmwDemo_edmaErrorCallbackFxn;
2256  errorConfig.transferControllerCallbackFxn = MmwDemo_edmaTransferControllerErrorCallbackFxn;
2257  if ((errorCode = EDMA_configErrorMonitoring(handle, &errorConfig)) != EDMA_NO_ERROR)
2258  {
2259  // System_printf("Debug: EDMA_configErrorMonitoring() failed with errorCode = %d\n", errorCode);
2260  return -1;
2261  }
2262  }
2263  return 0;
2264 }
2265 
2275 int32_t MmwDemo_dataPathCopyEdmaHandle(DSS_DataPathObj *objOutput, DSS_DataPathObj *objInput)
2276 {
2277  uint8_t numInstances;
2278  uint32_t instanceId;
2279 
2280  numInstances = EDMA_getNumInstances();
2281 
2282  /* Initialize the edma instance to be tested */
2283  for (instanceId = 0; instanceId < numInstances; instanceId++)
2284  {
2285  objOutput->edmaHandle[instanceId] = objInput->edmaHandle[instanceId];
2286  }
2287  return 0;
2288 }
2289 
2300 void MmwDemo_printHeapStats(char *name, uint32_t heapUsed, uint32_t heapSize)
2301 {
2302  System_printf("Heap %s : size %d (0x%x), free %d (0x%x)\n", name, heapSize, heapSize, heapSize - heapUsed, heapSize - heapUsed);
2303 }
2304 
2332 #define SOC_MAX_NUM_RX_ANTENNAS 4
2333 #define SOC_MAX_NUM_TX_ANTENNAS 3
2334 void MmwDemo_dataPathConfigBuffers(DSS_DataPathObj *objIn, uint32_t adcBufAddress)
2335 {
2336 
2337  volatile DSS_DataPathObj *obj = &objIn[0];
2338 
2339  volatile uint32_t prev_end;
2340  volatile uint32_t l2HeapEndLocationForSubframe[NUM_SUBFRAMES];
2341 
2342  /* below defines for debugging purposes, do not remove as overlays can be hard to debug */
2343 
2344 #define ALIGN(x,a) (((x)+((a)-1))&~((a)-1))
2345 
2346 #define MMW_ALLOC_BUF(name, nameType, startAddr, alignment, size) \
2347  obj->name = (nameType *) ALIGN(startAddr, alignment); \
2348  uint32_t name##_end = (uint32_t)obj->name + (size) * sizeof(nameType);
2349 
2350  uint32_t subframeIndx;
2351  uint32_t numChirpTypes = 1;
2352  volatile uint32_t heapUsed;
2353  uint32_t heapL1start = (uint32_t)&gMmwL1[0];
2354  uint32_t heapL2start = (uint32_t)&gMmwL2[0];
2355  uint32_t heapL3start = (uint32_t)&gMmwL3[0];
2356 
2357  uint32_t azimuthMagSqrLen;
2358  uint32_t azimuthInLen;
2359  volatile uint32_t size;
2360  /* L3 is overlaid with one-time only accessed code. Although heap is not
2361  required to be initialized to 0, it may help during debugging when viewing memory
2362  in CCS */
2363  memset((void *)heapL3start, 0, sizeof(gMmwL3));
2364 
2365  for (subframeIndx = 0; subframeIndx < NUM_SUBFRAMES; subframeIndx++, obj++)
2366  {
2368  {
2369  numChirpTypes = 2;
2370  }
2371  else
2372  {
2373  numChirpTypes = 1;
2374  }
2375 
2376 
2377  /* L1 allocation
2378 
2379  Buffers are overlaid in the following order. Notation "|" indicates parallel
2380  and "+" means cascade
2381 
2382  { 1D
2383  (adcDataIn)
2384  } |
2385  { 2D
2386  (dstPingPong + fftOut2D) +
2387  (windowingBuf2D | log2Abs) + sumAbs + sumAbsSlowChirp (only for subframe MAX_VEL_ENH)
2388  + detObj1DRaw (must_be_after detObj2DRaw, only for subframe MAX_VEL_ENH)
2389  } |
2390  { 3D
2391  (detObj2DRaw +
2392  ((azimuthIn (must be at least beyond dstPingPong)
2393  + azimuthOut + azimuthMagSqr) )
2394  } |
2395  { Clustering (scratch pad)
2396  +
2397  Tracking (scratch pad)
2398  } |
2399  {
2400  Final outputs.
2401  }
2402  */
2403  /* 1D FFT */
2404  MMW_ALLOC_BUF(adcDataIn, cmplx16ReIm_t,
2406  2 * obj->numRangeBins);
2407  memset((void *)obj->adcDataIn, 0, 2 * obj->numRangeBins * sizeof(cmplx16ReIm_t));
2408 
2409  /* 2D FFT. */
2410  MMW_ALLOC_BUF(dstPingPong, cmplx16ReIm_t,
2412  2 * obj->numDopplerBins);
2413 
2414  MMW_ALLOC_BUF(fftOut2D, cmplx32ReIm_t,
2415  dstPingPong_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2416  obj->numDopplerBins);
2417 
2418  MMW_ALLOC_BUF(windowingBuf2D, cmplx32ReIm_t,
2420  obj->numDopplerBins);
2421 
2422  MMW_ALLOC_BUF(log2Abs, uint16_t,
2424  obj->numDopplerBins);
2425 
2426  MMW_ALLOC_BUF(sumAbs, uint16_t,
2427  MAX(log2Abs_end, windowingBuf2D_end), MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2428  2 * obj->numDopplerBins);
2429 
2431  {
2432  MMW_ALLOC_BUF(sumAbsSlowChirp, uint16_t,
2433  MAX(sumAbs_end, windowingBuf2D_end), MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2434  2 * obj->numDopplerBins);
2435 
2436  sumAbs_end = sumAbsSlowChirp_end;
2437  }
2438 
2439  /* Detected objects (2D). */
2440  MMW_ALLOC_BUF(detObj2DRaw, MmwDemo_objRaw2D_t,
2442  obj->maxNumObj2DRaw);
2443 
2444  /* 3D FFT. */
2446  {
2447  /* For the 'point cloud processing' we use 2-tx mimo and in order to have 2x velocity
2448  * disambiguation, we perform the azimuth-FFT twice (once with a 180 phase offset across
2449  * the two Tx.So we need extra space to save input to azimuth FFT for second call */
2450  azimuthInLen = obj->numAngleBins + obj->numVirtualAntAzim;
2451  }
2452  else
2453  {
2454  azimuthInLen = obj->numAngleBins;
2455  }
2456 
2457  MMW_ALLOC_BUF(antInp, cmplx32ReIm_t,
2458  MAX(detObj2DRaw_end, dstPingPong_end), MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2459  obj->numVirtualAntennas );
2460 
2461  MMW_ALLOC_BUF(azimuthIn, cmplx32ReIm_t,
2463  azimuthInLen);
2464 
2465  MMW_ALLOC_BUF(azimuthOut, cmplx32ReIm_t,
2467 
2468  MMW_ALLOC_BUF(elevationIn, cmplx32ReIm_t,
2470  azimuthInLen);
2471 
2472  MMW_ALLOC_BUF(elevationOut, cmplx32ReIm_t,
2473  elevationIn_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN, obj->numAngleBins);
2474 
2476  {
2477  /* 2 sets for velocity disambiguation, see above comment. */
2478  azimuthMagSqrLen = obj->numAngleBins * 2;
2479  }
2480  else
2481  {
2482  azimuthMagSqrLen = obj->numAngleBins;
2483  }
2484  MMW_ALLOC_BUF(azimuthMagSqr, float, elevationOut_end, sizeof(float), azimuthMagSqrLen);
2485 
2486  /* Detected objects (1D). */
2488  {
2489  MMW_ALLOC_BUF(detObj1DRaw, MmwDemo_objRaw1D_t,
2490  MAX(detObj2DRaw_end, sumAbs_end), MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2492  detObj2DRaw_end = detObj1DRaw_end;
2493  sumAbs_end = detObj1DRaw_end;
2494  }
2495 
2496  /* Clustering. */
2497  MMW_ALLOC_BUF(dBscanScratchPad, uint8_t,
2499  MRR_MAX_OBJ_OUT * 4);
2500 
2501  MMW_ALLOC_BUF(dbscanOutputDataIndexArray, uint16_t,
2502  dBscanScratchPad_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2503  MRR_MAX_OBJ_OUT);
2504 
2505  size = obj->dbScanInstance.maxClusters;
2506  MMW_ALLOC_BUF(dbscanOutputDataReport, clusteringDBscanReport_t,
2507  dbscanOutputDataIndexArray_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2508  size);
2509 
2510  /* Tracking buffers are only necessary for the long range subframe. */
2512  {
2513  size = obj->dbScanInstance.maxClusters;
2514  MMW_ALLOC_BUF(trackingInput, trackingInputReport_t,
2515  dbscanOutputDataReport_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2516  size);
2517 
2518  MMW_ALLOC_BUF(trackerScratchPadFlt, float,
2519  trackingInput_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2521 
2522  MMW_ALLOC_BUF(trackerScratchPadShort, int16_t,
2523  trackerScratchPadFlt_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2525  dbscanOutputDataReport_end = trackerScratchPadShort_end;
2526  }
2527 
2530  MRR_MAX_OBJ_OUT);
2531 
2532  size = obj->dbScanInstance.maxClusters;
2534  detObjFinal_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2535  size);
2536 
2537  size = obj->trackerInstance.maxTrackers;
2538  MMW_ALLOC_BUF(trackerOpFinal, trackingReportForTx, clusterOpFinal_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN, size);
2539 
2540  size = obj->parkingAssistNumBins;
2541  MMW_ALLOC_BUF(parkingAssistBins, uint16_t, trackerOpFinal_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN, size);
2542 
2543  prev_end = MAX(MAX(MAX(sumAbs_end, adcDataIn_end),azimuthMagSqr_end),detObj2DRaw_end);
2544  prev_end = MAX(MAX(prev_end,dbscanOutputDataReport_end), parkingAssistBins_end);
2545  heapUsed = prev_end - heapL1start;
2546  //MmwDemo_printHeapStats("L1", heapUsed, MMW_L1_HEAP_SIZE);
2547  MmwDemo_dssAssert(heapUsed <= MMW_L1_HEAP_SIZE);
2548 
2549  MmwDemo_printHeapStats("L1", heapUsed, MMW_L1_HEAP_SIZE);
2550 
2551  /* L2 allocation (part 1)
2552  The L2 hallocation is done in two parts, the first part consists of memory buffers that can be
2553  shared between the two subframes. The 2nd part consists of memory buffers that hold state
2554  information and constants (like the twiddle factors, or the windowing array). These
2555  cannot be shared (or overlaid in any way).
2556 
2557  The last occupied memory of L2 after the allocation of the first part is stored in
2558  the array 'l2HeapEndLocationForSubframe' for each subframe, and is used to compute the
2559  starting address for the 2nd part of L2 allocation.
2560 
2561  The allocations are :
2562  {
2563  {
2564  { 1D
2565  (fftOut1D)
2566  } |
2567  { 2D + 3D
2568  (cfarDetObjIndexBuf + detDopplerLines.dopplerLineMask) + sumAbsRange + detMatrix + detObj2D
2569  }
2570  }
2571  }
2572 
2573  */
2574 
2575  MMW_ALLOC_BUF(fftOut1D, cmplx16ReIm_t,
2577  2 * obj->numRxAntennas * obj->numRangeBins);
2578 
2579  MMW_ALLOC_BUF(cfarDetObjIndexBuf, uint16_t,
2580  heapL2start, sizeof(uint16_t),
2581  MAX(obj->numRangeBins, obj->numDopplerBins));
2582 
2583  MMW_ALLOC_BUF(cfarDetObjSNR, uint16_t,
2584  cfarDetObjIndexBuf_end, sizeof(uint16_t),
2585  MAX(obj->numRangeBins, obj->numDopplerBins));
2586 
2587 
2588  /* Expansion of below macro (macro cannot be used due to x.y type reference)
2589  MMW_ALLOC_BUF(detDopplerLines.dopplerLineMask, uint32_t,
2590  cfarDetObjIndexBuf_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2591  MAX((obj->numDopplerBins>>5),1));
2592  */
2593  obj->detDopplerLines.dopplerLineMask = (uint32_t *)ALIGN(cfarDetObjSNR_end,
2595  uint32_t detDopplerLines_dopplerLineMask_end = (uint32_t)obj->detDopplerLines.dopplerLineMask +
2596  MAX((obj->numDopplerBins >> 5), 1) * sizeof(uint32_t); /* should be ceil */
2597 
2598  obj->detDopplerLines.dopplerLineMaskLen = MAX((obj->numDopplerBins >> 5), 1);
2599 
2600  MMW_ALLOC_BUF(sumAbsRange, uint16_t,
2601  detDopplerLines_dopplerLineMask_end, sizeof(uint16_t),
2602  2 * obj->numRangeBins);
2603 
2604  MMW_ALLOC_BUF(detMatrix, uint16_t,
2605  sumAbsRange_end, sizeof(uint16_t),
2606  obj->numRangeBins * obj->numDopplerBins);
2607 
2610  MRR_MAX_OBJ_OUT);
2611 
2612 
2613  l2HeapEndLocationForSubframe[subframeIndx] = MAX(fftOut1D_end, detObj2D_end);
2614 
2615  /* L3 allocation:
2616  radarCube +
2617  detMatrix
2618  */
2619  obj->ADCdataBuf = (cmplx16ReIm_t *)adcBufAddress;
2620 
2621  MMW_ALLOC_BUF(radarCube, cmplx16ReIm_t,
2623  obj->numRangeBins * obj->numDopplerBins * obj->numRxAntennas * obj->numTxAntennas * numChirpTypes);
2624  heapUsed = radarCube_end - heapL3start;
2625  MmwDemo_printHeapStats("L3", heapUsed, sizeof(gMmwL3));
2626 
2627  MmwDemo_dssAssert(heapUsed <= sizeof(gMmwL3));
2628  }
2629 
2630  volatile uint32_t prevL2End = 0;
2631 
2632  /* Find the last occupied memory of the L2, for the subsequent assignments. */
2633  for (subframeIndx = 0; subframeIndx < NUM_SUBFRAMES; subframeIndx ++)
2634  {
2635  if (prevL2End < l2HeapEndLocationForSubframe[subframeIndx])
2636  {
2637  prevL2End = l2HeapEndLocationForSubframe[subframeIndx];
2638  }
2639  }
2640 
2641  /* L2 allocation (part 2)
2642  * These allocations are static, and are used as long as the radar is alive.
2643  * They correspond to constants for the FFT and the tracking 'state' and the
2644  * clustering 'state'
2645  {
2646  twiddle16x16_1D +
2647  window1D +
2648  twiddle16x32_2D +
2649  window2D +
2650  azimuthTwiddle16x32 +
2651  azimuthModCoefs +
2652  trackerState + trackerQvecList +
2653  dbScanState + parkingAssistBinsState + parkingAssistBinsStateCnt + rxChPhaseComp
2654  }
2655  */
2656  obj = &objIn[0];
2657  for (subframeIndx = 0; subframeIndx < NUM_SUBFRAMES; subframeIndx++, obj++)
2658  {
2659 
2660  MMW_ALLOC_BUF(twiddle16x16_1D, cmplx16ReIm_t,
2662  obj->numRangeBins);
2663 
2664  MMW_ALLOC_BUF(window1D, int16_t,
2665  twiddle16x16_1D_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2666  obj->numAdcSamples / 2);
2667 
2668  MMW_ALLOC_BUF(twiddle32x32_2D, cmplx32ReIm_t,
2670  obj->numDopplerBins);
2671 
2672  MMW_ALLOC_BUF(window2D, int32_t,
2673  twiddle32x32_2D_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2674  obj->numDopplerBins / 2);
2675 
2676  MMW_ALLOC_BUF(azimuthTwiddle32x32, cmplx32ReIm_t,
2678  obj->numAngleBins);
2679 
2680  MMW_ALLOC_BUF(azimuthModCoefs, cmplx16ImRe_t,
2681  azimuthTwiddle32x32_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2682  obj->numDopplerBins);
2683 
2684  MMW_ALLOC_BUF(dcRangeSigMean, cmplx32ImRe_t,
2685  azimuthModCoefs_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2687 
2688  MMW_ALLOC_BUF(rxChPhaseComp, cmplx16ImRe_t,
2689  dcRangeSigMean_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2690  obj->numTxAntennas*obj->numRxAntennas);
2691 
2693  {
2694  /* If the tracker is being used assign memory for that. */
2695  size = obj->trackerInstance.maxTrackers;
2696  MMW_ALLOC_BUF(trackerState, KFstate_t,
2697  rxChPhaseComp_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2698  size);
2699 
2700  MMW_ALLOC_BUF(trackerQvecList, float,
2701  trackerState_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2702  3*N_STATES);
2703 
2704  prevL2End = trackerQvecList_end;
2705  }
2706  else if (obj->processingPath == POINT_CLOUD_PROCESSING)
2707  {
2708  /* For the point cloud processing, we keep a record of
2709  * the clusters, and associate them between frames. */
2711  rxChPhaseComp_end, MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN,
2713 
2714  size = obj->parkingAssistNumBins;
2715  MMW_ALLOC_BUF(parkingAssistBinsState, uint16_t,
2716  dbScanState_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2717  size);
2718 
2719  MMW_ALLOC_BUF(parkingAssistBinsStateCnt, uint16_t,
2720  parkingAssistBinsState_end, MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN,
2721  size);
2722 
2723 
2724  prevL2End = parkingAssistBinsStateCnt_end;
2725  }
2726  else
2727  {
2728  MmwDemo_dssAssert(0);
2729  }
2730 
2731 
2732  heapUsed = prevL2End - heapL2start;
2733  MmwDemo_dssAssert(heapUsed <= MMW_L2_HEAP_SIZE);
2734 
2735  MmwDemo_printHeapStats("L2", heapUsed, MMW_L2_HEAP_SIZE);
2736 
2737  }
2738 }
2739 
2750 {
2751  MmwDemo_genWindow((void *)obj->window1D,
2753  obj->numAdcSamples,
2754  obj->numAdcSamples / 2,
2755  ONE_Q15,
2757 
2758  MmwDemo_genWindow((void *)obj->window2D,
2760  obj->numDopplerBins,
2761  obj->numDopplerBins / 2,
2762  ONE_Q19,
2763  MMW_WIN_HAMMING);
2764 
2765  /* Generate twiddle factors for 1D FFT. */
2766  gen_twiddle_fft16x16((int16_t *)obj->twiddle16x16_1D, obj->numRangeBins);
2767 
2768  /* Generate twiddle factors for 2D FFT */
2769  gen_twiddle_fft32x32((int32_t *)obj->twiddle32x32_2D, obj->numDopplerBins, 2147483647.5);
2770 
2771  /* Generate twiddle factors for azimuth FFT */
2772  gen_twiddle_fft32x32((int32_t *)obj->azimuthTwiddle32x32, obj->numAngleBins, 2147483647.5);
2773 
2774  /* Generate SIN/COS table for single point DFT */
2776  &obj->azimuthModCoefsHalfBin,
2779  obj->numDopplerBins);
2780 }
2781 
2799 void MmwDemo_genWindow(void *win,
2800  uint32_t windowDatumType,
2801  uint32_t winLen,
2802  uint32_t winGenLen,
2803  int32_t oneQformat,
2804  uint32_t winType)
2805 {
2806  uint32_t winIndx;
2807  int32_t winVal;
2808  int16_t * win16 = (int16_t *)win;
2809  int32_t * win32 = (int32_t *)win;
2810 
2811  float phi = 2 * PI_ / ((float)winLen - 1);
2812 
2813  if (winType == MMW_WIN_BLACKMAN)
2814  {
2815  //Blackman window
2816  float a0 = 0.42;
2817  float a1 = 0.5;
2818  float a2 = 0.08;
2819  for (winIndx = 0; winIndx < winGenLen; winIndx++)
2820  {
2821  winVal = (int32_t)((oneQformat * (a0 - a1*cos(phi * winIndx) +
2822  a2*cos(2 * phi * winIndx))) + 0.5);
2823  if (winVal >= oneQformat)
2824  {
2825  winVal = oneQformat - 1;
2826  }
2827  switch (windowDatumType)
2828  {
2829  case FFT_WINDOW_INT16:
2830  win16[winIndx] = (int16_t)winVal;
2831  break;
2832  case FFT_WINDOW_INT32:
2833  win32[winIndx] = (int32_t)winVal;
2834  break;
2835  }
2836 
2837  }
2838  }
2839  else if (winType == MMW_WIN_HAMMING)
2840  {
2841  //Hanning window
2842  for (winIndx = 0; winIndx < winGenLen; winIndx++)
2843  {
2844  winVal = (int32_t)((oneQformat * (0.53836 - (0.46164*cos(phi * winIndx)))) + 0.5);
2845 
2846  if (winVal >= oneQformat)
2847  {
2848  winVal = oneQformat - 1;
2849  }
2850 
2851  switch (windowDatumType)
2852  {
2853  case FFT_WINDOW_INT16:
2854  win16[winIndx] = (int16_t)winVal;
2855  break;
2856  case FFT_WINDOW_INT32:
2857  win32[winIndx] = (int32_t)winVal;
2858  break;
2859  }
2860  }
2861  }
2862  else if (winType == MMW_WIN_RECT)
2863  {
2864  //Rectangular window
2865  for (winIndx = 0; winIndx < winGenLen; winIndx++)
2866  {
2867  switch (windowDatumType)
2868  {
2869  case FFT_WINDOW_INT16:
2870  win16[winIndx] = (int16_t)(oneQformat - 1);
2871  break;
2872  case FFT_WINDOW_INT32:
2873  win32[winIndx] = (int32_t)(oneQformat - 1);
2874  break;
2875  }
2876  }
2877  }
2878  else if (winType == MMW_WIN_HANNING_RECT)
2879  {
2880 
2881  phi = 2 * PI_ / ((float)(winLen/8) - 1);
2882 
2883  //Rectangular window
2884  for (winIndx = 0; winIndx < winGenLen; winIndx++)
2885  {
2886  if (winIndx <= winLen/16)
2887  {
2888  winVal = (int32_t)((oneQformat * 0.5* (1 - cos(phi * winIndx))) + 0.5);
2889  }
2890  else
2891  {
2892  winVal = oneQformat - 1;
2893  }
2894 
2895  if (winVal >= oneQformat)
2896  {
2897  winVal = oneQformat - 1;
2898  }
2899 
2900  switch (windowDatumType)
2901  {
2902  case FFT_WINDOW_INT16:
2903  win16[winIndx] = (int16_t)(winVal);
2904  break;
2905  case FFT_WINDOW_INT32:
2906  win32[winIndx] = (int32_t)(winVal);
2907  break;
2908  }
2909  }
2910  }
2911 }
2912 
2913 
2929 uint32_t secondDimFFTandLog2Computation(DSS_DataPathObj * restrict obj, uint16_t * restrict sumAbs, uint16_t checkDetMatrixTx, uint16_t rangeIdx, uint32_t * pingPongIdxPtr)
2930 {
2931  int32_t rxAntIdx, idx;
2932  volatile uint32_t startTime;
2933  volatile uint32_t startTimeWait;
2934  uint32_t waitingTime = 0;
2935  uint16_t subframeIndx = obj->subframeIndx;
2936  uint16_t continueDMA = ((obj->processingPath == MAX_VEL_ENH_PROCESSING) &&
2937  (checkDetMatrixTx == 1));
2938  uint32_t pingPongIdx = *pingPongIdxPtr;
2939 
2940  /* 2nd Dimension FFT is done here */
2941  for (rxAntIdx = 0; rxAntIdx < (obj->numRxAntennas * obj->numTxAntennas); rxAntIdx++)
2942  {
2943  /* verify that previous DMA has completed */
2944  startTimeWait = Cycleprofiler_getTimeStamp();
2945  MmwDemo_dataPathWait2DInputData(obj, pingPongId(pingPongIdx), subframeIndx);
2946  waitingTime += Cycleprofiler_getTimeStamp() - startTimeWait;
2947 
2948  /* kick off next DMA */
2949  if ((rangeIdx < obj->numRangeBins - 1) ||
2950  (rxAntIdx < (obj->numRxAntennas * obj->numTxAntennas) - 1) ||
2951  (continueDMA == 1))
2952  {
2953  if (isPong(pingPongIdx))
2954  {
2957  subframeIndx);
2958  }
2959  else
2960  {
2963  subframeIndx);
2964  }
2965  }
2966 
2967  /* process data that has just been DMA-ed */
2968  mmwavelib_windowing16x32(
2969  (int16_t *)&obj->dstPingPong[pingPongId(pingPongIdx) * obj->numDopplerBins],
2970  obj->window2D,
2971  (int32_t *)obj->windowingBuf2D,
2972  obj->numDopplerBins);
2973 
2974  DSP_fft32x32(
2975  (int32_t *)obj->twiddle32x32_2D,
2976  obj->numDopplerBins,
2977  (int32_t *)obj->windowingBuf2D,
2978  (int32_t *)obj->fftOut2D);
2979 
2980  mmwavelib_log2Abs32(
2981  (int32_t *)obj->fftOut2D,
2982  obj->log2Abs,
2983  obj->numDopplerBins);
2984 
2985  if (rxAntIdx == 0)
2986  {
2987  /* check if previous sumAbs has been transferred */
2988  if ((rangeIdx > 0) && (checkDetMatrixTx == 1))
2989  {
2990  startTimeWait = Cycleprofiler_getTimeStamp();
2991  MmwDemo_dataPathWaitTransDetMatrix(obj, subframeIndx);
2992  waitingTime += Cycleprofiler_getTimeStamp() - startTimeWait;
2993  }
2994 
2995  _nassert((uint32_t) sumAbs % 8 == 0);
2996  _nassert((uint32_t) obj->log2Abs % 8 == 0);
2997  _nassert(obj->numDopplerBins % 8 == 0);
2998  for (idx = 0; idx < obj->numDopplerBins; idx++)
2999  {
3000  sumAbs[idx] = obj->log2Abs[idx];
3001  }
3002  }
3003  else
3004  {
3005  mmwavelib_accum16(obj->log2Abs, sumAbs, obj->numDopplerBins);
3006  }
3007  pingPongIdx ^= 1;
3008  }
3009 
3010  *pingPongIdxPtr = pingPongIdx;
3011  return waitingTime;
3012 }
3013 
3035  DSS_DataPathObj * restrict obj,
3036  uint32_t numDetObjPerCfar,
3037  uint16_t dopplerLine,
3038  uint32_t numDetObj2D,
3039  uint16_t * restrict sumAbsRange)
3040 {
3041 
3042  uint32_t detIdx1, detIdx2;
3043  uint16_t rangeIdx;
3044  float disambiguatedSpeed;
3045  float range;
3046  uint32_t detObj1DRawIdx;
3047  int16_t dopplerIdxActual;
3048  uint32_t oneQFormat = (1 << obj->xyzOutputQFormat);
3049  MmwDemo_objRaw2D_t* restrict detObj2DRaw = obj->detObj2DRaw;
3050  MmwDemo_objRaw1D_t* restrict detObj1DRaw = obj->detObj1DRaw;
3051  uint16_t * restrict cfarDetObjIndexBuf = obj->cfarDetObjIndexBuf;
3052  uint16_t * restrict cfarDetObjSNR = obj->cfarDetObjSNR;
3053  uint16_t maxNumObj2DRaw = obj->maxNumObj2DRaw;
3054 
3055  /* For each object in the CFAR detected object list, */
3056  for (detIdx2 = 0; detIdx2 < numDetObjPerCfar; detIdx2++)
3057  {
3058  /* if there is space in the detObj2DRaw matrix, */
3059  if (numDetObj2D < maxNumObj2DRaw)
3060  {
3061  /* locate the 1D CFAR corresponding to the current range gate. */
3062  for (detIdx1 = 0; detIdx1 < MAX_NUM_DET_PER_RANGE_GATE; detIdx1++)
3063  {
3064  rangeIdx = cfarDetObjIndexBuf[detIdx2];
3065 
3066  detObj1DRawIdx = (rangeIdx*MAX_NUM_DET_PER_RANGE_GATE) + detIdx1;
3067 
3068  /* Check if the 1D CFAR matches the current objects doppler.
3069  * Also, check if the velocity disambiguation output is valid. */
3070  if ((detObj1DRaw[detObj1DRawIdx].velDisambFacValidity >= 0) &&
3071  (detObj1DRaw[detObj1DRawIdx].dopplerIdx == dopplerLine))
3072  {
3073 
3074  /* Calculate
3075  * 1. The speed (after disambiguation). */
3076  if (dopplerLine >= (obj->numDopplerBins >> 1))
3077  {
3078  dopplerIdxActual = dopplerLine - obj->numDopplerBins;
3079  }
3080  else
3081  {
3082  dopplerIdxActual = dopplerLine;
3083  }
3084 
3085  disambiguatedSpeed = ((float)dopplerIdxActual * obj->velResolution) +
3086  ((float)(2*(detObj1DRaw[detObj1DRawIdx].velDisambFacValidity - 1)) * obj->maxUnambiguousVel);
3087 
3088  /* 2. The range (after correcting for the antenna delay). */
3089  range = (( (float)rangeIdx * obj->rangeResolution) - MIN_RANGE_OFFSET_METERS);
3090 
3091  if (range < 0.0f)
3092  {
3093  range = 0.0f;
3094  }
3095 
3096  /* 3. Populate the output Array. */
3097  detObj2DRaw[numDetObj2D].dopplerIdx = dopplerLine;
3098  detObj2DRaw[numDetObj2D].rangeIdx = rangeIdx;
3099 
3100  detObj2DRaw[numDetObj2D].speed = (int16_t) (disambiguatedSpeed * oneQFormat);
3101  detObj2DRaw[numDetObj2D].range = (uint16_t)(range * oneQFormat);
3102  /* 4. Note that the peakVal is taken from the sumAbsRange. */
3103  detObj2DRaw[numDetObj2D].peakVal = sumAbsRange[rangeIdx] >> obj->log2numVirtAnt;;
3104  /* 5. Note that the SNR is taken from the CFAR output. */
3105  detObj2DRaw[numDetObj2D].rangeSNRdB = cfarDetObjSNR[detIdx2] >> obj->log2numVirtAnt;
3106  detObj2DRaw[numDetObj2D].dopplerSNRdB = detObj1DRaw[detObj1DRawIdx].dopplerSNRdB;
3107  numDetObj2D++;
3108  break;
3109  }
3110  }
3111  }
3112  }
3113 
3114  return numDetObj2D;
3115 }
3116 
3134  DSS_DataPathObj * restrict obj,
3135  uint32_t numDetObjPerCfar,
3136  uint16_t dopplerLine,
3137  uint32_t numDetObj2D,
3138  uint16_t * restrict sumAbsRange)
3139 {
3140 
3141  uint32_t detIdx2;
3142  uint16_t rangeIdx;
3143  float speed, range;
3144  int16_t dopplerIdxActual;
3145  uint32_t oneQFormat = (1 << obj->xyzOutputQFormat);
3146  MmwDemo_objRaw2D_t* restrict detObj2DRaw = obj->detObj2DRaw;
3147  uint16_t * restrict cfarDetObjIndexBuf = obj->cfarDetObjIndexBuf;
3148  uint16_t * restrict cfarDetObjSNR = obj->cfarDetObjSNR;
3149 
3150  /* For each object in the CFAR detected object list, */
3151  for (detIdx2 = 0; detIdx2 < numDetObjPerCfar; detIdx2++)
3152  {
3153  /* if there is space in the detObj2DRaw matrix, */
3154  if (numDetObj2D < obj->maxNumObj2DRaw)
3155  {
3156  rangeIdx = cfarDetObjIndexBuf[detIdx2];
3157 
3158  /* Calculate
3159  * 1. The speed. */
3160  if (dopplerLine >= (obj->numDopplerBins >> 1))
3161  {
3162  dopplerIdxActual = (int16_t) dopplerLine - (int16_t)obj->numDopplerBins;
3163  }
3164  else
3165  {
3166  dopplerIdxActual = (int16_t)dopplerLine;
3167  }
3168 
3169  speed = ((float)dopplerIdxActual) * obj->velResolution;
3170  /* 2. The range (after correcting for the antenna delay). */
3171  range = (((float)rangeIdx) * obj->rangeResolution) - MIN_RANGE_OFFSET_METERS;
3172  if (range < 0.0f)
3173  {
3174  range = 0.0f;
3175  }
3176 
3177  /* 3. Populate the output Array. */
3178  detObj2DRaw[numDetObj2D].rangeIdx = rangeIdx;
3179  detObj2DRaw[numDetObj2D].dopplerIdx = dopplerLine;
3180 
3181  detObj2DRaw[numDetObj2D].speed = (int16_t) (speed * oneQFormat);
3182  detObj2DRaw[numDetObj2D].range = (uint16_t)(range * oneQFormat);
3183  /* 4. Note that the peakVal is taken from the sumAbsRange. */
3184  detObj2DRaw[numDetObj2D].peakVal = sumAbsRange[rangeIdx] >> obj->log2numVirtAnt;
3185  /* 5. Note that the SNR is taken from the CFAR output. */
3186  detObj2DRaw[numDetObj2D].rangeSNRdB = cfarDetObjSNR[detIdx2] >> obj->log2numVirtAnt;
3187  /* 6. Since we have no estimate of the doppler SNR, set it to 0. */
3188  detObj2DRaw[numDetObj2D].dopplerSNRdB = 0;
3189 
3190  numDetObj2D++;
3191  }
3192  }
3193  return numDetObj2D;
3194 }
3195 
3196 
3211 uint32_t pruneToPeaks(uint16_t* restrict cfarDetObjIndexBuf,
3212  uint16_t* restrict cfarDetObjSNR,
3213  uint32_t numDetObjPerCfar,
3214  uint16_t* restrict sumAbs,
3215  uint16_t numBins)
3216 {
3217  uint32_t detIdx2;
3218  uint32_t numDetObjPerCfarActual = 0;
3219  uint16_t currObjLoc, prevIdx, nextIdx;
3220 
3221  if (numDetObjPerCfar == 0)
3222  {
3223  return 0;
3224  }
3225  /* Prune to peaks */
3226  for (detIdx2 = 0; detIdx2 < numDetObjPerCfar; detIdx2++)
3227  {
3228  currObjLoc = cfarDetObjIndexBuf[detIdx2];
3229 
3230  if (currObjLoc == 0)
3231  {
3232  prevIdx = numBins - 1;
3233  }
3234  else
3235  {
3236  prevIdx = currObjLoc - 1;
3237  }
3238 
3239  if (currObjLoc == numBins - 1)
3240  {
3241  nextIdx = 0;
3242  }
3243  else
3244  {
3245  nextIdx = currObjLoc + 1;
3246  }
3247 
3248  if ((sumAbs[nextIdx] < sumAbs[currObjLoc])
3249  && (sumAbs[prevIdx] < sumAbs[currObjLoc]))
3250  {
3251  cfarDetObjIndexBuf[numDetObjPerCfarActual] = currObjLoc;
3252  cfarDetObjSNR[numDetObjPerCfarActual] = cfarDetObjSNR[detIdx2];
3253  numDetObjPerCfarActual++;
3254  }
3255  }
3256 
3257  return numDetObjPerCfarActual;
3258 }
3259 
3279 uint32_t findKLargestPeaks(uint16_t * restrict cfarDetObjIndexBuf,
3280  uint16_t * restrict cfarDetObjSNR,
3281  uint32_t numDetObjPerCfar,
3282  uint16_t * restrict sumAbs,
3283  uint16_t numBins,
3284  uint16_t K)
3285 {
3286  uint32_t detIdx1, detIdx2;
3287  uint16_t currMax;
3288  uint16_t currMaxIdx;
3289  uint16_t tempIdx;
3290  uint16_t tempSNR;
3291 
3292  if (numDetObjPerCfar <= 1)
3293  {
3294  return numDetObjPerCfar;
3295  }
3296 
3297  /* if the number of peaks is already less than or equal to K, we would still like the algorithm
3298  * to run, so as to organise the peaks in descending order. . */
3299  if (K >= numDetObjPerCfar)
3300  {
3301  K = numDetObjPerCfar;
3302  }
3303 
3304  /* Find the largest K peaks. K is typically a small value (1, 2 or 3). Hence the suboptimal
3305  * algorithm. */
3306  _nassert((uint32_t) K > 0);
3307  for (detIdx1 = 0; detIdx1 < K; detIdx1++)
3308  {
3309  currMax = 0;
3310  for (detIdx2 = detIdx1; detIdx2 < numDetObjPerCfar; detIdx2++)
3311  {
3312  if (currMax <= sumAbs[cfarDetObjIndexBuf[detIdx2]])
3313  {
3314  currMax = sumAbs[cfarDetObjIndexBuf[detIdx2]];
3315  currMaxIdx = detIdx2;
3316  }
3317  }
3318 
3319  /* Replace the cfarDetObjIndexBuf[detIdx1] with the obj at detIdx1. */
3320  tempIdx = cfarDetObjIndexBuf[detIdx1];
3321  tempSNR = cfarDetObjSNR[detIdx1];
3322  cfarDetObjIndexBuf[detIdx1] = cfarDetObjIndexBuf[currMaxIdx];
3323  cfarDetObjSNR[detIdx1] = cfarDetObjSNR[currMaxIdx];
3324  cfarDetObjIndexBuf[currMaxIdx] = tempIdx;
3325  cfarDetObjSNR[currMaxIdx] = tempSNR;
3326  }
3327 
3328  return K;
3329 }
3330 
3331 
3373 /*!*****************************************************************************************************************
3374  * \brief
3375  * Function Name : cfarCadB_SO_withSNR
3376  *
3377  * \par
3378  * <b>Description</b> : Performs a CFAR SO on an 16-bit unsigned input vector. The input values are assumed to be
3379  * in lograthimic scale. So the comparision between the CUT and the noise samples is additive
3380  * rather than multiplicative.
3381  *
3382  * @param[in] inp : input array (16 bit unsigned numbers)
3383  * @param[in] out : output array (indices of detected peaks (zero based counting))
3384  * @param[in] outSNR : output array (SNR of detected peaks)
3385  * @param[in] len : number of elements in input array
3386  * @param[in] const1,const2 : used to compare the Cell Under Test (CUT) to the sum of the noise cells:
3387  * [noise sum /(2^(const2-1))]+const1 for one sided comparison
3388  * (at the begining and end of the input vector).
3389  * [noise sum /(2^(const2))]+const1 for two sided comparison
3390  * @param[in] guardLen : one sided guard length
3391  * @param[in] noiseLen : one sided noise length
3392  * @param[in] minIndxToIgnoreHPF : the number of indices to force one sided CFAR, so as to avoid false
3393  * detections due to effect of the HPF.
3394  * @param[out] out : output array with indices of the detected peaks
3395  *
3396  * @return Number of detected peaks (i.e length of out)
3397  *
3398  * @pre Input (inp) and Output (out) arrays are non-aliased.
3399  * @ingroup MMWAVELIB_DETECT
3400  *
3401  *******************************************************************************************************************
3402  */
3403 uint32_t cfarCadB_SO_withSNR(const uint16_t inp[restrict],
3404  uint16_t out[restrict],
3405  uint16_t outSNR[restrict], uint32_t len,
3406  uint32_t const1, uint32_t const2,
3407  uint32_t guardLen, uint32_t noiseLen, uint32_t minIndxToIgnoreHPF)
3408 {
3409  uint32_t idx, idxLeftNext, idxLeftPrev, idxRightNext,
3410  idxRightPrev, outIdx, idxCUT;
3411  uint32_t sum, sumLeft, sumRight;
3412 
3413  /* initializations */
3414  outIdx = 0;
3415  sumLeft = 0;
3416  sumRight = 0;
3417  for (idx = 0; idx < noiseLen; idx++)
3418  {
3419  sumRight += inp[idx + guardLen + 1U];
3420  }
3421 
3422  /* One-sided comparision for the first segment (for the first noiseLen+gaurdLen samples */
3423  idxCUT = 0;
3424  if ((uint32_t) inp[idxCUT] > ((sumRight >> (const2 - 1U)) + const1))
3425  {
3426  out[outIdx] = (uint16_t)idxCUT;
3427  /* SNR (dB) is simply the peak - noise floor) */
3428  outSNR[outIdx] = inp[idxCUT] - (sumRight >> (const2 - 1));
3429  outIdx++;
3430  }
3431  idxCUT++;
3432 
3433  idxLeftNext = 0;
3434  idxRightPrev = idxCUT + guardLen;
3435  idxRightNext = idxRightPrev + noiseLen;
3436  for (idx = 0; idx < (noiseLen + guardLen - 1U); idx++)
3437  {
3438  sumRight = (sumRight + inp[idxRightNext]) - inp[idxRightPrev];
3439  idxRightNext++;
3440  idxRightPrev++;
3441 
3442  if (idx < noiseLen)
3443  {
3444  sumLeft += inp[idxLeftNext];
3445  idxLeftNext++;
3446  }
3447 
3448  if ((uint32_t) inp[idxCUT] > ((sumRight >> (const2 - 1U)) + const1))
3449  {
3450  out[outIdx] = (uint16_t)idxCUT;
3451  outSNR[outIdx] = inp[idxCUT] - (sumRight >> (const2 - 1));
3452  outIdx++;
3453  }
3454  idxCUT++;
3455  }
3456 
3457  /* Two-sided comparision for the middle segment */
3458  sumRight = (sumRight + inp[idxRightNext]) - inp[idxRightPrev];
3459  idxRightNext++;
3460  idxRightPrev++;
3461 
3462 
3463  {
3464  sum = (sumLeft < sumRight) ? sumLeft : sumRight;
3465  if ((uint32_t) inp[idxCUT] > ((sum >> (const2-1U)) + const1))
3466  {
3467  out[outIdx] = (uint16_t)idxCUT;
3468  outSNR[outIdx] = inp[idxCUT] - (sum >> (const2 - 1));
3469  outIdx++;
3470  }
3471  idxCUT++;
3472 
3473  idxLeftPrev = 0;
3474  for (idx = 0; idx < (len - 2U*(noiseLen + guardLen) - 1U); idx++)
3475  {
3476  sumLeft = (sumLeft + inp[idxLeftNext]) - inp[idxLeftPrev];
3477  sumRight = (sumRight + inp[idxRightNext]) - inp[idxRightPrev];
3478  idxLeftNext++;
3479  idxLeftPrev++;
3480  idxRightNext++;
3481  idxRightPrev++;
3482 
3483  if (idx < minIndxToIgnoreHPF)
3484  {
3485  sum = sumRight;
3486  }
3487  else
3488  {
3489  sum = (sumLeft < sumRight) ? sumLeft : sumRight;
3490  }
3491 
3492  if ((uint32_t)(inp[idxCUT]) >((sum >> (const2 - 1U)) + const1))
3493  {
3494  out[outIdx] = idxCUT;
3495  outSNR[outIdx] = inp[idxCUT] - (sum >> (const2 - 1U));
3496  outIdx++;
3497  }
3498  idxCUT++;
3499  }
3500  } /*CFAR_CASO*/
3501 
3502  /* One-sided comparision for the last segment (for the last noiseLen+gaurdLen samples) */
3503  for (idx = 0; idx < (noiseLen + guardLen); idx++)
3504  {
3505  sumLeft += inp[idxLeftNext] - inp[idxLeftPrev];
3506  idxLeftNext++;
3507  idxLeftPrev++;
3508  if ((uint32_t)inp[idxCUT] >((sumLeft >> (const2 - 1)) + const1))
3509  {
3510  out[outIdx] = idxCUT;
3511  outSNR[outIdx] = inp[idxCUT] - (sumLeft >> (const2 - 1));
3512  outIdx++;
3513  }
3514  idxCUT++;
3515  }
3516 
3517  return (outIdx);
3518 
3519 }
3520 
3521 
3522 /*!*****************************************************************************************************************
3523  * \brief
3524  * Function Name : cfarCa_SO_dBwrap_withSNR
3525  *
3526  * \par
3527  * <b>Description</b> : Performs a CFAR on an 16-bit unsigned input vector (CFAR-CA). The input values are assumed to be
3528  * in logarithmic scale. So the comparison between the CUT and the noise samples is additive
3529  * rather than multiplicative. Comparison is two-sided (wrap around when needed) for all CUTs.
3530  *
3531  * @param[in] inp : input array (16 bit unsigned numbers)
3532  * @param[in] out : output array (indices of detected peaks (zero based counting))
3533  * @param[in] outSNR : SNR array (SNR of detected peaks)
3534  * @param[in] len : number of elements in input array
3535  * @param[in] const1,const2 : used to compare the Cell Under Test (CUT) to the sum of the noise cells:
3536  * [noise sum /(2^(const2))] +const1 for two sided comparison.
3537  * @param[in] guardLen : one sided guard length
3538  * @param[in] noiseLen : one sided Noise length
3539  *
3540  * @param[out] out : output array with indices of the detected peaks
3541  *
3542  * @return Number of detected peaks (i.e length of out)
3543  *
3544  * @pre Input (inp) and Output (out) arrays are non-aliased.
3545  * @ingroup MMWAVELIB_DETECT
3546  *
3547  *******************************************************************************************************************
3548  */
3549 uint32_t cfarCa_SO_dBwrap_withSNR(const uint16_t inp[restrict],
3550  uint16_t out[restrict],
3551  uint16_t outSNR[restrict],
3552  uint32_t len,
3553  uint32_t const1, uint32_t const2,
3554  uint32_t guardLen, uint32_t noiseLen)
3555 {
3556  uint32_t idx, idxLeftNext, idxLeftPrev, idxRightNext,
3557  idxRightPrev, outIdx, idxCUT;
3558  uint32_t sum, sumLeft, sumRight;
3559 
3560  /*initializations */
3561  outIdx = 0;
3562  sumLeft = 0;
3563  sumRight = 0;
3564  for (idx = 1; idx <= noiseLen; idx++)
3565  {
3566  sumLeft += inp[len - guardLen - idx];
3567  }
3568 
3569  for (idx = 1; idx <= noiseLen; idx++)
3570  {
3571  sumRight += inp[idx + guardLen];
3572  }
3573 
3574  /*CUT 0: */
3575  sum = (sumLeft < sumRight) ? sumLeft:sumRight;
3576  if ((uint32_t) inp[0] > ((sum >> (const2-1)) + const1))
3577  {
3578  out[outIdx] = 0;
3579  outSNR[outIdx] = inp[0] - (sum >> (const2 - 1));
3580  outIdx++;
3581  }
3582 
3583  /* CUT 1 to guardLen: */
3584  idxLeftPrev = len - guardLen - noiseLen; /*e.g. 32-4-8 = 20 */
3585  idxLeftNext = idxLeftPrev + noiseLen; /*e.g. 28 */
3586  idxRightPrev = 1 + guardLen; /*e.g. 1+4=5 */
3587  idxRightNext = idxRightPrev + noiseLen; /*e.g. 13 */
3588  for (idxCUT = 1; idxCUT <= guardLen; idxCUT++)
3589  {
3590  sumLeft += inp[idxLeftNext] - inp[idxLeftPrev];
3591  idxLeftNext++;
3592  idxLeftPrev++;
3593  sumRight += inp[idxRightNext] - inp[idxRightPrev];
3594  idxRightNext++;
3595  idxRightPrev++;
3596  sum = (sumLeft < sumRight) ? sumLeft:sumRight;
3597 
3598  if ((uint32_t) (inp[idxCUT]) > ((sum >> (const2 - 1)) + const1))
3599  {
3600  out[outIdx] = idxCUT;
3601  outSNR[outIdx] = inp[idxCUT] - (sum >> (const2 - 1));
3602  outIdx++;
3603  }
3604  }
3605 
3606  /* CUT guardLen+1 to guardLen+noiseLen: e.g. CUT 5 to 12 */
3607  idxLeftNext = 0;
3608  for (idxCUT = guardLen + 1; idxCUT <= guardLen + noiseLen;
3609  idxCUT++)
3610  {
3611  sumLeft += inp[idxLeftNext] - inp[idxLeftPrev];
3612  idxLeftNext++;
3613  idxLeftPrev++;
3614  sumRight += inp[idxRightNext] - inp[idxRightPrev];
3615  idxRightNext++;
3616  idxRightPrev++;
3617  sum = (sumLeft < sumRight) ? sumLeft:sumRight;
3618  if ((uint32_t) (inp[idxCUT]) > ((sum >> (const2 - 1)) + const1))
3619  {
3620  out[outIdx] = idxCUT;
3621  outSNR[outIdx] = inp[idxCUT] - (sum >> (const2 - 1));
3622  outIdx++;
3623  }
3624  }
3625 
3626  /* CUTs in the middle. e.g. CUT 13 to 19 */
3627  idxLeftPrev = 0;
3628  for (idxCUT = guardLen + noiseLen + 1;
3629  idxCUT < len - (noiseLen + guardLen); idxCUT++)
3630  {
3631  sumLeft += inp[idxLeftNext] - inp[idxLeftPrev];
3632  idxLeftNext++;
3633  idxLeftPrev++;
3634  sumRight += inp[idxRightNext] - inp[idxRightPrev];
3635  idxRightNext++;
3636  idxRightPrev++;
3637  sum = (sumLeft < sumRight) ? sumLeft:sumRight;
3638  if ((uint32_t) (inp[idxCUT]) > ((sum >> (const2 - 1)) + const1))
3639  {
3640  out[outIdx] = idxCUT;
3641  outSNR[outIdx] = inp[idxCUT] - (sum >> (const2 - 1));
3642  outIdx++;
3643  }
3644  }
3645 
3646  /* noiseLen number of CUTs before the last guardLen CUTs. e.g. CUT 20 to 27 */
3647  idxRightNext = 0;
3648  for (idxCUT = len - (noiseLen + guardLen);
3649  idxCUT < len - guardLen; idxCUT++)
3650  {
3651  sumLeft += inp[idxLeftNext] - inp[idxLeftPrev];
3652  idxLeftNext++;
3653  idxLeftPrev++;
3654  sumRight += inp[idxRightNext] - inp[idxRightPrev];
3655  idxRightNext++;
3656  idxRightPrev++;
3657  sum = (sumLeft < sumRight) ? sumLeft:sumRight;
3658  if ((uint32_t) (inp[idxCUT]) > ((sum >> (const2 - 1)) + const1))
3659  {
3660  out[outIdx] = idxCUT;
3661  outSNR[outIdx] = inp[idxCUT] - (sum >> (const2 - 1));
3662  outIdx++;
3663  }
3664  }
3665 
3666  /* The last guardLen number of CUTs */
3667  idxRightPrev = 0;
3668  for (idxCUT = len - guardLen; idxCUT < len; idxCUT++)
3669  {
3670  sumLeft += inp[idxLeftNext] - inp[idxLeftPrev];
3671  idxLeftNext++;
3672  idxLeftPrev++;
3673  sumRight += inp[idxRightNext] - inp[idxRightPrev];
3674  idxRightNext++;
3675  idxRightPrev++;
3676  sum = (sumLeft < sumRight) ? sumLeft:sumRight;
3677  if ((uint32_t) (inp[idxCUT]) > ((sum >> (const2 - 1)) + const1))
3678  {
3679  out[outIdx] = idxCUT;
3680  outSNR[outIdx] = inp[idxCUT] - (sum >> (const2 - 1));
3681  outIdx++;
3682  }
3683  }
3684  return (outIdx);
3685 } /* cfarCa_SO_dBwrap_withSNR */
3686 
3687 
3713 uint32_t MmwDemo_cfarPeakGrouping(
3714  MmwDemo_detectedObjActual* objOut,
3715  uint32_t numDetectedObjects,
3716  uint16_t* detMatrix,
3717  uint32_t numRangeBins,
3718  uint32_t numDopplerBins,
3719  uint32_t groupInDopplerDirection,
3720  uint32_t groupInRangeDirection)
3721 {
3722  int32_t i, j;
3723  int32_t rowStart, rowEnd;
3724  uint32_t numObjOut = 0;
3725  uint32_t rangeIdx, dopplerIdx;
3726  uint16_t *tempPtr;
3727  uint16_t kernel[9], detectedObjFlag;
3728  int32_t k, l;
3729  uint32_t startInd, stepInd, endInd;
3730  MmwDemo_detectedObjActual * objRaw = objOut;
3731 
3732  if ((groupInDopplerDirection == 1) && (groupInRangeDirection == 1))
3733  {
3734  /* Grouping both in Range and Doppler direction */
3735  startInd = 0;
3736  stepInd = 1;
3737  endInd = 8;
3738  }
3739  else if ((groupInDopplerDirection == 0) && (groupInRangeDirection == 1))
3740  {
3741  /* Grouping only in Range direction */
3742  startInd = 1;
3743  stepInd = 3;
3744  endInd = 7;
3745  }
3746  else if ((groupInDopplerDirection == 1) && (groupInRangeDirection == 0))
3747  {
3748  /* Grouping only in Doppler direction */
3749  startInd = 3;
3750  stepInd = 1;
3751  endInd = 5;
3752  }
3753  else
3754  {
3755  /* No grouping, copy all detected objects to the output matrix within specified min max range*/
3756  return numDetectedObjects;
3757  }
3758 
3759  /* Start checking */
3760  for(i = 0; i < numDetectedObjects; i++)
3761  {
3762  rangeIdx = objRaw[i].rangeIdx;
3763  dopplerIdx = objRaw[i].dopplerIdx;
3764 
3765  detectedObjFlag = 1;
3766 
3767  /* Fill local 3x3 kernel from detection matrix in L3*/
3768  tempPtr = detMatrix + (rangeIdx-1)*numDopplerBins;
3769  rowStart = 0;
3770  rowEnd = 2;
3771 
3772  if (rangeIdx == 0)
3773  {
3774  tempPtr = detMatrix + (rangeIdx)*numDopplerBins;
3775  rowStart = 1;
3776  memset((void *) kernel, 0, 3 * sizeof(uint16_t));
3777  }
3778  else if (rangeIdx == numRangeBins-1)
3779  {
3780  rowEnd = 1;
3781  memset((void *) &kernel[6], 0, 3 * sizeof(uint16_t));
3782  }
3783 
3784  for (j = rowStart; j <= rowEnd; j++)
3785  {
3786  for (k = 0; k < 3; k++)
3787  {
3788  l = dopplerIdx + (k - 1);
3789  if(l < 0)
3790  {
3791  l += numDopplerBins;
3792  }
3793  else if(l >= numDopplerBins)
3794  {
3795  l -= numDopplerBins;
3796  }
3797  kernel[j*3+k] = tempPtr[l];
3798  }
3799  tempPtr += numDopplerBins;
3800  }
3801 
3802  /* Compare the detected object to its neighbors.
3803  * Detected object is at index 4*/
3804  for (k = startInd; k <= endInd; k += stepInd)
3805  {
3806  if(kernel[k] > kernel[4])
3807  {
3808  detectedObjFlag = 0;
3809  }
3810  }
3811 
3812  if (detectedObjFlag == 1)
3813  {
3814  objOut[numObjOut] = objRaw[i];
3815  numObjOut++;
3816  }
3817 
3818  if (numObjOut >= MRR_MAX_OBJ_OUT)
3819  {
3820  break;
3821  }
3822  }
3823 
3824  return (numObjOut);
3825 }
3826 
3849  MmwDemo_objRaw2D_t * restrict objOut,
3850  uint32_t numDetectedObjects,
3851  uint16_t * restrict detMatrix,
3852  uint32_t numRangeBins,
3853  uint32_t numDopplerBins)
3854 {
3855  int32_t i;
3856  uint32_t numObjOut = 0;
3857  uint32_t rangeIdx, dopplerIdx;
3858  uint16_t *tempPtr;
3859  uint16_t kernel[3], detectedObjFlag;
3860  int32_t k, l;
3861 
3862  /* Grouping only in Doppler direction */
3863 
3864  /* Start checking */
3865  for(i = 0; i < numDetectedObjects; i++)
3866  {
3867  rangeIdx = objOut[i].rangeIdx;
3868  dopplerIdx = objOut[i].dopplerIdx;
3869 
3870  detectedObjFlag = 1;
3871 
3872  /* Fill local 1x3 kernel from detection matrix in L3*/
3873  tempPtr = detMatrix + (rangeIdx)*numDopplerBins;
3874 
3875  for (k = 0; k < 3; k++)
3876  {
3877  l = dopplerIdx + (k - 1);
3878 
3879  if(l < 0)
3880  {
3881  l += numDopplerBins;
3882  }
3883  else if(l >= numDopplerBins)
3884  {
3885  l -= numDopplerBins;
3886  }
3887 
3888  kernel[k] = tempPtr[l];
3889  }
3890 
3891  /* Compare the detected object to its neighbors.*/
3892  if ( (kernel[1] < kernel[0]) ||
3893  (kernel[1] < kernel[2]))
3894  {
3895  detectedObjFlag = 0;
3896  }
3897 
3898  if (detectedObjFlag == 1)
3899  {
3900  objOut[numObjOut] = objOut[i];
3901  numObjOut++;
3902  }
3903  }
3904 
3905  return (numObjOut);
3906 }
3907 
3922 uint16_t computeSinAzimSNR(float * azimuthMagSqr, uint16_t azimIdx, uint16_t numVirtualAntAzim, uint16_t numAngleBins, uint16_t xyzOutputQFormat)
3923 {
3924  uint16_t ik, Idx, stepSize;
3925  uint16_t SNR;
3926  stepSize = numAngleBins/numVirtualAntAzim;
3927  float NoiseFloorSqrSum = 0;
3928  float SNRflt;
3929 
3930  for (ik = 1; ik < numVirtualAntAzim ; ik ++)
3931  {
3932  Idx = stepSize*ik + azimIdx;
3933  if (Idx > (numAngleBins - 1))
3934  {
3935  Idx -= numAngleBins;
3936  }
3937  /* azimuthMagSqrLim[Idx]| Idx== 0 is the peak index, azimuthMagSqrLim[Idx] |
3938  * Idx == 1:numVirtualAntAzim-1] are the noise samples. */
3939  NoiseFloorSqrSum += azimuthMagSqr[Idx];
3940  }
3941 
3942  /* SNR = azimuthMagSqr[azimIdx]/(NoiseFloorSqrSum/(numVirtualAntAzim-1)) */
3943  SNRflt = divsp((azimuthMagSqr[azimIdx]*(numVirtualAntAzim-1)),NoiseFloorSqrSum);
3944 
3945  /* Some checks before converting to uint16_t */
3946  SNRflt = (SNRflt * (float) (1 << xyzOutputQFormat));
3947  if (SNRflt > 65535.0f)
3948  {
3949  SNR = 65535;
3950  }
3951  else
3952  {
3953  SNR = (uint16_t) _spint(SNRflt);
3954  }
3955 
3956  return SNR;
3957 }
3958 
3959 
3974 float convertSNRdBToVar(uint16_t SNRdB,uint16_t bitW, uint16_t n_samples, float resolution)
3975 {
3976  float fVar, RVar;
3977  float scaleFac = (n_samples*resolution);
3978  float resThresh = 2 * resolution * resolution;
3979  float invSNRlin = antilog2(-SNRdB, bitW) * 2; // We assume our estimator is 3dB worse than the CRLB.
3980 
3981  /* CRLB for a frequency estimate */
3982  fVar = (float)invSNRlin * (6.0f/((2.0f*PI_)*(2.0f*PI_))) * recipsp((n_samples*n_samples - 1));
3983 
3984  /* Convert to a parameter variance using the scalefactor. */
3985  RVar = fVar*scaleFac*scaleFac;
3986 
3987  if (RVar < resThresh)
3988  {
3989  RVar = resThresh;
3990  }
3991  return RVar;
3992 
3993 }
3994 
4011 float convertSNRLinToVar(uint16_t SNRLin,uint16_t bitW, uint16_t n_samples, float resolution)
4012 {
4013  float fVar, RVar;
4014  float scaleFac = (n_samples*resolution);
4015  float invSNRlin;
4016 
4017  DebugP_assert(SNRLin);
4018  invSNRlin = recipsp( (float) SNRLin) * ((float) (1 << bitW));
4019 
4020  /* CRLB for a frequency estimate */
4021  fVar = (float)invSNRlin * (6.0f/((2.0f*PI_)*(2.0f*PI_))) * recipsp((n_samples*n_samples - 1));
4022 
4023  /* Convert to a parameter variance using the scalefactor. */
4024  RVar = fVar*scaleFac*scaleFac;
4025 
4026  return RVar;
4027 }
4028 
4040 float antilog2(int32_t inputActual, uint16_t fracBitIn)
4041 {
4042  float output;
4043  float input = (float)inputActual;
4044 
4045  input = divsp(input , (float)(1 << fracBitIn));
4046  output = exp2sp(input);
4047 
4048  return output;
4049 }
4050 
4062 uint32_t aziEleProcessing(DSS_DataPathObj *obj, uint32_t subframeIndx)
4063 {
4064  volatile uint32_t detIdx2;
4065  uint32_t numChirpTypes = 1;
4066  uint32_t numDetObj2D = obj->numDetObj;
4067  volatile uint32_t startTime;
4068  volatile uint32_t startTimeWait;
4069  uint32_t waitingTime = 0;
4070  uint32_t rxAntIdx;
4071  uint32_t cubeOffset;
4072 
4074  {
4075  numChirpTypes = 2;
4076  }
4077 
4081  for (detIdx2 = 0; detIdx2 < numDetObj2D; detIdx2++)
4082  {
4083  uint8_t chId;
4084 
4085 
4086  if (subframeIndx == 0)
4087  {
4089  }
4090  /* else
4091  {
4092  chId = MRR_SF1_EDMA_CH_3D_IN_PING;
4093  }*/
4094 
4095  /* Set source for first (ping) DMA and trigger it, and set source second (Pong) DMA */
4096  cubeOffset = obj->numDopplerBins * obj->numRxAntennas *
4097  obj->numTxAntennas * (uint32_t) obj->detObj2D[detIdx2].rangeIdx * numChirpTypes;
4100  (uint8_t *)(&obj->radarCube[cubeOffset]),
4101  (uint8_t *)NULL,
4102  (uint8_t)chId,
4103  (uint8_t)MRR_EDMA_TRIGGER_ENABLE);
4104 
4105  if (subframeIndx == 0)
4106  {
4108  }
4109  /*else
4110  {
4111  chId = MRR_SF1_EDMA_CH_3D_IN_PONG;
4112  } */
4113 
4114  cubeOffset = ((obj->numDopplerBins * obj->numRxAntennas *
4115  obj->numTxAntennas * ((uint32_t)obj->detObj2D[detIdx2].rangeIdx) * numChirpTypes) + obj->numDopplerBins);
4118  (uint8_t *)(&obj->radarCube[cubeOffset]),
4119  (uint8_t *)NULL,
4120  (uint8_t)chId,
4121  (uint8_t)MRR_EDMA_TRIGGER_DISABLE);
4122 
4123  for (rxAntIdx = 0; rxAntIdx < (obj->numRxAntennas * obj->numTxAntennas); rxAntIdx++)
4124  {
4125  /* verify that previous DMA has completed. */
4126  startTimeWait = Cycleprofiler_getTimeStamp();
4127  MmwDemo_dataPathWait3DInputData(obj, pingPongId(rxAntIdx), subframeIndx);
4128  waitingTime += Cycleprofiler_getTimeStamp() - startTimeWait;
4129 
4130  /* kick off next DMA. */
4131  if (rxAntIdx < (obj->numRxAntennas * obj->numTxAntennas) - 1)
4132  {
4133  if (isPong(rxAntIdx))
4134  {
4137  subframeIndx);
4138  }
4139  else
4140  {
4143  subframeIndx);
4144  }
4145  }
4146 
4147  /* Calculate one bin DFT, at detected doppler index. */
4148  mmwavelib_dftSingleBinWithWindow(
4149  (uint32_t *)&obj->dstPingPong[pingPongId(rxAntIdx) * obj->numDopplerBins],
4150  (uint32_t *) obj->azimuthModCoefs,
4151  obj->window2D,
4152  (uint64_t *) &obj->antInp[rxAntIdx],
4153  obj->numDopplerBins,
4155 
4156 
4157  }
4158  /* Rx channel gain/phase offset compensation. */
4160  (int64_t *) obj->antInp,
4161  obj->numTxAntennas * obj->numRxAntennas);
4162 
4163 
4164  /* Reset input buffer to azimuth FFT */
4165  memset((uint8_t *)obj->azimuthIn, 0, obj->numAngleBins * sizeof(cmplx32ReIm_t));
4166 
4167  /* Reset input buffer to azimuth FFT */
4168  memset((uint8_t *)obj->elevationIn, 0, obj->numAngleBins * sizeof(cmplx32ReIm_t));
4169 
4170  /* Populate the first four. */
4171  for (rxAntIdx = 0; rxAntIdx < (obj->numRxAntennas); rxAntIdx++)
4172  {
4173  obj->azimuthIn[rxAntIdx].real = obj->antInp[rxAntIdx].real/8;
4174  obj->azimuthIn[rxAntIdx].imag = obj->antInp[rxAntIdx].imag/8;
4175  }
4176 
4177  if (obj->numTxAntennas == 2)
4178  {
4179  /* Populate the second four. */
4180  for (rxAntIdx = 0; rxAntIdx < (obj->numRxAntennas); rxAntIdx++)
4181  {
4182  obj->azimuthIn[rxAntIdx+obj->numRxAntennas].real = obj->antInp[rxAntIdx+obj->numRxAntennas].real/8;
4183  obj->azimuthIn[rxAntIdx+obj->numRxAntennas].imag = obj->antInp[rxAntIdx+obj->numRxAntennas].imag/8;
4184  }
4185 
4186  }
4187  else if(obj->numTxAntennas == 3)
4188  {
4189  /* Populate the second four. */
4190  for (rxAntIdx = 0; rxAntIdx < (obj->numRxAntennas); rxAntIdx++)
4191  {
4192  obj->azimuthIn[rxAntIdx+obj->numRxAntennas].real = obj->antInp[rxAntIdx + (2*(obj->numRxAntennas))].real/8;
4193  obj->azimuthIn[rxAntIdx+obj->numRxAntennas].imag = obj->antInp[rxAntIdx + (2*(obj->numRxAntennas))].imag/8;
4194  }
4195 
4196  /* Populate the samples corresponding to the 'Tx' that is offset in elevation. */
4197  for (rxAntIdx = 0; rxAntIdx < (obj->numRxAntennas); rxAntIdx++)
4198  {
4199  /* The 'virtual antenna' corresponding to the tx is offset in elevation. */
4200  obj->elevationIn[rxAntIdx + 2].real = obj->antInp[rxAntIdx + obj->numRxAntennas].real/8;
4201  obj->elevationIn[rxAntIdx + 2].imag = obj->antInp[rxAntIdx + obj->numRxAntennas].imag/8;
4202  }
4203  }
4204 
4205  /* Compensation of Doppler phase shift in the virtual antennas, (correponding
4206  * to second Tx antenna chirps). Symbols corresponding to virtual antennas,
4207  * are rotated by half of the Doppler phase shift measured by Doppler FFT.
4208  * The phase shift read from the table using half of the object
4209  * Doppler index value. If the Doppler index is odd, an extra half
4210  * of the bin phase shift is added. */
4211  if (obj->numTxAntennas > 1)
4212  {
4213  #if 1
4214  /* Add doppler compensation for the virtual antennas ([8 9 10 11] corresponding to the second half of the azimuthIn vector. */
4216  (int32_t) obj->numDopplerBins,
4217  (uint32_t *) obj->azimuthModCoefs,
4218  (uint32_t *) &obj->azimuthModCoefsThirdBin,
4219  (uint32_t *) &obj->azimuthModCoefsTwoThirdBin,
4220  (int64_t *) &obj->azimuthIn[obj->numRxAntennas],
4221  obj->numRxAntennas * (1),
4222  obj->numTxAntennas, 2/*For Tx3*/);
4223  /* Add doppler compensation for the virtual antennas ([4 5 6 7] corresponding to the elevationIn vector. */
4225  (int32_t) obj->numDopplerBins,
4226  (uint32_t *) obj->azimuthModCoefs,
4227  (uint32_t *)&obj->azimuthModCoefsThirdBin,
4228  (uint32_t *)&obj->azimuthModCoefsTwoThirdBin,
4229  (int64_t *) &obj->elevationIn[0],
4230  obj->numRxAntennas * (1),
4231  obj->numTxAntennas, 1 /*for Tx2*/);
4232  #endif
4233 
4234  }
4235 
4236  /* FFT on the antenna array [4 5 6 7]. */
4238  {
4239  /* 3D-FFT (Azimuth FFT on the second row) */
4240 
4241  DSP_fft32x32((int32_t *)obj->azimuthTwiddle32x32, obj->numAngleBins,
4242  (int32_t *)obj->elevationIn, (int32_t *)obj->elevationOut);
4243  }
4244 
4245 
4246 
4247 
4249  {
4250  //TODO DIsable for 3 Tx mode.
4251  /* Save copy for the flipped version for Velocity disambiguation */
4252  memcpy((void *) &obj->azimuthIn[obj->numAngleBins],
4253  (void *) &obj->azimuthIn[0],
4254  obj->numVirtualAntAzim * sizeof(cmplx32ReIm_t));
4255  }
4256 
4257  /* 3D-FFT (Azimuth FFT on the first row) i.e [0 1 2 3 8 9 10 11]. */
4258  DSP_fft32x32((int32_t *)obj->azimuthTwiddle32x32, obj->numAngleBins,
4259  (int32_t *)obj->azimuthIn, (int32_t *)obj->azimuthOut);
4260 
4262 
4263 
4265  {
4266  /* Zero padding */
4267  memset((void *) &obj->azimuthIn[obj->numVirtualAntAzim], 0,
4268  (obj->numAngleBins - obj->numVirtualAntAzim) * sizeof(cmplx32ReIm_t));
4269  /* Retrieve saved copy of FFT input symbols */
4270  memcpy((void *) &obj->azimuthIn[0], (void *) &obj->azimuthIn[obj->numAngleBins],
4271  obj->numVirtualAntAzim * sizeof(cmplx32ReIm_t));
4272 
4273  {
4274  /* Negate symbols corresponding to Tx2 antenna */
4275  uint32_t jj;
4276  for(jj = obj->numRxAntennas; jj<obj->numVirtualAntAzim; jj++)
4277  {
4278  obj->azimuthIn[jj].imag = -obj->azimuthIn[jj].imag;
4279  obj->azimuthIn[jj].real = -obj->azimuthIn[jj].real;
4280  }
4281  }
4282 
4283  /* 3D-FFT (Azimuth FFT) */
4284  DSP_fft32x32(
4285  (int32_t *)obj->azimuthTwiddle32x32,
4286  obj->numAngleBins,
4287  (int32_t *) obj->azimuthIn,
4288  (int32_t *) obj->azimuthOut);
4289 
4291  obj->azimuthOut,
4292  &obj->azimuthMagSqr[obj->numAngleBins],
4293  obj->numAngleBins);
4294  }
4295 
4296  /* Calculate XY coordinates in meters */
4298  {
4299  MmwDemo_XYZestimation(obj, detIdx2);
4300  }
4301  else
4302  {
4303  MmwDemo_XYestimation(obj, detIdx2);
4304  }
4305  }
4306 
4307  return waitingTime;
4308 }
4309 
4325 void associateClustering(clusteringDBscanOutput_t * restrict output,
4326  clusteringDBscanReport_t * restrict state,
4327  uint16_t maxNumClusters,
4328  int32_t epsilon2,
4329  int32_t vFactor)
4330 {
4331  uint32_t outputIdx, stateIdx;
4332  int32_t a;
4333  int32_t b;
4334  int32_t c;
4335  int32_t vFactorTmp;
4336  int32_t assocIndx = -1;
4337  uint32_t distSqMax;
4338  uint32_t distSq;
4339 
4340  for (stateIdx = 0; stateIdx < maxNumClusters; stateIdx++)
4341  {
4342  int32_t isAssociated = 0;
4343 
4344  if (state[stateIdx].numPoints == 0)
4345  {
4346  continue;
4347  }
4348 
4349  assocIndx = -1;
4350  distSqMax = UINT32_MAX;
4351  for (outputIdx = 0; outputIdx < output->numCluster; outputIdx++)
4352  {
4353  /* Check if it is a valid cluster. */
4354  if (output->report[outputIdx].numPoints == 0)
4355  {
4356  continue;
4357  }
4358 
4359  /* Check if it's velocity is close. */
4360  c = (state[stateIdx].avgVel - output->report[outputIdx].avgVel);
4361 
4362  vFactorTmp = vFactor;
4363 
4364  if (_abs(state[stateIdx].avgVel) < vFactorTmp)
4365  {
4366  vFactorTmp = _abs(state[stateIdx].avgVel);
4367  }
4368 
4369  if (_abs(c) > vFactorTmp)
4370  {
4371  continue;
4372  }
4373 
4374  /* Finally, associate using distance */
4375  a = (state[stateIdx].xCenter - output->report[outputIdx].xCenter);
4376  b = (state[stateIdx].yCenter - output->report[outputIdx].yCenter);
4377  distSq = (a*a + b*b);
4378 
4379 
4380  if (distSq < epsilon2)
4381  {
4382  if (distSq < distSqMax)
4383  {
4384  distSqMax = distSq;
4385  assocIndx = outputIdx;
4386  }
4387  }
4388  }
4389 
4390  if (distSqMax < UINT32_MAX)
4391  {
4392  state[stateIdx].xCenter = output->report[assocIndx].xCenter;
4393  state[stateIdx].yCenter = output->report[assocIndx].yCenter;
4394  state[stateIdx].numPoints = output->report[assocIndx].numPoints;
4395  state[stateIdx].avgVel = output->report[assocIndx].avgVel;
4396 
4397  /* IIR filter the sizes, so that they don't change too rapidly. */
4398  state[stateIdx].xSize = (int16_t)(7*((int32_t)state[stateIdx].xSize) + (int32_t)(output->report[assocIndx].xSize)) >> 3;
4399  state[stateIdx].ySize = (int16_t)(7*((int32_t)state[stateIdx].ySize) + (int32_t)(output->report[assocIndx].ySize)) >> 3;
4400 
4401 
4402  /* Having been associate, clear out this report. */
4403  output->report[assocIndx].numPoints = 0;
4404  isAssociated = 1;
4405  }
4406 
4407  if (isAssociated == 0)
4408  {
4409  state[stateIdx].numPoints = 0;
4410  }
4411  }
4412 
4413  for (outputIdx = 0; outputIdx < output->numCluster; outputIdx++)
4414  {
4415  if (output->report[outputIdx].numPoints == 0)
4416  {
4417  /* Already associated, so ignore. */
4418  continue;
4419  }
4420 
4421  for (stateIdx = 0; stateIdx < maxNumClusters; stateIdx++)
4422  {
4423  /* Find an empty state. */
4424  if (state[stateIdx].numPoints == 0)
4425  {
4426  state[stateIdx] = output->report[outputIdx];
4427  output->report[outputIdx].numPoints = 0;
4428  break;
4429  }
4430  }
4431  }
4432 }
4433 
4434 
4451 #define TWENTY_TWO_DB_DOPPLER_SNR ((22 *(256))/6)
4452 #define EIGHTEEN_DB_DOPPLER_SNR ((18 *(256))/6)
4453 #define ZERO_POINT_FIVE_METERS (0.5f * 128)
4454 #define FOUR_POINT_ZERO_METERS (4 * 128)
4456 {
4457  uint32_t ik,jk;
4458  float oneQFormat = (float) (1U << obj->xyzOutputQFormat);
4459 
4460  MmwDemo_detectedObjActual * restrict detObj2D = obj->detObj2D;
4461  MmwDemo_detectedObjForTx * restrict detObjFinal = obj->detObjFinal;
4462  clusteringDBscanReport_t * restrict clusterReport = obj->dbScanState;
4463  clusteringDBscanReportForTx * restrict clusterRepFinal = obj->clusterOpFinal;
4464  KFstate_t * restrict trackerState = obj->trackerState;
4465  trackingReportForTx * restrict trackerOpFinal = obj->trackerOpFinal;
4466 
4467  _nassert((uint32_t) detObjFinal % 8 == 0);
4468  _nassert((uint32_t) detObj2D % 8 == 0);
4469 
4470 
4471  /* 1. Detected Object List */
4472  for (ik = 0; ik < obj->numDetObj; ik ++)
4473  {
4474  detObjFinal[ik].speed = detObj2D[ik].speed;
4475  detObjFinal[ik].peakVal = detObj2D[ik].peakVal;
4476  detObjFinal[ik].x = detObj2D[ik].x;
4477  detObjFinal[ik].y = detObj2D[ik].y;
4478  detObjFinal[ik].z = detObj2D[ik].z;
4479 
4480 #ifdef SEND_SNR_INFO
4481  detObjFinal[ik].rangeSNRdB = detObj2D[ik].rangeSNRdB;
4482  detObjFinal[ik].dopplerSNRdB = detObj2D[ik].dopplerSNRdB;
4483 #endif
4484  }
4485 
4486 
4487  /* 2. Clustering output for the point cloud subframe. */
4489  {
4490  _nassert((uint32_t) clusterReport % 8 == 0);
4491  _nassert((uint32_t) clusterRepFinal % 8 == 0);
4492 
4493  jk = 0;
4494  for (ik = 0; ik < obj->dbScanInstance.maxClusters; ik ++)
4495  {
4496  if (clusterReport[ik].numPoints == 0)
4497  {
4498  continue;
4499  }
4500 
4501  clusterRepFinal[jk].xCenter = clusterReport[ik].xCenter;
4502  clusterRepFinal[jk].yCenter = clusterReport[ik].yCenter;
4503  clusterRepFinal[jk].xSize = clusterReport[ik].xSize;
4504  clusterRepFinal[jk].ySize = clusterReport[ik].ySize;
4505  jk ++;
4506  }
4508  }
4509 
4510  /* 3. Tracking output for the max-vel-enh subframe. */
4512  {
4513  _nassert((uint32_t) trackerState % 8 == 0);
4514  _nassert((uint32_t) trackerOpFinal % 8 == 0);
4515 
4516  jk = 0;
4517 
4519  for (ik = 0; ik < obj->trackerInstance.maxTrackers; ik ++)
4520  {
4521  if (trackerState[ik].validity == 0)
4522  {
4523  continue;
4524  }
4525 
4526  if (trackerState[ik].tick < MIN_TICK_FOR_TX)
4527  {
4528  continue;
4529  }
4530 
4531  if (trackerState[ik].age > AGED_OBJ_DELETION_THRESH)
4532  {
4533  continue;
4534  }
4535 
4536  trackerOpFinal[jk].x = (int16_t) (obj->trackerState[ik].vec[iX]*oneQFormat);
4537  trackerOpFinal[jk].y = (int16_t) (obj->trackerState[ik].vec[iY]*oneQFormat);
4538  trackerOpFinal[jk].xd = (int16_t) (obj->trackerState[ik].vec[iXd]*oneQFormat);
4539  trackerOpFinal[jk].yd = (int16_t) (obj->trackerState[ik].vec[iYd]*oneQFormat);
4540  trackerOpFinal[jk].xSize = obj->trackerState[ik].xSize;
4541  trackerOpFinal[jk].ySize = obj->trackerState[ik].ySize;
4542 
4543  jk ++;
4544  }
4545  obj->numActiveTrackers = jk;
4546  }
4547 
4548  /* 4. Parking assist : i.e Closest obstruction as a function of angle.*/
4550  {
4551  uint16_t range;
4552  int32_t sinAzim;
4553  int16_t binIdx, binIdxTmp, nExp;
4554 
4555  _nassert((uint32_t) obj->parkingAssistBins % 8 == 0);
4556  _nassert((uint32_t) obj->parkingAssistBinsState % 8 == 0);
4557 
4558  /* Initialize the parking grid to the maximum value. */
4559  for (ik = 0; ik < obj->parkingAssistNumBins; ik++)
4560  {
4561  obj->parkingAssistBins[ik] = obj->parkingAssistMaxRange;
4562  }
4563 
4564  for (ik = 0; ik < obj->numDetObj; ik ++)
4565  {
4566  range = (uint16_t) detObj2D[ik].range;
4567 
4568  if (range > obj->parkingAssistMaxRange)
4569  continue;
4570 
4571  if (range < obj->parkingAssistMinRange)
4572  continue;
4573 
4574  /* Compute the angle (i.e. sin (azim) ). */
4575  sinAzim = (int32_t) detObj2D[ik].sinAzim;
4576  if (sinAzim < 0)
4577  {
4578  /* Since sinAzim can vary from -2^sinAzimQFormat to + 2^sinAzimQFormat,
4579  * convert it to a positive number. */
4580  sinAzim = sinAzim + (1 << (obj->sinAzimQFormat+1));
4581  }
4582  /* Quantize the angle to a number between 0 and parkingAssistNumBins */
4583  binIdx = (int16_t) (sinAzim >> (1 + obj->sinAzimQFormat - obj->parkingAssistNumBinsLog2));
4584 
4585  if (binIdx > obj->parkingAssistNumBins - 1)
4586  {
4587  binIdx = obj->parkingAssistNumBins - 1;
4588  }
4589 
4590  /* The default object obstructs only one bin. However, if the object is stationary, the
4591  * poor angle resolution of 4x2 antenna array needs to be compensated for. */
4592  nExp = 1;
4593 
4594  if (detObj2D[ik].dopplerIdx == 0)
4595  {
4596  /* If the object has zero relative velocity w.r.t the radar, the point cloud it can
4597  * generate would be quite sparse. Therefore, we use the RCS (peakVal is a function
4598  * of RCS), and expand the object size based on heuristics related to peakVal. */
4599  if (detObj2D[ik].dopplerSNRdB > TWENTY_TWO_DB_DOPPLER_SNR)
4600  {
4601  nExp = 5;
4602  }
4603  else if (detObj2D[ik].dopplerSNRdB > EIGHTEEN_DB_DOPPLER_SNR)
4604  {
4605  nExp = 3;
4606  }
4607  else
4608  {
4609  nExp = 2;
4610  }
4611  }
4612 
4613  for (jk = 0; jk < 2*nExp + 1; jk++)
4614  {
4615  binIdxTmp = binIdx - nExp + jk;
4616 
4617  if (binIdxTmp > obj->parkingAssistNumBins - 1)
4618  {
4619  binIdxTmp = binIdxTmp - obj->parkingAssistNumBins ;
4620  }
4621 
4622  if (obj->parkingAssistBins[binIdxTmp] > range)
4623  {
4624  obj->parkingAssistBins[binIdxTmp] = range;
4625  }
4626  }
4627  }
4628 
4629  for (ik = 0; ik < obj->parkingAssistNumBins; ik++)
4630  {
4631  uint32_t State = obj->parkingAssistBinsState[ik];
4632  uint16_t StateCnt = obj->parkingAssistBinsStateCnt[ik];
4633  uint32_t Meas = obj->parkingAssistBins[ik];
4634 
4635  /* In general, we would like to update the parking grid instantaneously based on the
4636  * current list of detected objects, however, in most cases, clutter, and inconsistent
4637  * detection results can give rise to cases where objects blink in and out of existance.
4638  * the instantaeous output may not best reflect the scene in front of the car. Some
4639  * filtering on the grid positions is necessary. The state of the grid is saved across
4640  * frames and updated in a 2-stage manner.
4641  *
4642  * The filtering is performed in two stages, the first adds hysterisis to the grid. It
4643  * takes into account the fact that some objects are intermittent (i.e they tend to
4644  * appear and disappear), and some objects located at the boundary of two neighbouring
4645  * grids, and could move between the two. Each grid is assigned an age, and only
4646  * updated after the age exceeds a threshold. The thresholds are different if the object
4647  * is before the grid or after the grid because objects appearing before a grid (i.e a
4648  * a target moving closer) is considered higher priority. There is a threshold
4649  *
4650  *
4651  * The 2nd stage is a simple IIR filter with different constants depending on whether the
4652  * updated position is before or behind the current grid location. */
4653 
4654 
4655  if ( (Meas > State) && ((Meas - State) > ZERO_POINT_FIVE_METERS) && (StateCnt < 3) )
4656  {
4657  /* If a detected point disappears, wait for three epochs to begin updating it. */
4658  obj->parkingAssistBinsState[ik] = obj->parkingAssistBinsState[ik];
4659  obj->parkingAssistBins[ik] = obj->parkingAssistBinsState[ik];
4660  if (obj->parkingAssistBinsStateCnt[ik] < 8)
4661  {
4662  obj->parkingAssistBinsStateCnt[ik]++;
4663  }
4664  }
4665  else if ((Meas > State) && ((Meas - State) > ZERO_POINT_FIVE_METERS) && (StateCnt < 10))
4666  {
4667  /* If a point moves away rapidly (ie 0.5 meters in about 60ms), let it update slower. */
4668  obj->parkingAssistBinsState[ik] = (uint16_t) (15*(State) + Meas) >> 4;
4669  obj->parkingAssistBins[ik] = obj->parkingAssistBinsState[ik];
4670  if (obj->parkingAssistBinsStateCnt[ik] < 16)
4671  {
4672  obj->parkingAssistBinsStateCnt[ik]++;
4673  }
4674  }
4675  else if ((Meas < State) && ((State - Meas) > FOUR_POINT_ZERO_METERS) && (StateCnt < 1))
4676  {
4677  /* If a point disappears, wait for one epoch to begin updating it. */
4678  obj->parkingAssistBinsState[ik] = obj->parkingAssistBinsState[ik];
4679  obj->parkingAssistBins[ik] = obj->parkingAssistBinsState[ik];
4680  if (obj->parkingAssistBinsStateCnt[ik] < 1)
4681  {
4682  obj->parkingAssistBinsStateCnt[ik]++;
4683  }
4684  }
4685  else
4686  {
4687  /* Regular IIR update of the parking distance. */
4688  obj->parkingAssistBinsState[ik] = (uint16_t) (3*(State) + Meas) >> 2;
4689  obj->parkingAssistBins[ik] = obj->parkingAssistBinsState[ik];
4690  obj->parkingAssistBinsStateCnt[ik] = 0;
4691  }
4692  }
4693  }
4694 }
4695 
4696 
4709 uint32_t pruneTrackingInput(trackingInputReport_t * trackingInput, const uint32_t numCluster)
4710 {
4711  uint32_t ik = 0;
4712  uint32_t jk = 0;
4713 
4714  for (ik = 0; ik < numCluster; ik ++)
4715  {
4716  if ( (_fabsf(trackingInput[ik].measVec[iSIN_AZIM]) < SIN_55_DEGREES)
4717  || (trackingInput[ik].measCovVec[iSIN_AZIM] < TRK_SIN_AZIM_THRESH))
4718  {
4719  if (ik > jk)
4720  {
4721  trackingInput[jk] = trackingInput[ik];
4722  }
4723  jk++;
4724  }
4725  }
4726 
4727  return jk;
4728 }
4729 
4744 float quadraticInterpFltPeakLoc(float * restrict y, int32_t len, int32_t indx)
4745 {
4746  float y0 = y[indx];
4747  float ym1, yp1, thetaPk;
4748  float Den;
4749  if (indx == len - 1)
4750  {
4751  yp1 = y[0];
4752  }
4753  else
4754  {
4755  yp1 = y[indx + 1];
4756  }
4757 
4758  if (indx == 0)
4759  {
4760  ym1 = y[len - 1];
4761  }
4762  else
4763  {
4764  ym1 = y[indx - 1];
4765  }
4766 
4767  Den = (2.0f*( (2.0f*y0) - yp1 - ym1));
4768 
4769  /* A reasonable restriction on the inverse.
4770  * Note that y0 is expected to be larger than
4771  * yp1 and ym1. */
4772  if (Den > 0.15)
4773  {
4774  thetaPk = (yp1 - ym1)* recipsp(Den);
4775  }
4776  else
4777  {
4778  thetaPk = 0.0f;
4779  }
4780  return thetaPk;
4781 }
4782 
4798 float quadraticInterpLog2ShortPeakLoc(uint16_t * restrict y, int32_t len, int32_t indx, uint16_t fracBitIn)
4799 {
4800  float y0 = (float)antilog2(y[indx], fracBitIn);
4801  float ym1, yp1, thetaPk;
4802  float Den;
4803 
4804  /* Circular shifting for finding the neighbour at the extremes. */
4805  if (indx == len - 1)
4806  {
4807  yp1 = antilog2(y[0], fracBitIn);
4808  }
4809  else
4810  {
4811  yp1 = antilog2(y[indx + 1], fracBitIn);
4812  }
4813 
4814  if (indx == 0)
4815  {
4816  ym1 = antilog2(y[len - 1], fracBitIn);
4817  }
4818  else
4819  {
4820  ym1 = antilog2(y[indx - 1], fracBitIn);
4821  }
4822 
4823  Den = (2.0f*( (2.0f*y0) - yp1 - ym1));
4824 
4825  /* A reasonable restriction on the inverse.
4826  * Note that y0 is expected to be larger than
4827  * yp1 and ym1. */
4828  if (Den > 0.15)
4829  {
4830  /* Compute the interpolated maxima as
4831  * thetaPk = (yp1 - ym1)/(2.0f*( (2.0f*y0) - yp1 - ym1))
4832  */
4833  thetaPk = (yp1 - ym1)* recipsp(Den);
4834  }
4835  else
4836  {
4837  thetaPk = 0.0f;
4838  }
4839 
4840  return thetaPk;
4841 }
4842 
4843 
4844 /*!*****************************************************************************************************************
4845  * \brief
4846  * Function Name : MmwDemo_DopplerCompensation
4847  *
4848  * \par
4849  * <b>Description</b> : Compensation of Doppler phase shift in the virtual antennas,
4850  * (corresponding to second Tx antenna chirps). Symbols
4851  * corresponding to virtual antennas, are rotated by half
4852  * of the Doppler phase shift measured by Doppler FFT.
4853  * The phase shift read from the table using half of the
4854  * object Doppler index value. If the Doppler index is
4855  * odd, an extra half of the bin phase shift is added.
4856  *
4857  * @param[in] dopplerIdx : Doppler index of the object
4858  * @param[in] numDopplerBins : Number of Doppler bins
4859  * @param[in] azimuthModCoefs: Table with cos/sin values SIN in even position, COS in odd position
4860  * exp(1j*2*pi*k/N) for k=0,...,N-1 where N is number of Doppler bins.
4861  * @param[out] azimuthModCoefsHalfBin : exp(1j*2*pi* 0.5 /N) //TODO change to 1/3 instead of 1/2 for the correction.
4862  * @param[in,out] azimuthIn :Pointer to antenna symbols to be Doppler compensated
4863  * @param[in] numAnt : Number of antenna symbols to be Doppler compensated
4864  *
4865  * @return void
4866  *
4867  *******************************************************************************************************************
4868  */
4869 void MmwDemo_addDopplerCompensation(int32_t dopplerIdx,
4870  int32_t numDopplerBins,
4871  uint32_t *azimuthModCoefs,
4872  uint32_t *azimuthModCoefsThirdBin,
4873  uint32_t *azimuthModCoefsTwoThirdBin,
4874  int64_t *azimuthIn,
4875  uint32_t numAnt,
4876  uint32_t numTxAnt,
4877  uint16_t txAntIdx)
4878 {
4879  uint32_t expDoppComp;
4880  int32_t dopplerCompensationIdx = dopplerIdx;
4881  int64_t azimuthVal;
4882  int32_t Re, Im;
4883  uint32_t antIndx;
4884 
4885  if (numAnt == 0)
4886  {
4887  return;
4888  }
4889 
4890  /*Divide Doppler index by 2*/
4891  if (dopplerCompensationIdx >= (numDopplerBins >> 1))
4892  {
4893  dopplerCompensationIdx -= (int32_t)numDopplerBins;
4894  }
4895  // dopplerCompensationIdx = (dopplerCompensationIdx >> 1);
4896  /* Doppler phase correction is 1/2 or (1/3 in elevation case) of the phase between two chirps of the same antenna */
4897  dopplerCompensationIdx = ((dopplerCompensationIdx * txAntIdx )/numTxAnt);
4898 
4899  if (dopplerCompensationIdx < 0)
4900  {
4901  dopplerCompensationIdx += (int32_t) numDopplerBins;
4902  }
4903  expDoppComp = azimuthModCoefs[dopplerCompensationIdx];
4904  /* Add third bin rotation if Doppler index was odd */
4905  if ((dopplerIdx%numTxAnt) == 1)
4906  {
4907  expDoppComp = _cmpyr1(expDoppComp, *azimuthModCoefsThirdBin);
4908  }
4909  else if((dopplerIdx%numTxAnt) == 2)
4910  {
4911  expDoppComp = _cmpyr1(expDoppComp, *azimuthModCoefsTwoThirdBin);
4912  }
4913 
4914  /* Rotate symbols */
4915  for (antIndx = 0; antIndx < numAnt; antIndx++)
4916  {
4917  azimuthVal = _amem8(&azimuthIn[antIndx]);
4918  Re = _ssub(_mpyhir(expDoppComp, _loll(azimuthVal) ),
4919  _mpylir(expDoppComp, _hill(azimuthVal)));
4920  Im = _sadd(_mpylir(expDoppComp, _loll(azimuthVal)),
4921  _mpyhir(expDoppComp, _hill(azimuthVal)));
4922  _amem8(&azimuthIn[antIndx]) = _itoll(Im, Re);
4923  }
4924 }
4925 
4926 //#ifdef COMPENSATE_FOR_GAIN_PHASE_OFFSET
4927 /*!*****************************************************************************************************************
4928  * \brief
4929  * Function Name : MmwDemo_rxChanPhaseBiasCompensation
4930  *
4931  * \par
4932  * <b>Description</b> : Compensation of rx channel phase bias
4933  *
4934  * @param[in] rxChComp : rx channel compensation coefficient
4935  * @param[in] input : 32-bit complex input symbols must be 64 bit aligned
4936  * @param[in] numAnt : number of symbols
4937  *
4938  * @return void
4939  *
4940  *******************************************************************************************************************
4941  */
4942 static inline void MmwDemo_rxChanPhaseBiasCompensation(uint32_t *rxChComp,
4943  int64_t *input,
4944  uint32_t numAnt)
4945 {
4946  int64_t azimuthVal;
4947  int32_t Re, Im;
4948  uint32_t antIndx;
4949  uint32_t rxChCompVal;
4950 
4951 
4952  /* Compensation */
4953  for (antIndx = 0; antIndx < numAnt; antIndx++)
4954  {
4955  azimuthVal = _amem8(&input[antIndx]);
4956 
4957  rxChCompVal = _amem4(&rxChComp[antIndx]);
4958 
4959 
4960 
4961  Re = _ssub(_mpyhir(rxChCompVal, _loll(azimuthVal) ),
4962  _mpylir(rxChCompVal, _hill(azimuthVal)));
4963  Im = _sadd(_mpylir(rxChCompVal, _loll(azimuthVal)),
4964  _mpyhir(rxChCompVal, _hill(azimuthVal)));
4965  _amem8(&input[antIndx]) = _itoll(Im, Re);
4966  }
4967 }
4968 //#endif
4969 
4985 void MmwDemo_XYcalc (DSS_DataPathObj *obj,
4986  uint32_t objIndex,
4987  uint16_t azimIdx,
4988  float * azimuthMagSqr)
4989 {
4990  int32_t sMaxIdx;
4991  float temp;
4992  float Wx, offset, sMaxIdxFlt;
4993  float range;
4994  float x, y;
4995  uint32_t xyzOutputQFormat = obj->xyzOutputQFormat;
4996  uint32_t oneQFormat = (1 << xyzOutputQFormat);
4997  float invOneQFormat = obj->invOneQFormat;
4998  uint32_t sinAzimOneQFormat = (1 << obj->sinAzimQFormat);
4999 
5000  uint32_t numAngleBins = obj->numAngleBins;
5001 
5002  /* Calculate X and Y coordiantes in meters in Q8 format */
5003  range = ((float) obj->detObj2D[objIndex].range) * invOneQFormat;
5004 
5005  if (azimIdx > ((numAngleBins >> 1) - 1))
5006  {
5007  sMaxIdx = azimIdx - numAngleBins;
5008  }
5009  else
5010  {
5011  sMaxIdx = azimIdx;
5012  }
5013 
5014  /* Add in the offset from the quadratic interpolation. */
5015  offset = quadraticInterpFltPeakLoc(azimuthMagSqr, numAngleBins, azimIdx);
5016  sMaxIdxFlt = ((float)sMaxIdx) + offset;
5017 
5018  Wx = 2 * sMaxIdxFlt *obj->invNumAngleBins;
5019  x = range * Wx;
5020 
5021  /* y = sqrt(range^2 - x^2) */
5022  temp = range*range - x*x;
5023  if (temp > 0)
5024  {
5025  y = sqrtsp(temp);
5026  }
5027  else
5028  {
5029  y = 0;
5030  }
5031 
5032  /* Convert to Q8 format */
5033  obj->detObj2D[objIndex].x = (int16_t)ROUNDF(x * oneQFormat);
5034  obj->detObj2D[objIndex].y = (int16_t)ROUNDF(y * oneQFormat);
5035  obj->detObj2D[objIndex].z = 0;
5036  obj->detObj2D[objIndex].sinAzim = (int16_t)ROUNDF(Wx * sinAzimOneQFormat);
5037  obj->detObj2D[objIndex].sinAzimSNRLin = computeSinAzimSNR(azimuthMagSqr, azimIdx, obj->numVirtualAntAzim, obj->numAngleBins, obj->xyzOutputQFormat);
5038 }
5039 
5055 void MmwDemo_XYZcalc (DSS_DataPathObj *obj,
5056  uint32_t objIndex,
5057  uint16_t azimIdx,
5058  float * azimuthMagSqr)
5059 {
5060  int32_t sMaxIdx;
5061  float temp;
5062  float Wx, offset, sMaxIdxFlt, Wz;
5063  float range;
5064  float x, y , z;
5065  uint32_t xyzOutputQFormat = obj->xyzOutputQFormat;
5066  uint32_t oneQFormat = (1 << xyzOutputQFormat);
5067  float invOneQFormat = obj->invOneQFormat;
5068  uint32_t sinAzimOneQFormat = (1 << obj->sinAzimQFormat);
5069  //int32_t *azimFFTPtr, *elevFFTPtr;
5070  float peakAzimRe, peakAzimIm, peakElevRe, peakElevIm;
5071  float tempRe, tempIm;
5072 
5073 
5074  uint32_t numAngleBins = obj->numAngleBins;
5075 
5076  /* Calculate X, Y and Z coordiantes in meters in Q8 format */
5077  range = ((float) obj->detObj2D[objIndex].range) * invOneQFormat;
5078 
5079  if (azimIdx > ((numAngleBins >> 1) - 1))
5080  {
5081  sMaxIdx = azimIdx - numAngleBins;
5082  }
5083  else
5084  {
5085  sMaxIdx = azimIdx;
5086  }
5087 
5088  /* Add in the offset from the quadratic interpolation. */
5089  offset = quadraticInterpFltPeakLoc(azimuthMagSqr, numAngleBins, azimIdx);
5090  sMaxIdxFlt = ((float)sMaxIdx) + offset;
5091 
5092  Wx = 2 * sMaxIdxFlt *obj->invNumAngleBins;
5093 
5094  x = range * Wx;
5095 
5096 
5097  peakAzimIm = (float) obj->azimuthOut[azimIdx].imag;
5098  peakAzimRe = (float) obj->azimuthOut[azimIdx].real;
5099 
5100  peakElevIm = (float) obj->elevationOut[azimIdx].imag;
5101  peakElevRe = (float) obj->elevationOut[azimIdx].real;
5102 
5103  tempIm = (peakAzimIm * peakElevRe) - (peakAzimRe * peakElevIm);
5104  tempRe = (peakAzimRe * peakElevRe) + (peakAzimIm * peakElevIm);
5105 
5106  Wz = (float) atan2sp(tempIm, tempRe) * (1.0f/PI_) ;
5107  if (Wz > 1)
5108  {
5109  Wz = Wz - 2;
5110  }
5111  else if (Wz < -1)
5112  {
5113  Wz = Wz + 2;
5114  }
5115  z = range * Wz;
5116 
5117 
5118  /* y = sqrt(range^2 - x^2) */
5119  temp = (range*range) - (x*x) - (z*z);
5120  if (temp > 0)
5121  {
5122  y = sqrtsp(temp);
5123  }
5124  else
5125  {
5126  y = 0;
5127  }
5128 
5129  /* Convert to Q8 format */
5130  obj->detObj2D[objIndex].x = (int16_t)ROUNDF(x * oneQFormat);
5131  obj->detObj2D[objIndex].y = (int16_t)ROUNDF(y * oneQFormat);
5132  obj->detObj2D[objIndex].z = (int16_t)ROUNDF(z * oneQFormat);
5133  obj->detObj2D[objIndex].sinAzim = (int16_t)ROUNDF(Wx * sinAzimOneQFormat);
5134  obj->detObj2D[objIndex].sinAzimSNRLin = computeSinAzimSNR(azimuthMagSqr, azimIdx, obj->numVirtualAntAzim, obj->numAngleBins, obj->xyzOutputQFormat);
5135 }
5136 
5137 
5150 {
5151  uint32_t ik;
5152  for (ik = 0; ik < obj->parkingAssistNumBins; ik++)
5153  {
5155  obj->parkingAssistBinsStateCnt[ik] = 0;
5156  }
5157 }
5158 
5176 uint32_t pruneToPeaksOrNeighbourOfPeaks(uint16_t* restrict cfarDetObjIndexBuf,
5177  uint16_t* restrict cfarDetObjSNR,
5178  uint32_t numDetObjPerCfar,
5179  uint16_t* restrict sumAbs,
5180  uint16_t numBins)
5181 {
5182 
5183  uint32_t detIdx2;
5184  uint32_t numDetObjPerCfarActual = 0;
5185  uint16_t currObjLoc, prevIdx, nextIdx;
5186  uint16_t prevPrevIdx, nextNextIdx;
5187  uint16_t is_peak, is_neighbourOfPeakNext, is_neighbourOfPeakPrev;
5188 
5189  if (numDetObjPerCfar == 0)
5190  {
5191  return 0;
5192  }
5193  /* Prune to peaks or neighbours of peaks. */
5194  for (detIdx2 = 0; detIdx2 < numDetObjPerCfar; detIdx2++)
5195  {
5196  currObjLoc = cfarDetObjIndexBuf[detIdx2];
5197 
5198  if (currObjLoc == 0)
5199  {
5200  prevIdx = numBins - 1;
5201  }
5202  else
5203  {
5204  prevIdx = currObjLoc - 1;
5205  }
5206 
5207  if (prevIdx == 0)
5208  {
5209  prevPrevIdx = numBins - 1;
5210  }
5211  else
5212  {
5213  prevPrevIdx = prevIdx ;
5214  }
5215 
5216  if (currObjLoc == numBins - 1)
5217  {
5218  nextIdx = 0;
5219  }
5220  else
5221  {
5222  nextIdx = currObjLoc + 1;
5223  }
5224 
5225  if (nextIdx == numBins - 1)
5226  {
5227  nextNextIdx = 0;
5228  }
5229  else
5230  {
5231  nextNextIdx = currObjLoc + 1;
5232  }
5233 
5234  is_peak = ((sumAbs[nextIdx] < sumAbs[currObjLoc]) && (sumAbs[prevIdx] < sumAbs[currObjLoc]));
5235  is_neighbourOfPeakNext = ((sumAbs[nextNextIdx] < sumAbs[currObjLoc]) && (sumAbs[prevIdx] < sumAbs[currObjLoc]));
5236  is_neighbourOfPeakPrev = ((sumAbs[nextIdx] < sumAbs[currObjLoc]) && (sumAbs[prevPrevIdx] < sumAbs[currObjLoc]));
5237  if (is_peak || is_neighbourOfPeakNext || is_neighbourOfPeakPrev)
5238  {
5239  cfarDetObjIndexBuf[numDetObjPerCfarActual] = currObjLoc;
5240  cfarDetObjSNR[numDetObjPerCfarActual] = cfarDetObjSNR[detIdx2];
5241  numDetObjPerCfarActual++;
5242  }
5243  }
5244 
5245  return numDetObjPerCfarActual;
5246 }
KFstate::ySize
int16_t ySize
Definition: dss_data_path.h:429
MmwDemo_1D_DopplerLines::dopplerLineMaskLen
uint16_t dopplerLineMaskLen
size of dopplerLineMask array, (number of 32_bit words, for example for Doppler FFT size of 64 this l...
Definition: dss_data_path.h:248
DSS_DataPathObj_t::rxChPhaseComp
cmplx16ImRe_t * rxChPhaseComp
Pointer to the Rx Gain phase compensation params.
Definition: dss_data_path.h:531
MmwDemo_interChirpProcessing
void MmwDemo_interChirpProcessing(DSS_DataPathObj *obj, uint32_t chirpPingPongId, uint8_t subframeIndx)
Definition: dss_data_path.c:1562
SNRThresholds
These parameters allow the SNR requirements to be varied as a function of range.
Definition: dss_data_path.h:224
gCycleLog
volatile cycleLog_t gCycleLog
Definition: dss_main.c:99
DSS_DataPathObj_t::edmaHandle
EDMA_Handle edmaHandle[2]
Handle of the EDMA driver.
Definition: dss_data_path.h:450
MmwDemo_CfarCfg_t::winLen
uint8_t winLen
CFAR noise avraging window length.
Definition: mrr_config.h:70
MAX_VEL_ENH_PROCESSING
#define MAX_VEL_ENH_PROCESSING
There are two processing paths in the MRR Demo.
Definition: app_cfg.h:111
clusteringDBscan.h
DBscan clustering module.
MRR_SF0_EDMA_CH_3D_IN_PONG
#define MRR_SF0_EDMA_CH_3D_IN_PONG
Definition: app_cfg.h:196
FFT_WINDOW_INT32
#define FFT_WINDOW_INT32
Definition: dss_data_path.c:142
DSS_DataPathObj_t::detObj2DRaw
MmwDemo_objRaw2D_t * detObj2DRaw
Detected objects before peak grouping.
Definition: dss_data_path.h:713
MmwDemo_MultiObjBeamFormingCfg_t::multiPeakThrsScal
float multiPeakThrsScal
second peak detection threshold
Definition: mrr_config.h:123
MmwDemo_CfarCfg_t::noiseDivShift
uint8_t noiseDivShift
CFAR cumulative noise sum divisor.
Definition: mrr_config.h:76
DC_RANGE_SIGNATURE_COMP_MAX_BIN_SIZE
#define DC_RANGE_SIGNATURE_COMP_MAX_BIN_SIZE
Maximum number of 1D FFT bins in DC range antenna signature compensation.
Definition: mrr_config.h:52
MmwDemo_setDopplerLine
void MmwDemo_setDopplerLine(MmwDemo_1D_DopplerLines_t *ths, uint16_t dopplerIndex)
Definition: dss_data_path.c:336
MRR_MAX_OBJ_OUT
#define MRR_MAX_OBJ_OUT
The maximum number of objects to be send out per frame. This number is upper bounded by the transfer ...
Definition: app_cfg.h:150
MAX_NUM_RANGE_DEPENDANT_SNR_THRESHOLDS
#define MAX_NUM_RANGE_DEPENDANT_SNR_THRESHOLDS
The number of SNR Thresholds - used to vary the SNR requirement as a function of range.
Definition: app_cfg.h:108
MmwDemo_objRaw1D::dopplerSNRdB
uint16_t dopplerSNRdB
Peak value.
Definition: dss_data_path.h:128
N_STATES
#define N_STATES
Definition: EKF_XYZ_Consts.h:61
clusteringDBscanReportForTx_t
Structure for each cluster information report .
Definition: dss_data_path.h:179
MRR_EDMA_TRIGGER_DISABLE
#define MRR_EDMA_TRIGGER_DISABLE
Definition: app_cfg.h:205
DSS_DataPathObj_t::trackerState
KFstate_t * trackerState
tracking state.
Definition: dss_data_path.h:747
MIN_TICK_FOR_TX
#define MIN_TICK_FOR_TX
Wait for MIN_TICK_FOR_TX before letting the tracker results out.
Definition: app_cfg.h:133
MmwDemo_XYcalc
void MmwDemo_XYcalc(DSS_DataPathObj *obj, uint32_t objIndex, uint16_t azimIdx, float *azimuthMagSqr)
Definition: dss_data_path.c:4982
quadraticInterpLog2ShortPeakLoc
float quadraticInterpLog2ShortPeakLoc(uint16_t *restrict y, int32_t len, int32_t indx, uint16_t fracBitIn)
Definition: dss_data_path.c:4795
DSS_DataPathObj_t::maxRange
uint16_t maxRange
maximum range at which a target is detected ( in xyzOutputQFormat precision).
Definition: dss_data_path.h:619
MRR_SF0_EDMA_CH_1D_OUT_PING
#define MRR_SF0_EDMA_CH_1D_OUT_PING
Definition: app_cfg.h:189
MRR_SF0_EDMA_CH_1D_IN_PONG
#define MRR_SF0_EDMA_CH_1D_IN_PONG
Definition: app_cfg.h:188
pruneTrackingInput
uint32_t pruneTrackingInput(trackingInputReport_t *trackingInput, uint32_t numCluster)
Definition: dss_data_path.c:4706
MRR_SF0_EDMA_CH_DET_MATRIX2
#define MRR_SF0_EDMA_CH_DET_MATRIX2
Definition: app_cfg.h:194
ONE_Q19
#define ONE_Q19
Definition: dss_data_path.h:70
PI_
#define PI_
Definition: dss_data_path.h:68
DSS_DataPathObj_t::detDopplerLines
MmwDemo_1D_DopplerLines_t detDopplerLines
Detected Doppler lines.
Definition: dss_data_path.h:703
findandPopulateIntersectionOfDetectedObjects
uint32_t findandPopulateIntersectionOfDetectedObjects(DSS_DataPathObj *restrict obj, uint32_t numDetObjPerCfar, uint16_t dopplerLine, uint32_t numDetObj2D, uint16_t *restrict sumAbsRange)
Definition: dss_data_path.c:3031
SOC_MAX_NUM_TX_ANTENNAS
#define SOC_MAX_NUM_TX_ANTENNAS
Definition: dss_data_path.c:2330
MmwDemo_1D_DopplerLines::currentIndex
uint16_t currentIndex
starting index for the search for next active Doppler line
Definition: dss_data_path.h:246
MmwDemo_objRaw1D
Parameters of CFAR detected object during the first round of CFAR detections.
Definition: dss_data_path.h:123
DSS_DataPathObj_t::azimuthModCoefs
cmplx16ImRe_t * azimuthModCoefs
Pointer to single point DFT coefficients used for Azimuth processing.
Definition: dss_data_path.h:528
gen_twiddle_fft32x32
int gen_twiddle_fft32x32(int *w, int n, double scale)
Definition: gen_twiddle_fft32x32.c:98
MmwDemo_detectedObjActual_t::sinAzim
int16_t sinAzim
wx sin(Azim). Q format provides the bitwidth.
Definition: dss_data_path.h:160
DSS_DataPathObj_t::minRange
uint16_t minRange
minimum range at which a target is detected ( in xyzOutputQFormat precision).
Definition: dss_data_path.h:616
MmwDemo_CfarCfg_t::guardLen
uint8_t guardLen
CFAR guard length.
Definition: mrr_config.h:73
MmwDemo_objRaw2D
Parameters of CFAR detected object during the second round of CFAR detections.
Definition: dss_data_path.h:138
DSS_DataPathObj_t::dbScanReport
clusteringDBscanOutput_t dbScanReport
The dBscan clustering result structures (holds pointers to the result).
Definition: dss_data_path.h:741
EDMAutil_configType2a
int32_t EDMAutil_configType2a(EDMA_Handle handle, uint8_t *srcBuff, uint8_t *dstBuff, uint8_t chId, bool isEventTriggered, uint16_t shadowParamId, uint16_t sampleLenInBytes, uint16_t numRangeBins, uint8_t numTxAnt, uint8_t numRxAnt, uint16_t numDopplerBins, uint8_t eventQueueId, EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn, uintptr_t transferCompletionCallbackFxnArg)
Definition: dss_config_edma_util.c:153
MmwDemo_printHeapStats
void MmwDemo_printHeapStats(char *name, uint32_t heapUsed, uint32_t heapSize)
Definition: dss_data_path.c:2297
MmwDemo_edmaTransferControllerErrorCallbackFxn
void MmwDemo_edmaTransferControllerErrorCallbackFxn(EDMA_Handle handle, EDMA_transferControllerErrorInfo_t *errorInfo)
Definition: dss_data_path.c:2178
DSS_DataPathObj_t::radarCube
cmplx16ReIm_t * radarCube
Pointer to Radar Cube memory in L3 RAM.
Definition: dss_data_path.h:537
MmwDemo_dataPathWait1DInputData
void MmwDemo_dataPathWait1DInputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
Definition: dss_data_path.c:703
DSS_DataPathObj_t::trackerQvecList
float * trackerQvecList
Process noise constants.
Definition: dss_data_path.h:750
DSS_DataPathObj_t::antInp
cmplx32ReIm_t * antInp
input for Azimuth FFT
Definition: dss_data_path.h:510
EKF_XYZ_Interface.h
Interface the Extended Kalman Filter.
ALIGN
#define ALIGN(x, a)
DSS_DataPathObj_t::detObj1DRaw
MmwDemo_objRaw1D_t * detObj1DRaw
Detected objects after first pass in Doppler direction.
Definition: dss_data_path.h:710
MMW_WIN_BLACKMAN
#define MMW_WIN_BLACKMAN
Definition: dss_data_path.c:148
MmwDemo_startDmaTransfer
void MmwDemo_startDmaTransfer(EDMA_Handle handle, uint8_t channelId0, uint8_t subframeIndx)
Definition: dss_data_path.c:303
MmwDemo_waitEndOfChirps
void MmwDemo_waitEndOfChirps(DSS_DataPathObj *obj, uint8_t subframeIndx)
Definition: dss_data_path.c:2079
MmwDemo_addDopplerCompensation
void MmwDemo_addDopplerCompensation(int32_t dopplerIdx, int32_t numDopplerBins, uint32_t *azimuthModCoefs, uint32_t *azimuthModCoefsThirdBin, uint32_t *azimuthModCoefsTwoThirdBin, int64_t *azimuthIn, uint32_t numAnt, uint32_t numTxAnt, uint16_t txAntIdx)
Function Name : MmwDemo_DopplerCompensation.
Definition: dss_data_path.c:4866
cycleLog_t_::interFrameWaitTime
uint32_t interFrameWaitTime
total wait time for 2D and 3D EDMA data transfer
Definition: dss_data_path.h:103
KFstate
Kalman filter state.
Definition: dss_data_path.h:423
MmwDemo_XYestimation
void MmwDemo_XYestimation(DSS_DataPathObj *obj, uint32_t objIndex)
Definition: dss_data_path.c:431
DSS_DataPathObj_t::SNRThresholds
RangeDependantThresh_t SNRThresholds[MAX_NUM_RANGE_DEPENDANT_SNR_THRESHOLDS]
SNR thresholds as a function of range.
Definition: dss_data_path.h:697
MmwDemo_dataPathCopyEdmaHandle
int32_t MmwDemo_dataPathCopyEdmaHandle(DSS_DataPathObj *objOutput, DSS_DataPathObj *objInput)
Definition: dss_data_path.c:2272
AGED_OBJ_DELETION_THRESH
#define AGED_OBJ_DELETION_THRESH
Delete objects that haven't been associated after these many ticks.
Definition: EKF_XYZ_Consts.h:186
cfarCa_SO_dBwrap_withSNR
uint32_t cfarCa_SO_dBwrap_withSNR(const uint16_t inp[restrict], uint16_t out[restrict], uint16_t outSNR[restrict], uint32_t len, uint32_t const1, uint32_t const2, uint32_t guardLen, uint32_t noiseLen)
Function Name : cfarCa_SO_dBwrap_withSNR.
Definition: dss_data_path.c:3546
MmwDemo_getDopplerLine
int32_t MmwDemo_getDopplerLine(MmwDemo_1D_DopplerLines_t *ths)
Definition: dss_data_path.c:377
DSS_DataPathObj_t::azimuthIn
cmplx32ReIm_t * azimuthIn
input for Azimuth FFT
Definition: dss_data_path.h:507
TRACKER_SCRATCHPAD_SHORT_SIZE
#define TRACKER_SCRATCHPAD_SHORT_SIZE
Definition: dss_data_path.h:386
DSS_DataPathObj_t::numVirtualAntAzim
uint16_t numVirtualAntAzim
number of virtual azimuth antennas
Definition: dss_data_path.h:637
DSS_DataPathObj_t::sumAbsRange
uint16_t * sumAbsRange
input buffer for CFAR processing from the detection matrix
Definition: dss_data_path.h:498
DSS_DataPathObj_t::parkingAssistBinsState
uint16_t * parkingAssistBinsState
Filtered result of the nearest object as a function of azimuth.
Definition: dss_data_path.h:768
computeSinAzimSNR
uint16_t computeSinAzimSNR(float *azimuthMagSqr, uint16_t azimIdx, uint16_t numVirtualAntAzim, uint16_t numAngleBins, uint16_t xyzOutputQFormat)
Definition: dss_data_path.c:3919
DSS_DataPathObj_t::numDopplerBins
uint16_t numDopplerBins
number of doppler bins
Definition: dss_data_path.h:649
DSS_DataPathObj_t::numAngleBins
uint16_t numAngleBins
number of angle bins
Definition: dss_data_path.h:643
quadraticInterpFltPeakLoc
float quadraticInterpFltPeakLoc(float *restrict y, int32_t len, int32_t indx)
Definition: dss_data_path.c:4741
cycleLog_t_::interChirpProcessingTime
uint32_t interChirpProcessingTime
total processing time during all chirps in a frame excluding EDMA waiting time
Definition: dss_data_path.h:100
MmwDemo_detectedObjActual_t::rangeIdx
uint16_t rangeIdx
Range index.
Definition: dss_data_path.h:155
MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN
#define MMWDEMO_MEMORY_ALLOC_DOUBLE_WORD_ALIGN
Definition: dss_data_path.h:73
DSS_DataPathObj_t::log2numVirtAnt
uint8_t log2numVirtAnt
log2 of the number of virtual antennas.
Definition: dss_data_path.h:582
MmwDemo_CalibDcRangeSigCfg_t::positiveBinIdx
int16_t positiveBinIdx
maximum positive range bin (1D FFT index) to be compensated
Definition: mrr_config.h:229
trackingInputReport
Input to tracking from the clustering output.
Definition: dss_data_path.h:358
DSS_DataPathObj_t::cfarDetObjSNR
uint16_t * cfarDetObjSNR
CFAR output objects' SNR buffer.
Definition: dss_data_path.h:504
MmwDemo_dataPathWait2DInputData
void MmwDemo_dataPathWait2DInputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
Definition: dss_data_path.c:786
SOC_MAX_NUM_RX_ANTENNAS
#define SOC_MAX_NUM_RX_ANTENNAS
Definition: dss_data_path.c:2329
MmwDemo_detectedObjActual_t::y
int16_t y
y - coordinate in meters. Q format provides the bitwidth.
Definition: dss_data_path.h:169
DSS_DataPathObj_t::maxUnambiguousVel
float maxUnambiguousVel
maximum unambiguous velocity (without algorithmic improvements) in meters/sec
Definition: dss_data_path.h:685
DSS_DataPathObj_t::azimuthMagSqr
float * azimuthMagSqr
output of Azimuth FFT magnitude squared
Definition: dss_data_path.h:522
TRACKER_SCRATCHPAD_FLT_SIZE
#define TRACKER_SCRATCHPAD_FLT_SIZE
Definition: dss_data_path.h:376
TRK_SIN_AZIM_THRESH
#define TRK_SIN_AZIM_THRESH
We discard objects with poor azimuth SNR from the tracking procedure.
Definition: app_cfg.h:141
MmwDemo_dssAssert
#define MmwDemo_dssAssert(expression)
Definition: mmWave_XSS.h:259
associateClustering
void associateClustering(clusteringDBscanOutput_t *restrict output, clusteringDBscanReport_t *restrict state, uint16_t maxNumTrackers, int32_t epsilon2, int32_t vFactor)
Definition: dss_data_path.c:4322
MmwDemo_dataPathInitEdma
int32_t MmwDemo_dataPathInitEdma(DSS_DataPathObj *obj)
Definition: dss_data_path.c:2223
convertSNRdBToVar
float convertSNRdBToVar(uint16_t SNRdB, uint16_t bitW, uint16_t n_samples, float resolution)
Definition: dss_data_path.c:3971
MmwDemo_dataPathConfigFFTs
void MmwDemo_dataPathConfigFFTs(DSS_DataPathObj *obj)
Definition: dss_data_path.c:2746
MmwDemo_genWindow
void MmwDemo_genWindow(void *win, uint32_t windowDatumType, uint32_t winLen, uint32_t winGenLen, int32_t oneQformat, uint32_t winType)
Definition: dss_data_path.c:2796
clusteringDBscanInstance::fixedPointScale
uint16_t fixedPointScale
Definition: dss_data_path.h:319
iY
#define iY
Definition: EKF_XYZ_Consts.h:56
MmwDemo_detectedObjForTx_t
Detected object estimated parameters to be transmitted out.
Definition: dss_data_path.h:205
MmwDemo_dataPathWait1DOutputData
void MmwDemo_dataPathWait1DOutputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
Definition: dss_data_path.c:755
MmwDemo_dataPathConfigEdma
int32_t MmwDemo_dataPathConfigEdma(DSS_DataPathObj *obj)
Definition: dss_data_path.c:936
MmwDemo_1D_DopplerLines
Active Doppler lines, lines (bins) on which the CFAR detector detected objects during the detections ...
Definition: dss_data_path.h:238
MmwDemo_CalibDcRangeSigCfg_t::negativeBinIdx
int16_t negativeBinIdx
maximum negative range bin (1D FFT index) to be compensated
Definition: mrr_config.h:226
DSS_DataPathObj_t::azimuthTwiddle32x32
cmplx32ReIm_t * azimuthTwiddle32x32
twiddle factors table for Azimuth FFT
Definition: dss_data_path.h:525
MmwDemo_pow2roundup
uint32_t MmwDemo_pow2roundup(uint32_t x)
Definition: dss_data_path.c:404
DSS_DataPathObj_t::trackerOpFinal
trackingReportForTx * trackerOpFinal
Final list of tracked objects for transmission.
Definition: dss_data_path.h:762
pruneToPeaksOrNeighbourOfPeaks
uint32_t pruneToPeaksOrNeighbourOfPeaks(uint16_t *restrict cfarDetObjIndexBuf, uint16_t *restrict cfarDetObjSNR, uint32_t numDetObjPerCfar, uint16_t *restrict sumAbs, uint16_t numBins)
Definition: dss_data_path.c:5173
DSS_DataPathObj_t::numTxAntennas
uint16_t numTxAntennas
number of transmit antennas
Definition: dss_data_path.h:631
DSS_DataPathObj_t::numAdcSamples
uint16_t numAdcSamples
number of ADC samples
Definition: dss_data_path.h:664
DSS_DataPathObj_t::EDMA_transferControllerErrorInfo
EDMA_transferControllerErrorInfo_t EDMA_transferControllerErrorInfo
EDMA transfer controller error information.
Definition: dss_data_path.h:456
DSS_DataPathObj_t::parkingAssistBins
uint16_t * parkingAssistBins
Nearest object as a function of azimuth.
Definition: dss_data_path.h:765
SOC_XWR18XX_DSS_L3RAM_SIZE
#define SOC_XWR18XX_DSS_L3RAM_SIZE
Definition: dss_data_path.c:111
DSS_DataPathObj_t::window2D
int32_t * window2D
window coefficients for 2D FFT
Definition: dss_data_path.h:477
SIN_55_DEGREES
#define SIN_55_DEGREES
We discard objects at extreme angles (greater than 55 degrees) from the tracking procedure.
Definition: app_cfg.h:137
MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN
#define MMWDEMO_MEMORY_ALLOC_MAX_STRUCT_ALIGN
Definition: dss_data_path.h:74
MmwDemo_rxChanPhaseBiasCompensation
static void MmwDemo_rxChanPhaseBiasCompensation(uint32_t *rxChComp, int64_t *input, uint32_t numAnt)
Function Name : MmwDemo_rxChanPhaseBiasCompensation.
Definition: dss_data_path.c:4939
DSS_DataPathObj_t::dbScanInstance
clusteringDBscanInstance_t dbScanInstance
The dBscan clustering configuration structure.
Definition: dss_data_path.h:738
DSS_DataPathObj_t::dstPingPong
cmplx16ReIm_t * dstPingPong
ping pong buffer for 2D from radar Cube
Definition: dss_data_path.h:480
ONE_Q15
#define ONE_Q15
Definition: dss_data_path.h:69
DSS_DataPathObj_t::cfarDetObjIndexBuf
uint16_t * cfarDetObjIndexBuf
CFAR output objects index buffer.
Definition: dss_data_path.h:501
DSS_DataPathObj_t::azimuthModCoefsTwoThirdBin
cmplx16ImRe_t azimuthModCoefsTwoThirdBin
Half bin needed for doppler correction as part of Azimuth processing.
Definition: dss_data_path.h:676
DSS_DataPathObj_t::numActiveTrackers
uint16_t numActiveTrackers
number of active trackers.
Definition: dss_data_path.h:622
DSS_DataPathObj_t::window1D
int16_t * window1D
window coefficients for 1D FFT
Definition: dss_data_path.h:465
MAX_NUM_DET_PER_RANGE_GATE
#define MAX_NUM_DET_PER_RANGE_GATE
Restrict the number of detected objects per range-gate to 3.
Definition: app_cfg.h:168
ZERO_POINT_FIVE_METERS
#define ZERO_POINT_FIVE_METERS
Definition: dss_data_path.c:4450
DSS_DataPathObj_t::detObj2D
MmwDemo_detectedObjActual * detObj2D
Detected objects after second pass in Range direction. These objects are send out as point clouds.
Definition: dss_data_path.h:707
DSS_DataPathObj_t::cfarCfgRange
MmwDemo_CfarCfg cfarCfgRange
CFAR configuration in Range direction.
Definition: dss_data_path.h:719
DSS_DataPathObj_t::trackerInstance
KFtrackerInstance_t trackerInstance
Tracking configuration structure.
Definition: dss_data_path.h:744
iSIN_AZIM
#define iSIN_AZIM
Definition: EKF_XYZ_Consts.h:52
DSS_DataPathObj_t::cfarCfgRange_minIndxToIgnoreHPF
uint16_t cfarCfgRange_minIndxToIgnoreHPF
The HPF can mess up the noise floor computation. So for a certain number of indices,...
Definition: dss_data_path.h:598
DSS_DataPathObj_t::txAntennaCount
uint16_t txAntennaCount
chirp counter modulo number of tx antennas
Definition: dss_data_path.h:655
MmwDemo_detectedObjActual_t::x
int16_t x
x - coordinate in meters. Q format provides the bitwidth.
Definition: dss_data_path.h:168
ROUND
#define ROUND(x)
Definition: dss_data_path.c:109
DSS_DataPathObj_t::elevationOut
cmplx32ReIm_t * elevationOut
output of Elevation FFT
Definition: dss_data_path.h:519
DSS_DataPathObj_t::numDetObj
uint16_t numDetObj
Number of detected objects.
Definition: dss_data_path.h:610
MIN_RANGE_OFFSET_METERS
#define MIN_RANGE_OFFSET_METERS
The radar's range estimate has a constant error due to the finite distance from the antenna to the LO...
Definition: app_cfg.h:130
DSS_DataPathObj_t::sinAzimQFormat
uint8_t sinAzimQFormat
Q format of the sin of the azimuth.
Definition: dss_data_path.h:585
trackingReportForTx_t
Structure for tracking report.
Definition: dss_data_path.h:191
DSS_DataPathObj_t::dcRangeSigMean
cmplx32ImRe_t * dcRangeSigMean
Pointer to DC range signature compensation buffer.
Definition: dss_data_path.h:534
DSS_DataPathObj_t::detMatrix
uint16_t * detMatrix
Pointer to range/Doppler log2 magnitude detection matrix in L3 RAM.
Definition: dss_data_path.h:540
cycleLog_t_::interFrameProcessingTime
uint32_t interFrameProcessingTime
total processing time for 2D and 3D excluding EDMA waiting time
Definition: dss_data_path.h:102
MmwDemo_CalibDcRangeSigCfg_t::numAvgChirps
uint16_t numAvgChirps
number of chirps in the averaging phase
Definition: mrr_config.h:232
KFstate::xSize
int16_t xSize
Definition: dss_data_path.h:428
DSS_DataPathObj_t::fftOut1D
cmplx16ReIm_t * fftOut1D
1D FFT output
Definition: dss_data_path.h:471
pruneToPeaks
uint32_t pruneToPeaks(uint16_t *restrict cfarDetObjIndexBuf, uint16_t *restrict cfarDetObjSNR, uint32_t numDetObjPerCfar, uint16_t *restrict sumAbs, uint16_t numBins)
Definition: dss_data_path.c:3208
EDMAutil_triggerType3
int32_t EDMAutil_triggerType3(EDMA_Handle handle, uint8_t *srcBuff, uint8_t *dstBuff, uint8_t chId, uint8_t triggerEnabled)
Definition: dss_config_edma_util.c:364
DSS_DataPathObj_t::numDetObjRaw
uint16_t numDetObjRaw
Number of detected objects.
Definition: dss_data_path.h:613
gen_twiddle_fft16x16
int gen_twiddle_fft16x16(short *w, int n)
Definition: gen_twiddle_fft16x16.c:128
EIGHTEEN_DB_DOPPLER_SNR
#define EIGHTEEN_DB_DOPPLER_SNR
Definition: dss_data_path.c:4449
MMW_WIN_RECT
#define MMW_WIN_RECT
Definition: dss_data_path.c:150
MmwDemo_CfarCfg_t::thresholdScale
uint16_t thresholdScale
CFAR threshold scale.
Definition: mrr_config.h:64
cfarCadB_SO_withSNR
uint32_t cfarCadB_SO_withSNR(const uint16_t inp[restrict], uint16_t out[restrict], uint16_t outSNR[restrict], uint32_t len, uint32_t const1, uint32_t const2, uint32_t guardLen, uint32_t noiseLen, uint32_t minIndxToIgnoreHPF)
Function Name : cfarCadB_SO_withSNR.
Definition: dss_data_path.c:3400
MRR_SF0_EDMA_CH_DET_MATRIX
#define MRR_SF0_EDMA_CH_DET_MATRIX
Definition: app_cfg.h:193
app_cfg.h
EDMAutil_configType3
int32_t EDMAutil_configType3(EDMA_Handle handle, uint8_t *srcBuff, uint8_t *dstBuff, uint8_t chId, bool isEventTriggered, uint16_t shadowParamId, uint16_t aCount, uint16_t bCount, int16_t srcBIdx, int16_t destBIdx, uint8_t eventQueueId, EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn, uintptr_t transferCompletionCallbackFxnArg)
Definition: dss_config_edma_util.c:297
FFT_WINDOW_INT16
#define FFT_WINDOW_INT16
Definition: dss_data_path.c:140
DSS_DataPathObj_t::azimuthOut
cmplx32ReIm_t * azimuthOut
output of Azimuth FFT
Definition: dss_data_path.h:516
gMCB
MCB gMCB
Global Variable for tracking information required by the design.
Definition: dss_main.c:97
gMmwL3
uint8_t gMmwL3[SOC_XWR18XX_DSS_L3RAM_SIZE]
Definition: dss_data_path.c:126
clusteringDBscanReport
Structure for each cluster information report .
Definition: dss_data_path.h:347
MmwDemo_objRaw1D::velDisambFacValidity
int16_t velDisambFacValidity
velocity disambiguation factor
Definition: dss_data_path.h:127
DSS_DataPathObj_t::adcDataIn
cmplx16ReIm_t * adcDataIn
ADCBUF input samples in L2 scratch memory.
Definition: dss_data_path.h:468
ekfRun
void ekfRun(const int32_t numMeas, trackingInputReport_t const *restrict measArray, DSS_DataPathObj *restrict obj, float const *restrict QvecList, const float td)
Definition: Extended_Kalman_Filter_xyz.c:166
gMmwL2
uint8_t gMmwL2[MMW_L2_HEAP_SIZE]
Definition: dss_data_path.c:131
MmwDemo_detectedObjActual_t::speed
int16_t speed
Doppler (m/s in oneQformat)
Definition: dss_data_path.h:159
DSS_DataPathObj_t::detObjFinal
MmwDemo_detectedObjForTx * detObjFinal
Final list of detected object for transmission.
Definition: dss_data_path.h:756
MmwDemo_detectedObjActual_t::z
int16_t z
z - coordinate in meters. Q format provides the bitwidth.
Definition: dss_data_path.h:170
pingPongId
#define pingPongId(x)
Definition: dss_data_path.c:158
MRR_SF0_EDMA_CH_1D_IN_PING
#define MRR_SF0_EDMA_CH_1D_IN_PING
EDMA allocation and configuration table for FFT processing of subframe 0 AKA: (The whole frame)
Definition: app_cfg.h:187
DSS_DataPathObj_t::numRangeBins
uint16_t numRangeBins
number of range bins
Definition: dss_data_path.h:667
MmwDemo_XYZestimation
void MmwDemo_XYZestimation(DSS_DataPathObj *obj, uint32_t objIndex)
Definition: dss_data_path.c:563
MmwDemo_dataPathWait3DInputData
void MmwDemo_dataPathWait3DInputData(DSS_DataPathObj *obj, uint32_t pingPongId, uint32_t subframeIndx)
Definition: dss_data_path.c:818
iX
#define iX
Definition: EKF_XYZ_Consts.h:55
MmwDemo_detectedObjActual_t
Detected object estimated parameters.
Definition: dss_data_path.h:153
DSS_DataPathObj_t::xyzOutputQFormat
uint8_t xyzOutputQFormat
Q format of the output x/y/z coordinates.
Definition: dss_data_path.h:576
populateOutputs
void populateOutputs(DSS_DataPathObj *obj)
Definition: dss_data_path.c:4452
MRR_SF0_EDMA_CH_3D_IN_PING
#define MRR_SF0_EDMA_CH_3D_IN_PING
Definition: app_cfg.h:195
FRAME_PERIODICITY_SEC
#define FRAME_PERIODICITY_SEC
The total frame periodicity in seconds.
Definition: app_cfg.h:105
FOUR_POINT_ZERO_METERS
#define FOUR_POINT_ZERO_METERS
Definition: dss_data_path.c:4451
DSS_DataPathObj_t::calibDcRangeSigCfg
MmwDemo_CalibDcRangeSigCfg calibDcRangeSigCfg
DC Range antenna signature callibration configuration.
Definition: dss_data_path.h:725
MmwDemo_resetDopplerLines
void MmwDemo_resetDopplerLines(MmwDemo_1D_DopplerLines_t *ths)
Definition: dss_data_path.c:323
MRR_SF0_EDMA_CH_2D_IN_PONG
#define MRR_SF0_EDMA_CH_2D_IN_PONG
Definition: app_cfg.h:192
CHECK_FOR_DET_MATRIX_TX
#define CHECK_FOR_DET_MATRIX_TX
In processing the max-velocity enhancement subframe we need to check for det matrix transfer only aft...
Definition: app_cfg.h:145
MmwDemo_interFrameProcessing
void MmwDemo_interFrameProcessing(DSS_DataPathObj *obj, uint8_t subframeIndx)
Definition: dss_data_path.c:1633
MmwDemo_genDftSinCosTable
void MmwDemo_genDftSinCosTable(cmplx16ImRe_t *dftSinCosTable, cmplx16ImRe_t *dftHalfBinVal, cmplx16ImRe_t *dftThirdBinVal, cmplx16ImRe_t *dftTwoThirdBinVal, uint32_t dftLen)
Definition: dss_data_path.c:2130
BYTES_PER_SAMP_DET
#define BYTES_PER_SAMP_DET
Definition: dss_data_path.h:60
DO_NOT_CHECK_FOR_DET_MATRIX_TX
#define DO_NOT_CHECK_FOR_DET_MATRIX_TX
Definition: app_cfg.h:146
MMW_WIN_HAMMING
#define MMW_WIN_HAMMING
Definition: dss_data_path.c:146
DSS_DataPathObj_t::invOneQFormat
float invOneQFormat
inverse of the oneQformat
Definition: dss_data_path.h:688
aziEleProcessing
uint32_t aziEleProcessing(DSS_DataPathObj *obj, uint32_t subframeIndx)
Definition: dss_data_path.c:4059
MRR_SF0_EDMA_CH_1D_OUT_PONG
#define MRR_SF0_EDMA_CH_1D_OUT_PONG
Definition: app_cfg.h:190
MAX_VEL_POINT_CLOUD_PROCESSING_IS_ENABLED
#define MAX_VEL_POINT_CLOUD_PROCESSING_IS_ENABLED
Flag to enable the max velocity enhancement in point cloud processing.
Definition: app_cfg.h:211
POINT_CLOUD_PROCESSING
#define POINT_CLOUD_PROCESSING
Definition: app_cfg.h:112
MmwDemo_dataPathConfigBuffers
void MmwDemo_dataPathConfigBuffers(DSS_DataPathObj *objIn, uint32_t adcBufAddress)
Definition: dss_data_path.c:2331
MmwDemo_processChirp
void MmwDemo_processChirp(DSS_DataPathObj *obj, uint8_t subframeIndx)
Definition: dss_data_path.c:1974
DSS_DataPathObj_t::sumAbs
uint16_t * sumAbs
accumulated sum of log2 absolute over the antennae
Definition: dss_data_path.h:492
gMmwL1
uint8_t gMmwL1[MMW_L1_HEAP_SIZE]
Definition: dss_data_path.c:136
select_channel
uint8_t select_channel(uint8_t subframeIndx, uint8_t pingPongId, uint8_t option0ping, uint8_t option0pong)
Definition: dss_data_path.c:266
KFstate::vec
float vec[N_STATES]
Definition: dss_data_path.h:430
MmwDemo_XYZcalc
void MmwDemo_XYZcalc(DSS_DataPathObj *obj, uint32_t objIndex, uint16_t azimIdx, float *azimuthMagSqr)
Definition: dss_data_path.c:5052
clusteringDBscanOutput
Structure of clustering output.
Definition: dss_data_path.h:367
DSS_DataPathObj_t::log2NumAvgChirps
uint8_t log2NumAvgChirps
log2 of number of averaged chirps
Definition: dss_data_path.h:570
MmwDemo_dcRangeSignatureCompensation
void MmwDemo_dcRangeSignatureCompensation(DSS_DataPathObj *obj, uint8_t chirpPingPongId)
Definition: dss_data_path.c:1447
CFARTHRESHOLD_N_BIT_FRAC
#define CFARTHRESHOLD_N_BIT_FRAC
Fractional bit width for Thresholds for CFAR data (rangeSNRdB, dopplerSNRdB, AzimSNR,...
Definition: app_cfg.h:127
MCB_t
DSP-Subsystem (DSS) Master control block (MCB) The structure is used to hold handling information,...
Definition: mmWave_XSS.h:210
KFtrackerInstance::maxTrackers
uint16_t maxTrackers
Definition: dss_data_path.h:398
DSS_DataPathObj_t::twiddle32x32_2D
cmplx32ReIm_t * twiddle32x32_2D
twiddle table for 2D FFT
Definition: dss_data_path.h:474
DSS_DataPathObj_t::processingPath
uint8_t processingPath
Processing path - either point-cloud or max-vel enhancement.
Definition: dss_data_path.h:561
cycleLog_t_::interChirpWaitTime
uint32_t interChirpWaitTime
total wait time for EDMA data transfer during all chirps in a frame
Definition: dss_data_path.h:101
MmwDemo_dataPathInit1Dstate
void MmwDemo_dataPathInit1Dstate(DSS_DataPathObj *obj)
Definition: dss_data_path.c:2198
MCB_t::dataPathObj
DSS_DataPathObj dataPathObj[NUM_SUBFRAMES]
! mmw Demo statistics
Definition: mmWave_XSS.h:227
DSS_DataPathObj_t::chirpTypeCount
uint16_t chirpTypeCount
chirp counter modulo number of subframe
Definition: dss_data_path.h:661
clusteringDBscanRun
int32_t clusteringDBscanRun(clusteringDBscanInstance_t *inst, DSS_DataPathObj *obj, uint16_t numDetetectedObj, clusteringDBscanOutput_t *output, trackingInputReport_t *trackingInput)
Definition: clusteringDBscan.c:79
MMW_L1_HEAP_SIZE
#define MMW_L1_HEAP_SIZE
L1 heap used for allocating buffers in L1D SRAM, mostly scratch buffers.
Definition: dss_data_path.c:121
clusteringDBscanOutput::numCluster
uint16_t numCluster
Definition: dss_data_path.h:370
MRR_EDMA_TRIGGER_ENABLE
#define MRR_EDMA_TRIGGER_ENABLE
Definition: app_cfg.h:204
DSS_DataPathObj_t
Millimeter Wave Demo Data Path Information.
Definition: dss_data_path.h:444
DSS_DataPathObj_t::cfarCfgDoppler
MmwDemo_CfarCfg cfarCfgDoppler
CFAR configuration in Doppler direction.
Definition: dss_data_path.h:716
MRR_SF0_EDMA_CH_2D_IN_PING
#define MRR_SF0_EDMA_CH_2D_IN_PING
Definition: app_cfg.h:191
mmWave_XSS.h
DSS_DataPathObj_t::maxVelEnhStruct
maxVelEnhStruct_t maxVelEnhStruct
Max-velocity constants.
Definition: dss_data_path.h:735
MMW_ALLOC_BUF
#define MMW_ALLOC_BUF(name, nameType, startAddr, alignment, size)
MmwDemo_MultiObjBeamFormingCfg_t::enabled
uint8_t enabled
enabled flag: 1-enabled 0-disabled
Definition: mrr_config.h:120
DSS_DataPathObj_t::clusterOpFinal
clusteringDBscanReportForTx * clusterOpFinal
Final list of clusters for transmission.
Definition: dss_data_path.h:759
DSS_DataPathObj_t::invNumAngleBins
float invNumAngleBins
inverse of the numAngleBins
Definition: dss_data_path.h:694
DSS_DataPathObj_t::elevationIn
cmplx32ReIm_t * elevationIn
input for Elevation FFT
Definition: dss_data_path.h:513
maxVelEnhStruct_t_::velResolutionFastChirp
float velResolutionFastChirp
Definition: dss_data_path.h:111
convertSNRLinToVar
float convertSNRLinToVar(uint16_t SNRLin, uint16_t bitW, uint16_t n_samples, float resolution)
Definition: dss_data_path.c:4008
MmwDemo_objRaw1D::dopplerIdx
uint16_t dopplerIdx
Doppler index.
Definition: dss_data_path.h:126
DSS_DataPathObj_t::peakValThresholds
RangeDependantThresh_t peakValThresholds[MAX_NUM_RANGE_DEPENDANT_SNR_THRESHOLDS]
SNR thresholds as a function of range.
Definition: dss_data_path.h:700
cfarPeakGroupingAlongDoppler
uint32_t cfarPeakGroupingAlongDoppler(MmwDemo_objRaw2D_t *restrict objOut, uint32_t numDetectedObjects, uint16_t *detMatrix, uint32_t numRangeBins, uint32_t numDopplerBins)
MmwDemo_detectedObjActual_t::sinAzimSNRLin
uint16_t sinAzimSNRLin
omega SNR (linear scale)
Definition: dss_data_path.h:166
DSS_DataPathObj_t::azimuthModCoefsThirdBin
cmplx16ImRe_t azimuthModCoefsThirdBin
Half bin needed for doppler correction as part of Azimuth processing.
Definition: dss_data_path.h:673
clusteringDBscanInstance::vFactor
float vFactor
Definition: dss_data_path.h:312
DOPPLER_IDX_TO_UNSIGNED
#define DOPPLER_IDX_TO_UNSIGNED(_idx, _fftSize)
Converts signed Doppler index to unsigned variable (zero to FFT size -1).
Definition: detected_obj.h:21
DSS_DataPathObj_t::trackingInput
trackingInputReport_t * trackingInput
Pointer to dBScan output used as input to the tracker.
Definition: dss_data_path.h:552
MMW_L2_HEAP_SIZE
#define MMW_L2_HEAP_SIZE
L2 heap used for allocating buffers in L2 SRAM, mostly scratch buffers.
Definition: dss_data_path.c:117
MCB_t::subframeIndx
uint8_t subframeIndx
! Logging buffer flag
Definition: mmWave_XSS.h:229
MmwDemo_detectedObjActual_t::range
uint16_t range
Range (meters in oneQformat)
Definition: dss_data_path.h:158
dss_config_edma_util.h
EDMA Configuration Utility API definitions.
cycleLog_t_
DSP cycle profiling structure to accumulate different processing times in chirp and frame processing ...
Definition: dss_data_path.h:99
DSS_DataPathObj_t::multiObjBeamFormingCfg
MmwDemo_MultiObjBeamFormingCfg multiObjBeamFormingCfg
Multi object beam forming configuration.
Definition: dss_data_path.h:722
MmwDemo_magnitudeSquared
void MmwDemo_magnitudeSquared(cmplx32ReIm_t *restrict inpBuff, float *restrict magSqrdBuff, uint32_t numSamples)
Definition: dss_data_path.c:1428
DSS_DataPathObj_t::ADCdataBuf
cmplx16ReIm_t * ADCdataBuf
pointer to ADC buffer
Definition: dss_data_path.h:459
clusteringDBscanInstance::epsilon
float epsilon
Definition: dss_data_path.h:310
MAX
#define MAX(x, y)
Definition: dss_config_edma_util.c:44
DSS_DataPathObj_t::azimuthModCoefsHalfBin
cmplx16ImRe_t azimuthModCoefsHalfBin
Half bin needed for doppler correction as part of Azimuth processing.
Definition: dss_data_path.h:670
MmwDemo_1D_DopplerLines::dopplerLineMask
uint32_t * dopplerLineMask
Doppler line bit mask of active (CFAR detected) Doppler bins in the first round of CFAR detections in...
Definition: dss_data_path.h:240
iYd
#define iYd
Definition: EKF_XYZ_Consts.h:58
antilog2
float antilog2(int32_t inputActual, uint16_t fracBitIn)
Definition: dss_data_path.c:4037
MmwDemo_isSetDopplerLine
uint32_t MmwDemo_isSetDopplerLine(MmwDemo_1D_DopplerLines_t *ths, uint16_t index)
Definition: dss_data_path.c:352
DSS_DataPathObj_t::sumAbsSlowChirp
uint16_t * sumAbsSlowChirp
accumulated sum of log2 absolute over the antennae
Definition: dss_data_path.h:495
iXd
#define iXd
Definition: EKF_XYZ_Consts.h:57
TWENTY_TWO_DB_DOPPLER_SNR
#define TWENTY_TWO_DB_DOPPLER_SNR
Definition: dss_data_path.c:4448
DSS_DataPathObj_t::maxNumObj2DRaw
uint16_t maxNumObj2DRaw
number of objects to be detected in 2D-CFAR.
Definition: dss_data_path.h:625
MmwDemo_dataPathWaitTransDetMatrix
void MmwDemo_dataPathWaitTransDetMatrix(DSS_DataPathObj *obj, uint8_t subframeIndx)
Definition: dss_data_path.c:848
clusteringDBscanInstance::maxClusters
uint16_t maxClusters
Definition: dss_data_path.h:314
DSS_DataPathObj_t::numVirtualAntennas
uint16_t numVirtualAntennas
number of virtual antennas
Definition: dss_data_path.h:634
secondDimFFTandLog2Computation
uint32_t secondDimFFTandLog2Computation(DSS_DataPathObj *obj, uint16_t *sumAbs, uint16_t checkDetMatrixTx, uint16_t rangeIdx, uint32_t *pingPongIdxPtr)
rangeBasedPruning
uint32_t rangeBasedPruning(MmwDemo_detectedObjActual *restrict objOut, MmwDemo_objRaw2D_t *restrict objRaw, RangeDependantThresh_t *restrict SNRThresh, RangeDependantThresh_t *restrict peakValThresh, uint32_t numDetectedObjects, uint32_t numDopplerBins, uint32_t maxRange, uint32_t minRange)
Definition: dss_data_path.c:1317
findKLargestPeaks
uint32_t findKLargestPeaks(uint16_t *restrict cfarDetObjIndexBuf, uint16_t *restrict cfarDetObjSNR, uint32_t numDetObjPerCfar, uint16_t *restrict sumAbs, uint16_t numBins, uint16_t K)
Definition: dss_data_path.c:3276
DSS_DataPathObj_t::chirpCount
uint16_t chirpCount
chirp counter modulo number of chirps per frame
Definition: dss_data_path.h:652
NUM_SUBFRAMES
#define NUM_SUBFRAMES
Definition: app_cfg.h:80
BYTES_PER_SAMP_1D
#define BYTES_PER_SAMP_1D
Definition: dss_data_path.h:58
DSS_DataPathObj_t::dcRangeSigCalibCntr
uint8_t dcRangeSigCalibCntr
DC range signature calibration counter.
Definition: dss_data_path.h:567
ROUNDF
#define ROUNDF(x)
Definition: dss_data_path.c:154
calc_cmplx_exp
void calc_cmplx_exp(cmplx16ImRe_t *dftSinCos, float i, uint32_t dftLen)
Definition: dss_data_path.c:2090
DSS_DataPathObj_t::dbScanState
clusteringDBscanReport_t * dbScanState
Pointer to dBScan output Report array.
Definition: dss_data_path.h:753
EDMA_INSTANCE_DSS
#define EDMA_INSTANCE_DSS
Definition: app_cfg.h:200
MmwDemo_cfarPeakGrouping
uint32_t MmwDemo_cfarPeakGrouping(MmwDemo_detectedObjActual *objOut, uint32_t numDetectedObjects, uint16_t *detMatrix, uint32_t numRangeBins, uint32_t numDopplerBins, uint32_t groupInDopplerDirection, uint32_t groupInRangeDirection)
Definition: dss_data_path.c:3710
DSS_DataPathObj_t::parkingAssistNumBinsLog2
uint8_t parkingAssistNumBinsLog2
log2 of the number of bins for the parkingAssist module (used for scaling operations).
Definition: dss_data_path.h:591
DSS_DataPathObj_t::parkingAssistNumBins
uint8_t parkingAssistNumBins
Number of bins for the parkingAssist module.
Definition: dss_data_path.h:588
MMW_WIN_HANNING_RECT
#define MMW_WIN_HANNING_RECT
Definition: dss_data_path.c:152
DSS_DataPathObj_t::twiddle16x16_1D
cmplx16ReIm_t * twiddle16x16_1D
twiddle table for 1D FFT
Definition: dss_data_path.h:462
DSS_DataPathObj_t::dopplerBinCount
uint16_t dopplerBinCount
chirp counter modulo number of Doppler bins
Definition: dss_data_path.h:658
MmwDemo_edmaErrorCallbackFxn
void MmwDemo_edmaErrorCallbackFxn(EDMA_Handle handle, EDMA_errorInfo_t *errorInfo)
Definition: dss_data_path.c:2163
dss_data_path.h
This is the data path processing header.
EDMAutil_configType1
int32_t EDMAutil_configType1(EDMA_Handle handle, uint8_t *srcBuff, uint8_t *dstBuff, uint8_t chId, bool isEventTriggered, uint16_t shadowParamId, uint16_t aCount, uint16_t bCount, int16_t srcBIdx, int16_t dstBIdx, uint8_t eventQueueId, EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn, uintptr_t transferCompletionCallbackFxnArg)
Definition: dss_config_edma_util.c:86
DSS_DataPathObj_t::parkingAssistBinsStateCnt
uint16_t * parkingAssistBinsStateCnt
The 'age' of the filtered result of the parking state. Added to make the 'smoother' visually.
Definition: dss_data_path.h:772
parkingAssistInit
void parkingAssistInit(DSS_DataPathObj *obj)
Definition: dss_data_path.c:5146
MmwDemo_dataPathWaitTransDetMatrix2
void MmwDemo_dataPathWaitTransDetMatrix2(DSS_DataPathObj *obj, uint32_t subframeIndx)
Definition: dss_data_path.c:885
DSS_DataPathObj_t::parkingAssistMaxRange
uint16_t parkingAssistMaxRange
maximum range to look for obstacles. .
Definition: dss_data_path.h:601
findandPopulateDetectedObjects
uint32_t findandPopulateDetectedObjects(DSS_DataPathObj *restrict obj, uint32_t numDetObjPerCfar, uint16_t dopplerLine, uint32_t numDetObj2D, uint16_t *restrict sumAbsRange)
Definition: dss_data_path.c:3130
isPong
#define isPong(x)
Definition: dss_data_path.c:159
MmwDemo_objRaw1D::rangeIdx
uint16_t rangeIdx
Range index.
Definition: dss_data_path.h:125
DSS_DataPathObj_t::numRxAntennas
uint16_t numRxAntennas
Number of receive channels.
Definition: dss_data_path.h:628
MmwDemo_detectedObjActual_t::dopplerIdx
uint16_t dopplerIdx
Doppler index.
Definition: dss_data_path.h:156