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_16ic_deinterleave_16i_x2.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_16ic_deinterleave_16i_x2
25  *
26  * \b Overview
27  *
28  * Deinterleaves the complex 16 bit vector into I & Q vector data.
29  *
30  * <b>Dispatcher Prototype</b>
31  * \code
32  * void volk_16ic_deinterleave_16i_x2(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points)
33  * \endcode
34  *
35  * \b Inputs
36  * \li complexVector: The complex input vector.
37  * \li num_points: The number of complex data values to be deinterleaved.
38  *
39  * \b Outputs
40  * \li iBuffer: The I buffer output data.
41  * \li qBuffer: The Q buffer output data.
42  *
43  * \b Example
44  * \code
45  * int N = 10000;
46  *
47  * volk_16ic_deinterleave_16i_x2();
48  *
49  * volk_free(x);
50  * volk_free(t);
51  * \endcode
52  */
53 
54 #ifndef INCLUDED_volk_16ic_deinterleave_16i_x2_a_H
55 #define INCLUDED_volk_16ic_deinterleave_16i_x2_a_H
56 
57 #include <inttypes.h>
58 #include <stdio.h>
59 
60 #ifdef LV_HAVE_SSSE3
61 #include <tmmintrin.h>
62 
63 static inline void
64 volk_16ic_deinterleave_16i_x2_a_ssse3(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points)
65 {
66  unsigned int number = 0;
67  const int8_t* complexVectorPtr = (int8_t*)complexVector;
68  int16_t* iBufferPtr = iBuffer;
69  int16_t* qBufferPtr = qBuffer;
70 
71  __m128i iMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 13, 12, 9, 8, 5, 4, 1, 0);
72  __m128i iMoveMask2 = _mm_set_epi8(13, 12, 9, 8, 5, 4, 1, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
73 
74  __m128i qMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 14, 11, 10, 7, 6, 3, 2);
75  __m128i qMoveMask2 = _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
76 
77  __m128i complexVal1, complexVal2, iOutputVal, qOutputVal;
78 
79  unsigned int eighthPoints = num_points / 8;
80 
81  for(number = 0; number < eighthPoints; number++){
82  complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
83  complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16;
84 
85  iOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, iMoveMask1) , _mm_shuffle_epi8(complexVal2, iMoveMask2));
86  qOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, qMoveMask1) , _mm_shuffle_epi8(complexVal2, qMoveMask2));
87 
88  _mm_store_si128((__m128i*)iBufferPtr, iOutputVal);
89  _mm_store_si128((__m128i*)qBufferPtr, qOutputVal);
90 
91  iBufferPtr += 8;
92  qBufferPtr += 8;
93  }
94 
95  number = eighthPoints * 8;
96  int16_t* int16ComplexVectorPtr = (int16_t*)complexVectorPtr;
97  for(; number < num_points; number++){
98  *iBufferPtr++ = *int16ComplexVectorPtr++;
99  *qBufferPtr++ = *int16ComplexVectorPtr++;
100  }
101 }
102 #endif /* LV_HAVE_SSSE3 */
103 
104 #ifdef LV_HAVE_SSE2
105 #include <emmintrin.h>
106 
107 static inline void
108 volk_16ic_deinterleave_16i_x2_a_sse2(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points)
109 {
110  unsigned int number = 0;
111  const int16_t* complexVectorPtr = (int16_t*)complexVector;
112  int16_t* iBufferPtr = iBuffer;
113  int16_t* qBufferPtr = qBuffer;
114  __m128i complexVal1, complexVal2, iComplexVal1, iComplexVal2, qComplexVal1, qComplexVal2, iOutputVal, qOutputVal;
115  __m128i lowMask = _mm_set_epi32(0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF);
116  __m128i highMask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0);
117 
118  unsigned int eighthPoints = num_points / 8;
119 
120  for(number = 0; number < eighthPoints; number++){
121  complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 8;
122  complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 8;
123 
124  iComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(3,1,2,0));
125 
126  iComplexVal1 = _mm_shufflehi_epi16(iComplexVal1, _MM_SHUFFLE(3,1,2,0));
127 
128  iComplexVal1 = _mm_shuffle_epi32(iComplexVal1, _MM_SHUFFLE(3,1,2,0));
129 
130  iComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(3,1,2,0));
131 
132  iComplexVal2 = _mm_shufflehi_epi16(iComplexVal2, _MM_SHUFFLE(3,1,2,0));
133 
134  iComplexVal2 = _mm_shuffle_epi32(iComplexVal2, _MM_SHUFFLE(2,0,3,1));
135 
136  iOutputVal = _mm_or_si128(_mm_and_si128(iComplexVal1, lowMask), _mm_and_si128(iComplexVal2, highMask));
137 
138  _mm_store_si128((__m128i*)iBufferPtr, iOutputVal);
139 
140  qComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(2,0,3,1));
141 
142  qComplexVal1 = _mm_shufflehi_epi16(qComplexVal1, _MM_SHUFFLE(2,0,3,1));
143 
144  qComplexVal1 = _mm_shuffle_epi32(qComplexVal1, _MM_SHUFFLE(3,1,2,0));
145 
146  qComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(2,0,3,1));
147 
148  qComplexVal2 = _mm_shufflehi_epi16(qComplexVal2, _MM_SHUFFLE(2,0,3,1));
149 
150  qComplexVal2 = _mm_shuffle_epi32(qComplexVal2, _MM_SHUFFLE(2,0,3,1));
151 
152  qOutputVal = _mm_or_si128(_mm_and_si128(qComplexVal1, lowMask), _mm_and_si128(qComplexVal2, highMask));
153 
154  _mm_store_si128((__m128i*)qBufferPtr, qOutputVal);
155 
156  iBufferPtr += 8;
157  qBufferPtr += 8;
158  }
159 
160  number = eighthPoints * 8;
161  for(; number < num_points; number++){
162  *iBufferPtr++ = *complexVectorPtr++;
163  *qBufferPtr++ = *complexVectorPtr++;
164  }
165 }
166 #endif /* LV_HAVE_SSE2 */
167 
168 #ifdef LV_HAVE_GENERIC
169 
170 static inline void
171 volk_16ic_deinterleave_16i_x2_generic(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points)
172 {
173  const int16_t* complexVectorPtr = (const int16_t*)complexVector;
174  int16_t* iBufferPtr = iBuffer;
175  int16_t* qBufferPtr = qBuffer;
176  unsigned int number;
177  for(number = 0; number < num_points; number++){
178  *iBufferPtr++ = *complexVectorPtr++;
179  *qBufferPtr++ = *complexVectorPtr++;
180  }
181 }
182 #endif /* LV_HAVE_GENERIC */
183 
184 #ifdef LV_HAVE_ORC
185 
186 extern void
187 volk_16ic_deinterleave_16i_x2_a_orc_impl(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points);
188 static inline void
189 volk_16ic_deinterleave_16i_x2_u_orc(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points)
190 {
191  volk_16ic_deinterleave_16i_x2_a_orc_impl(iBuffer, qBuffer, complexVector, num_points);
192 }
193 #endif /* LV_HAVE_ORC */
194 
195 #endif /* INCLUDED_volk_16ic_deinterleave_16i_x2_a_H */
short complex lv_16sc_t
Definition: volk_complex.h:53
signed short int16_t
Definition: stdint.h:76
signed char int8_t
Definition: stdint.h:75