GNU Radio 3.6.5 C++ API
|
00001 #ifndef INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H 00002 #define INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H 00003 00004 #include <inttypes.h> 00005 #include <stdio.h> 00006 #include <math.h> 00007 00008 #ifdef LV_HAVE_SSE3 00009 #include <pmmintrin.h> 00010 00011 #ifdef LV_HAVE_LIB_SIMDMATH 00012 #include <simdmath.h> 00013 #endif /* LV_HAVE_LIB_SIMDMATH */ 00014 00015 /*! 00016 \brief Calculates the log10 power value for each input point 00017 \param logPowerOutput The 10.0 * log10(r*r + i*i) for each data point 00018 \param complexFFTInput The complex data output from the FFT point 00019 \param normalizationFactor This value is divided against all the input values before the power is calculated 00020 \param num_points The number of fft data points 00021 */ 00022 static inline void volk_32fc_s32f_power_spectrum_32f_a_sse3(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, unsigned int num_points){ 00023 const float* inputPtr = (const float*)complexFFTInput; 00024 float* destPtr = logPowerOutput; 00025 uint64_t number = 0; 00026 const float iNormalizationFactor = 1.0 / normalizationFactor; 00027 #ifdef LV_HAVE_LIB_SIMDMATH 00028 __m128 magScalar = _mm_set_ps1(10.0); 00029 magScalar = _mm_div_ps(magScalar, logf4(magScalar)); 00030 00031 __m128 invNormalizationFactor = _mm_set_ps1(iNormalizationFactor); 00032 00033 __m128 power; 00034 __m128 input1, input2; 00035 const uint64_t quarterPoints = num_points / 4; 00036 for(;number < quarterPoints; number++){ 00037 // Load the complex values 00038 input1 =_mm_load_ps(inputPtr); 00039 inputPtr += 4; 00040 input2 =_mm_load_ps(inputPtr); 00041 inputPtr += 4; 00042 00043 // Apply the normalization factor 00044 input1 = _mm_mul_ps(input1, invNormalizationFactor); 00045 input2 = _mm_mul_ps(input2, invNormalizationFactor); 00046 00047 // Multiply each value by itself 00048 // (r1*r1), (i1*i1), (r2*r2), (i2*i2) 00049 input1 = _mm_mul_ps(input1, input1); 00050 // (r3*r3), (i3*i3), (r4*r4), (i4*i4) 00051 input2 = _mm_mul_ps(input2, input2); 00052 00053 // Horizontal add, to add (r*r) + (i*i) for each complex value 00054 // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4) 00055 power = _mm_hadd_ps(input1, input2); 00056 00057 // Calculate the natural log power 00058 power = logf4(power); 00059 00060 // Convert to log10 and multiply by 10.0 00061 power = _mm_mul_ps(power, magScalar); 00062 00063 // Store the floating point results 00064 _mm_store_ps(destPtr, power); 00065 00066 destPtr += 4; 00067 } 00068 00069 number = quarterPoints*4; 00070 #endif /* LV_HAVE_LIB_SIMDMATH */ 00071 // Calculate the FFT for any remaining points 00072 00073 for(; number < num_points; number++){ 00074 // Calculate dBm 00075 // 50 ohm load assumption 00076 // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10) 00077 // 75 ohm load assumption 00078 // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15) 00079 00080 const float real = *inputPtr++ * iNormalizationFactor; 00081 const float imag = *inputPtr++ * iNormalizationFactor; 00082 00083 *destPtr = 10.0*log10f(((real * real) + (imag * imag)) + 1e-20); 00084 00085 destPtr++; 00086 } 00087 00088 } 00089 #endif /* LV_HAVE_SSE3 */ 00090 00091 #ifdef LV_HAVE_GENERIC 00092 /*! 00093 \brief Calculates the log10 power value for each input point 00094 \param logPowerOutput The 10.0 * log10(r*r + i*i) for each data point 00095 \param complexFFTInput The complex data output from the FFT point 00096 \param normalizationFactor This value is divided agains all the input values before the power is calculated 00097 \param num_points The number of fft data points 00098 */ 00099 static inline void volk_32fc_s32f_power_spectrum_32f_a_generic(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, unsigned int num_points){ 00100 // Calculate the Power of the complex point 00101 const float* inputPtr = (float*)complexFFTInput; 00102 float* realFFTDataPointsPtr = logPowerOutput; 00103 const float iNormalizationFactor = 1.0 / normalizationFactor; 00104 unsigned int point; 00105 for(point = 0; point < num_points; point++){ 00106 // Calculate dBm 00107 // 50 ohm load assumption 00108 // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10) 00109 // 75 ohm load assumption 00110 // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15) 00111 00112 const float real = *inputPtr++ * iNormalizationFactor; 00113 const float imag = *inputPtr++ * iNormalizationFactor; 00114 00115 *realFFTDataPointsPtr = 10.0*log10f(((real * real) + (imag * imag)) + 1e-20); 00116 00117 00118 realFFTDataPointsPtr++; 00119 } 00120 } 00121 #endif /* LV_HAVE_GENERIC */ 00122 00123 00124 00125 00126 #endif /* INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H */