GNU Radio Manual and C++ API Reference  3.7.7
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
volk_32f_s32f_32f_fm_detect_32f.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012, 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 /*!
24  * \page volk_32f_s32f_32f_fm_detect_32f
25  *
26  * \b Overview
27  *
28  * Performs FM-detect differentiation on the input vector and stores
29  * the results in the output vector.
30  *
31  * <b>Dispatcher Prototype</b>
32  * \code
33  * void volk_32f_s32f_32f_fm_detect_32f(float* outputVector, const float* inputVector, const float bound, float* saveValue, unsigned int num_points)
34  * \endcode
35  *
36  * \b Inputs
37  * \li inputVector: The input vector containing phase data (must be on the interval (-bound, bound]).
38  * \li bound: The interval that the input phase data is in, which is used to modulo the differentiation.
39  * \li saveValue: A pointer to a float which contains the phase value of the sample before the first input sample.
40  * \li num_points The number of data points.
41  *
42  * \b Outputs
43  * \li outputVector: The vector where the results will be stored.
44  *
45  * \b Example
46  * \code
47  * int N = 10000;
48  *
49  * <FIXME>
50  *
51  * volk_32f_s32f_32f_fm_detect_32f();
52  *
53  * \endcode
54  */
55 
56 #ifndef INCLUDED_volk_32f_s32f_32f_fm_detect_32f_a_H
57 #define INCLUDED_volk_32f_s32f_32f_fm_detect_32f_a_H
58 
59 #include <inttypes.h>
60 #include <stdio.h>
61 
62 #ifdef LV_HAVE_SSE
63 #include <xmmintrin.h>
64 
65 static inline void volk_32f_s32f_32f_fm_detect_32f_a_sse(float* outputVector, const float* inputVector, const float bound, float* saveValue, unsigned int num_points){
66  if (num_points < 1) {
67  return;
68  }
69  unsigned int number = 1;
70  unsigned int j = 0;
71  // num_points-1 keeps Fedora 7's gcc from crashing...
72  // num_points won't work. :(
73  const unsigned int quarterPoints = (num_points-1) / 4;
74 
75  float* outPtr = outputVector;
76  const float* inPtr = inputVector;
77  __m128 upperBound = _mm_set_ps1(bound);
78  __m128 lowerBound = _mm_set_ps1(-bound);
79  __m128 next3old1;
80  __m128 next4;
81  __m128 boundAdjust;
82  __m128 posBoundAdjust = _mm_set_ps1(-2*bound); // Subtract when we're above.
83  __m128 negBoundAdjust = _mm_set_ps1(2*bound); // Add when we're below.
84  // Do the first 4 by hand since we're going in from the saveValue:
85  *outPtr = *inPtr - *saveValue;
86  if (*outPtr > bound) *outPtr -= 2*bound;
87  if (*outPtr < -bound) *outPtr += 2*bound;
88  inPtr++;
89  outPtr++;
90  for (j = 1; j < ( (4 < num_points) ? 4 : num_points); j++) {
91  *outPtr = *(inPtr) - *(inPtr-1);
92  if (*outPtr > bound) *outPtr -= 2*bound;
93  if (*outPtr < -bound) *outPtr += 2*bound;
94  inPtr++;
95  outPtr++;
96  }
97 
98  for (; number < quarterPoints; number++) {
99  // Load data
100  next3old1 = _mm_loadu_ps((float*) (inPtr-1));
101  next4 = _mm_load_ps(inPtr);
102  inPtr += 4;
103  // Subtract and store:
104  next3old1 = _mm_sub_ps(next4, next3old1);
105  // Bound:
106  boundAdjust = _mm_cmpgt_ps(next3old1, upperBound);
107  boundAdjust = _mm_and_ps(boundAdjust, posBoundAdjust);
108  next4 = _mm_cmplt_ps(next3old1, lowerBound);
109  next4 = _mm_and_ps(next4, negBoundAdjust);
110  boundAdjust = _mm_or_ps(next4, boundAdjust);
111  // Make sure we're in the bounding interval:
112  next3old1 = _mm_add_ps(next3old1, boundAdjust);
113  _mm_store_ps(outPtr,next3old1); // Store the results back into the output
114  outPtr += 4;
115  }
116 
117  for (number = (4 > (quarterPoints*4) ? 4 : (4 * quarterPoints)); number < num_points; number++) {
118  *outPtr = *(inPtr) - *(inPtr-1);
119  if (*outPtr > bound) *outPtr -= 2*bound;
120  if (*outPtr < -bound) *outPtr += 2*bound;
121  inPtr++;
122  outPtr++;
123  }
124 
125  *saveValue = inputVector[num_points-1];
126 }
127 #endif /* LV_HAVE_SSE */
128 
129 #ifdef LV_HAVE_GENERIC
130 
131 static inline void volk_32f_s32f_32f_fm_detect_32f_generic(float* outputVector, const float* inputVector, const float bound, float* saveValue, unsigned int num_points){
132  if (num_points < 1) {
133  return;
134  }
135  unsigned int number = 0;
136  float* outPtr = outputVector;
137  const float* inPtr = inputVector;
138 
139  // Do the first 1 by hand since we're going in from the saveValue:
140  *outPtr = *inPtr - *saveValue;
141  if (*outPtr > bound) *outPtr -= 2*bound;
142  if (*outPtr < -bound) *outPtr += 2*bound;
143  inPtr++;
144  outPtr++;
145 
146  for (number = 1; number < num_points; number++) {
147  *outPtr = *(inPtr) - *(inPtr-1);
148  if (*outPtr > bound) *outPtr -= 2*bound;
149  if (*outPtr < -bound) *outPtr += 2*bound;
150  inPtr++;
151  outPtr++;
152  }
153 
154  *saveValue = inputVector[num_points-1];
155 }
156 #endif /* LV_HAVE_GENERIC */
157 
158 
159 
160 
161 #endif /* INCLUDED_volk_32f_s32f_32f_fm_detect_32f_a_H */