IWR1642运行driver vital signals demo心率和呼吸一直都是0

Other Parts Discussed in Thread: MATHLIB

  • 问题1,烧录的程序是官方的pre-built,调试运行的曲线如上图所示

    问题2,编译工程vitalSigns_16xx_dss,vitalSigns_16xx_mss都有报错

    **** Build of configuration Debug for project vitalSigns_16xx_dss ****

    "C:\\ti\\ccs930\\ccs\\utils\\bin\\gmake" -k -j 2 all -O
     
    rm -f C:/Users/shenmai/Desktop/TI/radar/lab0001-driver-vital-signs/vitalSigns_target/vitalSigns_16xx_dss/vitalSigns_16xx_dss.bin
    makefile:189: recipe for target 'pre-build' failed
    process_begin: CreateProcess(NULL, rm -f C:/Users/shenmai/Desktop/TI/radar/lab0001-driver-vital-signs/vitalSigns_target/vitalSigns_16xx_dss/vitalSigns_16xx_dss.bin, ...) failed.
    make (e=2): 系统找不到指定的文件。
     
    gmake[1]: [pre-build] Error 2 (ignored)
     
    Building file: "../dss_data_path.c"
    Invoking: C6000 Compiler
    "C:/ti/ccs930/ccs/tools/compiler/ti-cgt-c6000_8.3.5/bin/cl6x" -mv6740 --abi=eabi -O3 --include_path="C:/Users/shenmai/Desktop/TI/radar/lab0001-driver-vital-signs/vitalSigns_target/vitalSigns_16xx_dss" --include_path="C:/ti/mmwave_sdk_02_01_00_04/packages" --include_path="C:/ti/mathlib_c674x_3_1_2_1/packages" --include_path="C:/ti/dsplib_c64Px_3_4_0_0/packages/ti/dsplib/src/DSP_fft16x16/c64P" --include_path="C:/ti/dsplib_c64Px_3_4_0_0/packages/ti/dsplib/src/DSP_fft32x32/c64P" --include_path="C:/ti/ccs930/ccs/tools/compiler/ti-cgt-c6000_8.3.5/include" --define=SOC_XWR16XX --define=SUBSYS_DSS --define=DOWNLOAD_FROM_CCS --define=MMWAVE_L3RAM_SIZE=0xC0000 --define=DebugP_ASSERT_ENABLED -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --obj_extension=.oe674 --preproc_with_compile --preproc_dependency="dss_data_path.d_raw" --cmd_file="configPkg/compiler.opt" "../dss_data_path.c"
     
    >> Compilation failure
    subdir_rules.mk:9: recipe for target 'dss_data_path.oe674' failed
    makefile:155: recipe for target 'all' failed
    "../dss_data_path.c", line 437: error #20: identifier "MMWAVE_L3RAM_NUM_BANK" is undefined
    "../dss_data_path.c", line 437: error #20: identifier "MMWAVE_SHMEM_BANK_SIZE" is undefined
    2 errors detected in the compilation of "../dss_data_path.c".
    gmake[1]: *** [dss_data_path.oe674] Error 1
    gmake[1]: Target 'main-build' not remade because of errors.
    gmake: *** [all] Error 2

    **** Build Finished ****


    **** Build of configuration Debug for project vitalSigns_16xx_mss ****

    "C:\\ti\\ccs930\\ccs\\utils\\bin\\gmake" -k -j 2 all -O
     
    rm -f C:/Users/shenmai/Desktop/TI/radar/lab0001-driver-vital-signs/vitalSigns_target/vitalSigns_16xx_mss/vitalSigns_16xx_mss.bin
    makefile:186: recipe for target 'pre-build' failed
    process_begin: CreateProcess(NULL, rm -f C:/Users/shenmai/Desktop/TI/radar/lab0001-driver-vital-signs/vitalSigns_target/vitalSigns_16xx_mss/vitalSigns_16xx_mss.bin, ...) failed.
    make (e=2): 系统找不到指定的文件。
     
    gmake[1]: [pre-build] Error 2 (ignored)
     
    Building file: "../mss_main.c"
    Invoking: ARM Compiler
    "C:/ti/ccs930/ccs/tools/compiler/ti-cgt-arm_18.12.4.LTS/bin/armcl" -mv7R4 --code_state=16 --float_support=VFPv3D16 -me -O3 --include_path="C:/Users/shenmai/Desktop/TI/radar/lab0001-driver-vital-signs/vitalSigns_target/vitalSigns_16xx_mss" --include_path="C:/ti/mmwave_sdk_02_01_00_04" --include_path="C:/ti/mmwave_sdk_02_01_00_04/packages" --include_path="C:/ti/ccs930/ccs/tools/compiler/ti-cgt-arm_18.12.4.LTS/include" --define=_LITTLE_ENDIAN --define=SOC_XWR16XX --define=SUBSYS_MSS --define=DOWNLOAD_FROM_CCS --define=MMWAVE_L3RAM_SIZE=0x40000 --define=DebugP_ASSERT_ENABLED -g --c99 --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --enum_type=int --abi=eabi --preproc_with_compile --preproc_dependency="mss_main.d_raw" --cmd_file="configPkg/compiler.opt" "../mss_main.c"
     
    >> Compilation failure
    subdir_rules.mk:9: recipe for target 'mss_main.obj' failed
    "../mss_main.c", line 562: warning #169-D: argument of type "int32_t *" is incompatible with parameter of type "rlCalibrationData_t *"
    "../mss_main.c", line 562: error #167: too few arguments in function call
    1 error detected in the compilation of "../mss_main.c".
    gmake[1]: *** [mss_main.obj] Error 1
    gmake[1]: Target 'main-build' not remade because of errors.
    gmake: *** [all] Error 2
    makefile:152: recipe for target 'all' failed

    **** Build Finished ****

  • 第一个问题与这个链接相同e2echina.ti.com/.../550421
    有个解答是初始化心率函数中的所有变量,能否指出对于的源文件?
  • "../dss_data_path.c", line 437: error #20: identifier "MMWAVE_L3RAM_NUM_BANK" is undefined
    "../dss_data_path.c", line 437: error #20: identifier "MMWAVE_SHMEM_BANK_SIZE" is undefined
    以上报错,有可能是sdk版本不匹配导致的。
    请问是哪个版本的toolbox?

    "../mss_main.c", line 562: error #167: too few arguments in function call
    对应到程序里是哪段代码?
  • user6319700 说:
    第一个问题与这个链接相同e2echina.ti.com/.../550421
    有个解答是初始化心率函数中的所有变量,能否指出对于的源文件?

    你好,

    请把dss_data_path.c里面void MmwDemo_interFrameProcessing(MmwDemo_DSS_DataPathObj *obj)函数里所有没有设定初始值的变量设定初始值为0.

  • 你好,

    请确认你安装的sdk版本是DriverVitalSigns_Release_Notes.pdf里面提到的版本。
  • 编译报错的问题确实是当前SDK版本不兼容引起的,应该使用SDK2.0.0.4
  • 将函数void MmwDemo_interFrameProcessing(MmwDemo_DSS_DataPathObj *obj)中未初始化的变量初始化后出现了新的问题,vitalSigns_host  gui运行如下图:

    请问是什么原因,怎么解决?

  • 你好,

    你能提供一下你修改的部分代码么?

  • 修改过的代码是dss_data_path.c文件中的函数void MmwDemo_interFrameProcessing(MmwDemo_DSS_DataPathObj *obj)中未初始化的变量进行初始化,就出现上图的问题
  • 你好,

    能否提供具体的代码,让我看看是否有遗漏?
  • 修改过的函数代码如下
    void MmwDemo_interFrameProcessing(MmwDemo_DSS_DataPathObj *obj)
    {
    //Vital Signs Demo Processing Chain

    gFrameCount++; // Increment the Global Frame Count
    static uint16_t frameCountLocal = 0; // Local circular count
    uint16_t loopIndexBuffer = 0; // Index that loops over the buffers

    /* Obtain GUI-related Flags sent through the CLI */
    VitalSignsDemo_GuiMonSel *pGuiMonSel;
    pGuiMonSel = (VitalSignsDemo_GuiMonSel *) &(obj->cliCfg->vitalSigns_GuiMonSel);

    /* Variables for Impulse Noise Removal */
    static float dataCurr = 0;
    static float dataPrev2 = 0;
    static float dataPrev1 = 0;

    /* Variables for Clutter Removal */
    float maxValClutter = 0;
    uint16_t guiFlag_ClutterRemoval = pGuiMonSel->guiFlag_ClutterRemoval;
    uint16_t rangeBinMaxClutter = 0;

    /* Variables for Phase Unwrapping */
    static float phasePrevFrame = 0; // Phase value of Previous frame (For phase unwrapping)
    static float diffPhaseCorrectionCum = 0; // Phase correction *** (For phase unwrapping)
    static float phaseUsedComputationPrev = 0; // Phase values used for the Previous frame
    float phaseUsedComputation = 0; // Unwrapped Phase value used for computation

    /* Variables for Detecting Motion Corrupted Segments */
    uint16_t guiFlag_MotionDetection = obj->cliCfg->motionDetectionParamsCfg.enabled; // GUI Flag. Set from the configuration File
    uint16_t guiFlag_GainControl = obj->cliCfg->motionDetectionParamsCfg.gainControl; // GUI Flag. Set from the configuration File
    uint16_t indexMotionDetection = 0; // Temporary Index
    float sumEnergy = 0; // Energy in the data-segment checked for presence of large-scale motion

    /* Vital Signs Waveform */
    float outputFilterBreathOut = 0; // Breathing waveform after the IIR-Filter
    float outputFilterHeartOut = 0; // Cardiac waveform after the IIR-Filter

    /* Variables for FFT-based Spectral Estimation */
    uint16_t pPeakSortOutIndex[MAX_NUM_PEAKS_SPECTRUM] = {0}; // Sorted Peaks in the Spectrum
    uint16_t numPeaks_BreathSpectrum = 0; // Number of Peaks in the Breathing Spectrum
    uint16_t numPeaks_heartSpectrum = 0; // Number of Peaks in the Cardiac Spectrum
    uint16_t maxIndexHeartBeatSpect = 0, maxIndexBreathSpect = 0; // Indices corresponding to the max peak in the Breathing and Cardiac Spectrum
    uint16_t maxIndexHeartBeatSpect_4Hz = 0; // Indices corresponding to the max peak from [1.6 - 4.0] Hz
    float breathingRateEst_FFT = 0, heartRateEst_FFT = 0; // Vital Signs Estimate based on the FFT
    float heartRateEst_FFT_4Hz = 0; // Vital Signs Estimate based on the FFT

    /* Confidence Metric associated with the estimates */
    float confidenceMetricBreath[MAX_NUM_PEAKS_SPECTRUM] = {0}; // Confidence Metric associated with each Breathing Spectrum Peak
    float confidenceMetricHeart[MAX_NUM_PEAKS_SPECTRUM] = {0}; // Confidence Metric associated with each Cardiac Spectrum Peak
    float confidenceMetricBreathOut = 0, confidenceMetricHeartOut = 0; // Confidence Metric associated with the estimates
    float confidenceMetricHeartOut_4Hz = 0; // Confidence Metric for the 1st Heart beat Harmonic
    float confidenceMetricHeartOut_xCorr = 0; // Confidence Metric for the Autocorrelation
    float confidenceMetricBreathOut_xCorr = 0; // Confidence Metric for the Autocorrelation based breathing-rate estimate
    float peakValueBreathSpect = 0;

    /* Variables for peak-counting */
    uint16_t pPeakLocsHeart[MAX_PEAKS_ALLOWED_WFM] = {0}; // Peak locations (indices) of the Cardiac Waveform
    uint16_t pPeakLocsBreath[MAX_PEAKS_ALLOWED_WFM] = {0}; // Peak locations (indices) of the Breathing Waveform
    uint16_t pPeakLocsValid[MAX_PEAKS_ALLOWED_WFM] = {0}; // Peak locations after only retaining the valid peaks
    uint16_t numPeaksBreath = 0, numPeaksHeart = 0; // Number of peaks in the time-domain filtered waveform
    float breathingRateEst_peakCount = 0, heartRateEst_peakCount = 0; // Vital Signs Estimate based on peak-Interval
    float heartRateEst_peakCount_filtered = 0; // Heart-rate peak-interval based estimate after filtering

    /* Exponential smoothing filter */
    static float breathWfmOutUpdated = 0;
    static float heartWfmOutUpdated = 0; // Updated values after exponential smoothing
    float breathWfmOutPrev = 0, heartWfmOutPrev = 0; // Exponential smoothing values at time instance (t-1)
    float sumEnergyBreathWfm = 0, sumEnergyHeartWfm = 0; // These values are used to make a decision if the energy in the waveform is sufficient for it to be classfied as a valid waveform

    /* Variables for Auto-Correlation */
    float heartRateEst_xCorr = 0; // Heart-rate estimate from the Autocorrelation Method
    float breathRateEst_xCorr = 0; // Breathing-rate estimate from the Autocorrelation Method

    /* For FIR Filtering */
    static float pDataIn[FIR_FILTER_SIZE] = {0};

    /* Variables for Extracting the Range-FFT output */
    uint16_t rangeBinIndex = 0; // Range-bin Index
    float rangeBinPhase = 0; // Phase of the Range-bin selected for processing
    static uint16_t rangeBinIndexPhase = 0; // Index of the Range Bin for which the phase is computed
    uint16_t rangeBinMax = 0; // Index of the Strongest Range-Bin

    uint16_t indexTemp = 0, indexNumPeaks = 0; // Temporary Indices
    int16_t temp_real = 0, temp_imag = 0; // Temporary variables storing the Real and Imaginary part of a range-bin in the Range-FFT Output
    float absVal = 0; // Absolute value based on the Real and Imaginary values
    float maxVal = 0; // Maximum Value of the Range-Bin in the current range-profile

    if (pGuiMonSel->guiFlag_Reset == 1) // Refresh Pushbutton on the GUI Pressed
    {
    gFrameCount = 1;
    pGuiMonSel->guiFlag_Reset = 0;
    breathWfmOutUpdated = 0;
    heartWfmOutUpdated = 0;
    }

    if (RANGE_BIN_TRACKING)
    {
    frameCountLocal = gFrameCount % RESET_LOCAL_COUNT_VAL;
    }
    else
    {
    frameCountLocal = gFrameCount;
    }

    rangeBinMax = 0;
    maxVal = 0;
    rangeBinMaxClutter = 0;
    maxValClutter = 0;

    // tempPtr points towards the RX-Channel to process
    cmplx16ReIm_t *tempPtr = obj->fftOut1D + (obj->rxAntennaProcess - 1)*obj->numRangeBins;
    // tempPtr points towards rangeBinStartIndex
    tempPtr += (obj->rangeBinStartIndex) ;

    for (rangeBinIndex = obj->rangeBinStartIndex; rangeBinIndex <= obj->rangeBinEndIndex; rangeBinIndex++)
    {
    // Points towards the real part of the current range-bin i.e. rangeBinIndex
    temp_real = (int16_t) tempPtr->real;
    obj->pRangeProfileCplx[rangeBinIndex - obj->rangeBinStartIndex].real = temp_real;

    // Points towards the imaginary part of the current range-bin i.e. rangeBinIndex
    temp_imag = (int16_t) tempPtr->imag;
    obj->pRangeProfileCplx[rangeBinIndex - obj->rangeBinStartIndex].imag = temp_imag;

    // Move the pointer towards the next range-bin
    tempPtr ++;


    if (guiFlag_ClutterRemoval == 1)
    {
    // Clutter Removed Range Profile
    float tempReal_Curr,tempImag_Curr;
    float alphaClutter = 0.01;
    float currVal;

    tempReal_Curr = (float) temp_real;
    tempImag_Curr = (float) temp_imag;
    uint16_t currRangeIndex;
    currRangeIndex = rangeBinIndex - obj->rangeBinStartIndex;

    obj->pTempReal_Prev[currRangeIndex] = alphaClutter*tempReal_Curr + (1-alphaClutter)*obj->pTempReal_Prev[currRangeIndex];
    obj->pTempImag_Prev[currRangeIndex] = alphaClutter*tempImag_Curr + (1-alphaClutter)*obj->pTempImag_Prev[currRangeIndex];

    currVal = sqrt((tempReal_Curr - obj->pTempReal_Prev[currRangeIndex])*(tempReal_Curr - obj->pTempReal_Prev[currRangeIndex]) + (tempImag_Curr - obj->pTempImag_Prev[currRangeIndex])*(tempImag_Curr - obj->pTempImag_Prev[currRangeIndex]));
    obj->pRangeProfileClutterRemoved[rangeBinIndex - obj->rangeBinStartIndex] = currVal;

    // Based on the Max value Range-bin
    if (currVal > maxValClutter)
    {
    maxValClutter = currVal;
    rangeBinMaxClutter = rangeBinIndex;
    }
    }
    else
    {
    // Magnitude of the current range-bin
    absVal = (float) temp_real * (float) temp_real + (float) temp_imag * (float) temp_imag;
    // Maximum value range-bin of the current range-profile
    if (absVal > maxVal)
    {
    maxVal = absVal;
    rangeBinMax = rangeBinIndex;
    }
    }
    // If the Refresh button in the GUI is pressed
    if (frameCountLocal == 1)
    {
    if (guiFlag_ClutterRemoval == 1)
    {
    rangeBinIndexPhase = rangeBinMaxClutter;
    }
    else
    {
    rangeBinIndexPhase = rangeBinMax;
    }
    }
    if (rangeBinIndex == (rangeBinIndexPhase))
    {
    rangeBinPhase = atan2(temp_imag, temp_real);
    }
    } // For Loop ends

    // Phase-Unwrapping
    obj->unwrapPhasePeak = unwrap(rangeBinPhase, phasePrevFrame, &diffPhaseCorrectionCum);
    phasePrevFrame = rangeBinPhase;

    #ifdef TEST_TONE // Generates a Test-Tone

    float testTone_ampBreath_mm = 1.0;
    float testTone_freqBreath_Hz = 0.45;
    float testTone_ampHeart_mm = 0.01;
    float testTone_freqHeart_Hz = 1.8;

    obj->unwrapPhasePeak = (4 * PI_/WAVELENGTH_MM) *(
    (testTone_ampBreath_mm * sin(2*PI_*testTone_freqBreath_Hz* gFrameCount/obj->samplingFreq_Hz))+
    (testTone_ampHeart_mm * sin(2*PI_*testTone_freqHeart_Hz*gFrameCount/obj->samplingFreq_Hz))
    );
    // +0.5*(testTone_ampBreath_mm *sin(2*PI_*(2*testTone_freqBreath_Hz)* gFrameCount/obj->samplingFreq_Hz)); // Harmonic signal
    #endif

    // Computes the phase differences between successive phase samples
    if(FLAG_COMPUTE_PHASE_DIFFERENCE)
    {
    phaseUsedComputation = obj->unwrapPhasePeak - phaseUsedComputationPrev;
    phaseUsedComputationPrev = obj->unwrapPhasePeak;
    }
    else
    {
    phaseUsedComputation = obj->unwrapPhasePeak;
    }

    // Removes impulse like noise from the waveforms
    if (FLAG_REMOVE_IMPULSE_NOISE)
    {
    dataPrev2 = dataPrev1;
    dataPrev1 = dataCurr;
    dataCurr = phaseUsedComputation;
    phaseUsedComputation = filter_RemoveImpulseNoise(dataPrev2, dataPrev1, dataCurr, obj->noiseImpulse_Thresh);
    }

    // IIR Filtering
    outputFilterBreathOut = filter_IIR_BiquadCascade(phaseUsedComputation, obj->pFilterCoefsBreath, obj->pScaleValsBreath, obj->pDelayBreath, IIR_FILTER_BREATH_NUM_STAGES);
    outputFilterHeartOut = filter_IIR_BiquadCascade(phaseUsedComputation, obj->pFilterCoefsHeart_4Hz, obj->pScaleValsHeart_4Hz, obj->pDelayHeart, IIR_FILTER_HEART_NUM_STAGES);

    // Copies the "Breathing Waveform" in a circular Buffer
    for (loopIndexBuffer = 1; loopIndexBuffer < obj->circularBufferSizeBreath; loopIndexBuffer++)
    {
    obj->pVitalSigns_Breath_CircularBuffer[loopIndexBuffer - 1] = obj->pVitalSigns_Breath_CircularBuffer[loopIndexBuffer];
    }
    obj->pVitalSigns_Breath_CircularBuffer[obj->circularBufferSizeBreath - 1] = outputFilterBreathOut;

    // Detection of Motion corrupted Segments
    if (guiFlag_MotionDetection == 1)
    {
    // Update the Motion Removal Circular Buffer
    for (loopIndexBuffer = 1; loopIndexBuffer < obj->motionDetection_BlockSize; loopIndexBuffer++)
    {
    obj->pMotionCircularBuffer[loopIndexBuffer - 1] = obj->pMotionCircularBuffer[loopIndexBuffer] ;
    }
    obj->pMotionCircularBuffer[obj->motionDetection_BlockSize-1] = outputFilterHeartOut;
    indexMotionDetection = gFrameCount % obj->motionDetection_BlockSize;

    // Only perform these steps for every obj->motionDetection_BlockSize sample
    if (indexMotionDetection == 0)
    {
    // Check if the current segment is "Noisy"
    sumEnergy = 0;
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->motionDetection_BlockSize; loopIndexBuffer++)
    {
    sumEnergy += (obj->pMotionCircularBuffer[loopIndexBuffer]*obj->pMotionCircularBuffer[loopIndexBuffer]);
    }

    if (sumEnergy > obj->motionDetection_Thresh)
    {
    obj->motionDetected = 1; // Temporary variable to send to the GUI
    }
    else
    {
    obj->motionDetected = 0; // Temporary variable to send to the GUI
    }

    // If NO motion detected in the current segment
    if ( obj->motionDetected == 0)
    {
    uint16_t tempEndIndex;
    // Shift the current contents of the circular Buffer
    for (loopIndexBuffer = obj->motionDetection_BlockSize; loopIndexBuffer < obj->circularBufferSizeHeart; loopIndexBuffer++)
    {
    obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer - obj->motionDetection_BlockSize] = obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer] ;
    }
    // Copy the current data segment to the end of the Circular Buffer
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->motionDetection_BlockSize; loopIndexBuffer++)
    {
    tempEndIndex = obj->circularBufferSizeHeart - obj->motionDetection_BlockSize;
    obj->pVitalSigns_Heart_CircularBuffer[ tempEndIndex + loopIndexBuffer] = obj->pMotionCircularBuffer[loopIndexBuffer] ;
    }
    }
    }
    }
    // If Motion DETECTED then don't UPDATE or SHIFT the values in the buffer
    else // Regular processing
    {
    // Copies the "Cardiac Waveform" in a circular Buffer
    for (loopIndexBuffer = 1; loopIndexBuffer < obj->circularBufferSizeHeart; loopIndexBuffer++)
    {
    obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer - 1] = obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer];
    }
    obj->pVitalSigns_Heart_CircularBuffer[obj->circularBufferSizeHeart - 1] = outputFilterHeartOut;
    }

    /* Spectral Estimation based on the Inter-Peaks Distance */
    numPeaksHeart = find_Peaks(obj->pVitalSigns_Heart_CircularBuffer, float_type, pPeakLocsHeart,obj->pPeakValues, 0, obj->circularBufferSizeHeart - 1);
    if (numPeaksHeart != 0)
    {
    numPeaksHeart = filterPeaksWfm(pPeakLocsHeart, pPeakLocsValid, numPeaksHeart, obj->peakDistanceHeart_Min, obj->peakDistanceHeart_Max);
    }
    heartRateEst_peakCount = CONVERT_HZ_BPM * ((numPeaksHeart * obj->samplingFreq_Hz) / obj->circularBufferSizeHeart);

    for (loopIndexBuffer = 1; loopIndexBuffer < FIR_FILTER_SIZE; loopIndexBuffer++)
    {
    pDataIn[loopIndexBuffer - 1] = pDataIn[loopIndexBuffer];
    }
    pDataIn[FIR_FILTER_SIZE - 1] = heartRateEst_peakCount;
    heartRateEst_peakCount_filtered = filter_FIR(pDataIn, obj->pFilterCoefs, FIR_FILTER_SIZE);

    numPeaksBreath = find_Peaks(obj->pVitalSigns_Breath_CircularBuffer, int32_type, pPeakLocsBreath, obj->pPeakValues, 0, obj->circularBufferSizeBreath - 1);
    if (numPeaksBreath != 0)
    {
    numPeaksBreath = filterPeaksWfm(pPeakLocsBreath, pPeakLocsValid, numPeaksBreath, obj->peakDistanceBreath_Min, obj->peakDistanceBreath_Max);
    }

    breathingRateEst_peakCount = CONVERT_HZ_BPM * ((numPeaksBreath * obj->samplingFreq_Hz) / obj->circularBufferSizeHeart);
    heartRateEst_peakCount = CONVERT_HZ_BPM * ((numPeaksHeart * obj->samplingFreq_Hz) / obj->circularBufferSizeBreath);

    // Input to the FFT needs to be complex
    memset((uint8_t *)obj->pVitalSignsBuffer_Cplx, 0, obj->breathingWfm_Spectrum_FftSize * sizeof(cmplx32ReIm_t));
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->circularBufferSizeBreath; loopIndexBuffer++)
    {
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].real = (int32_t) obj->scale_breathingWfm*obj->pVitalSigns_Breath_CircularBuffer[loopIndexBuffer];
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].imag=0;
    }

    // Input is overwritten by the DSP_fft32x32 function
    DSP_fft32x32(
    (int32_t *)obj->pVitalSignsSpectrumTwiddle32x32,
    obj->breathingWfm_Spectrum_FftSize,
    (int32_t *) obj->pVitalSignsBuffer_Cplx,
    (int32_t *) obj->pVitalSigns_SpectrumCplx);

    MmwDemo_magnitudeSquared(
    obj->pVitalSigns_SpectrumCplx,
    obj->pVitalSigns_Breath_AbsSpectrum,
    obj->breathingWfm_Spectrum_FftSize);

    memset((uint8_t *)obj->pVitalSignsBuffer_Cplx, 0, obj->heartWfm_Spectrum_FftSize * sizeof(cmplx32ReIm_t));

    // Pre-Processing Steps for the Cardiac Waveform
    // Perform Automatic Gain Control if enabled from the GUI
    if (guiFlag_GainControl == 1)
    {
    computeAGC ( obj->pVitalSigns_Heart_CircularBuffer, obj->circularBufferSizeHeart, obj->motionDetection_BlockSize, obj->motionDetection_Thresh);
    }

    if (guiFlag_MotionDetection == 1)
    {
    outputFilterHeartOut = obj->pMotionCircularBuffer[obj->motionDetection_BlockSize-1];
    }
    else
    {
    outputFilterHeartOut = obj->pVitalSigns_Heart_CircularBuffer[obj->circularBufferSizeHeart-1];
    }

    // Perform Autocorrelation on the Waveform
    if (PERFORM_XCORR)
    {
    float temp;
    // Perform Autocorrelation on the Cardiac-Waveform
    uint16_t xCorr_numPeaks;
    uint16_t maxIndex_lag;
    computeAutoCorrelation ( obj->pVitalSigns_Heart_CircularBuffer, obj->circularBufferSizeHeart , obj->pXcorr, obj->xCorr_minLag, obj->xCorr_maxLag);
    xCorr_numPeaks = find_Peaks(obj->pXcorr, float_type, obj->pPeakIndex, obj->pPeakValues, obj->xCorr_minLag, obj->xCorr_maxLag);
    maxIndex_lag = computeMaxIndex((float*) obj->pXcorr, obj->xCorr_minLag, obj->xCorr_maxLag);
    temp = (float) (1.0)/(maxIndex_lag/obj->samplingFreq_Hz);
    heartRateEst_xCorr = (float) CONVERT_HZ_BPM *temp;

    if (xCorr_numPeaks == 0 )
    {
    confidenceMetricHeartOut_xCorr = 0;
    }
    else
    {
    confidenceMetricHeartOut_xCorr = obj->pXcorr[maxIndex_lag];
    }

    // Auto-correlation on the Breathing Waveform
    computeAutoCorrelation ( obj->pVitalSigns_Breath_CircularBuffer, obj->circularBufferSizeBreath,
    obj->pXcorr, obj->xCorr_Breath_minLag, obj->xCorr_Breath_maxLag);
    xCorr_numPeaks = find_Peaks(obj->pXcorr, float_type, obj->pPeakIndex, obj->pPeakValues, obj->xCorr_Breath_minLag, obj->xCorr_Breath_maxLag);
    maxIndex_lag = computeMaxIndex((float*) obj->pXcorr, obj->xCorr_Breath_minLag, obj->xCorr_Breath_maxLag);
    temp = (float) (1.0)/(maxIndex_lag/obj->samplingFreq_Hz);
    breathRateEst_xCorr = (float) CONVERT_HZ_BPM *temp;

    if (xCorr_numPeaks == 0 )
    {
    confidenceMetricBreathOut_xCorr = 0;
    }
    else
    {
    confidenceMetricBreathOut_xCorr = obj->pXcorr[maxIndex_lag];
    }
    }

    // Apply Window on the Cardiac Waveform prior to FFT-based spectral estimation
    // and copies the Pre-processed data to pCircularBufferHeart
    if (FLAG_APPLY_WINDOW)
    {
    uint16_t index_win;
    uint16_t index_WinEnd;

    float tempFloat;
    index_WinEnd = obj->circularBufferSizeHeart - 1;
    for (index_win = 0; index_win < DOPPLER_WINDOW_SIZE; index_win++)
    {
    tempFloat = obj->pDopplerWindow[index_win];
    obj->pVitalSignsBuffer_Cplx[index_win].real = (int32_t) obj->scale_heartWfm * tempFloat * obj->pVitalSigns_Heart_CircularBuffer[index_win];
    obj->pVitalSignsBuffer_Cplx[index_WinEnd].real = (int32_t) obj->scale_heartWfm * tempFloat * obj->pVitalSigns_Heart_CircularBuffer[index_WinEnd];
    obj->pVitalSignsBuffer_Cplx[index_win].imag = 0;
    obj->pVitalSignsBuffer_Cplx[index_WinEnd].imag = 0;
    index_WinEnd --;
    }
    for (loopIndexBuffer = DOPPLER_WINDOW_SIZE; loopIndexBuffer < obj->circularBufferSizeHeart - DOPPLER_WINDOW_SIZE ; loopIndexBuffer++)
    {
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].real = (int32_t) (obj->scale_heartWfm)*obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer];
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].imag = 0;
    }
    }
    else
    {
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->circularBufferSizeHeart; loopIndexBuffer++)
    {
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].real = (int32_t) (obj->scale_heartWfm)*obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer];
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].imag=0;
    }
    }

    // FFT of the Cardiac Waveform
    DSP_fft32x32(
    (int32_t *)obj->pVitalSignsSpectrumTwiddle32x32,
    obj->heartWfm_Spectrum_FftSize,
    (int32_t *) obj->pVitalSignsBuffer_Cplx,
    (int32_t *) obj->pVitalSigns_SpectrumCplx);

    MmwDemo_magnitudeSquared(
    obj->pVitalSigns_SpectrumCplx,
    obj->pVitalSigns_Heart_AbsSpectrum,
    obj->heartWfm_Spectrum_FftSize);

    // Pick the Peaks in the Breathing Spectrum
    numPeaks_BreathSpectrum = find_Peaks(obj->pVitalSigns_Breath_AbsSpectrum, float_type, obj->pPeakIndex, obj->pPeakValues,
    obj->breath_startFreq_Index, obj->breath_endFreq_Index);
    indexNumPeaks = (numPeaks_BreathSpectrum < MAX_NUM_PEAKS_SPECTRUM) ? numPeaks_BreathSpectrum : MAX_NUM_PEAKS_SPECTRUM;

    if (indexNumPeaks != 0)
    {
    heapsort_index(obj->pPeakValues, numPeaks_BreathSpectrum, obj->pPeakIndexSorted);
    for(indexTemp = 0; indexTemp < indexNumPeaks; indexTemp++ )
    {
    pPeakSortOutIndex[indexTemp] = obj->pPeakIndex [obj->pPeakIndexSorted[numPeaks_BreathSpectrum-indexTemp-1] ];
    confidenceMetricBreath[indexTemp] = computeConfidenceMetric(obj->pVitalSigns_Breath_AbsSpectrum,
    obj->confMetric_spectrumBreath_IndexStart,
    obj->confMetric_spectrumBreath_IndexEnd,
    pPeakSortOutIndex[indexTemp],
    obj->confMetric_numIndexAroundPeak_breath);
    }
    maxIndexBreathSpect = pPeakSortOutIndex[0]; // The maximum peak
    confidenceMetricBreathOut = confidenceMetricBreath[0];
    }
    else
    {
    maxIndexBreathSpect = computeMaxIndex((float*) obj->pVitalSigns_Breath_AbsSpectrum, obj->breath_startFreq_Index, obj->breath_endFreq_Index);
    confidenceMetricBreathOut = computeConfidenceMetric(obj->pVitalSigns_Breath_AbsSpectrum,
    0,
    PHASE_FFT_SIZE/4,
    maxIndexBreathSpect,
    obj->confMetric_numIndexAroundPeak_breath);
    }
    peakValueBreathSpect = obj->pVitalSigns_Breath_AbsSpectrum[maxIndexBreathSpect]/(10*obj->scale_breathingWfm);

    // Pick the Peaks in the Heart Spectrum [1.6 - 4.0 Hz]
    numPeaks_heartSpectrum = find_Peaks(obj->pVitalSigns_Heart_AbsSpectrum, uint32_type, obj->pPeakIndex, obj->pPeakValues,
    obj->heart_startFreq_Index_1p6Hz, obj->heart_endFreq_Index_4Hz);
    indexNumPeaks = (numPeaks_heartSpectrum < MAX_NUM_PEAKS_SPECTRUM) ? numPeaks_heartSpectrum : MAX_NUM_PEAKS_SPECTRUM;
    if (indexNumPeaks != 0)
    {
    heapsort_index(obj->pPeakValues, numPeaks_heartSpectrum, obj->pPeakIndexSorted);
    for(indexTemp = 0; indexTemp < indexNumPeaks; indexTemp++ )
    {
    pPeakSortOutIndex[indexTemp] = obj->pPeakIndex [obj->pPeakIndexSorted[numPeaks_heartSpectrum-indexTemp-1] ];
    }
    maxIndexHeartBeatSpect_4Hz = pPeakSortOutIndex[0]; // The maximum peak
    confidenceMetricHeartOut_4Hz = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    obj->confMetric_spectrumHeart_IndexStart_1p6Hz,
    obj->confMetric_spectrumHeart_IndexStart_4Hz,
    maxIndexHeartBeatSpect_4Hz,
    obj->confMetric_numIndexAroundPeak_heart);
    }
    else
    {
    maxIndexHeartBeatSpect_4Hz = computeMaxIndex((float*) obj->pVitalSigns_Heart_AbsSpectrum, obj->heart_startFreq_Index_1p6Hz, obj->heart_endFreq_Index_4Hz);
    confidenceMetricHeartOut_4Hz = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    0,
    PHASE_FFT_SIZE/4,
    maxIndexHeartBeatSpect_4Hz,
    obj->confMetric_numIndexAroundPeak_heart);
    }
    heartRateEst_FFT_4Hz = (float) CONVERT_HZ_BPM * maxIndexHeartBeatSpect_4Hz * (obj->freqIncrement_Hz);

    // If a peak is within [1.6 2.0] Hz then check if a harmonic is present is the cardiac spectrum region [0.8 - 2.0] Hz
    if (heartRateEst_FFT_4Hz < MAX_HEART_RATE_BPM)
    {
    for (indexTemp =1; indexTemp<numPeaks_heartSpectrum;indexTemp++)

    if(abs(heartRateEst_FFT_4Hz - CONVERT_HZ_BPM *(obj->freqIncrement_Hz)*pPeakSortOutIndex[indexTemp]) < HEART_HAMRONIC_THRESH_BPM)
    {
    heartRateEst_FFT_4Hz = CONVERT_HZ_BPM *(obj->freqIncrement_Hz)*pPeakSortOutIndex[indexTemp];
    break;
    }
    }

    // Pick the Peaks in the Cardiac Spectrum
    numPeaks_heartSpectrum = find_Peaks(obj->pVitalSigns_Heart_AbsSpectrum, float_type, obj->pPeakIndex, obj->pPeakValues, obj->heart_startFreq_Index, obj->heart_endFreq_Index);
    indexNumPeaks = (numPeaks_heartSpectrum < MAX_NUM_PEAKS_SPECTRUM) ? numPeaks_heartSpectrum : MAX_NUM_PEAKS_SPECTRUM;

    if (indexNumPeaks != 0)
    {
    heapsort_index(obj->pPeakValues, numPeaks_heartSpectrum, obj->pPeakIndexSorted);
    for(indexTemp = 0; indexTemp < indexNumPeaks; indexTemp++ )
    {
    pPeakSortOutIndex[indexTemp] = obj->pPeakIndex [obj->pPeakIndexSorted[numPeaks_heartSpectrum-indexTemp-1] ];
    confidenceMetricHeart[indexTemp] = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    obj->confMetric_spectrumHeart_IndexStart,
    obj->confMetric_spectrumHeart_IndexEnd,
    pPeakSortOutIndex[indexTemp],
    obj->confMetric_numIndexAroundPeak_heart);
    }
    maxIndexHeartBeatSpect = pPeakSortOutIndex[0]; // The maximum peak
    confidenceMetricHeartOut = confidenceMetricHeart[0];
    }
    else
    {
    maxIndexHeartBeatSpect = computeMaxIndex((float*) obj->pVitalSigns_Heart_AbsSpectrum, obj->heart_startFreq_Index, obj->heart_endFreq_Index);
    confidenceMetricHeartOut = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    0,
    PHASE_FFT_SIZE/4,
    maxIndexHeartBeatSpect,
    obj->confMetric_numIndexAroundPeak_heart);
    }

    // Remove the First Breathing Harmonic (if present in the cardiac Spectrum)
    if(FLAG_HARMONIC_CANCELLATION)
    {
    float diffIndex = abs(maxIndexHeartBeatSpect - BREATHING_HARMONIC_NUM*maxIndexBreathSpect);
    if ( diffIndex*(obj->freqIncrement_Hz)*CONVERT_HZ_BPM < BREATHING_HAMRONIC_THRESH_BPM ) // Only cancel the 2nd Breathing Harmonic
    {
    maxIndexHeartBeatSpect = pPeakSortOutIndex[1]; // Pick the 2nd Largest peak in the cardiac-spectrum
    confidenceMetricHeartOut = confidenceMetricHeart[1];
    }
    }

    heartRateEst_FFT = (float) CONVERT_HZ_BPM * maxIndexHeartBeatSpect * (obj->freqIncrement_Hz);
    breathingRateEst_FFT = (float) CONVERT_HZ_BPM * maxIndexBreathSpect * (obj->freqIncrement_Hz);

    #ifdef HARMONICS_ENERGY
    float heartRateEst_HarmonicEnergy;
    float breathRateEst_HarmonicEnergy;
    uint16_t maxIndexHeartBeatSpect_temp;
    uint16_t maxIndexBreathSpect_temp;

    memset((void *)obj->pDataOutTemp, 0, obj->heartWfm_Spectrum_FftSize*sizeof(float));
    computeEnergyHarmonics (obj->pVitalSigns_Heart_AbsSpectrum,
    obj->pDataOutTemp,
    obj->confMetric_spectrumHeart_IndexStart,
    obj->confMetric_spectrumHeart_IndexEnd,
    obj->confMetric_numIndexAroundPeak_heart);
    maxIndexHeartBeatSpect_temp = computeMaxIndex(obj->pDataOutTemp,
    obj->confMetric_spectrumHeart_IndexStart,
    obj->confMetric_spectrumHeart_IndexEnd);
    heartRateEst_HarmonicEnergy = (float) CONVERT_HZ_BPM * maxIndexHeartBeatSpect_temp * (obj->freqIncrement_Hz);


    memset((void *)obj->pDataOutTemp, 0, obj->heartWfm_Spectrum_FftSize*sizeof(float));
    computeEnergyHarmonics (obj->pVitalSigns_Breath_AbsSpectrum,
    obj->pDataOutTemp,
    obj->confMetric_spectrumBreath_IndexStart,
    obj->confMetric_spectrumBreath_IndexEnd,
    obj->confMetric_numIndexAroundPeak_breath);
    maxIndexBreathSpect_temp = computeMaxIndex(obj->pDataOutTemp,
    obj->confMetric_spectrumBreath_IndexStart,
    obj->confMetric_spectrumBreath_IndexEnd);
    breathRateEst_HarmonicEnergy = (float) CONVERT_HZ_BPM * maxIndexBreathSpect_temp * (obj->freqIncrement_Hz);

    #endif

    // Median Value for Heart Rate and Breathing Rate based on 'MEDIAN_WINDOW_LENGTH' previous estimates
    if(FLAG_MEDIAN_FILTER)
    {
    for (loopIndexBuffer = 1; loopIndexBuffer < MEDIAN_WINDOW_LENGTH; loopIndexBuffer++)
    {
    obj->pBufferHeartRate[loopIndexBuffer - 1] = obj->pBufferHeartRate[loopIndexBuffer];
    obj->pBufferBreathingRate[loopIndexBuffer - 1] = obj->pBufferBreathingRate[loopIndexBuffer];
    obj->pBufferHeartRate_4Hz[loopIndexBuffer - 1] = obj->pBufferHeartRate_4Hz[loopIndexBuffer];
    }
    obj->pBufferHeartRate[MEDIAN_WINDOW_LENGTH - 1] = heartRateEst_FFT;
    obj->pBufferBreathingRate[MEDIAN_WINDOW_LENGTH - 1] = breathingRateEst_FFT;
    obj->pBufferHeartRate_4Hz[MEDIAN_WINDOW_LENGTH - 1] = heartRateEst_FFT_4Hz;

    heapsort_index(obj->pBufferHeartRate, MEDIAN_WINDOW_LENGTH, obj->pPeakSortTempIndex);
    heartRateEst_FFT = obj->pBufferHeartRate[ obj->pPeakSortTempIndex[MEDIAN_WINDOW_LENGTH/2+1]];

    heapsort_index(obj->pBufferHeartRate_4Hz, MEDIAN_WINDOW_LENGTH, obj->pPeakSortTempIndex);
    heartRateEst_FFT_4Hz = obj->pBufferHeartRate_4Hz[ obj->pPeakSortTempIndex[MEDIAN_WINDOW_LENGTH/2+1]];

    heapsort_index(obj->pBufferBreathingRate, MEDIAN_WINDOW_LENGTH, obj->pPeakSortTempIndex);
    breathingRateEst_FFT = obj->pBufferBreathingRate[ obj->pPeakSortTempIndex[MEDIAN_WINDOW_LENGTH/2+1]];
    }

    // Exponential Smoothing
    breathWfmOutPrev = breathWfmOutUpdated;
    breathWfmOutUpdated = (obj->alpha_breathing)*(outputFilterBreathOut*outputFilterBreathOut) + (1 - (obj->alpha_breathing))*breathWfmOutPrev; // Exponential Smoothing
    sumEnergyBreathWfm = breathWfmOutUpdated*10000;

    heartWfmOutPrev = heartWfmOutUpdated;
    heartWfmOutUpdated = (obj->alpha_heart)*(outputFilterHeartOut*outputFilterHeartOut) + (1 - (obj->alpha_heart))*heartWfmOutPrev; // Exponential Smoothing
    sumEnergyHeartWfm = heartWfmOutUpdated*10000;

    // Output Values
    obj->VitalSigns_Output.unwrapPhasePeak_mm = obj->unwrapPhasePeak;
    obj->VitalSigns_Output.outputFilterBreathOut = outputFilterBreathOut;
    obj->VitalSigns_Output.outputFilterHeartOut = outputFilterHeartOut;
    obj->VitalSigns_Output.rangeBinIndexPhase = rangeBinIndexPhase; //frameCountLocal;
    obj->VitalSigns_Output.maxVal = maxVal;
    obj->VitalSigns_Output.sumEnergyHeartWfm = sumEnergyHeartWfm;
    obj->VitalSigns_Output.sumEnergyBreathWfm = sumEnergyBreathWfm*peakValueBreathSpect;

    obj->VitalSigns_Output.confidenceMetricBreathOut = confidenceMetricBreathOut;
    obj->VitalSigns_Output.confidenceMetricHeartOut = confidenceMetricHeartOut; // Confidence Metric associated with the estimates
    obj->VitalSigns_Output.confidenceMetricHeartOut_4Hz = confidenceMetricHeartOut_4Hz;
    obj->VitalSigns_Output.confidenceMetricHeartOut_xCorr = confidenceMetricHeartOut_xCorr;

    obj->VitalSigns_Output.breathingRateEst_FFT = breathingRateEst_FFT;
    obj->VitalSigns_Output.breathingRateEst_peakCount = breathingRateEst_peakCount;
    obj->VitalSigns_Output.heartRateEst_peakCount_filtered = heartRateEst_peakCount_filtered;
    obj->VitalSigns_Output.heartRateEst_xCorr = heartRateEst_xCorr;
    obj->VitalSigns_Output.heartRateEst_FFT_4Hz = heartRateEst_FFT_4Hz;
    obj->VitalSigns_Output.heartRateEst_FFT = heartRateEst_FFT;

    obj->VitalSigns_Output.processingCyclesOut = obj->timingInfo.interFrameProcCycles/DSP_CLOCK_MHZ;
    obj->VitalSigns_Output.rangeBinStartIndex = obj->rangeBinStartIndex;
    obj->VitalSigns_Output.rangeBinEndIndex = obj->rangeBinEndIndex;
    obj->VitalSigns_Output.motionDetectedFlag = obj->motionDetected;
    obj->VitalSigns_Output.breathingRateEst_xCorr = breathRateEst_xCorr; //breathRateEst_HarmonicEnergy;
    obj->VitalSigns_Output.confidenceMetricBreathOut_xCorr = confidenceMetricBreathOut_xCorr; //breathRateEst_HarmonicEnergy;
    obj->VitalSigns_Output.breathingRateEst_harmonicEnergy = breathRateEst_HarmonicEnergy; //heartRateEst_HarmonicEnergy;
    obj->VitalSigns_Output.heartRateEst_harmonicEnergy = heartRateEst_HarmonicEnergy;

    }
  • 请问下您是哪个版本的toolbox?我找的driver vital signals demo都是应用于AWR硬件上的
  • 我也遇到您同样的问题,请问您解决了吗?