GNU Radio 3.6.5 C++ API
|
00001 #ifndef INCLUDED_volk_16ic_deinterleave_16i_x2_a_H 00002 #define INCLUDED_volk_16ic_deinterleave_16i_x2_a_H 00003 00004 #include <inttypes.h> 00005 #include <stdio.h> 00006 00007 #ifdef LV_HAVE_SSSE3 00008 #include <tmmintrin.h> 00009 /*! 00010 \brief Deinterleaves the complex 16 bit vector into I & Q vector data 00011 \param complexVector The complex input vector 00012 \param iBuffer The I buffer output data 00013 \param qBuffer The Q buffer output data 00014 \param num_points The number of complex data values to be deinterleaved 00015 */ 00016 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){ 00017 unsigned int number = 0; 00018 const int8_t* complexVectorPtr = (int8_t*)complexVector; 00019 int16_t* iBufferPtr = iBuffer; 00020 int16_t* qBufferPtr = qBuffer; 00021 00022 __m128i iMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 13, 12, 9, 8, 5, 4, 1, 0); 00023 __m128i iMoveMask2 = _mm_set_epi8(13, 12, 9, 8, 5, 4, 1, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80); 00024 00025 __m128i qMoveMask1 = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 14, 11, 10, 7, 6, 3, 2); 00026 __m128i qMoveMask2 = _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80); 00027 00028 __m128i complexVal1, complexVal2, iOutputVal, qOutputVal; 00029 00030 unsigned int eighthPoints = num_points / 8; 00031 00032 for(number = 0; number < eighthPoints; number++){ 00033 complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16; 00034 complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16; 00035 00036 iOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, iMoveMask1) , _mm_shuffle_epi8(complexVal2, iMoveMask2)); 00037 qOutputVal = _mm_or_si128( _mm_shuffle_epi8(complexVal1, qMoveMask1) , _mm_shuffle_epi8(complexVal2, qMoveMask2)); 00038 00039 _mm_store_si128((__m128i*)iBufferPtr, iOutputVal); 00040 _mm_store_si128((__m128i*)qBufferPtr, qOutputVal); 00041 00042 iBufferPtr += 8; 00043 qBufferPtr += 8; 00044 } 00045 00046 number = eighthPoints * 8; 00047 int16_t* int16ComplexVectorPtr = (int16_t*)complexVectorPtr; 00048 for(; number < num_points; number++){ 00049 *iBufferPtr++ = *int16ComplexVectorPtr++; 00050 *qBufferPtr++ = *int16ComplexVectorPtr++; 00051 } 00052 } 00053 #endif /* LV_HAVE_SSSE3 */ 00054 00055 #ifdef LV_HAVE_SSE2 00056 #include <emmintrin.h> 00057 /*! 00058 \brief Deinterleaves the complex 16 bit vector into I & Q vector data 00059 \param complexVector The complex input vector 00060 \param iBuffer The I buffer output data 00061 \param qBuffer The Q buffer output data 00062 \param num_points The number of complex data values to be deinterleaved 00063 */ 00064 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){ 00065 unsigned int number = 0; 00066 const int16_t* complexVectorPtr = (int16_t*)complexVector; 00067 int16_t* iBufferPtr = iBuffer; 00068 int16_t* qBufferPtr = qBuffer; 00069 __m128i complexVal1, complexVal2, iComplexVal1, iComplexVal2, qComplexVal1, qComplexVal2, iOutputVal, qOutputVal; 00070 __m128i lowMask = _mm_set_epi32(0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF); 00071 __m128i highMask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0); 00072 00073 unsigned int eighthPoints = num_points / 8; 00074 00075 for(number = 0; number < eighthPoints; number++){ 00076 complexVal1 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 8; 00077 complexVal2 = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 8; 00078 00079 iComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(3,1,2,0)); 00080 00081 iComplexVal1 = _mm_shufflehi_epi16(iComplexVal1, _MM_SHUFFLE(3,1,2,0)); 00082 00083 iComplexVal1 = _mm_shuffle_epi32(iComplexVal1, _MM_SHUFFLE(3,1,2,0)); 00084 00085 iComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(3,1,2,0)); 00086 00087 iComplexVal2 = _mm_shufflehi_epi16(iComplexVal2, _MM_SHUFFLE(3,1,2,0)); 00088 00089 iComplexVal2 = _mm_shuffle_epi32(iComplexVal2, _MM_SHUFFLE(2,0,3,1)); 00090 00091 iOutputVal = _mm_or_si128(_mm_and_si128(iComplexVal1, lowMask), _mm_and_si128(iComplexVal2, highMask)); 00092 00093 _mm_store_si128((__m128i*)iBufferPtr, iOutputVal); 00094 00095 qComplexVal1 = _mm_shufflelo_epi16(complexVal1, _MM_SHUFFLE(2,0,3,1)); 00096 00097 qComplexVal1 = _mm_shufflehi_epi16(qComplexVal1, _MM_SHUFFLE(2,0,3,1)); 00098 00099 qComplexVal1 = _mm_shuffle_epi32(qComplexVal1, _MM_SHUFFLE(3,1,2,0)); 00100 00101 qComplexVal2 = _mm_shufflelo_epi16(complexVal2, _MM_SHUFFLE(2,0,3,1)); 00102 00103 qComplexVal2 = _mm_shufflehi_epi16(qComplexVal2, _MM_SHUFFLE(2,0,3,1)); 00104 00105 qComplexVal2 = _mm_shuffle_epi32(qComplexVal2, _MM_SHUFFLE(2,0,3,1)); 00106 00107 qOutputVal = _mm_or_si128(_mm_and_si128(qComplexVal1, lowMask), _mm_and_si128(qComplexVal2, highMask)); 00108 00109 _mm_store_si128((__m128i*)qBufferPtr, qOutputVal); 00110 00111 iBufferPtr += 8; 00112 qBufferPtr += 8; 00113 } 00114 00115 number = eighthPoints * 8; 00116 for(; number < num_points; number++){ 00117 *iBufferPtr++ = *complexVectorPtr++; 00118 *qBufferPtr++ = *complexVectorPtr++; 00119 } 00120 } 00121 #endif /* LV_HAVE_SSE2 */ 00122 00123 #ifdef LV_HAVE_GENERIC 00124 /*! 00125 \brief Deinterleaves the complex 16 bit vector into I & Q vector data 00126 \param complexVector The complex input vector 00127 \param iBuffer The I buffer output data 00128 \param qBuffer The Q buffer output data 00129 \param num_points The number of complex data values to be deinterleaved 00130 */ 00131 static inline void volk_16ic_deinterleave_16i_x2_a_generic(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){ 00132 const int16_t* complexVectorPtr = (const int16_t*)complexVector; 00133 int16_t* iBufferPtr = iBuffer; 00134 int16_t* qBufferPtr = qBuffer; 00135 unsigned int number; 00136 for(number = 0; number < num_points; number++){ 00137 *iBufferPtr++ = *complexVectorPtr++; 00138 *qBufferPtr++ = *complexVectorPtr++; 00139 } 00140 } 00141 #endif /* LV_HAVE_GENERIC */ 00142 00143 #ifdef LV_HAVE_ORC 00144 /*! 00145 \brief Deinterleaves the complex 16 bit vector into I & Q vector data 00146 \param complexVector The complex input vector 00147 \param iBuffer The I buffer output data 00148 \param qBuffer The Q buffer output data 00149 \param num_points The number of complex data values to be deinterleaved 00150 */ 00151 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); 00152 static inline void volk_16ic_deinterleave_16i_x2_a_orc(int16_t* iBuffer, int16_t* qBuffer, const lv_16sc_t* complexVector, unsigned int num_points){ 00153 volk_16ic_deinterleave_16i_x2_a_orc_impl(iBuffer, qBuffer, complexVector, num_points); 00154 } 00155 #endif /* LV_HAVE_ORC */ 00156 00157 00158 #endif /* INCLUDED_volk_16ic_deinterleave_16i_x2_a_H */