GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_32fc_s32f_power_spectrum_32f.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2014 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H
24 #define INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H
25 
26 #include <inttypes.h>
27 #include <stdio.h>
28 #include <math.h>
29 
30 #ifdef LV_HAVE_SSE3
31 #include <pmmintrin.h>
32 
33 #ifdef LV_HAVE_LIB_SIMDMATH
34 #include <simdmath.h>
35 #endif /* LV_HAVE_LIB_SIMDMATH */
36 
37 /*!
38  \brief Calculates the log10 power value for each input point
39  \param logPowerOutput The 10.0 * log10(r*r + i*i) for each data point
40  \param complexFFTInput The complex data output from the FFT point
41  \param normalizationFactor This value is divided against all the input values before the power is calculated
42  \param num_points The number of fft data points
43 */
44 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){
45  const float* inputPtr = (const float*)complexFFTInput;
46  float* destPtr = logPowerOutput;
47  uint64_t number = 0;
48  const float iNormalizationFactor = 1.0 / normalizationFactor;
49 #ifdef LV_HAVE_LIB_SIMDMATH
50  __m128 magScalar = _mm_set_ps1(10.0);
51  magScalar = _mm_div_ps(magScalar, logf4(magScalar));
52 
53  __m128 invNormalizationFactor = _mm_set_ps1(iNormalizationFactor);
54 
55  __m128 power;
56  __m128 input1, input2;
57  const uint64_t quarterPoints = num_points / 4;
58  for(;number < quarterPoints; number++){
59  // Load the complex values
60  input1 =_mm_load_ps(inputPtr);
61  inputPtr += 4;
62  input2 =_mm_load_ps(inputPtr);
63  inputPtr += 4;
64 
65  // Apply the normalization factor
66  input1 = _mm_mul_ps(input1, invNormalizationFactor);
67  input2 = _mm_mul_ps(input2, invNormalizationFactor);
68 
69  // Multiply each value by itself
70  // (r1*r1), (i1*i1), (r2*r2), (i2*i2)
71  input1 = _mm_mul_ps(input1, input1);
72  // (r3*r3), (i3*i3), (r4*r4), (i4*i4)
73  input2 = _mm_mul_ps(input2, input2);
74 
75  // Horizontal add, to add (r*r) + (i*i) for each complex value
76  // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4)
77  power = _mm_hadd_ps(input1, input2);
78 
79  // Calculate the natural log power
80  power = logf4(power);
81 
82  // Convert to log10 and multiply by 10.0
83  power = _mm_mul_ps(power, magScalar);
84 
85  // Store the floating point results
86  _mm_store_ps(destPtr, power);
87 
88  destPtr += 4;
89  }
90 
91  number = quarterPoints*4;
92 #endif /* LV_HAVE_LIB_SIMDMATH */
93  // Calculate the FFT for any remaining points
94 
95  for(; number < num_points; number++){
96  // Calculate dBm
97  // 50 ohm load assumption
98  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
99  // 75 ohm load assumption
100  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
101 
102  const float real = *inputPtr++ * iNormalizationFactor;
103  const float imag = *inputPtr++ * iNormalizationFactor;
104 
105  *destPtr = 10.0*log10f(((real * real) + (imag * imag)) + 1e-20);
106 
107  destPtr++;
108  }
109 
110 }
111 #endif /* LV_HAVE_SSE3 */
112 
113 #ifdef LV_HAVE_GENERIC
114 /*!
115  \brief Calculates the log10 power value for each input point
116  \param logPowerOutput The 10.0 * log10(r*r + i*i) for each data point
117  \param complexFFTInput The complex data output from the FFT point
118  \param normalizationFactor This value is divided agains all the input values before the power is calculated
119  \param num_points The number of fft data points
120 */
121 static inline void volk_32fc_s32f_power_spectrum_32f_generic(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, unsigned int num_points){
122  // Calculate the Power of the complex point
123  const float* inputPtr = (float*)complexFFTInput;
124  float* realFFTDataPointsPtr = logPowerOutput;
125  const float iNormalizationFactor = 1.0 / normalizationFactor;
126  unsigned int point;
127  for(point = 0; point < num_points; point++){
128  // Calculate dBm
129  // 50 ohm load assumption
130  // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
131  // 75 ohm load assumption
132  // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
133 
134  const float real = *inputPtr++ * iNormalizationFactor;
135  const float imag = *inputPtr++ * iNormalizationFactor;
136 
137  *realFFTDataPointsPtr = 10.0*log10f(((real * real) + (imag * imag)) + 1e-20);
138 
139 
140  realFFTDataPointsPtr++;
141  }
142 }
143 #endif /* LV_HAVE_GENERIC */
144 
145 
146 
147 
148 #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