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