Statistics
| Branch: | Tag: | Revision:

root / host / lib / convert / convert_common.hpp @ 3122bff9

History | View | Annotate | Download (9.72 KB)

1
//
2
// Copyright 2011-2012 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_CONVERT_COMMON_HPP
19
#define INCLUDED_LIBUHD_CONVERT_COMMON_HPP
20

    
21
#include <uhd/convert.hpp>
22
#include <uhd/utils/static.hpp>
23
#include <boost/cstdint.hpp>
24
#include <complex>
25

    
26
#define _DECLARE_CONVERTER(name, in_form, num_in, out_form, num_out, prio) \
27
    struct name : public uhd::convert::converter{ \
28
        static sptr make(void){return sptr(new name());} \
29
        double scale_factor; \
30
        void set_scalar(const double s){scale_factor = s;} \
31
        void operator()(const input_type&, const output_type&, const size_t); \
32
    }; \
33
    UHD_STATIC_BLOCK(__register_##name##_##prio){ \
34
        uhd::convert::id_type id; \
35
        id.input_format = #in_form; \
36
        id.num_inputs = num_in; \
37
        id.output_format = #out_form; \
38
        id.num_outputs = num_out; \
39
        uhd::convert::register_converter(id, &name::make, prio); \
40
    } \
41
    void name::operator()( \
42
        const input_type &inputs, const output_type &outputs, const size_t nsamps \
43
    )
44

    
45
#define DECLARE_CONVERTER(in_form, num_in, out_form, num_out, prio) \
46
    _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out##_##prio, in_form, num_in, out_form, num_out, prio)
47

    
48
/***********************************************************************
49
 * Setup priorities
50
 **********************************************************************/
51
static const int PRIORITY_GENERAL = 0;
52
static const int PRIORITY_EMPTY = -1;
53

    
54
#ifdef __ARM_NEON__
55
static const int PRIORITY_LIBORC = 3;
56
static const int PRIORITY_SIMD = 2; //neon conversions could be implemented better, orc wins
57
static const int PRIORITY_TABLE = 1; //tables require large cache, so they are slower on arm
58
#else
59
static const int PRIORITY_LIBORC = 2;
60
static const int PRIORITY_SIMD = 3;
61
static const int PRIORITY_TABLE = 1;
62
#endif
63

    
64
/***********************************************************************
65
 * Typedefs
66
 **********************************************************************/
67
typedef std::complex<double>         fc64_t;
68
typedef std::complex<float>          fc32_t;
69
typedef std::complex<boost::int32_t> sc32_t;
70
typedef std::complex<boost::int16_t> sc16_t;
71
typedef std::complex<boost::int8_t>  sc8_t;
72
typedef double                       f64_t;
73
typedef float                        f32_t;
74
typedef boost::int32_t               s32_t;
75
typedef boost::int16_t               s16_t;
76
typedef boost::int8_t                s8_t;
77

    
78
typedef boost::uint32_t              item32_t;
79

    
80
typedef item32_t (*xtox_t)(item32_t);
81

    
82
/***********************************************************************
83
 * Convert xx to items32 sc16 buffer
84
 **********************************************************************/
85
template <typename T> UHD_INLINE item32_t xx_to_item32_sc16_x1(
86
    const std::complex<T> &num, const double scale_factor
87
){
88
    boost::uint16_t real = boost::int16_t(num.real()*float(scale_factor));
89
    boost::uint16_t imag = boost::int16_t(num.imag()*float(scale_factor));
90
    return (item32_t(real) << 16) | (item32_t(imag) << 0);
91
}
92

    
93
template <> UHD_INLINE item32_t xx_to_item32_sc16_x1(
94
    const sc16_t &num, const double
95
){
96
    boost::uint16_t real = boost::int16_t(num.real());
97
    boost::uint16_t imag = boost::int16_t(num.imag());
98
    return (item32_t(real) << 16) | (item32_t(imag) << 0);
99
}
100

    
101
template <xtox_t to_wire, typename T>
102
UHD_INLINE void xx_to_item32_sc16(
103
    const std::complex<T> *input,
104
    item32_t *output,
105
    const size_t nsamps,
106
    const double scale_factor
107
){
108
    for (size_t i = 0; i < nsamps; i++){
109
        const item32_t item = xx_to_item32_sc16_x1(input[i], scale_factor);
110
        output[i] = to_wire(item);
111
    }
112
}
113

    
114
/***********************************************************************
115
 * Convert items32 sc16 buffer to xx
116
 **********************************************************************/
117
template <typename T> UHD_INLINE std::complex<T> item32_sc16_x1_to_xx(
118
    const item32_t item, const double scale_factor
119
){
120
    return std::complex<T>(
121
        T(boost::int16_t(item >> 16)*float(scale_factor)),
122
        T(boost::int16_t(item >> 0)*float(scale_factor))
123
    );
124
}
125

    
126
template <> UHD_INLINE sc16_t item32_sc16_x1_to_xx(
127
    const item32_t item, const double
128
){
129
    return sc16_t(
130
        boost::int16_t(item >> 16), boost::int16_t(item >> 0)
131
    );
132
}
133

    
134
template <xtox_t to_host, typename T>
135
UHD_INLINE void item32_sc16_to_xx(
136
    const item32_t *input,
137
    std::complex<T> *output,
138
    const size_t nsamps,
139
    const double scale_factor
140
){
141
    for (size_t i = 0; i < nsamps; i++){
142
        const item32_t item_i = to_host(input[i]);
143
        output[i] = item32_sc16_x1_to_xx<T>(item_i, scale_factor);
144
    }
145
}
146

    
147
/***********************************************************************
148
 * Convert xx to items32 sc8 buffer
149
 **********************************************************************/
150
template <typename T> UHD_INLINE item32_t xx_to_item32_sc8_x1(
151
    const std::complex<T> &in0, const std::complex<T> &in1, const double scale_factor
152
){
153
    boost::uint8_t real0 = boost::int8_t(in0.real()*float(scale_factor));
154
    boost::uint8_t imag0 = boost::int8_t(in0.imag()*float(scale_factor));
155
    boost::uint8_t real1 = boost::int8_t(in1.real()*float(scale_factor));
156
    boost::uint8_t imag1 = boost::int8_t(in1.imag()*float(scale_factor));
157
    return
158
        (item32_t(real0) << 8) | (item32_t(imag0) << 0) |
159
        (item32_t(real1) << 24) | (item32_t(imag1) << 16)
160
    ;
161
}
162

    
163
template <> UHD_INLINE item32_t xx_to_item32_sc8_x1(
164
    const sc16_t &in0, const sc16_t &in1, const double
165
){
166
    boost::uint8_t real0 = boost::int8_t(in0.real());
167
    boost::uint8_t imag0 = boost::int8_t(in0.imag());
168
    boost::uint8_t real1 = boost::int8_t(in1.real());
169
    boost::uint8_t imag1 = boost::int8_t(in1.imag());
170
    return
171
        (item32_t(real0) << 8) | (item32_t(imag0) << 0) |
172
        (item32_t(real1) << 24) | (item32_t(imag1) << 16)
173
    ;
174
}
175

    
176
template <> UHD_INLINE item32_t xx_to_item32_sc8_x1(
177
    const sc8_t &in0, const sc8_t &in1, const double
178
){
179
    boost::uint8_t real0 = boost::int8_t(in0.real());
180
    boost::uint8_t imag0 = boost::int8_t(in0.imag());
181
    boost::uint8_t real1 = boost::int8_t(in1.real());
182
    boost::uint8_t imag1 = boost::int8_t(in1.imag());
183
    return
184
        (item32_t(real0) << 8) | (item32_t(imag0) << 0) |
185
        (item32_t(real1) << 24) | (item32_t(imag1) << 16)
186
    ;
187
}
188

    
189
template <xtox_t to_wire, typename T>
190
UHD_INLINE void xx_to_item32_sc8(
191
    const std::complex<T> *input,
192
    item32_t *output,
193
    const size_t nsamps,
194
    const double scale_factor
195
){
196
    const size_t num_pairs = nsamps/2;
197
    for (size_t i = 0, j = 0; i < num_pairs; i++, j+=2){
198
        const item32_t item = xx_to_item32_sc8_x1(input[j], input[j+1], scale_factor);
199
        output[i] = to_wire(item);
200
    }
201

    
202
    if (nsamps != num_pairs*2){
203
        const item32_t item = xx_to_item32_sc8_x1(input[nsamps-1], std::complex<T>(0), scale_factor);
204
        output[num_pairs] = to_wire(item);
205
    }
206
}
207

    
208
/***********************************************************************
209
 * Convert items32 sc8 buffer to xx
210
 **********************************************************************/
211
template <typename T> UHD_INLINE void item32_sc8_x1_to_xx(
212
    const item32_t item, std::complex<T> &out0, std::complex<T> &out1, const double scale_factor
213
){
214
    out0 = std::complex<T>(
215
        T(boost::int8_t(item >> 8)*float(scale_factor)),
216
        T(boost::int8_t(item >> 0)*float(scale_factor))
217
    );
218
    out1 = std::complex<T>(
219
        T(boost::int8_t(item >> 24)*float(scale_factor)),
220
        T(boost::int8_t(item >> 16)*float(scale_factor))
221
    );
222
}
223

    
224
template <> UHD_INLINE void item32_sc8_x1_to_xx(
225
    const item32_t item, sc16_t &out0, sc16_t &out1, const double
226
){
227
    out0 = sc16_t(
228
        boost::int16_t(boost::int8_t(item >> 8)),
229
        boost::int16_t(boost::int8_t(item >> 0))
230
    );
231
    out1 = sc16_t(
232
        boost::int16_t(boost::int8_t(item >> 24)),
233
        boost::int16_t(boost::int8_t(item >> 16))
234
    );
235
}
236

    
237
template <> UHD_INLINE void item32_sc8_x1_to_xx(
238
    const item32_t item, sc8_t &out0, sc8_t &out1, const double
239
){
240
    out0 = sc8_t(
241
        boost::int8_t(boost::int8_t(item >> 8)),
242
        boost::int8_t(boost::int8_t(item >> 0))
243
    );
244
    out1 = sc8_t(
245
        boost::int8_t(boost::int8_t(item >> 24)),
246
        boost::int8_t(boost::int8_t(item >> 16))
247
    );
248
}
249

    
250
template <xtox_t to_host, typename T>
251
UHD_INLINE void item32_sc8_to_xx(
252
    const item32_t *input,
253
    std::complex<T> *output,
254
    const size_t nsamps,
255
    const double scale_factor
256
){
257
    input = reinterpret_cast<const item32_t *>(size_t(input) & ~0x3);
258
    std::complex<T> dummy;
259
    size_t num_samps = nsamps;
260

    
261
    if ((size_t(input) & 0x3) != 0){
262
        const item32_t item0 = to_host(*input++);
263
        item32_sc8_x1_to_xx(item0, dummy, *output++, scale_factor);
264
        num_samps--;
265
    }
266

    
267
    const size_t num_pairs = num_samps/2;
268
    for (size_t i = 0, j = 0; i < num_pairs; i++, j+=2){
269
        const item32_t item_i = to_host(input[i]);
270
        item32_sc8_x1_to_xx(item_i, output[j], output[j+1], scale_factor);
271
    }
272

    
273
    if (num_samps != num_pairs*2){
274
        const item32_t item_n = to_host(input[num_pairs]);
275
        item32_sc8_x1_to_xx(item_n, output[num_samps-1], dummy, scale_factor);
276
    }
277
}
278

    
279
#endif /* INCLUDED_LIBUHD_CONVERT_COMMON_HPP */