//
// Copyright 2017 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
#include
#include
#include "convert_common.hpp"
using namespace uhd::convert;
typedef uint32_t (*towire32_type)(uint32_t);
/* C language specification requires this to be packed
* (i.e., line0, line1, line2 will be in adjacent memory locations).
* If this was not true, we'd need compiler flags here to specify
* alignment/packing.
*/
struct item32_sc12_3x
{
item32_t line0;
item32_t line1;
item32_t line2;
};
enum item32_sc12_3x_enable {
CONVERT12_LINE0 = 0x01,
CONVERT12_LINE1 = 0x02,
CONVERT12_LINE2 = 0x04,
CONVERT12_LINE_ALL = 0x07,
};
/*
* Packed 12-bit converter with selective line enable
*
* The converter operates on 4 complex inputs and selectively writes to one to
* three 32-bit lines. Line selection allows for partial writes of less than
* 4 complex samples, or a full 3 x 32-bit struct. Writes are always full 32-bit
* lines, so in the case of partial writes, the number of bytes written will
* exceed the the number of bytes filled by actual samples.
*
* _ _ _ _ _ _ _ _
* |_ _ _1_ _ _|_ _| 0
* |_2_ _ _|_ _ _3_|
* |_ _|_ _ _4_ _ _| 2
* 31 0
*/
template
void pack(item32_sc12_3x &output, int enable, const int32_t iq[8])
{
if (enable & CONVERT12_LINE0)
output.line0 = towire(iq[0] << 20 | iq[1] << 8 | iq[2] >> 4);
if (enable & CONVERT12_LINE1)
output.line1 = towire(iq[2] << 28 | iq[3] << 16 | iq[4] << 4 | iq[5] >> 8);
if (enable & CONVERT12_LINE2)
output.line2 = towire(iq[5] << 24 | iq[6] << 12 | iq[7] << 0);
}
template
void convert_star_4_to_sc12_item32_3
(
const std::complex &in0,
const std::complex &in1,
const std::complex &in2,
const std::complex &in3,
const int enable,
item32_sc12_3x &output,
const double scalar,
typename std::enable_if::value>::type* = NULL
)
{
int32_t iq[8] {
int32_t(in0.real()*scalar) & 0xfff,
int32_t(in0.imag()*scalar) & 0xfff,
int32_t(in1.real()*scalar) & 0xfff,
int32_t(in1.imag()*scalar) & 0xfff,
int32_t(in2.real()*scalar) & 0xfff,
int32_t(in2.imag()*scalar) & 0xfff,
int32_t(in3.real()*scalar) & 0xfff,
int32_t(in3.imag()*scalar) & 0xfff,
};
pack(output, enable, iq);
}
template
void convert_star_4_to_sc12_item32_3
(
const std::complex &in0,
const std::complex &in1,
const std::complex &in2,
const std::complex &in3,
const int enable,
item32_sc12_3x &output,
const double,
typename std::enable_if::value>::type* = NULL
)
{
int32_t iq[8] {
int32_t(in0.real() >> 4) & 0xfff,
int32_t(in0.imag() >> 4) & 0xfff,
int32_t(in1.real() >> 4) & 0xfff,
int32_t(in1.imag() >> 4) & 0xfff,
int32_t(in2.real() >> 4) & 0xfff,
int32_t(in2.imag() >> 4) & 0xfff,
int32_t(in3.real() >> 4) & 0xfff,
int32_t(in3.imag() >> 4) & 0xfff,
};
pack(output, enable, iq);
}