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