Statistics
| Branch: | Tag: | Revision:

root / host / lib / transport / convert_types_impl.hpp @ 79ea83d6

History | View | Annotate | Download (9.5 kB)

1
//
2
// Copyright 2010 Ettus Research LLC
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

    
18
#ifndef INCLUDED_LIBUHD_TRANSPORT_CONVERT_TYPES_IMPL_HPP
19
#define INCLUDED_LIBUHD_TRANSPORT_CONVERT_TYPES_IMPL_HPP
20

    
21
#include <uhd/config.hpp>
22
#include <uhd/utils/byteswap.hpp>
23
#include <boost/cstdint.hpp>
24
#include <cstring>
25
#include <complex>
26

    
27
#ifdef HAVE_EMMINTRIN_H
28
    #define USE_EMMINTRIN_H //use sse2 intrinsics
29
#endif
30

    
31
#if defined(USE_EMMINTRIN_H)
32
    #include <emmintrin.h>
33
#endif
34

    
35
/***********************************************************************
36
 * Typedefs
37
 **********************************************************************/
38
typedef std::complex<float>          fc32_t;
39
typedef std::complex<boost::int16_t> sc16_t;
40
typedef boost::uint32_t              item32_t;
41

    
42
/***********************************************************************
43
 * Convert complex short buffer to items32
44
 **********************************************************************/
45
static UHD_INLINE item32_t sc16_to_item32(sc16_t num){
46
    boost::uint16_t real = num.real();
47
    boost::uint16_t imag = num.imag();
48
    return (item32_t(real) << 16) | (item32_t(imag) << 0);
49
}
50

    
51
static UHD_INLINE void sc16_to_item32_nswap(
52
    const sc16_t *input, item32_t *output, size_t nsamps
53
){
54
    for (size_t i = 0; i < nsamps; i++){
55
        output[i] = sc16_to_item32(input[i]);
56
    }
57
}
58

    
59
static UHD_INLINE void sc16_to_item32_bswap(
60
    const sc16_t *input, item32_t *output, size_t nsamps
61
){
62
    for (size_t i = 0; i < nsamps; i++){
63
        output[i] = uhd::byteswap(sc16_to_item32(input[i]));
64
    }
65
}
66

    
67
/***********************************************************************
68
 * Convert items32 buffer to complex short
69
 **********************************************************************/
70
static UHD_INLINE sc16_t item32_to_sc16(item32_t item){
71
    return sc16_t(
72
        boost::int16_t(item >> 16),
73
        boost::int16_t(item >> 0)
74
    );
75
}
76

    
77
static UHD_INLINE void item32_to_sc16_nswap(
78
    const item32_t *input, sc16_t *output, size_t nsamps
79
){
80
    for (size_t i = 0; i < nsamps; i++){
81
        output[i] = item32_to_sc16(input[i]);
82
    }
83
}
84

    
85
static UHD_INLINE void item32_to_sc16_bswap(
86
    const item32_t *input, sc16_t *output, size_t nsamps
87
){
88
    for (size_t i = 0; i < nsamps; i++){
89
        output[i] = item32_to_sc16(uhd::byteswap(input[i]));
90
    }
91
}
92

    
93
/***********************************************************************
94
 * Convert complex float buffer to items32 (no swap)
95
 **********************************************************************/
96
static const float shorts_per_float = float(32767);
97

    
98
static UHD_INLINE item32_t fc32_to_item32(fc32_t num){
99
    boost::uint16_t real = boost::int16_t(num.real()*shorts_per_float);
100
    boost::uint16_t imag = boost::int16_t(num.imag()*shorts_per_float);
101
    return (item32_t(real) << 16) | (item32_t(imag) << 0);
102
}
103

    
104
////////////////////////////////////
105
// none-swap
106
////////////////////////////////////
107
#if defined(USE_EMMINTRIN_H)
108
static UHD_INLINE void fc32_to_item32_nswap(
109
    const fc32_t *input, item32_t *output, size_t nsamps
110
){
111
    __m128 scalar = _mm_set_ps1(shorts_per_float);
112

    
113
    //convert blocks of samples with intrinsics
114
    size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
115
        //load from input
116
        __m128 tmplo = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+0));
117
        __m128 tmphi = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+2));
118

    
119
        //convert and scale
120
        __m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
121
        __m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
122

    
123
        //pack + swap 16-bit pairs
124
        __m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
125
        tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
126
        tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
127

    
128
        //store to output
129
        _mm_storeu_si128(reinterpret_cast<__m128i *>(output+i), tmpi);
130
    }
131

    
132
    //convert remainder
133
    for (; i < nsamps; i++){
134
        output[i] = fc32_to_item32(input[i]);
135
    }
136
}
137

    
138
#else
139
static UHD_INLINE void fc32_to_item32_nswap(
140
    const fc32_t *input, item32_t *output, size_t nsamps
141
){
142
    for (size_t i = 0; i < nsamps; i++){
143
        output[i] = fc32_to_item32(input[i]);
144
    }
145
}
146

    
147
#endif
148

    
149
////////////////////////////////////
150
// byte-swap
151
////////////////////////////////////
152
#if defined(USE_EMMINTRIN_H)
153
static UHD_INLINE void fc32_to_item32_bswap(
154
    const fc32_t *input, item32_t *output, size_t nsamps
155
){
156
    __m128 scalar = _mm_set_ps1(shorts_per_float);
157

    
158
    //convert blocks of samples with intrinsics
159
    size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
160
        //load from input
161
        __m128 tmplo = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+0));
162
        __m128 tmphi = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+2));
163

    
164
        //convert and scale
165
        __m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
166
        __m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
167

    
168
        //pack + byteswap -> byteswap 16 bit words
169
        __m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
170
        tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
171

    
172
        //store to output
173
        _mm_storeu_si128(reinterpret_cast<__m128i *>(output+i), tmpi);
174
    }
175

    
176
    //convert remainder
177
    for (; i < nsamps; i++){
178
        output[i] = uhd::byteswap(fc32_to_item32(input[i]));
179
    }
180
}
181

    
182
#else
183
static UHD_INLINE void fc32_to_item32_bswap(
184
    const fc32_t *input, item32_t *output, size_t nsamps
185
){
186
    for (size_t i = 0; i < nsamps; i++){
187
        output[i] = uhd::byteswap(fc32_to_item32(input[i]));
188
    }
189
}
190

    
191
#endif
192

    
193
/***********************************************************************
194
 * Convert items32 buffer to complex float
195
 **********************************************************************/
196
static const float floats_per_short = float(1.0/shorts_per_float);
197

    
198
static UHD_INLINE fc32_t item32_to_fc32(item32_t item){
199
    return fc32_t(
200
        float(boost::int16_t(item >> 16)*floats_per_short),
201
        float(boost::int16_t(item >> 0)*floats_per_short)
202
    );
203
}
204

    
205
////////////////////////////////////
206
// none-swap
207
////////////////////////////////////
208
#if defined(USE_EMMINTRIN_H)
209
static UHD_INLINE void item32_to_fc32_nswap(
210
    const item32_t *input, fc32_t *output, size_t nsamps
211
){
212
    __m128 scalar = _mm_set_ps1(floats_per_short/(1 << 16));
213
    __m128i zeroi = _mm_setzero_si128();
214

    
215
    //convert blocks of samples with intrinsics
216
    size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
217
        //load from input
218
        __m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
219

    
220
        //unpack + swap 16-bit pairs
221
        tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
222
        tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
223
        __m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
224
        __m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
225

    
226
        //convert and scale
227
        __m128 tmplo = _mm_mul_ps(_mm_cvtepi32_ps(tmpilo), scalar);
228
        __m128 tmphi = _mm_mul_ps(_mm_cvtepi32_ps(tmpihi), scalar);
229

    
230
        //store to output
231
        _mm_storeu_ps(reinterpret_cast<float *>(output+i+0), tmplo);
232
        _mm_storeu_ps(reinterpret_cast<float *>(output+i+2), tmphi);
233
    }
234

    
235
    //convert remainder
236
    for (; i < nsamps; i++){
237
        output[i] = item32_to_fc32(input[i]);
238
    }
239
}
240

    
241
#else
242
static UHD_INLINE void item32_to_fc32_nswap(
243
    const item32_t *input, fc32_t *output, size_t nsamps
244
){
245
    for (size_t i = 0; i < nsamps; i++){
246
        output[i] = item32_to_fc32(input[i]);
247
    }
248
}
249
#endif
250

    
251
////////////////////////////////////
252
// byte-swap
253
////////////////////////////////////
254
#if defined(USE_EMMINTRIN_H)
255
static UHD_INLINE void item32_to_fc32_bswap(
256
    const item32_t *input, fc32_t *output, size_t nsamps
257
){
258
    __m128 scalar = _mm_set_ps1(floats_per_short/(1 << 16));
259
    __m128i zeroi = _mm_setzero_si128();
260

    
261
    //convert blocks of samples with intrinsics
262
    size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
263
        //load from input
264
        __m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
265

    
266
        //byteswap + unpack -> byteswap 16 bit words
267
        tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
268
        __m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
269
        __m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
270

    
271
        //convert and scale
272
        __m128 tmplo = _mm_mul_ps(_mm_cvtepi32_ps(tmpilo), scalar);
273
        __m128 tmphi = _mm_mul_ps(_mm_cvtepi32_ps(tmpihi), scalar);
274

    
275
        //store to output
276
        _mm_storeu_ps(reinterpret_cast<float *>(output+i+0), tmplo);
277
        _mm_storeu_ps(reinterpret_cast<float *>(output+i+2), tmphi);
278
    }
279

    
280
    //convert remainder
281
    for (; i < nsamps; i++){
282
        output[i] = item32_to_fc32(uhd::byteswap(input[i]));
283
    }
284
}
285

    
286
#else
287
static UHD_INLINE void item32_to_fc32_bswap(
288
    const item32_t *input, fc32_t *output, size_t nsamps
289
){
290
    for (size_t i = 0; i < nsamps; i++){
291
        output[i] = item32_to_fc32(uhd::byteswap(input[i]));
292
    }
293
}
294

    
295
#endif
296

    
297
#endif /* INCLUDED_LIBUHD_TRANSPORT_CONVERT_TYPES_IMPL_HPP */