diff options
Diffstat (limited to 'gr-uhd')
-rw-r--r-- | gr-uhd/examples/tag_sink_demo.h | 66 | ||||
-rw-r--r-- | gr-uhd/examples/tag_source_demo.h | 129 | ||||
-rw-r--r-- | gr-uhd/examples/tags_demo.cc | 139 | ||||
-rw-r--r-- | gr-uhd/grc/gen_uhd_usrp_blocks.py | 5 | ||||
-rw-r--r-- | gr-uhd/include/gr_uhd_usrp_sink.h | 27 | ||||
-rw-r--r-- | gr-uhd/include/gr_uhd_usrp_source.h | 23 | ||||
-rw-r--r-- | gr-uhd/lib/gr_uhd_usrp_sink.cc | 87 | ||||
-rw-r--r-- | gr-uhd/lib/gr_uhd_usrp_source.cc | 27 | ||||
-rw-r--r-- | gr-uhd/swig/__init__.py | 6 |
9 files changed, 495 insertions, 14 deletions
diff --git a/gr-uhd/examples/tag_sink_demo.h b/gr-uhd/examples/tag_sink_demo.h new file mode 100644 index 000000000..84baf0a9c --- /dev/null +++ b/gr-uhd/examples/tag_sink_demo.h @@ -0,0 +1,66 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gr_sync_block.h> +#include <gr_io_signature.h> +#include <gr_tag_info.h> +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <iostream> +#include <complex> + +class tag_sink_demo : public gr_sync_block{ +public: + + tag_sink_demo(void): + gr_sync_block( + "uhd tag sink demo", + gr_make_io_signature(1, 1, sizeof(std::complex<float>)), + gr_make_io_signature(0, 0, 0) + ) + { + //NOP + } + + int work( + int ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + //grab all "rx time" tags in this work call + const uint64_t samp0_count = this->nitems_read(0); + std::vector<pmt::pmt_t> rx_time_tags; + get_tags_in_range(rx_time_tags, 0, samp0_count, samp0_count + ninput_items, pmt::pmt_string_to_symbol("rx_time")); + + //print all tags + BOOST_FOREACH(const pmt::pmt_t &rx_time_tag, rx_time_tags){ + const uint64_t count = gr_tags::get_nitems(rx_time_tag); + const pmt::pmt_t &value = gr_tags::get_value(rx_time_tag); + + std::cout << boost::format("Full seconds %u, Frac seconds %f") + % pmt::pmt_to_uint64(pmt_tuple_ref(value, 0)) + % pmt::pmt_to_double(pmt_tuple_ref(value, 1)) + << std::endl; + } + + return ninput_items; + } +}; diff --git a/gr-uhd/examples/tag_source_demo.h b/gr-uhd/examples/tag_source_demo.h new file mode 100644 index 000000000..c7c0884d3 --- /dev/null +++ b/gr-uhd/examples/tag_source_demo.h @@ -0,0 +1,129 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gr_sync_block.h> +#include <gr_io_signature.h> +#include <gr_tag_info.h> +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <iostream> +#include <complex> + +class tag_source_demo : public gr_sync_block{ +public: + + tag_source_demo( + const uint64_t start_secs, + const double start_fracs, + const double samp_rate, + const double idle_duration, + const double burst_duration + ): + gr_sync_block( + "uhd tag source demo", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, sizeof(std::complex<float>)) + ), + _time_secs(start_secs), + _time_fracs(start_fracs), + _samp_rate(samp_rate), + _samps_per_burst(samp_rate*burst_duration), + _cycle_duration(idle_duration + burst_duration), + _samps_left_in_burst(1), //immediate EOB + _do_new_burst(false) + { + //NOP + } + + void make_time_tag(const uint64_t tag_count){; + const pmt::pmt_t key = pmt::pmt_string_to_symbol("tx_time"); + const pmt::pmt_t value = pmt::pmt_make_tuple( + pmt::pmt_from_uint64(_time_secs), + pmt::pmt_from_double(_time_fracs) + ); + const pmt::pmt_t srcid = pmt::pmt_string_to_symbol(this->name()); + this->add_item_tag(0/*chan0*/, tag_count, key, value, srcid); + } + + void make_sob_tag(const uint64_t tag_count){ + const pmt::pmt_t key = pmt::pmt_string_to_symbol("tx_sob"); + const pmt::pmt_t value = pmt::PMT_T; + const pmt::pmt_t srcid = pmt::pmt_string_to_symbol(this->name()); + this->add_item_tag(0/*chan0*/, tag_count, key, value, srcid); + } + + void make_eob_tag(const uint64_t tag_count){; + const pmt::pmt_t key = pmt::pmt_string_to_symbol("tx_eob"); + const pmt::pmt_t value = pmt::PMT_T; + const pmt::pmt_t srcid = pmt::pmt_string_to_symbol(this->name()); + this->add_item_tag(0/*chan0*/, tag_count, key, value, srcid); + } + + int work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + //load the output with a constant + std::complex<float> *output = reinterpret_cast<std::complex<float> *>(output_items[0]); + for (size_t i = 0; i < size_t(noutput_items); i++){ + output[i] = std::complex<float>(0.7, 0.7); + } + + //Handle the start of burst condition. + //Tag a start of burst and timestamp. + //Increment the time for the next burst. + if (_do_new_burst){ + _do_new_burst = false; + _samps_left_in_burst = _samps_per_burst; + + this->make_sob_tag(this->nitems_written(0)); + this->make_time_tag(this->nitems_written(0)); + + _time_fracs += _cycle_duration; + double intpart; //normalize + _time_fracs = std::modf(_time_fracs, &intpart); + _time_secs += uint64_t(intpart); + } + + //Handle the end of burst condition. + //Tag an end of burst and return early. + //the next work call will be a start of burst. + if (_samps_left_in_burst < size_t(noutput_items)){ + this->make_eob_tag(this->nitems_written(0) + _samps_left_in_burst - 1); + _do_new_burst = true; + noutput_items = _samps_left_in_burst; + } + + _samps_left_in_burst -= noutput_items; + return noutput_items; + } + +private: + uint64_t _time_secs; + double _time_fracs; + const double _samp_rate; + const uint64_t _samps_per_burst; + const double _cycle_duration; + bool _do_new_burst; + uint64_t _samps_left_in_burst; + +}; diff --git a/gr-uhd/examples/tags_demo.cc b/gr-uhd/examples/tags_demo.cc new file mode 100644 index 000000000..b40518f34 --- /dev/null +++ b/gr-uhd/examples/tags_demo.cc @@ -0,0 +1,139 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gr_top_block.h> +#include <gr_uhd_usrp_source.h> +#include <gr_uhd_usrp_sink.h> +#include <tag_source_demo.h> +#include <tag_sink_demo.h> +#include <boost/make_shared.hpp> +#include <boost/thread/thread.hpp> //sleep +#include <boost/program_options.hpp> +#include <csignal> +#include <iostream> + +namespace po = boost::program_options; + +/*********************************************************************** + * Signal handlers + **********************************************************************/ +static bool stop_signal_called = false; +void sig_int_handler(int){stop_signal_called = true;} + +/*********************************************************************** + * Main w/ program options + **********************************************************************/ +int main(int argc, char *argv[]){ + + std::string device_addr; + double center_freq, samp_rate, burst_dur, idle_dur; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("addr", po::value<std::string>(&device_addr)->default_value(""), "the device address in string format") + ("rate", po::value<double>(&samp_rate)->default_value(1e6), "the sample rate in samples per second") + ("freq", po::value<double>(¢er_freq)->default_value(10e6), "the center frequency in Hz") + ("burst", po::value<double>(&burst_dur)->default_value(0.1), "the duration of each burst in seconds") + ("idle", po::value<double>(&idle_dur)->default_value(0.05), "idle time between bursts in seconds") + ; + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + //print the help message + if (vm.count("help")){ + std::cout + << boost::format("UHD Tags Demo %s") % desc << std::endl + << "The tags sink demo block will print USRP source time stamps." << std::endl + << "The tags source demo block will send bursts to the USRP sink." << std::endl + << "Look at the USRP output on a scope to see the timed bursts." << std::endl + << std::endl; + return ~0; + } + + //------------------------------------------------------------------ + //-- make a top block + //------------------------------------------------------------------ + gr_top_block_sptr tb = gr_make_top_block("tags_demo"); + + //------------------------------------------------------------------ + //-- make the usrp source test blocks + //------------------------------------------------------------------ + boost::shared_ptr<uhd_usrp_source> usrp_source = uhd_make_usrp_source( + device_addr, uhd::io_type_t::COMPLEX_FLOAT32, 1 + ); + usrp_source->set_samp_rate(samp_rate); + usrp_source->set_center_freq(center_freq); + + boost::shared_ptr<tag_sink_demo> tag_sink = boost::make_shared<tag_sink_demo>(); + + //------------------------------------------------------------------ + //-- connect the usrp source test blocks + //------------------------------------------------------------------ + tb->connect(usrp_source, 0, tag_sink, 0); + + //------------------------------------------------------------------ + //-- make the usrp sink test blocks + //------------------------------------------------------------------ + boost::shared_ptr<uhd_usrp_sink> usrp_sink = uhd_make_usrp_sink( + device_addr, uhd::io_type_t::COMPLEX_FLOAT32, 1 + ); + usrp_sink->set_samp_rate(samp_rate); + usrp_sink->set_center_freq(center_freq); + const uhd::time_spec_t time_now = usrp_sink->get_time_now(); + + boost::shared_ptr<tag_source_demo> tag_source = boost::make_shared<tag_source_demo>( + time_now.get_full_secs() + 1, time_now.get_frac_secs(), //time now + 1 second + samp_rate, idle_dur, burst_dur + ); + + //------------------------------------------------------------------ + //-- connect the usrp sink test blocks + //------------------------------------------------------------------ + tb->connect(tag_source, 0, usrp_sink, 0); + + //------------------------------------------------------------------ + //-- start flow graph execution + //------------------------------------------------------------------ + std::cout << "starting flow graph" << std::endl; + tb->start(); + + //------------------------------------------------------------------ + //-- poll the exit signal while running + //------------------------------------------------------------------ + std::signal(SIGINT, &sig_int_handler); + std::cout << "press ctrl + c to exit" << std::endl; + while (not stop_signal_called){ + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + + //------------------------------------------------------------------ + //-- stop flow graph execution + //------------------------------------------------------------------ + std::cout << "stopping flow graph" << std::endl; + tb->stop(); + tb->wait(); + + std::cout << "done!" << std::endl; + return 0; +} diff --git a/gr-uhd/grc/gen_uhd_usrp_blocks.py b/gr-uhd/grc/gen_uhd_usrp_blocks.py index c77df6c97..b6bc5fb79 100644 --- a/gr-uhd/grc/gen_uhd_usrp_blocks.py +++ b/gr-uhd/grc/gen_uhd_usrp_blocks.py @@ -256,6 +256,8 @@ The center frequency is the overall frequency of the RF chain. \\ For greater control of how the UHD tunes elements in the RF chain, \\ pass a tune_request object rather than a simple target frequency. Tuning with an LO offset example: uhd.tune_request(freq, lo_off) +Tuning without DSP: uhd.tune_request(target_freq, dsp_freq=0, \\ +dsp_freq_policy=uhd.tune_request.POLICY_MANUAL) Antenna: For subdevices with only one antenna, this may be left blank. \\ @@ -266,6 +268,9 @@ Bandwidth: To use the default bandwidth filter setting, this should be zero. \\ Only certain subdevices have configurable bandwidth filters. \\ See the daughterboard application notes for possible configurations. + +See the UHD manual for more detailed documentation: +http://code.ettus.com/redmine/ettus/projects/uhd/wiki </doc> </block> """ diff --git a/gr-uhd/include/gr_uhd_usrp_sink.h b/gr-uhd/include/gr_uhd_usrp_sink.h index 2adc5f1bf..c1fc3b09e 100644 --- a/gr-uhd/include/gr_uhd_usrp_sink.h +++ b/gr-uhd/include/gr_uhd_usrp_sink.h @@ -28,6 +28,33 @@ class uhd_usrp_sink; +/*! + * \brief Make a new USRP sink block. + * + * The USRP sink block reads a stream and transmits the samples. + * The sink block also provides API calls for transmitter settings. + * + * TX Stream tagging: + * + * The following tag keys will be consumed by the work function: + * - pmt::pmt_string_to_symbol("tx_sob") + * - pmt::pmt_string_to_symbol("tx_eob") + * - pmt::pmt_string_to_symbol("tx_time") + * + * The sob and eob (start and end of burst) tag values are pmt booleans. + * When present, burst tags should be set to true (pmt::PMT_T). + * + * The timstamp tag value is a pmt tuple of the following: + * (uint64 seconds, and double fractional seconds). + * + * See the UHD manual for more detailed documentation: + * http://code.ettus.com/redmine/ettus/projects/uhd/wiki + * + * \param device_addr the address to identify the hardware + * \param io_type the desired input data type + * \param num_channels number of stream from the device + * \return a new USRP sink block object + */ GR_UHD_API boost::shared_ptr<uhd_usrp_sink> uhd_make_usrp_sink( const uhd::device_addr_t &device_addr, const uhd::io_type_t &io_type, diff --git a/gr-uhd/include/gr_uhd_usrp_source.h b/gr-uhd/include/gr_uhd_usrp_source.h index 6e51a1423..f8ac9361e 100644 --- a/gr-uhd/include/gr_uhd_usrp_source.h +++ b/gr-uhd/include/gr_uhd_usrp_source.h @@ -28,6 +28,29 @@ class uhd_usrp_source; +/*! + * \brief Make a new USRP source block. + * + * The USRP source block receives samples and writes to a stream. + * The source block also provides API calls for receiver settings. + * + * RX Stream tagging: + * + * The following tag keys will be produced by the work function: + * - pmt::pmt_string_to_symbol("rx_time") + * + * The timstamp tag value is a pmt tuple of the following: + * (uint64 seconds, and double fractional seconds). + * A timestamp tag is produced at start() and after overflows. + * + * See the UHD manual for more detailed documentation: + * http://code.ettus.com/redmine/ettus/projects/uhd/wiki + * + * \param device_addr the address to identify the hardware + * \param io_type the desired output data type + * \param num_channels number of stream from the device + * \return a new USRP source block object + */ GR_UHD_API boost::shared_ptr<uhd_usrp_source> uhd_make_usrp_source( const uhd::device_addr_t &device_addr, const uhd::io_type_t &io_type, diff --git a/gr-uhd/lib/gr_uhd_usrp_sink.cc b/gr-uhd/lib/gr_uhd_usrp_sink.cc index ce9d89d8d..a780f0551 100644 --- a/gr-uhd/lib/gr_uhd_usrp_sink.cc +++ b/gr-uhd/lib/gr_uhd_usrp_sink.cc @@ -21,8 +21,13 @@ #include <gr_uhd_usrp_sink.h> #include <gr_io_signature.h> +#include <gr_tag_info.h> #include <stdexcept> +static const pmt::pmt_t SOB_KEY = pmt::pmt_string_to_symbol("tx_sob"); +static const pmt::pmt_t EOB_KEY = pmt::pmt_string_to_symbol("tx_eob"); +static const pmt::pmt_t TIME_KEY = pmt::pmt_string_to_symbol("tx_time"); + /*********************************************************************** * UHD Multi USRP Sink Impl **********************************************************************/ @@ -39,8 +44,7 @@ public: gr_make_io_signature(0, 0, 0) ), _type(io_type), - _nchan(num_channels), - _has_time_spec(_nchan > 1) + _nchan(num_channels) { _dev = uhd::usrp::multi_usrp::make(device_addr); } @@ -180,13 +184,20 @@ public: gr_vector_const_void_star &input_items, gr_vector_void_star &output_items ){ + int ninput_items = noutput_items; //cuz its a sync block + //send a mid-burst packet with time spec _metadata.start_of_burst = false; _metadata.end_of_burst = false; - _metadata.has_time_spec = _has_time_spec; - size_t num_sent = _dev->get_device()->send( - input_items, noutput_items, _metadata, + //collect tags in this work() + const uint64_t samp0_count = nitems_read(0); + get_tags_in_range(_tags, 0, samp0_count, samp0_count + ninput_items); + if (not _tags.empty()) this->tag_work(ninput_items); + + //send all ninput_items with metadata + const size_t num_sent = _dev->get_device()->send( + input_items, ninput_items, _metadata, _type, uhd::device::SEND_MODE_FULL_BUFF, 1.0 ); @@ -195,12 +206,70 @@ public: return num_sent; } +/*********************************************************************** + * Tag Work + **********************************************************************/ + inline void tag_work(int &ninput_items){ + //the for loop below assumes tags sorted by count low -> high + std::sort(_tags.begin(), _tags.end(), gr_tags::nitems_compare); + + //extract absolute sample counts + const pmt::pmt_t &tag0 = _tags.front(); + const uint64_t tag0_count = gr_tags::get_nitems(tag0); + const uint64_t samp0_count = this->nitems_read(0); + + //only transmit nsamples from 0 to the first tag + //this ensures that the next work starts on a tag + if (samp0_count != tag0_count){ + ninput_items = tag0_count - samp0_count; + return; + } + + //time will not be set unless a time tag is found + _metadata.has_time_spec = false; + + //process all of the tags found with the same count as tag0 + BOOST_FOREACH(const pmt::pmt_t &my_tag, _tags){ + const uint64_t my_tag_count = gr_tags::get_nitems(my_tag); + const pmt::pmt_t &key = gr_tags::get_key(my_tag); + const pmt::pmt_t &value = gr_tags::get_value(my_tag); + + //determine how many samples to send... + //from zero until the next tag or end of work + if (my_tag_count != tag0_count){ + ninput_items = my_tag_count - samp0_count; + break; + } + + //handle end of burst with a mini end of burst packet + else if (pmt::pmt_equal(key, EOB_KEY)){ + _metadata.end_of_burst = pmt::pmt_to_bool(value); + ninput_items = 1; + return; + } + + //set the start of burst flag in the metadata + else if (pmt::pmt_equal(key, SOB_KEY)){ + _metadata.start_of_burst = pmt::pmt_to_bool(value); + } + + //set the time specification in the metadata + else if (pmt::pmt_equal(key, TIME_KEY)){ + _metadata.has_time_spec = true; + _metadata.time_spec = uhd::time_spec_t( + pmt::pmt_to_uint64(pmt_tuple_ref(value, 0)), + pmt::pmt_to_double(pmt_tuple_ref(value, 1)) + ); + } + } + } + //Send an empty start-of-burst packet to begin streaming. //Set at a time in the near future to avoid late packets. bool start(void){ _metadata.start_of_burst = true; _metadata.end_of_burst = false; - _metadata.has_time_spec = _has_time_spec; + _metadata.has_time_spec = _nchan > 1; _metadata.time_spec = get_time_now() + uhd::time_spec_t(0.01); _dev->get_device()->send( @@ -224,13 +293,15 @@ public: return true; } -protected: +private: uhd::usrp::multi_usrp::sptr _dev; const uhd::io_type_t _type; size_t _nchan; - bool _has_time_spec; uhd::tx_metadata_t _metadata; double _sample_rate; + + //stream tags related stuff + std::vector<pmt::pmt_t> _tags; }; /*********************************************************************** diff --git a/gr-uhd/lib/gr_uhd_usrp_source.cc b/gr-uhd/lib/gr_uhd_usrp_source.cc index 669f890ea..62da83d96 100644 --- a/gr-uhd/lib/gr_uhd_usrp_source.cc +++ b/gr-uhd/lib/gr_uhd_usrp_source.cc @@ -25,6 +25,8 @@ #include <iostream> #include <boost/format.hpp> +static const pmt::pmt_t TIME_KEY = pmt::pmt_string_to_symbol("rx_time"); + /*********************************************************************** * UHD Multi USRP Source Impl **********************************************************************/ @@ -43,8 +45,11 @@ public: _type(io_type), _nchan(num_channels), _stream_now(_nchan == 1), - _tmp_buffs(_nchan) + _tag_now(false) { + std::stringstream str; + str << name() << unique_id(); + _id = pmt::pmt_string_to_symbol(str.str()); _dev = uhd::usrp::multi_usrp::make(device_addr); } @@ -202,7 +207,18 @@ public: //handle possible errors conditions switch(_metadata.error_code){ case uhd::rx_metadata_t::ERROR_CODE_NONE: - //TODO insert tag for time stamp + if (_tag_now){ + _tag_now = false; + //create a timestamp pmt for the first sample + const pmt::pmt_t val = pmt::pmt_make_tuple( + pmt::pmt_from_uint64(_metadata.time_spec.get_full_secs()), + pmt::pmt_from_double(_metadata.time_spec.get_frac_secs()) + ); + //create a timestamp tag for each channel + for (size_t i = 0; i < _nchan; i++){ + this->add_item_tag(i, nitems_written(0), TIME_KEY, val, _id); + } + } break; case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: @@ -211,8 +227,8 @@ public: return WORK_DONE; case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: + _tag_now = true; //ignore overflows and try work again - //TODO insert tag for overflow return work(noutput_items, input_items, output_items); default: @@ -232,6 +248,7 @@ public: stream_cmd.stream_now = _stream_now; stream_cmd.time_spec = get_time_now() + uhd::time_spec_t(reasonable_delay); _dev->issue_stream_cmd(stream_cmd); + _tag_now = true; return true; } @@ -244,9 +261,9 @@ private: uhd::usrp::multi_usrp::sptr _dev; const uhd::io_type_t _type; size_t _nchan; - bool _stream_now; - gr_vector_void_star _tmp_buffs; + bool _stream_now, _tag_now; uhd::rx_metadata_t _metadata; + pmt::pmt_t _id; }; diff --git a/gr-uhd/swig/__init__.py b/gr-uhd/swig/__init__.py index 5c0c011b7..1f82b4a26 100644 --- a/gr-uhd/swig/__init__.py +++ b/gr-uhd/swig/__init__.py @@ -32,9 +32,13 @@ def _prepare_uhd_swig(): #Make the python tune request object inherit from float #so that it can be passed in GRC as a frequency parameter. #The type checking in GRC will accept the tune request. + #Also use kwargs to construct individual struct elements. class tune_request_t(uhd_swig.tune_request_t, float): - def __new__(self, *args): return float.__new__(self) + def __new__(self, *args, **kwargs): return float.__new__(self) def __float__(self): return self.target_freq + def __init__(self, *args, **kwargs): + super(tune_request_t, self).__init__(*args) + for key, val in kwargs.iteritems(): setattr(self, key, val) setattr(uhd_swig, 'tune_request_t', tune_request_t) #Make the python tune request object inherit from string |