GNU Radio Manual and C++ API Reference  3.7.4.1
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
volk_32fc_s32f_power_spectrum_32f.h
Go to the documentation of this file.
1 #ifndef INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H
2 #define INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H
3 
4 #include <inttypes.h>
5 #include <stdio.h>
6 #include <math.h>
7 
8 #ifdef LV_HAVE_SSE3
9 #include <pmmintrin.h>
10 
11 #ifdef LV_HAVE_LIB_SIMDMATH
12 #include <simdmath.h>
13 #endif /* LV_HAVE_LIB_SIMDMATH */
14 
15 /*!
16  \brief Calculates the log10 power value for each input point
17  \param logPowerOutput The 10.0 * log10(r*r + i*i) for each data point
18  \param complexFFTInput The complex data output from the FFT point
19  \param normalizationFactor This value is divided against all the input values before the power is calculated
20  \param num_points The number of fft data points
21 */
22 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){
23  const float* inputPtr = (const float*)complexFFTInput;
24  float* destPtr = logPowerOutput;
25  uint64_t number = 0;
26  const float iNormalizationFactor = 1.0 / normalizationFactor;
27 #ifdef LV_HAVE_LIB_SIMDMATH
28  __m128 magScalar = _mm_set_ps1(10.0);
29  magScalar = _mm_div_ps(magScalar, logf4(magScalar));
30 
31  __m128 invNormalizationFactor = _mm_set_ps1(iNormalizationFactor);
32 
33  __m128 power;
34  __m128 input1, input2;
35  const uint64_t quarterPoints = num_points / 4;
36  for(;number < quarterPoints; number++){
37  // Load the complex values
38  input1 =_mm_load_ps(inputPtr);
39  inputPtr += 4;
40  input2 =_mm_load_ps(inputPtr);
41  inputPtr += 4;
42 
43  // Apply the normalization factor
44  input1 = _mm_mul_ps(input1, invNormalizationFactor);
45  input2 = _mm_mul_ps(input2, invNormalizationFactor);
46 
47  // Multiply each value by itself
48  // (r1*r1), (i1*i1), (r2*r2), (i2*i2)
49  input1 = _mm_mul_ps(input1, input1);
50  // (r3*r3), (i3*i3), (r4*r4), (i4*i4)
51  input2 = _mm_mul_ps(input2, input2);
52 
53  // Horizontal add, to add (r*r) + (i*i) for each complex value
54  // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4)
55  power = _mm_hadd_ps(input1, input2);
56 
57  // Calculate the natural log power
58  power = logf4(power);
59 
60  // Convert to log10 and multiply by 10.0
61  power = _mm_mul_ps(power, magScalar);
62 
63  // Store the floating point results
64  _mm_store_ps(destPtr, power);
65 
66  destPtr += 4;
67  }
68 
69  number = quarterPoints*4;
70 #endif /* LV_HAVE_LIB_SIMDMATH */
71  // Calculate the FFT for any remaining points
72 
73  for(; number < num_points; number++){
74  // Calculate dBm
75  // 50 ohm load assumption
76  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
77  // 75 ohm load assumption
78  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
79 
80  const float real = *inputPtr++ * iNormalizationFactor;
81  const float imag = *inputPtr++ * iNormalizationFactor;
82 
83  *destPtr = 10.0*log10f(((real * real) + (imag * imag)) + 1e-20);
84 
85  destPtr++;
86  }
87 
88 }
89 #endif /* LV_HAVE_SSE3 */
90 
91 #ifdef LV_HAVE_GENERIC
92 /*!
93  \brief Calculates the log10 power value for each input point
94  \param logPowerOutput The 10.0 * log10(r*r + i*i) for each data point
95  \param complexFFTInput The complex data output from the FFT point
96  \param normalizationFactor This value is divided agains all the input values before the power is calculated
97  \param num_points The number of fft data points
98 */
99 static inline void volk_32fc_s32f_power_spectrum_32f_generic(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, unsigned int num_points){
100  // Calculate the Power of the complex point
101  const float* inputPtr = (float*)complexFFTInput;
102  float* realFFTDataPointsPtr = logPowerOutput;
103  const float iNormalizationFactor = 1.0 / normalizationFactor;
104  unsigned int point;
105  for(point = 0; point < num_points; point++){
106  // Calculate dBm
107  // 50 ohm load assumption
108  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
109  // 75 ohm load assumption
110  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
111 
112  const float real = *inputPtr++ * iNormalizationFactor;
113  const float imag = *inputPtr++ * iNormalizationFactor;
114 
115  *realFFTDataPointsPtr = 10.0*log10f(((real * real) + (imag * imag)) + 1e-20);
116 
117 
118  realFFTDataPointsPtr++;
119  }
120 }
121 #endif /* LV_HAVE_GENERIC */
122 
123 
124 
125 
126 #endif /* INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H */
unsigned __int64 uint64_t
Definition: stdint.h:90
float complex lv_32fc_t
Definition: volk_complex.h:56