GNU Radio Manual and C++ API Reference  3.7.6.1
The Free & Open Software Radio Ecosystem
volk_32f_s32f_32f_fm_detect_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_32f_s32f_32f_fm_detect_32f_a_H
24 #define INCLUDED_volk_32f_s32f_32f_fm_detect_32f_a_H
25 
26 #include <inttypes.h>
27 #include <stdio.h>
28 
29 #ifdef LV_HAVE_SSE
30 #include <xmmintrin.h>
31 /*!
32  \brief performs the FM-detect differentiation on the input vector and stores the results in the output vector.
33  \param outputVector The byte-aligned vector where the results will be stored.
34  \param inputVector The byte-aligned input vector containing phase data (must be on the interval (-bound,bound] )
35  \param bound The interval that the input phase data is in, which is used to modulo the differentiation
36  \param saveValue A pointer to a float which contains the phase value of the sample before the first input sample.
37  \param num_noints The number of real values in the input vector.
38 */
39 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){
40  if (num_points < 1) {
41  return;
42  }
43  unsigned int number = 1;
44  unsigned int j = 0;
45  // num_points-1 keeps Fedora 7's gcc from crashing...
46  // num_points won't work. :(
47  const unsigned int quarterPoints = (num_points-1) / 4;
48 
49  float* outPtr = outputVector;
50  const float* inPtr = inputVector;
51  __m128 upperBound = _mm_set_ps1(bound);
52  __m128 lowerBound = _mm_set_ps1(-bound);
53  __m128 next3old1;
54  __m128 next4;
55  __m128 boundAdjust;
56  __m128 posBoundAdjust = _mm_set_ps1(-2*bound); // Subtract when we're above.
57  __m128 negBoundAdjust = _mm_set_ps1(2*bound); // Add when we're below.
58  // Do the first 4 by hand since we're going in from the saveValue:
59  *outPtr = *inPtr - *saveValue;
60  if (*outPtr > bound) *outPtr -= 2*bound;
61  if (*outPtr < -bound) *outPtr += 2*bound;
62  inPtr++;
63  outPtr++;
64  for (j = 1; j < ( (4 < num_points) ? 4 : num_points); j++) {
65  *outPtr = *(inPtr) - *(inPtr-1);
66  if (*outPtr > bound) *outPtr -= 2*bound;
67  if (*outPtr < -bound) *outPtr += 2*bound;
68  inPtr++;
69  outPtr++;
70  }
71 
72  for (; number < quarterPoints; number++) {
73  // Load data
74  next3old1 = _mm_loadu_ps((float*) (inPtr-1));
75  next4 = _mm_load_ps(inPtr);
76  inPtr += 4;
77  // Subtract and store:
78  next3old1 = _mm_sub_ps(next4, next3old1);
79  // Bound:
80  boundAdjust = _mm_cmpgt_ps(next3old1, upperBound);
81  boundAdjust = _mm_and_ps(boundAdjust, posBoundAdjust);
82  next4 = _mm_cmplt_ps(next3old1, lowerBound);
83  next4 = _mm_and_ps(next4, negBoundAdjust);
84  boundAdjust = _mm_or_ps(next4, boundAdjust);
85  // Make sure we're in the bounding interval:
86  next3old1 = _mm_add_ps(next3old1, boundAdjust);
87  _mm_store_ps(outPtr,next3old1); // Store the results back into the output
88  outPtr += 4;
89  }
90 
91  for (number = (4 > (quarterPoints*4) ? 4 : (4 * quarterPoints)); number < num_points; number++) {
92  *outPtr = *(inPtr) - *(inPtr-1);
93  if (*outPtr > bound) *outPtr -= 2*bound;
94  if (*outPtr < -bound) *outPtr += 2*bound;
95  inPtr++;
96  outPtr++;
97  }
98 
99  *saveValue = inputVector[num_points-1];
100 }
101 #endif /* LV_HAVE_SSE */
102 
103 #ifdef LV_HAVE_GENERIC
104 /*!
105  \brief performs the FM-detect differentiation on the input vector and stores the results in the output vector.
106  \param outputVector The byte-aligned vector where the results will be stored.
107  \param inputVector The byte-aligned input vector containing phase data (must be on the interval (-bound,bound] )
108  \param bound The interval that the input phase data is in, which is used to modulo the differentiation
109  \param saveValue A pointer to a float which contains the phase value of the sample before the first input sample.
110  \param num_points The number of real values in the input vector.
111 */
112 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){
113  if (num_points < 1) {
114  return;
115  }
116  unsigned int number = 0;
117  float* outPtr = outputVector;
118  const float* inPtr = inputVector;
119 
120  // Do the first 1 by hand since we're going in from the saveValue:
121  *outPtr = *inPtr - *saveValue;
122  if (*outPtr > bound) *outPtr -= 2*bound;
123  if (*outPtr < -bound) *outPtr += 2*bound;
124  inPtr++;
125  outPtr++;
126 
127  for (number = 1; number < num_points; number++) {
128  *outPtr = *(inPtr) - *(inPtr-1);
129  if (*outPtr > bound) *outPtr -= 2*bound;
130  if (*outPtr < -bound) *outPtr += 2*bound;
131  inPtr++;
132  outPtr++;
133  }
134 
135  *saveValue = inputVector[num_points-1];
136 }
137 #endif /* LV_HAVE_GENERIC */
138 
139 
140 
141 
142 #endif /* INCLUDED_volk_32f_s32f_32f_fm_detect_32f_a_H */