#!/usr/bin/env python
#
# Copyright 2011-2012 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 .
#
TMPL_HEADER = """
<%
import time
%>
/***********************************************************************
* This file was generated by ${file} on ${time.strftime("%c")}
**********************************************************************/
#include "convert_common.hpp"
#include
using namespace uhd::convert;
// item32 -> item32: Just a memcpy. No scaling possible.
DECLARE_CONVERTER(item32, 1, item32, 1, PRIORITY_GENERAL) {
const item32_t *input = reinterpret_cast(inputs[0]);
item32_t *output = reinterpret_cast(outputs[0]);
memcpy(output, input, nsamps * sizeof(item32_t));
}
"""
TMPL_CONV_GEN2_ITEM32 = """
DECLARE_CONVERTER(item32, 1, sc16_item32_{end}, 1, PRIORITY_GENERAL) {{
const item32_t *input = reinterpret_cast(inputs[0]);
item32_t *output = reinterpret_cast(outputs[0]);
for (size_t i = 0; i < nsamps; i++) {{
output[i] = {to_wire}(input[i]);
}}
}}
DECLARE_CONVERTER(sc16_item32_{end}, 1, item32, 1, PRIORITY_GENERAL) {{
const item32_t *input = reinterpret_cast(inputs[0]);
item32_t *output = reinterpret_cast(outputs[0]);
for (size_t i = 0; i < nsamps; i++) {{
output[i] = {to_host}(input[i]);
}}
}}
"""
TMPL_CONV_U8 = """
DECLARE_CONVERTER(u8, 1, u8_item32_{end}, 1, PRIORITY_GENERAL) {{
const boost::uint32_t *input = reinterpret_cast(inputs[0]);
boost::uint32_t *output = reinterpret_cast(outputs[0]);
// 1) Copy all the 4-byte tuples
size_t n_words = nsamps / 4;
for (size_t i = 0; i < n_words; i++) {{
output[i] = {to_wire}(input[i]);
}}
// 2) If nsamps was not a multiple of 4, copy the rest by hand
size_t bytes_left = nsamps % 4;
if (bytes_left) {{
const u8_t *last_input_word = reinterpret_cast(&input[n_words]);
u8_t *last_output_word = reinterpret_cast(&output[n_words]);
for (size_t k = 0; k < bytes_left; k++) {{
last_output_word[k] = last_input_word[k];
}}
output[n_words] = {to_wire}(output[n_words]);
}}
}}
DECLARE_CONVERTER(u8_item32_{end}, 1, u8, 1, PRIORITY_GENERAL) {{
const boost::uint32_t *input = reinterpret_cast(inputs[0]);
boost::uint32_t *output = reinterpret_cast(outputs[0]);
// 1) Copy all the 4-byte tuples
size_t n_words = nsamps / 4;
for (size_t i = 0; i < n_words; i++) {{
output[i] = {to_host}(input[i]);
}}
// 2) If nsamps was not a multiple of 4, copy the rest by hand
size_t bytes_left = nsamps % 4;
if (bytes_left) {{
boost::uint32_t last_input_word = {to_host}(input[n_words]);
const u8_t *last_input_word_ptr = reinterpret_cast(&last_input_word);
u8_t *last_output_word = reinterpret_cast(&output[n_words]);
for (size_t k = 0; k < bytes_left; k++) {{
last_output_word[k] = last_input_word_ptr[k];
}}
}}
}}
"""
TMPL_CONV_USRP1_COMPLEX = """
DECLARE_CONVERTER(${cpu_type}, ${width}, sc16_item16_usrp1, 1, PRIORITY_GENERAL){
% for w in range(width):
const ${cpu_type}_t *input${w} = reinterpret_cast(inputs[${w}]);
% endfor
boost::uint16_t *output = reinterpret_cast(outputs[0]);
for (size_t i = 0, j = 0; i < nsamps; i++){
% for w in range(width):
output[j++] = ${to_wire}(boost::uint16_t(boost::int16_t(input${w}[i].real()${do_scale})));
output[j++] = ${to_wire}(boost::uint16_t(boost::int16_t(input${w}[i].imag()${do_scale})));
% endfor
}
}
DECLARE_CONVERTER(sc16_item16_usrp1, 1, ${cpu_type}, ${width}, PRIORITY_GENERAL){
const boost::uint16_t *input = reinterpret_cast(inputs[0]);
% for w in range(width):
${cpu_type}_t *output${w} = reinterpret_cast<${cpu_type}_t *>(outputs[${w}]);
% endfor
for (size_t i = 0, j = 0; i < nsamps; i++){
% for w in range(width):
output${w}[i] = ${cpu_type}_t(
boost::int16_t(${to_host}(input[j+0]))${do_scale},
boost::int16_t(${to_host}(input[j+1]))${do_scale}
);
j += 2;
% endfor
}
}
DECLARE_CONVERTER(sc8_item16_usrp1, 1, ${cpu_type}, ${width}, PRIORITY_GENERAL){
const boost::uint16_t *input = reinterpret_cast(inputs[0]);
% for w in range(width):
${cpu_type}_t *output${w} = reinterpret_cast<${cpu_type}_t *>(outputs[${w}]);
% endfor
for (size_t i = 0, j = 0; i < nsamps; i++){
% for w in range(width):
{
const boost::uint16_t num = ${to_host}(input[j++]);
output${w}[i] = ${cpu_type}_t(
boost::int8_t(num)${do_scale},
boost::int8_t(num >> 8)${do_scale}
);
}
% endfor
}
}
"""
def parse_tmpl(_tmpl_text, **kwargs):
from mako.template import Template
return Template(_tmpl_text).render(**kwargs)
if __name__ == '__main__':
import sys, os
file = os.path.basename(__file__)
output = parse_tmpl(TMPL_HEADER, file=file)
#generate complex converters for all gen2 platforms
for end, to_host, to_wire in (
('be', 'uhd::ntohx', 'uhd::htonx'),
('le', 'uhd::wtohx', 'uhd::htowx'),
):
output += TMPL_CONV_GEN2_ITEM32.format(
end=end, to_host=to_host, to_wire=to_wire
)
#generate raw (u8) converters:
for end, to_host, to_wire in (
('be', 'uhd::ntohx', 'uhd::htonx'),
('le', 'uhd::wtohx', 'uhd::htowx'),
):
output += TMPL_CONV_U8.format(
end=end, to_host=to_host, to_wire=to_wire
)
#generate complex converters for usrp1 format (requires Cheetah)
for width in 1, 2, 4:
for cpu_type, do_scale in (
('fc64', '*scale_factor'),
('fc32', '*float(scale_factor)'),
('sc16', ''),
):
output += parse_tmpl(
TMPL_CONV_USRP1_COMPLEX,
width=width, to_host='uhd::wtohx', to_wire='uhd::htowx',
cpu_type=cpu_type, do_scale=do_scale
)
open(sys.argv[1], 'w').write(output)