#!/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)