Statistics
| Branch: | Tag: | Revision:

root / host / test / convert_types_test.cpp @ 79ea83d6

History | View | Annotate | Download (7.8 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
#include <uhd/transport/convert_types.hpp>
19
#include <boost/test/unit_test.hpp>
20
#include <boost/foreach.hpp>
21
#include <boost/cstdint.hpp>
22
#include <boost/asio/buffer.hpp>
23
#include <complex>
24
#include <vector>
25
#include <cstdlib>
26

    
27
using namespace uhd;
28

    
29
//typedefs for complex types
30
typedef std::complex<boost::int16_t> sc16_t;
31
typedef std::complex<float> fc32_t;
32

    
33
//extract pointer to POD since using &vector.front() throws in MSVC
34
template <typename T> void * pod2ptr(T &pod){
35
    return boost::asio::buffer_cast<void *>(boost::asio::buffer(pod));
36
}
37
template <typename T> const void * pod2ptr(const T &pod){
38
    return boost::asio::buffer_cast<const void *>(boost::asio::buffer(pod));
39
}
40

    
41
/***********************************************************************
42
 * Loopback runner:
43
 *    convert input buffer into intermediate buffer
44
 *    convert intermediate buffer into output buffer
45
 **********************************************************************/
46
template <typename Range> static void loopback(
47
    size_t nsamps,
48
    const io_type_t &io_type,
49
    const otw_type_t &otw_type,
50
    const Range &input,
51
    Range &output
52
){
53
    //item32 is largest device type
54
    std::vector<boost::uint32_t> dev(nsamps);
55

    
56
    //convert to dev type
57
    transport::convert_io_type_to_otw_type(
58
        pod2ptr(input), io_type,
59
        pod2ptr(dev), otw_type,
60
        nsamps
61
    );
62

    
63
    //convert back to host type
64
    transport::convert_otw_type_to_io_type(
65
        pod2ptr(dev), otw_type,
66
        pod2ptr(output), io_type,
67
        nsamps
68
    );
69
}
70

    
71
/***********************************************************************
72
 * Test short conversion
73
 **********************************************************************/
74
static void test_convert_types_sc16(
75
    size_t nsamps,
76
    const io_type_t &io_type,
77
    const otw_type_t &otw_type
78
){
79
    //fill the input samples
80
    std::vector<sc16_t> input(nsamps), output(nsamps);
81
    BOOST_FOREACH(sc16_t &in, input) in = sc16_t(
82
        std::rand()-(RAND_MAX/2),
83
        std::rand()-(RAND_MAX/2)
84
    );
85

    
86
    //run the loopback and test
87
    loopback(nsamps, io_type, otw_type, input, output);
88
    BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
89
}
90

    
91
BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){
92
    io_type_t io_type(io_type_t::COMPLEX_INT16);
93
    otw_type_t otw_type;
94
    otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
95
    otw_type.width = 16;
96

    
97
    //try various lengths to test edge cases
98
    for (size_t nsamps = 0; nsamps < 16; nsamps++){
99
        test_convert_types_sc16(nsamps, io_type, otw_type);
100
    }
101
}
102

    
103
BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){
104
    io_type_t io_type(io_type_t::COMPLEX_INT16);
105
    otw_type_t otw_type;
106
    otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
107
    otw_type.width = 16;
108

    
109
    //try various lengths to test edge cases
110
    for (size_t nsamps = 0; nsamps < 16; nsamps++){
111
        test_convert_types_sc16(nsamps, io_type, otw_type);
112
    }
113
}
114

    
115
/***********************************************************************
116
 * Test float conversion
117
 **********************************************************************/
118
static void test_convert_types_fc32(
119
    size_t nsamps,
120
    const io_type_t &io_type,
121
    const otw_type_t &otw_type
122
){
123
    //fill the input samples
124
    std::vector<fc32_t> input(nsamps), output(nsamps);
125
    BOOST_FOREACH(fc32_t &in, input) in = fc32_t(
126
        (std::rand()/float(RAND_MAX/2)) - 1,
127
        (std::rand()/float(RAND_MAX/2)) - 1
128
    );
129

    
130
    //run the loopback and test
131
    loopback(nsamps, io_type, otw_type, input, output);
132
    for (size_t i = 0; i < nsamps; i++){
133
        BOOST_CHECK_CLOSE_FRACTION(input[i].real(), output[i].real(), float(0.01));
134
        BOOST_CHECK_CLOSE_FRACTION(input[i].imag(), output[i].imag(), float(0.01));
135
    }
136
}
137

    
138
BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){
139
    io_type_t io_type(io_type_t::COMPLEX_FLOAT32);
140
    otw_type_t otw_type;
141
    otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
142
    otw_type.width = 16;
143

    
144
    //try various lengths to test edge cases
145
    for (size_t nsamps = 0; nsamps < 16; nsamps++){
146
        test_convert_types_fc32(nsamps, io_type, otw_type);
147
    }
148
}
149

    
150
BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){
151
    io_type_t io_type(io_type_t::COMPLEX_FLOAT32);
152
    otw_type_t otw_type;
153
    otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
154
    otw_type.width = 16;
155

    
156
    //try various lengths to test edge cases
157
    for (size_t nsamps = 0; nsamps < 16; nsamps++){
158
        test_convert_types_fc32(nsamps, io_type, otw_type);
159
    }
160
}
161

    
162
/***********************************************************************
163
 * Test float to short conversion loopback
164
 **********************************************************************/
165
BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){
166
    io_type_t io_type_in(io_type_t::COMPLEX_FLOAT32);
167
    io_type_t io_type_out(io_type_t::COMPLEX_INT16);
168

    
169
    otw_type_t otw_type;
170
    otw_type.byteorder = otw_type_t::BO_NATIVE;
171
    otw_type.width = 16;
172

    
173
    const size_t nsamps = 13;
174
    std::vector<fc32_t> input(nsamps);
175
    BOOST_FOREACH(fc32_t &in, input) in = fc32_t(
176
        (std::rand()/float(RAND_MAX/2)) - 1,
177
        (std::rand()/float(RAND_MAX/2)) - 1
178
    );
179

    
180
    //convert float to dev
181
    std::vector<boost::uint32_t> tmp(nsamps);
182
    transport::convert_io_type_to_otw_type(
183
        pod2ptr(input), io_type_in,
184
        pod2ptr(tmp), otw_type,
185
        nsamps
186
    );
187

    
188
    //convert dev to short
189
    std::vector<sc16_t> output(nsamps);
190
    transport::convert_otw_type_to_io_type(
191
        pod2ptr(tmp), otw_type,
192
        pod2ptr(output), io_type_out,
193
        nsamps
194
    );
195

    
196
    //test that the inputs and outputs match
197
    for (size_t i = 0; i < nsamps; i++){
198
        BOOST_CHECK_CLOSE_FRACTION(input[i].real(), output[i].real()/float(32767), float(0.01));
199
        BOOST_CHECK_CLOSE_FRACTION(input[i].imag(), output[i].imag()/float(32767), float(0.01));
200
    }
201
}
202

    
203
/***********************************************************************
204
 * Test short to float conversion loopback
205
 **********************************************************************/
206
BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){
207
    io_type_t io_type_in(io_type_t::COMPLEX_INT16);
208
    io_type_t io_type_out(io_type_t::COMPLEX_FLOAT32);
209

    
210
    otw_type_t otw_type;
211
    otw_type.byteorder = otw_type_t::BO_NATIVE;
212
    otw_type.width = 16;
213

    
214
    const size_t nsamps = 13;
215
    std::vector<sc16_t> input(nsamps);
216
    BOOST_FOREACH(sc16_t &in, input) in = sc16_t(
217
        std::rand()-(RAND_MAX/2),
218
        std::rand()-(RAND_MAX/2)
219
    );
220

    
221
    //convert short to dev
222
    std::vector<boost::uint32_t> tmp(nsamps);
223
    transport::convert_io_type_to_otw_type(
224
        pod2ptr(input), io_type_in,
225
        pod2ptr(tmp), otw_type,
226
        nsamps
227
    );
228

    
229
    //convert dev to float
230
    std::vector<fc32_t> output(nsamps);
231
    transport::convert_otw_type_to_io_type(
232
        pod2ptr(tmp), otw_type,
233
        pod2ptr(output), io_type_out,
234
        nsamps
235
    );
236

    
237
    //test that the inputs and outputs match
238
    for (size_t i = 0; i < nsamps; i++){
239
        BOOST_CHECK_CLOSE_FRACTION(input[i].real()/float(32767), output[i].real(), float(0.01));
240
        BOOST_CHECK_CLOSE_FRACTION(input[i].imag()/float(32767), output[i].imag(), float(0.01));
241
    }
242
}