summaryrefslogtreecommitdiff
path: root/gr-uhd
diff options
context:
space:
mode:
Diffstat (limited to 'gr-uhd')
-rw-r--r--gr-uhd/CMakeLists.txt1
-rw-r--r--gr-uhd/examples/CMakeLists.txt39
-rw-r--r--gr-uhd/examples/tag_sink_demo.h66
-rw-r--r--gr-uhd/examples/tag_source_demo.h129
-rw-r--r--gr-uhd/examples/tags_demo.cc139
-rw-r--r--gr-uhd/grc/CMakeLists.txt1
-rw-r--r--gr-uhd/grc/Makefile.am1
-rw-r--r--gr-uhd/grc/gen_uhd_usrp_blocks.py5
-rw-r--r--gr-uhd/grc/uhd_amsg_source.xml24
-rw-r--r--gr-uhd/grc/uhd_block_tree.xml1
-rw-r--r--gr-uhd/include/CMakeLists.txt1
-rw-r--r--gr-uhd/include/Makefile.am3
-rw-r--r--gr-uhd/include/gr_uhd_amsg_source.h39
-rw-r--r--gr-uhd/include/gr_uhd_usrp_sink.h27
-rw-r--r--gr-uhd/include/gr_uhd_usrp_source.h23
-rw-r--r--gr-uhd/lib/CMakeLists.txt1
-rw-r--r--gr-uhd/lib/Makefile.am3
-rw-r--r--gr-uhd/lib/gr_uhd_amsg_source.cc88
-rw-r--r--gr-uhd/lib/gr_uhd_usrp_sink.cc87
-rw-r--r--gr-uhd/lib/gr_uhd_usrp_source.cc27
-rw-r--r--gr-uhd/swig/__init__.py8
-rw-r--r--gr-uhd/swig/uhd_swig.i4
22 files changed, 700 insertions, 17 deletions
diff --git a/gr-uhd/CMakeLists.txt b/gr-uhd/CMakeLists.txt
index 2e7e26ab0..102320884 100644
--- a/gr-uhd/CMakeLists.txt
+++ b/gr-uhd/CMakeLists.txt
@@ -83,6 +83,7 @@ CPACK_COMPONENT("uhd_swig"
########################################################################
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(lib)
+ADD_SUBDIRECTORY(examples)
IF(ENABLE_PYTHON)
ADD_SUBDIRECTORY(swig)
ADD_SUBDIRECTORY(grc)
diff --git a/gr-uhd/examples/CMakeLists.txt b/gr-uhd/examples/CMakeLists.txt
new file mode 100644
index 000000000..3e1c80362
--- /dev/null
+++ b/gr-uhd/examples/CMakeLists.txt
@@ -0,0 +1,39 @@
+# 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.
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+INCLUDE_DIRECTORIES(
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_UHD_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS})
+LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
+
+INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
+LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
+
+########################################################################
+# Build executable
+########################################################################
+ADD_EXECUTABLE(tags_demo tags_demo.cc)
+TARGET_LINK_LIBRARIES(tags_demo gnuradio-uhd)
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>(&center_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/CMakeLists.txt b/gr-uhd/grc/CMakeLists.txt
index 9e1cdb015..d89b8d77e 100644
--- a/gr-uhd/grc/CMakeLists.txt
+++ b/gr-uhd/grc/CMakeLists.txt
@@ -39,6 +39,7 @@ ADD_CUSTOM_TARGET(uhd_grc_xml_blocks ALL DEPENDS ${xml_blocks})
INSTALL(FILES
${xml_blocks}
+ uhd_amsg_source.xml
uhd_block_tree.xml
DESTINATION ${GRC_BLOCKS_DIR}
COMPONENT "uhd_python"
diff --git a/gr-uhd/grc/Makefile.am b/gr-uhd/grc/Makefile.am
index 7e73a5b39..42a35b1c1 100644
--- a/gr-uhd/grc/Makefile.am
+++ b/gr-uhd/grc/Makefile.am
@@ -31,6 +31,7 @@ BUILT_SOURCES += $(generated_uhd_usrp_blocks)
dist_grcblocks_DATA = \
uhd_block_tree.xml \
+ uhd_amsg_source.xml \
$(BUILT_SOURCES)
########################################################################
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/grc/uhd_amsg_source.xml b/gr-uhd/grc/uhd_amsg_source.xml
new file mode 100644
index 000000000..78c9d7b58
--- /dev/null
+++ b/gr-uhd/grc/uhd_amsg_source.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<block>
+ <name>UHD: USRP Async Msg Source</name>
+ <key>uhd_amsg_source</key>
+ <import>from gnuradio import uhd</import>
+ <make>uhd.amsg_source(device_addr=$dev_addr, msgq=$(id)_msgq_out)</make>
+ <param>
+ <name>Device Addr</name>
+ <key>dev_addr</key>
+ <value></value>
+ <type>string</type>
+ <hide>
+ #if $dev_addr()
+ none
+ #else
+ part
+ #end if
+ </hide>
+ </param>
+ <source>
+ <name>out</name>
+ <type>msg</type>
+ </source>
+</block>
diff --git a/gr-uhd/grc/uhd_block_tree.xml b/gr-uhd/grc/uhd_block_tree.xml
index 8a9f62f7c..5d3b49393 100644
--- a/gr-uhd/grc/uhd_block_tree.xml
+++ b/gr-uhd/grc/uhd_block_tree.xml
@@ -10,5 +10,6 @@
<name>UHD</name>
<block>uhd_usrp_source</block>
<block>uhd_usrp_sink</block>
+ <block>uhd_amsg_source</block>
</cat>
</cat>
diff --git a/gr-uhd/include/CMakeLists.txt b/gr-uhd/include/CMakeLists.txt
index d13f85c0f..20d152859 100644
--- a/gr-uhd/include/CMakeLists.txt
+++ b/gr-uhd/include/CMakeLists.txt
@@ -24,6 +24,7 @@ INSTALL(FILES
gr_uhd_api.h
gr_uhd_usrp_source.h
gr_uhd_usrp_sink.h
+ gr_uhd_amsg_source.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio
COMPONENT "uhd_devel"
)
diff --git a/gr-uhd/include/Makefile.am b/gr-uhd/include/Makefile.am
index 4a04c98c1..70b80681b 100644
--- a/gr-uhd/include/Makefile.am
+++ b/gr-uhd/include/Makefile.am
@@ -24,4 +24,5 @@ include $(top_srcdir)/Makefile.common
grinclude_HEADERS = \
gr_uhd_api.h \
gr_uhd_usrp_source.h \
- gr_uhd_usrp_sink.h
+ gr_uhd_usrp_sink.h \
+ gr_uhd_amsg_source.h
diff --git a/gr-uhd/include/gr_uhd_amsg_source.h b/gr-uhd/include/gr_uhd_amsg_source.h
new file mode 100644
index 000000000..bc0feb438
--- /dev/null
+++ b/gr-uhd/include/gr_uhd_amsg_source.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_GR_UHD_AMSG_SOURCE_H
+#define INCLUDED_GR_UHD_AMSG_SOURCE_H
+
+#include <gr_uhd_api.h>
+#include <uhd/usrp/multi_usrp.hpp>
+#include <gr_msg_queue.h>
+
+class uhd_amsg_source;
+
+GR_UHD_API boost::shared_ptr<uhd_amsg_source> uhd_make_amsg_source(
+ const uhd::device_addr_t &device_addr,
+ gr_msg_queue_sptr msgq
+);
+
+class GR_UHD_API uhd_amsg_source{
+};
+
+#endif /* INCLUDED_GR_UHD_AMSG_SOURCE_H */
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/CMakeLists.txt b/gr-uhd/lib/CMakeLists.txt
index 086126eb5..8afb48942 100644
--- a/gr-uhd/lib/CMakeLists.txt
+++ b/gr-uhd/lib/CMakeLists.txt
@@ -37,6 +37,7 @@ LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
LIST(APPEND gr_uhd_sources
gr_uhd_usrp_source.cc
gr_uhd_usrp_sink.cc
+ gr_uhd_amsg_source.cc
)
LIST(APPEND uhd_libs
diff --git a/gr-uhd/lib/Makefile.am b/gr-uhd/lib/Makefile.am
index c27682f7f..c322c6124 100644
--- a/gr-uhd/lib/Makefile.am
+++ b/gr-uhd/lib/Makefile.am
@@ -31,7 +31,8 @@ lib_LTLIBRARIES = libgnuradio-uhd.la
libgnuradio_uhd_la_SOURCES = \
gr_uhd_usrp_source.cc \
- gr_uhd_usrp_sink.cc
+ gr_uhd_usrp_sink.cc \
+ gr_uhd_amsg_source.cc
libgnuradio_uhd_la_LIBADD = \
$(GNURADIO_CORE_LA) \
diff --git a/gr-uhd/lib/gr_uhd_amsg_source.cc b/gr-uhd/lib/gr_uhd_amsg_source.cc
new file mode 100644
index 000000000..f2958f115
--- /dev/null
+++ b/gr-uhd/lib/gr_uhd_amsg_source.cc
@@ -0,0 +1,88 @@
+/*
+ * 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_uhd_amsg_source.h>
+#include <boost/bind.hpp>
+#include <gruel/thread.h>
+
+/***********************************************************************
+ * UHD Asynchronous Message Source Impl
+ **********************************************************************/
+class uhd_amsg_source_impl : public uhd_amsg_source{
+public:
+ uhd_amsg_source_impl(
+ const uhd::device_addr_t &device_addr,
+ gr_msg_queue_sptr msgq
+ ):
+ _msgq(msgq), _running(true)
+ {
+ _dev = uhd::usrp::multi_usrp::make(device_addr);
+ _amsg_thread =
+ gruel::thread(boost::bind(&uhd_amsg_source_impl::recv_loop, this));
+ }
+
+ ~uhd_amsg_source_impl()
+ {
+ _running = false;
+ _amsg_thread.join();
+ }
+
+ void recv_loop()
+ {
+ gr_message_sptr msg;
+ uhd::async_metadata_t *md;
+
+ while (_running) {
+ msg = gr_make_message(0, 0.0, 0.0, sizeof(uhd::async_metadata_t));
+ md = (uhd::async_metadata_t *) msg->msg();
+
+ while (!_dev->get_device()->recv_async_msg(*md, 0.1)) {
+ if (!_running)
+ return;
+ }
+
+ post(msg);
+ }
+ }
+
+ void post(gr_message_sptr msg)
+ {
+ _msgq->insert_tail(msg);
+ }
+
+protected:
+ uhd::usrp::multi_usrp::sptr _dev;
+ gruel::thread _amsg_thread;
+ gr_msg_queue_sptr _msgq;
+ bool _running;
+};
+
+/***********************************************************************
+ * Make UHD Asynchronous Message Source
+ **********************************************************************/
+boost::shared_ptr<uhd_amsg_source> uhd_make_amsg_source(
+ const uhd::device_addr_t &device_addr,
+ gr_msg_queue_sptr msgq
+){
+ return boost::shared_ptr<uhd_amsg_source>(
+ new uhd_amsg_source_impl(device_addr, msgq)
+ );
+}
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 7ed689ec0..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
@@ -60,7 +64,7 @@ def _prepare_uhd_swig():
if attr.endswith('_t'): setattr(uhd_swig, attr[:-2], myobj)
#Cast constructor args (FIXME swig handle overloads?)
- for attr in ('usrp_source', 'usrp_sink'):
+ for attr in ('usrp_source', 'usrp_sink', 'amsg_source'):
def constructor_factory(old_constructor):
def constructor_interceptor(*args, **kwargs):
args = list(args)
diff --git a/gr-uhd/swig/uhd_swig.i b/gr-uhd/swig/uhd_swig.i
index 9bdb962c9..b58fe9e18 100644
--- a/gr-uhd/swig/uhd_swig.i
+++ b/gr-uhd/swig/uhd_swig.i
@@ -55,6 +55,7 @@
%{
#include <gr_uhd_usrp_source.h>
#include <gr_uhd_usrp_sink.h>
+#include <gr_uhd_amsg_source.h>
%}
////////////////////////////////////////////////////////////////////////
@@ -114,6 +115,9 @@ GR_SWIG_BLOCK_MAGIC(uhd,usrp_source)
GR_SWIG_BLOCK_MAGIC(uhd,usrp_sink)
%include <gr_uhd_usrp_sink.h>
+GR_SWIG_BLOCK_MAGIC(uhd,amsg_source)
+%include <gr_uhd_amsg_source.h>
+
////////////////////////////////////////////////////////////////////////
// helpful constants
////////////////////////////////////////////////////////////////////////