1 //
2 // Copyright 2017 Ettus Research LLC
3 // Copyright 2018 Ettus Research, a National Instruments Company
4 //
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 
8 #include "convert_common.hpp"
9 #include <uhd/utils/byteswap.hpp>
10 #include <type_traits>
11 
12 using namespace uhd::convert;
13 
14 typedef uint32_t (*tohost32_type)(uint32_t);
15 
16 /* C language specification requires this to be packed
17  * (i.e., line0, line1, line2 will be in adjacent memory locations).
18  * If this was not true, we'd need compiler flags here to specify
19  * alignment/packing.
20  */
21 struct item32_sc12_3x
22 {
23     item32_t line0;
24     item32_t line1;
25     item32_t line2;
26 };
27 
28 /*
29  * convert_sc12_item32_3_to_star_4 takes in 3 lines with 32 bit each
30  * and converts them 4 samples of type 'std::complex<type>'.
31  * The structure of the 3 lines is as follows:
32  *  _ _ _ _ _ _ _ _
33  * |_ _ _1_ _ _|_ _|
34  * |_2_ _ _|_ _ _3_|
35  * |_ _|_ _ _4_ _ _|
36  *
37  * The numbers mark the position of one complex sample.
38  */
39 template <typename type, tohost32_type tohost>
convert_sc12_item32_3_to_star_4(const item32_sc12_3x & input,std::complex<type> & out0,std::complex<type> & out1,std::complex<type> & out2,std::complex<type> & out3,const double scalar,typename std::enable_if<std::is_floating_point<type>::value>::type * =NULL)40 void convert_sc12_item32_3_to_star_4(const item32_sc12_3x& input,
41     std::complex<type>& out0,
42     std::complex<type>& out1,
43     std::complex<type>& out2,
44     std::complex<type>& out3,
45     const double scalar,
46     typename std::enable_if<std::is_floating_point<type>::value>::type* = NULL)
47 {
48     // step 0: extract the lines from the input buffer
49     const item32_t line0  = tohost(input.line0);
50     const item32_t line1  = tohost(input.line1);
51     const item32_t line2  = tohost(input.line2);
52     const uint64_t line01 = (uint64_t(line0) << 32) | line1;
53     const uint64_t line12 = (uint64_t(line1) << 32) | line2;
54 
55     // step 1: shift out and mask off the individual numbers
56     const type i0 = type(int16_t((line0 >> 16) & 0xfff0) * scalar);
57     const type q0 = type(int16_t((line0 >> 4) & 0xfff0) * scalar);
58 
59     const type i1 = type(int16_t((line01 >> 24) & 0xfff0) * scalar);
60     const type q1 = type(int16_t((line1 >> 12) & 0xfff0) * scalar);
61 
62     const type i2 = type(int16_t((line1 >> 0) & 0xfff0) * scalar);
63     const type q2 = type(int16_t((line12 >> 20) & 0xfff0) * scalar);
64 
65     const type i3 = type(int16_t((line2 >> 8) & 0xfff0) * scalar);
66     const type q3 = type(int16_t((line2 << 4) & 0xfff0) * scalar);
67 
68     // step 2: load the outputs
69     out0 = std::complex<type>(i0, q0);
70     out1 = std::complex<type>(i1, q1);
71     out2 = std::complex<type>(i2, q2);
72     out3 = std::complex<type>(i3, q3);
73 }
74 
75 template <typename type, tohost32_type tohost>
convert_sc12_item32_3_to_star_4(const item32_sc12_3x & input,std::complex<type> & out0,std::complex<type> & out1,std::complex<type> & out2,std::complex<type> & out3,const double,typename std::enable_if<std::is_integral<type>::value>::type * =NULL)76 void convert_sc12_item32_3_to_star_4(const item32_sc12_3x& input,
77     std::complex<type>& out0,
78     std::complex<type>& out1,
79     std::complex<type>& out2,
80     std::complex<type>& out3,
81     const double,
82     typename std::enable_if<std::is_integral<type>::value>::type* = NULL)
83 {
84     // step 0: extract the lines from the input buffer
85     const item32_t line0  = tohost(input.line0);
86     const item32_t line1  = tohost(input.line1);
87     const item32_t line2  = tohost(input.line2);
88     const uint64_t line01 = (uint64_t(line0) << 32) | line1;
89     const uint64_t line12 = (uint64_t(line1) << 32) | line2;
90 
91     // step 1: extract and load the outputs
92     out0 = std::complex<type>(line0 >> 16 & 0xfff0, line0 >> 4 & 0xfff0);
93     out1 = std::complex<type>(line01 >> 24 & 0xfff0, line1 >> 12 & 0xfff0);
94     out2 = std::complex<type>(line1 >> 0 & 0xfff0, line12 >> 20 & 0xfff0);
95     out3 = std::complex<type>(line2 >> 8 & 0xfff0, line2 << 4 & 0xfff0);
96 }
97