diff options
author | Josh Blum | 2011-11-07 20:04:06 -0800 |
---|---|---|
committer | Josh Blum | 2011-11-07 20:04:06 -0800 |
commit | d4f209dcfef230e504179a9916c8167fa8d165f4 (patch) | |
tree | df56fe437eaf43de82e5859e97df6dabf02bf8ff | |
parent | 24d572bc56f265f99b1994cd031df6bd15607ff3 (diff) | |
parent | 24da5f495ca629113ea17f14e764af26a2285e73 (diff) | |
download | gnuradio-d4f209dcfef230e504179a9916c8167fa8d165f4.tar.gz gnuradio-d4f209dcfef230e504179a9916c8167fa8d165f4.tar.bz2 gnuradio-d4f209dcfef230e504179a9916c8167fa8d165f4.zip |
Merge remote-tracking branch 'jblum/uhd_next'
35 files changed, 819 insertions, 161 deletions
diff --git a/gnuradio-examples/python/tags/uhd_burst_detector.py b/gnuradio-examples/python/tags/uhd_burst_detector.py index ffa419562..7411ab06e 100755 --- a/gnuradio-examples/python/tags/uhd_burst_detector.py +++ b/gnuradio-examples/python/tags/uhd_burst_detector.py @@ -42,9 +42,7 @@ class uhd_burst_detector(gr.top_block): self.uhd_src = uhd.single_usrp_source( device_addr=self.uhd_addr, - io_type=uhd.io_type_t.COMPLEX_FLOAT32, - num_channels=1, - ) + stream_args=uhd.stream_args('fc32')) self.uhd_src.set_samp_rate(self.samp_rate) self.uhd_src.set_center_freq(self.freq, 0) diff --git a/gr-digital/examples/narrowband/uhd_interface.py b/gr-digital/examples/narrowband/uhd_interface.py index 21930ad01..27e370911 100644 --- a/gr-digital/examples/narrowband/uhd_interface.py +++ b/gr-digital/examples/narrowband/uhd_interface.py @@ -46,13 +46,9 @@ class uhd_interface: gain=None, spec=None, antenna=None): if(istx): - self.u = uhd.usrp_sink(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_sink(device_addr=args, stream_args=uhd.stream_args('fc32')) else: - self.u = uhd.usrp_source(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=args, stream_args=uhd.stream_args('fc32')) self._args = args self._ant = antenna diff --git a/gr-digital/examples/ofdm/uhd_interface.py b/gr-digital/examples/ofdm/uhd_interface.py index 476d3c842..14a542b0f 100644 --- a/gr-digital/examples/ofdm/uhd_interface.py +++ b/gr-digital/examples/ofdm/uhd_interface.py @@ -46,13 +46,9 @@ class uhd_interface: gain=None, spec=None, antenna=None): if(istx): - self.u = uhd.usrp_sink(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_sink(device_addr=args, stream_args=uhd.stream_args('fc32')) else: - self.u = uhd.usrp_source(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=args, stream_args=uhd.stream_args('fc32')) self._args = args self._ant = antenna diff --git a/gr-pager/apps/usrp_flex.py b/gr-pager/apps/usrp_flex.py index 7c90d9296..7d0d66a95 100755 --- a/gr-pager/apps/usrp_flex.py +++ b/gr-pager/apps/usrp_flex.py @@ -35,9 +35,7 @@ class app_top_block(gr.top_block): if options.from_file is None: # Set up USRP source - self.u = uhd.usrp_source(device_addr=options.address, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.address, stream_args=uhd.stream_args('fc32')) # Grab 250 KHz of spectrum # (A UHD facility to get sample rate range and granularity would be useful) diff --git a/gr-pager/apps/usrp_flex_all.py b/gr-pager/apps/usrp_flex_all.py index 71a0a398e..36bd90034 100755 --- a/gr-pager/apps/usrp_flex_all.py +++ b/gr-pager/apps/usrp_flex_all.py @@ -39,9 +39,7 @@ class app_top_block(gr.top_block): else: # Set up USRP source - self.u = uhd.usrp_source(device_addr=options.address, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.address, stream_args=uhd.stream_args('fc32')) # Tune daughterboard r = self.u.set_center_freq(options.freq+options.calibration, 0) diff --git a/gr-pager/apps/usrp_flex_band.py b/gr-pager/apps/usrp_flex_band.py index 8ea76c229..63fb93fa1 100755 --- a/gr-pager/apps/usrp_flex_band.py +++ b/gr-pager/apps/usrp_flex_band.py @@ -35,9 +35,7 @@ class app_top_block(gr.top_block): print "Reading samples from file", options.from_file else: # Set up USRP source - self.u = uhd.usrp_source(device_addr=options.address, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.address, stream_args=uhd.stream_args('fc32')) # Grab 1 MHz of spectrum # (A UHD facility to get sample rate range and granularity would be useful) diff --git a/gr-qtgui/apps/uhd_display.py b/gr-qtgui/apps/uhd_display.py index 806914797..94e4f099c 100755 --- a/gr-qtgui/apps/uhd_display.py +++ b/gr-qtgui/apps/uhd_display.py @@ -171,9 +171,7 @@ class my_top_block(gr.top_block): self.qapp = QtGui.QApplication(sys.argv) - self.u = uhd.usrp_source(device_addr=options.address, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.address, stream_args=uhd.stream_args('fc32')) self.set_bandwidth(options.samp_rate) if options.gain is None: diff --git a/gr-uhd/apps/uhd_fft.py b/gr-uhd/apps/uhd_fft.py index eec709c14..c06a23036 100755 --- a/gr-uhd/apps/uhd_fft.py +++ b/gr-uhd/apps/uhd_fft.py @@ -74,9 +74,7 @@ class app_top_block(stdgui2.std_top_block): self.options = options self.show_debug_info = True - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) # Set the subdevice spec if(options.spec): diff --git a/gr-uhd/apps/uhd_rx_cfile.py b/gr-uhd/apps/uhd_rx_cfile.py index 625de36d3..61d5342c5 100755 --- a/gr-uhd/apps/uhd_rx_cfile.py +++ b/gr-uhd/apps/uhd_rx_cfile.py @@ -41,14 +41,10 @@ class rx_cfile_block(gr.top_block): # Create a UHD device source if options.output_shorts: - self._u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_INT16, - num_channels=1) + self._u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('sc16')) self._sink = gr.file_sink(gr.sizeof_short*2, filename) else: - self._u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self._u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) self._sink = gr.file_sink(gr.sizeof_gr_complex, filename) # Set receiver sample rate diff --git a/gr-uhd/apps/uhd_rx_nogui.py b/gr-uhd/apps/uhd_rx_nogui.py index 25068b3ac..7a2e0a07a 100755 --- a/gr-uhd/apps/uhd_rx_nogui.py +++ b/gr-uhd/apps/uhd_rx_nogui.py @@ -88,9 +88,7 @@ class uhd_src(gr.hier_block2): gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - self._src = uhd.usrp_source(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self._src = uhd.usrp_source(device_addr=args, stream_args=uhd.stream_args('fc32')) self._src.set_samp_rate(samp_rate) dev_rate = self._src.get_samp_rate() diff --git a/gr-uhd/apps/uhd_siggen.py b/gr-uhd/apps/uhd_siggen.py index 08efc908f..27e9e8e01 100755 --- a/gr-uhd/apps/uhd_siggen.py +++ b/gr-uhd/apps/uhd_siggen.py @@ -92,9 +92,7 @@ class top_block(gr.top_block, pubsub): self[TYPE_KEY] = options.type #set type last def _setup_usrpx(self, options): - self._u = uhd.usrp_sink(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self._u = uhd.usrp_sink(device_addr=options.args, stream_args=uhd.stream_args('fc32')) self._u.set_samp_rate(options.samp_rate) # Set the subdevice spec diff --git a/gr-uhd/examples/fm_tx4.py b/gr-uhd/examples/fm_tx4.py index 11148ea63..714eed3cf 100755 --- a/gr-uhd/examples/fm_tx4.py +++ b/gr-uhd/examples/fm_tx4.py @@ -117,9 +117,7 @@ class fm_tx_block(stdgui2.std_top_block): # ---------------------------------------------------------------- # Set up constants and parameters - self.u = uhd.usrp_sink(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_sink(device_addr=options.args, stream_args=uhd.stream_args('fc32')) self.usrp_rate = options.samp_rate self.u.set_samp_rate(self.usrp_rate) diff --git a/gr-uhd/examples/fm_tx_2_daughterboards.py b/gr-uhd/examples/fm_tx_2_daughterboards.py index 61c437a98..c0a7112de 100755 --- a/gr-uhd/examples/fm_tx_2_daughterboards.py +++ b/gr-uhd/examples/fm_tx_2_daughterboards.py @@ -113,9 +113,8 @@ class my_top_block(gr.top_block): d = uhd.find_devices(uhd.device_addr(options.args)) uhd_type = d[0].get('type') - self.u = uhd.usrp_sink(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=2) + stream_args = uhd.stream_args('fc32', channels=range(2)) + self.u = uhd.usrp_sink(device_addr=options.args, stream_args=stream_args) # Set up USRP system based on type if(uhd_type == "usrp"): diff --git a/gr-uhd/examples/max_power.py b/gr-uhd/examples/max_power.py index 53e1b413c..a849432ee 100755 --- a/gr-uhd/examples/max_power.py +++ b/gr-uhd/examples/max_power.py @@ -59,9 +59,8 @@ class build_block(gr.top_block): if tx_enable: print "\nTRANSMIT CHAIN" - self.u_tx = uhd.usrp_sink(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=tx_nchan) + stream_args = uhd.stream_args('fc32', channels=range(tx_nchan)) + self.u_tx = uhd.usrp_sink(device_addr=args, stream_args=stream_args) self.u_tx.set_samp_rate(MAX_RATE) self.tx_src0 = gr.sig_source_c(self.u_tx.get_samp_rate(), diff --git a/gr-uhd/examples/tags_demo.cc b/gr-uhd/examples/tags_demo.cc index b40518f34..f7442f098 100644 --- a/gr-uhd/examples/tags_demo.cc +++ b/gr-uhd/examples/tags_demo.cc @@ -80,7 +80,7 @@ int main(int argc, char *argv[]){ //-- 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 + device_addr, uhd::stream_args_t("fc32") ); usrp_source->set_samp_rate(samp_rate); usrp_source->set_center_freq(center_freq); @@ -96,7 +96,7 @@ int main(int argc, char *argv[]){ //-- 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 + device_addr, uhd::stream_args_t("fc32") ); usrp_sink->set_samp_rate(samp_rate); usrp_sink->set_center_freq(center_freq); diff --git a/gr-uhd/examples/usrp_am_mw_rcv.py b/gr-uhd/examples/usrp_am_mw_rcv.py index db3b35760..31fe9af70 100755 --- a/gr-uhd/examples/usrp_am_mw_rcv.py +++ b/gr-uhd/examples/usrp_am_mw_rcv.py @@ -75,9 +75,7 @@ class wfm_rx_block (stdgui2.std_top_block): self.freq = 0 # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 256e3 demod_rate = 64e3 diff --git a/gr-uhd/examples/usrp_nbfm_ptt.py b/gr-uhd/examples/usrp_nbfm_ptt.py index 8f7ddee7d..3b28bc2ea 100755 --- a/gr-uhd/examples/usrp_nbfm_ptt.py +++ b/gr-uhd/examples/usrp_nbfm_ptt.py @@ -281,9 +281,7 @@ class transmit_path(gr.hier_block2): gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - self.u = uhd.usrp_sink(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_sink(device_addr=args, stream_args=uhd.stream_args('fc32')) self.if_rate = 320e3 self.audio_rate = 32e3 diff --git a/gr-uhd/examples/usrp_nbfm_rcv.py b/gr-uhd/examples/usrp_nbfm_rcv.py index a558b9347..7e15abbcf 100755 --- a/gr-uhd/examples/usrp_nbfm_rcv.py +++ b/gr-uhd/examples/usrp_nbfm_rcv.py @@ -266,9 +266,7 @@ class receive_path(gr.hier_block2): gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - self.u = uhd.usrp_source(device_addr=args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=args, stream_args=uhd.stream_args('fc32')) self.if_rate = 256e3 self.quad_rate = 64e3 diff --git a/gr-uhd/examples/usrp_spectrum_sense.py b/gr-uhd/examples/usrp_spectrum_sense.py index 01ca60396..ceb95ea2a 100755 --- a/gr-uhd/examples/usrp_spectrum_sense.py +++ b/gr-uhd/examples/usrp_spectrum_sense.py @@ -131,9 +131,7 @@ class my_top_block(gr.top_block): print "Note: failed to enable realtime scheduling" # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = options.samp_rate self.u.set_samp_rate(usrp_rate) diff --git a/gr-uhd/examples/usrp_tv_rcv.py b/gr-uhd/examples/usrp_tv_rcv.py index 22493dd00..6e61eceec 100755 --- a/gr-uhd/examples/usrp_tv_rcv.py +++ b/gr-uhd/examples/usrp_tv_rcv.py @@ -131,9 +131,7 @@ class tv_rx_block (stdgui2.std_top_block): self.gain=0.0 else: # use a UHD device - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) self.u.set_samp_rate(usrp_rate) dev_rate = self.u.get_samp_rate() diff --git a/gr-uhd/examples/usrp_tv_rcv_nogui.py b/gr-uhd/examples/usrp_tv_rcv_nogui.py index 2324eb29e..f6a40d675 100755 --- a/gr-uhd/examples/usrp_tv_rcv_nogui.py +++ b/gr-uhd/examples/usrp_tv_rcv_nogui.py @@ -131,9 +131,7 @@ class my_top_block(gr.top_block): raise SystemExit, 1 # build the graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) self.u.set_samp_rate(input_rate) dev_rate = self.u.get_samp_rate() diff --git a/gr-uhd/examples/usrp_wfm_rcv.py b/gr-uhd/examples/usrp_wfm_rcv.py index cfdaa6d6f..a4abdd2a7 100755 --- a/gr-uhd/examples/usrp_wfm_rcv.py +++ b/gr-uhd/examples/usrp_wfm_rcv.py @@ -69,9 +69,7 @@ class wfm_rx_block (stdgui2.std_top_block): self.fm_freq_max = options.freq_max # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 320e3 demod_rate = 320e3 diff --git a/gr-uhd/examples/usrp_wfm_rcv2_nogui.py b/gr-uhd/examples/usrp_wfm_rcv2_nogui.py index 8cbd18475..4173468ef 100755 --- a/gr-uhd/examples/usrp_wfm_rcv2_nogui.py +++ b/gr-uhd/examples/usrp_wfm_rcv2_nogui.py @@ -70,9 +70,8 @@ class wfm_rx_block (gr.top_block): self.fm_freq_max = options.freq_max # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=2) + stream_args = uhd.stream_args('fc32', channels=range(2)) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=stream_args) # Set front end channel mapping self.u.set_subdev_spec(options.spec) diff --git a/gr-uhd/examples/usrp_wfm_rcv_fmdet.py b/gr-uhd/examples/usrp_wfm_rcv_fmdet.py index 39c711a6d..225c9607b 100755 --- a/gr-uhd/examples/usrp_wfm_rcv_fmdet.py +++ b/gr-uhd/examples/usrp_wfm_rcv_fmdet.py @@ -71,9 +71,7 @@ class wfm_rx_block (stdgui2.std_top_block): self.fm_freq_max = options.freq_max # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 320e3 demod_rate = 320e3 diff --git a/gr-uhd/examples/usrp_wfm_rcv_nogui.py b/gr-uhd/examples/usrp_wfm_rcv_nogui.py index 90caf7d08..498d2dec6 100755 --- a/gr-uhd/examples/usrp_wfm_rcv_nogui.py +++ b/gr-uhd/examples/usrp_wfm_rcv_nogui.py @@ -63,9 +63,7 @@ class wfm_rx_block (gr.top_block): self.fm_freq_max = options.freq_max # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 320e3 demod_rate = 320e3 diff --git a/gr-uhd/examples/usrp_wfm_rcv_pll.py b/gr-uhd/examples/usrp_wfm_rcv_pll.py index 2901bf735..383670c75 100755 --- a/gr-uhd/examples/usrp_wfm_rcv_pll.py +++ b/gr-uhd/examples/usrp_wfm_rcv_pll.py @@ -71,9 +71,7 @@ class wfm_rx_block (stdgui2.std_top_block): self.fm_freq_max = options.freq_max # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 320e3 demod_rate = 320e3 diff --git a/gr-uhd/examples/usrp_wfm_rcv_sca.py b/gr-uhd/examples/usrp_wfm_rcv_sca.py index 9caef7499..9b233a7fb 100755 --- a/gr-uhd/examples/usrp_wfm_rcv_sca.py +++ b/gr-uhd/examples/usrp_wfm_rcv_sca.py @@ -100,9 +100,7 @@ class wfm_rx_sca_block (stdgui2.std_top_block): # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 320e3 demod_rate = 320e3 diff --git a/gr-uhd/examples/usrp_wxapt_rcv.py b/gr-uhd/examples/usrp_wxapt_rcv.py index 1da51d363..78cc7bd08 100755 --- a/gr-uhd/examples/usrp_wxapt_rcv.py +++ b/gr-uhd/examples/usrp_wxapt_rcv.py @@ -69,9 +69,7 @@ class wxapt_rx_block (stdgui2.std_top_block): self.freq_max = options.freq_max # build graph - self.u = uhd.usrp_source(device_addr=options.args, - io_type=uhd.io_type.COMPLEX_FLOAT32, - num_channels=1) + self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 320e3 demod_rate = 320e3 diff --git a/gr-uhd/grc/gen_uhd_usrp_blocks.py b/gr-uhd/grc/gen_uhd_usrp_blocks.py index 7116dad3b..67343541c 100644 --- a/gr-uhd/grc/gen_uhd_usrp_blocks.py +++ b/gr-uhd/grc/gen_uhd_usrp_blocks.py @@ -27,27 +27,28 @@ MAIN_TMPL = """\ <import>from gnuradio import uhd</import> <make>uhd.usrp_$(sourk)( device_addr=\$dev_addr, - io_type=uhd.io_type.\$type.type, - num_channels=\$nchan, + stream_args=uhd.stream_args( + cpu_format="\$type", + \#if \$otw() + otw_format=\$otw, + \#end if + \#if \$stream_args() + args=\$stream_args, + \#end if + channels=range(\$nchan), + ), ) \#if \$clock_rate() self.\$(id).set_clock_rate(\$clock_rate, uhd.ALL_MBOARDS) \#end if #for $m in range($max_mboards) ######################################################################## -\#if \$num_mboards() > $m and \$ref_source$(m)() == 'external' -self.\$(id).set_clock_config(uhd.clock_config.external(), $m) +\#if \$num_mboards() > $m and \$clock_source$(m)() +self.\$(id).set_clock_source(\$clock_source$(m), $m) \#end if ######################################################################## -\#if \$num_mboards() > $m and \$ref_source$(m)() == 'internal' -self.\$(id).set_clock_config(uhd.clock_config.internal(), $m) -\#end if -######################################################################## -\#if \$num_mboards() > $m and \$ref_source$(m)() == 'mimo' -_config = uhd.clock_config() -_config.ref_source = uhd.clock_config.REF_MIMO -_config.pps_source = uhd.clock_config.PPS_MIMO -self.\$(id).set_clock_config(_config, $m) +\#if \$num_mboards() > $m and \$time_source$(m)() +self.\$(id).set_time_source(\$time_source$(m), $m) \#end if ######################################################################## \#if \$num_mboards() > $m and \$sd_spec$(m)() @@ -84,16 +85,61 @@ self.\$(id).set_bandwidth(\$bw$(n), $n) <key>type</key> <type>enum</type> <option> - <name>Complex</name> - <key>complex</key> - <opt>type:COMPLEX_FLOAT32</opt> - <opt>vlen:1</opt> + <name>Complex float32</name> + <key>fc32</key> + <opt>type:fc32</opt> + </option> + <option> + <name>Complex int16</name> + <key>sc16</key> + <opt>type:sc16</opt> </option> <option> - <name>Short</name> - <key>short</key> - <opt>type:COMPLEX_INT16</opt> - <opt>vlen:2</opt> + <name>VITA word32</name> + <key>item32</key> + <opt>type:s32</opt> + </option> + </param> + <param> + <name>Wire Format</name> + <key>otw</key> + <value></value> + <type>string</type> + <hide> + \#if \$otw() + none + \#else + part + \#end if + </hide> + <option> + <name>Automatic</name> + <key></key> + </option> + <option> + <name>Complex int16</name> + <key>sc16</key> + </option> + <option> + <name>Complex int8</name> + <key>sc8</key> + </option> + </param> + <param> + <name>Stream args</name> + <key>stream_args</key> + <value></value> + <type>string</type> + <hide> + \#if \$stream_args() + none + \#else + part + \#end if + </hide> + <option> + <name>scalar=1024</name> + <key>scalar=1024</key> </option> </param> <param> @@ -150,14 +196,14 @@ self.\$(id).set_bandwidth(\$bw$(n), $n) </param> #for $m in range($max_mboards) <param> - <name>Mb$(m): Ref Source</name> - <key>ref_source$(m)</key> + <name>Mb$(m): Clock Source</name> + <key>clock_source$(m)</key> <value></value> - <type>enum</type> + <type>string</type> <hide> \#if not \$num_mboards() > $m all - \#elif \$ref_source$(m)() + \#elif \$clock_source$(m)() none \#else part @@ -167,6 +213,26 @@ self.\$(id).set_bandwidth(\$bw$(n), $n) <option><name>Internal</name><key>internal</key></option> <option><name>External</name><key>external</key></option> <option><name>MIMO Cable</name><key>mimo</key></option> + <option><name>O/B GPSDO</name><key>gpsdo</key></option> + </param> + <param> + <name>Mb$(m): Time Source</name> + <key>time_source$(m)</key> + <value></value> + <type>string</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$time_source$(m)() + none + \#else + part + \#end if + </hide> + <option><name>Default</name><key></key></option> + <option><name>External</name><key>external</key></option> + <option><name>MIMO Cable</name><key>mimo</key></option> + <option><name>O/B GPSDO</name><key>gpsdo</key></option> </param> <param> <name>Mb$(m): Subdev Spec</name> @@ -210,8 +276,7 @@ self.\$(id).set_bandwidth(\$bw$(n), $n) <check>\$nchan >= \$num_mboards</check> <$sourk> <name>$direction</name> - <type>\$type</type> - <vlen>\$type.vlen</vlen> + <type>\$type.type</type> <nports>\$nchan</nports> </$sourk> <doc> @@ -225,6 +290,19 @@ USRP1 Example: serial=12345678 USRP2 Example: addr=192.168.10.2 USRP2 Example: addr0=192.168.10.2, addr1=192.168.10.3 +$(direction.title()) Type: +This parameter controls the data type of the stream in gnuradio. + +Wire Format: +This parameter controls the form of the data over the bus/network. \ +Complex bytes may be used to trade off precision for bandwidth. \ +Not all formats are supported on all devices. + +Stream Args: +Optional arguments to be passed in the UHD streamer object. \ +Streamer args is a list of key/value pairs; usage is determined by the implementation. +Ex: the scalar key affects the scaling between 16 and 8 bit integers in sc8 wire format. + Num Motherboards: Selects the number of USRP motherboards in this device configuration. diff --git a/gr-uhd/include/gr_uhd_usrp_sink.h b/gr-uhd/include/gr_uhd_usrp_sink.h index f11d00063..ce76ec03b 100644 --- a/gr-uhd/include/gr_uhd_usrp_sink.h +++ b/gr-uhd/include/gr_uhd_usrp_sink.h @@ -26,6 +26,27 @@ #include <gr_sync_block.h> #include <uhd/usrp/multi_usrp.hpp> +#ifndef INCLUDED_UHD_STREAM_HPP +namespace uhd{ + struct GR_UHD_API stream_args_t{ + stream_args_t( + const std::string &cpu = "", + const std::string &otw = "" + ){ + cpu_format = cpu; + otw_format = otw; + } + std::string cpu_format; + std::string otw_format; + device_addr_t args; + std::vector<size_t> channels; + }; +} +# define INCLUDED_UHD_STREAM_HPP +#else +# define GR_UHD_USE_STREAM_API +#endif + class uhd_usrp_sink; /*! @@ -62,11 +83,42 @@ GR_UHD_API boost::shared_ptr<uhd_usrp_sink> uhd_make_usrp_sink( size_t num_channels ); +/*! + * \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 stream_args the IO format and channel specification + * \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::stream_args_t &stream_args +); + class GR_UHD_API uhd_usrp_sink : virtual public gr_sync_block{ public: /*! - * Set the subdevice specification. + * Set the frontend specification. * \param spec the subdev spec markup string * \param mboard the motherboard index 0 to M-1 */ @@ -86,6 +138,12 @@ public: virtual double get_samp_rate(void) = 0; /*! + * Get the possible sample rates for the usrp device. + * \return a range of rates in Sps + */ + virtual uhd::meta_range_t get_samp_rates(void) = 0; + + /*! * Tune the usrp device to the desired center frequency. * \param tune_request the tune request instructions * \param chan the channel index 0 to N-1 @@ -195,26 +253,53 @@ public: virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0; /*! - * Set the subdevice bandpass filter. + * Set the bandpass filter on the RF frontend. * \param chan the channel index 0 to N-1 * \param bandwidth the filter bandwidth in Hz */ virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0; /*! - * Get a daughterboard sensor value. + * Set a constant DC offset value. + * The value is complex to control both I and Q. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_dc_offset(const std::complex<double> &offset, size_t chan = 0) = 0; + + /*! + * Set the RX frontend IQ imbalance correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_iq_balance(const std::complex<double> &correction, size_t chan = 0) = 0; + + /*! + * Get an RF frontend sensor value. * \param name the name of the sensor * \param chan the channel index 0 to N-1 * \return a sensor value object */ - virtual uhd::sensor_value_t get_dboard_sensor(const std::string &name, size_t chan = 0) = 0; + virtual uhd::sensor_value_t get_sensor(const std::string &name, size_t chan = 0) = 0; /*! - * Get a list of possible daughterboard sensor names. + * Get a list of possible RF frontend sensor names. * \param chan the channel index 0 to N-1 * \return a vector of sensor names */ - virtual std::vector<std::string> get_dboard_sensor_names(size_t chan = 0) = 0; + virtual std::vector<std::string> get_sensor_names(size_t chan = 0) = 0; + + //! DEPRECATED use get_sensor + uhd::sensor_value_t get_dboard_sensor(const std::string &name, size_t chan = 0){ + return this->get_sensor(name, chan); + } + + //! DEPRECATED use get_sensor_names + std::vector<std::string> get_dboard_sensor_names(size_t chan = 0){ + return this->get_sensor_names(chan); + } /*! * Get a motherboard sensor value. @@ -233,12 +318,60 @@ public: /*! * Set the clock configuration. + * DEPRECATED for set_time/clock_source. * \param clock_config the new configuration * \param mboard the motherboard index 0 to M-1 */ virtual void set_clock_config(const uhd::clock_config_t &clock_config, size_t mboard = 0) = 0; /*! + * Set the time source for the usrp device. + * This sets the method of time synchronization, + * typically a pulse per second or an encoded time. + * Typical options for source: external, MIMO. + * \param source a string representing the time source + * \param mboard which motherboard to set the config + */ + virtual void set_time_source(const std::string &source, const size_t mboard = 0) = 0; + + /*! + * Get the currently set time source. + * \param mboard which motherboard to get the config + * \return the string representing the time source + */ + virtual std::string get_time_source(const size_t mboard) = 0; + + /*! + * Get a list of possible time sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector<std::string> get_time_sources(const size_t mboard) = 0; + + /*! + * Set the clock source for the usrp device. + * This sets the source for a 10 Mhz reference clock. + * Typical options for source: internal, external, MIMO. + * \param source a string representing the clock source + * \param mboard which motherboard to set the config + */ + virtual void set_clock_source(const std::string &source, const size_t mboard = 0) = 0; + + /*! + * Get the currently set clock source. + * \param mboard which motherboard to get the config + * \return the string representing the clock source + */ + virtual std::string get_clock_source(const size_t mboard) = 0; + + /*! + * Get a list of possible clock sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector<std::string> get_clock_sources(const size_t mboard) = 0; + + /*! * Get the master clock rate. * \param mboard the motherboard index 0 to M-1 * \return the clock rate in Hz @@ -286,6 +419,25 @@ public: virtual void set_time_unknown_pps(const uhd::time_spec_t &time_spec) = 0; /*! + * Set the time at which the control commands will take effect. + * + * A timed command will back-pressure all subsequent timed commands, + * assuming that the subsequent commands occur within the time-window. + * If the time spec is late, the command will be activated upon arrival. + * + * \param time_spec the time at which the next command will activate + * \param mboard which motherboard to set the config + */ + virtual void set_command_time(const uhd::time_spec_t &time_spec, size_t mboard = 0) = 0; + + /*! + * Clear the command time so future commands are sent ASAP. + * + * \param mboard which motherboard to set the config + */ + virtual void clear_command_time(size_t mboard = 0) = 0; + + /*! * Get access to the underlying uhd dboard iface object. * \return the dboard_iface object */ diff --git a/gr-uhd/include/gr_uhd_usrp_source.h b/gr-uhd/include/gr_uhd_usrp_source.h index fecc6e94d..e9fc41b93 100644 --- a/gr-uhd/include/gr_uhd_usrp_source.h +++ b/gr-uhd/include/gr_uhd_usrp_source.h @@ -26,6 +26,27 @@ #include <gr_sync_block.h> #include <uhd/usrp/multi_usrp.hpp> +#ifndef INCLUDED_UHD_STREAM_HPP +namespace uhd{ + struct GR_UHD_API stream_args_t{ + stream_args_t( + const std::string &cpu = "", + const std::string &otw = "" + ){ + cpu_format = cpu; + otw_format = otw; + } + std::string cpu_format; + std::string otw_format; + device_addr_t args; + std::vector<size_t> channels; + }; +} +# define INCLUDED_UHD_STREAM_HPP +#else +# define GR_UHD_USE_STREAM_API +#endif + class uhd_usrp_source; /*! @@ -58,11 +79,38 @@ GR_UHD_API boost::shared_ptr<uhd_usrp_source> uhd_make_usrp_source( size_t num_channels ); +/*! + * \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 stream_args the IO format and channel specification + * \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::stream_args_t &stream_args +); + class GR_UHD_API uhd_usrp_source : virtual public gr_sync_block{ public: /*! - * Set the subdevice specification. + * Set the frontend specification. * \param spec the subdev spec markup string * \param mboard the motherboard index 0 to M-1 */ @@ -82,6 +130,12 @@ public: virtual double get_samp_rate(void) = 0; /*! + * Get the possible sample rates for the usrp device. + * \return a range of rates in Sps + */ + virtual uhd::meta_range_t get_samp_rates(void) = 0; + + /*! * Tune the usrp device to the desired center frequency. * \param tune_request the tune request instructions * \param chan the channel index 0 to N-1 @@ -191,26 +245,68 @@ public: virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0; /*! - * Set the subdevice bandpass filter. + * Set the bandpass filter on the RF frontend. * \param bandwidth the filter bandwidth in Hz * \param chan the channel index 0 to N-1 */ virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0; /*! - * Get a daughterboard sensor value. + * Enable/disable the automatic DC offset correction. + * The automatic correction subtracts out the long-run average. + * + * When disabled, the averaging option operation is halted. + * Once halted, the average value will be held constant + * until the user re-enables the automatic correction + * or overrides the value by manually setting the offset. + * + * \param enb true to enable automatic DC offset correction + * \param chan the channel index 0 to N-1 + */ + virtual void set_dc_offset(const bool enb, size_t chan = 0) = 0; + + /*! + * Set a constant DC offset value. + * The value is complex to control both I and Q. + * Only set this when automatic correction is disabled. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_dc_offset(const std::complex<double> &offset, size_t chan = 0) = 0; + + /*! + * Set the RX frontend IQ imbalance correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction value + * \param chan the channel index 0 to N-1 + */ + virtual void set_iq_balance(const std::complex<double> &correction, size_t chan = 0) = 0; + + /*! + * Get a RF frontend sensor value. * \param name the name of the sensor * \param chan the channel index 0 to N-1 * \return a sensor value object */ - virtual uhd::sensor_value_t get_dboard_sensor(const std::string &name, size_t chan = 0) = 0; + virtual uhd::sensor_value_t get_sensor(const std::string &name, size_t chan = 0) = 0; /*! - * Get a list of possible daughterboard sensor names. + * Get a list of possible RF frontend sensor names. * \param chan the channel index 0 to N-1 * \return a vector of sensor names */ - virtual std::vector<std::string> get_dboard_sensor_names(size_t chan = 0) = 0; + virtual std::vector<std::string> get_sensor_names(size_t chan = 0) = 0; + + //! DEPRECATED use get_sensor + uhd::sensor_value_t get_dboard_sensor(const std::string &name, size_t chan = 0){ + return this->get_sensor(name, chan); + } + + //! DEPRECATED use get_sensor_names + std::vector<std::string> get_dboard_sensor_names(size_t chan = 0){ + return this->get_sensor_names(chan); + } /*! * Get a motherboard sensor value. @@ -229,11 +325,59 @@ public: /*! * Set the clock configuration. + * DEPRECATED for set_time/clock_source. * \param clock_config the new configuration * \param mboard the motherboard index 0 to M-1 */ virtual void set_clock_config(const uhd::clock_config_t &clock_config, size_t mboard = 0) = 0; + /*! + * Set the time source for the usrp device. + * This sets the method of time synchronization, + * typically a pulse per second or an encoded time. + * Typical options for source: external, MIMO. + * \param source a string representing the time source + * \param mboard which motherboard to set the config + */ + virtual void set_time_source(const std::string &source, const size_t mboard = 0) = 0; + + /*! + * Get the currently set time source. + * \param mboard which motherboard to get the config + * \return the string representing the time source + */ + virtual std::string get_time_source(const size_t mboard) = 0; + + /*! + * Get a list of possible time sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector<std::string> get_time_sources(const size_t mboard) = 0; + + /*! + * Set the clock source for the usrp device. + * This sets the source for a 10 Mhz reference clock. + * Typical options for source: internal, external, MIMO. + * \param source a string representing the clock source + * \param mboard which motherboard to set the config + */ + virtual void set_clock_source(const std::string &source, const size_t mboard = 0) = 0; + + /*! + * Get the currently set clock source. + * \param mboard which motherboard to get the config + * \return the string representing the clock source + */ + virtual std::string get_clock_source(const size_t mboard) = 0; + + /*! + * Get a list of possible clock sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector<std::string> get_clock_sources(const size_t mboard) = 0; + /*! * Get the master clock rate. * \param mboard the motherboard index 0 to M-1 @@ -282,6 +426,25 @@ public: virtual void set_time_unknown_pps(const uhd::time_spec_t &time_spec) = 0; /*! + * Set the time at which the control commands will take effect. + * + * A timed command will back-pressure all subsequent timed commands, + * assuming that the subsequent commands occur within the time-window. + * If the time spec is late, the command will be activated upon arrival. + * + * \param time_spec the time at which the next command will activate + * \param mboard which motherboard to set the config + */ + virtual void set_command_time(const uhd::time_spec_t &time_spec, size_t mboard = 0) = 0; + + /*! + * Clear the command time so future commands are sent ASAP. + * + * \param mboard which motherboard to set the config + */ + virtual void clear_command_time(size_t mboard = 0) = 0; + + /*! * Get access to the underlying uhd dboard iface object. * \return the dboard_iface object */ diff --git a/gr-uhd/lib/gr_uhd_usrp_sink.cc b/gr-uhd/lib/gr_uhd_usrp_sink.cc index 1a6595293..05237100c 100644 --- a/gr-uhd/lib/gr_uhd_usrp_sink.cc +++ b/gr-uhd/lib/gr_uhd_usrp_sink.cc @@ -22,11 +22,25 @@ #include <gr_uhd_usrp_sink.h> #include <gr_io_signature.h> #include <stdexcept> +#include <boost/make_shared.hpp> 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"); +#include <uhd/convert.hpp> +inline gr_io_signature_sptr args_to_io_sig(const uhd::stream_args_t &args){ + const size_t nchan = std::max<size_t>(args.channels.size(), 1); + #ifdef GR_UHD_USE_STREAM_API + const size_t size = uhd::convert::get_bytes_per_item(args.cpu_format); + #else + size_t size = 0; + if (args.cpu_format == "fc32") size = 8; + if (args.cpu_format == "sc16") size = 4; + #endif + return gr_make_io_signature(nchan, nchan, size); +} + /*********************************************************************** * UHD Multi USRP Sink Impl **********************************************************************/ @@ -34,17 +48,18 @@ class uhd_usrp_sink_impl : public uhd_usrp_sink{ public: uhd_usrp_sink_impl( const uhd::device_addr_t &device_addr, - const uhd::io_type_t &io_type, - size_t num_channels + const uhd::stream_args_t &stream_args ): gr_sync_block( "gr uhd usrp sink", - gr_make_io_signature(num_channels, num_channels, io_type.size), + args_to_io_sig(stream_args), gr_make_io_signature(0, 0, 0) ), - _type(io_type), - _nchan(num_channels) + _stream_args(stream_args), + _nchan(std::max<size_t>(1, stream_args.channels.size())) { + if (stream_args.cpu_format == "fc32") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_FLOAT32); + if (stream_args.cpu_format == "sc16") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_INT16); _dev = uhd::usrp::multi_usrp::make(device_addr); } @@ -61,6 +76,14 @@ public: return _dev->get_tx_rate(); } + uhd::meta_range_t get_samp_rates(void){ + #ifdef UHD_USRP_MULTI_USRP_GET_RATES_API + return _dev->get_tx_rates(); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + uhd::tune_result_t set_center_freq( const uhd::tune_request_t tune_request, size_t chan ){ @@ -119,11 +142,27 @@ public: return _dev->set_tx_bandwidth(bandwidth, chan); } - uhd::sensor_value_t get_dboard_sensor(const std::string &name, size_t chan){ + void set_dc_offset(const std::complex<double> &offset, size_t chan){ + #ifdef UHD_USRP_MULTI_USRP_FRONTEND_CAL_API + return _dev->set_tx_dc_offset(offset, chan); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + void set_iq_balance(const std::complex<double> &correction, size_t chan){ + #ifdef UHD_USRP_MULTI_USRP_FRONTEND_CAL_API + return _dev->set_tx_iq_balance(correction, chan); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + uhd::sensor_value_t get_sensor(const std::string &name, size_t chan){ return _dev->get_tx_sensor(name, chan); } - std::vector<std::string> get_dboard_sensor_names(size_t chan){ + std::vector<std::string> get_sensor_names(size_t chan){ return _dev->get_tx_sensor_names(chan); } @@ -139,6 +178,54 @@ public: return _dev->set_clock_config(clock_config, mboard); } + void set_time_source(const std::string &source, const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->set_time_source(source, mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::string get_time_source(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_time_source(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::vector<std::string> get_time_sources(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_time_sources(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + void set_clock_source(const std::string &source, const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->set_clock_source(source, mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::string get_clock_source(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_clock_source(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::vector<std::string> get_clock_sources(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_clock_sources(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + double get_clock_rate(size_t mboard){ return _dev->get_master_clock_rate(mboard); } @@ -167,6 +254,22 @@ public: return _dev->set_time_unknown_pps(time_spec); } + void set_command_time(const uhd::time_spec_t &time_spec, size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API + return _dev->set_command_time(time_spec, mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + void clear_command_time(size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API + return _dev->clear_command_time(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan){ return _dev->get_tx_dboard_iface(chan); } @@ -194,11 +297,17 @@ public: get_tags_in_range(_tags, 0, samp0_count, samp0_count + ninput_items); if (not _tags.empty()) this->tag_work(ninput_items); + #ifdef GR_UHD_USE_STREAM_API //send all ninput_items with metadata + const size_t num_sent = _tx_stream->send( + input_items, ninput_items, _metadata, 1.0 + ); + #else const size_t num_sent = _dev->get_device()->send( input_items, ninput_items, _metadata, - _type, uhd::device::SEND_MODE_FULL_BUFF, 1.0 + *_type, uhd::device::SEND_MODE_FULL_BUFF, 1.0 ); + #endif //increment the timespec by the number of samples sent _metadata.time_spec += uhd::time_spec_t(0, num_sent, _sample_rate); @@ -266,15 +375,25 @@ public: //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){ + #ifdef GR_UHD_USE_STREAM_API + _tx_stream = _dev->get_tx_stream(_stream_args); + #endif + _metadata.start_of_burst = true; _metadata.end_of_burst = false; _metadata.has_time_spec = _nchan > 1; _metadata.time_spec = get_time_now() + uhd::time_spec_t(0.01); + #ifdef GR_UHD_USE_STREAM_API + _tx_stream->send( + gr_vector_const_void_star(_nchan), 0, _metadata, 1.0 + ); + #else _dev->get_device()->send( gr_vector_const_void_star(_nchan), 0, _metadata, - _type, uhd::device::SEND_MODE_ONE_PACKET, 1.0 + *_type, uhd::device::SEND_MODE_ONE_PACKET, 1.0 ); + #endif return true; } @@ -285,16 +404,24 @@ public: _metadata.end_of_burst = true; _metadata.has_time_spec = false; + #ifdef GR_UHD_USE_STREAM_API + _tx_stream->send(gr_vector_const_void_star(_nchan), 0, _metadata, 1.0); + #else _dev->get_device()->send( gr_vector_const_void_star(_nchan), 0, _metadata, - _type, uhd::device::SEND_MODE_ONE_PACKET, 1.0 + *_type, uhd::device::SEND_MODE_ONE_PACKET, 1.0 ); + #endif return true; } private: uhd::usrp::multi_usrp::sptr _dev; - const uhd::io_type_t _type; + const uhd::stream_args_t _stream_args; + boost::shared_ptr<uhd::io_type_t> _type; + #ifdef GR_UHD_USE_STREAM_API + uhd::tx_streamer::sptr _tx_stream; + #endif size_t _nchan; uhd::tx_metadata_t _metadata; double _sample_rate; @@ -311,7 +438,25 @@ boost::shared_ptr<uhd_usrp_sink> uhd_make_usrp_sink( const uhd::io_type_t &io_type, size_t num_channels ){ + //fill in the streamer args + uhd::stream_args_t stream_args; + switch(io_type.tid){ + case uhd::io_type_t::COMPLEX_FLOAT32: stream_args.cpu_format = "fc32"; break; + case uhd::io_type_t::COMPLEX_INT16: stream_args.cpu_format = "sc16"; break; + default: throw std::runtime_error("only complex float and shorts known to work"); + } + stream_args.otw_format = "sc16"; //only sc16 known to work + for (size_t chan = 0; chan < num_channels; chan++) + stream_args.channels.push_back(chan); //linear mapping + + return uhd_make_usrp_sink(device_addr, stream_args); +} + +boost::shared_ptr<uhd_usrp_sink> uhd_make_usrp_sink( + const uhd::device_addr_t &device_addr, + const uhd::stream_args_t &stream_args +){ return boost::shared_ptr<uhd_usrp_sink>( - new uhd_usrp_sink_impl(device_addr, io_type, num_channels) + new uhd_usrp_sink_impl(device_addr, stream_args) ); } diff --git a/gr-uhd/lib/gr_uhd_usrp_source.cc b/gr-uhd/lib/gr_uhd_usrp_source.cc index a3369ade0..953ef6995 100644 --- a/gr-uhd/lib/gr_uhd_usrp_source.cc +++ b/gr-uhd/lib/gr_uhd_usrp_source.cc @@ -24,9 +24,23 @@ #include <stdexcept> #include <iostream> #include <boost/format.hpp> +#include <boost/make_shared.hpp> static const pmt::pmt_t TIME_KEY = pmt::pmt_string_to_symbol("rx_time"); +#include <uhd/convert.hpp> +inline gr_io_signature_sptr args_to_io_sig(const uhd::stream_args_t &args){ + const size_t nchan = std::max<size_t>(args.channels.size(), 1); + #ifdef GR_UHD_USE_STREAM_API + const size_t size = uhd::convert::get_bytes_per_item(args.cpu_format); + #else + size_t size = 0; + if (args.cpu_format == "fc32") size = 8; + if (args.cpu_format == "sc16") size = 4; + #endif + return gr_make_io_signature(nchan, nchan, size); +} + /*********************************************************************** * UHD Multi USRP Source Impl **********************************************************************/ @@ -34,19 +48,20 @@ class uhd_usrp_source_impl : public uhd_usrp_source{ public: uhd_usrp_source_impl( const uhd::device_addr_t &device_addr, - const uhd::io_type_t &io_type, - size_t num_channels + const uhd::stream_args_t &stream_args ): gr_sync_block( "gr uhd usrp source", gr_make_io_signature(0, 0, 0), - gr_make_io_signature(num_channels, num_channels, io_type.size) + args_to_io_sig(stream_args) ), - _type(io_type), - _nchan(num_channels), + _stream_args(stream_args), + _nchan(std::max<size_t>(1, stream_args.channels.size())), _stream_now(_nchan == 1), _tag_now(false) { + if (stream_args.cpu_format == "fc32") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_FLOAT32); + if (stream_args.cpu_format == "sc16") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_INT16); std::stringstream str; str << name() << unique_id(); _id = pmt::pmt_string_to_symbol(str.str()); @@ -65,6 +80,14 @@ public: return _dev->get_rx_rate(); } + uhd::meta_range_t get_samp_rates(void){ + #ifdef UHD_USRP_MULTI_USRP_GET_RATES_API + return _dev->get_rx_rates(); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + uhd::tune_result_t set_center_freq( const uhd::tune_request_t tune_request, size_t chan ){ @@ -123,11 +146,35 @@ public: return _dev->set_rx_bandwidth(bandwidth, chan); } - uhd::sensor_value_t get_dboard_sensor(const std::string &name, size_t chan){ + void set_dc_offset(const bool enable, size_t chan){ + #ifdef UHD_USRP_MULTI_USRP_FRONTEND_CAL_API + return _dev->set_rx_dc_offset(enable, chan); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + void set_dc_offset(const std::complex<double> &offset, size_t chan){ + #ifdef UHD_USRP_MULTI_USRP_FRONTEND_CAL_API + return _dev->set_rx_dc_offset(offset, chan); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + void set_iq_balance(const std::complex<double> &correction, size_t chan){ + #ifdef UHD_USRP_MULTI_USRP_FRONTEND_CAL_API + return _dev->set_rx_iq_balance(correction, chan); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + uhd::sensor_value_t get_sensor(const std::string &name, size_t chan){ return _dev->get_rx_sensor(name, chan); } - std::vector<std::string> get_dboard_sensor_names(size_t chan){ + std::vector<std::string> get_sensor_names(size_t chan){ return _dev->get_rx_sensor_names(chan); } @@ -143,6 +190,54 @@ public: return _dev->set_clock_config(clock_config, mboard); } + void set_time_source(const std::string &source, const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->set_time_source(source, mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::string get_time_source(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_time_source(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::vector<std::string> get_time_sources(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_time_sources(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + void set_clock_source(const std::string &source, const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->set_clock_source(source, mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::string get_clock_source(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_clock_source(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + std::vector<std::string> get_clock_sources(const size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API + return _dev->get_clock_sources(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + double get_clock_rate(size_t mboard){ return _dev->get_master_clock_rate(mboard); } @@ -171,6 +266,22 @@ public: return _dev->set_time_unknown_pps(time_spec); } + void set_command_time(const uhd::time_spec_t &time_spec, size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API + return _dev->set_command_time(time_spec, mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + + void clear_command_time(size_t mboard){ + #ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API + return _dev->clear_command_time(mboard); + #else + throw std::runtime_error("not implemented in this version"); + #endif + } + uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan){ return _dev->get_rx_dboard_iface(chan); } @@ -187,22 +298,33 @@ public: gr_vector_const_void_star &input_items, gr_vector_void_star &output_items ){ + #ifdef GR_UHD_USE_STREAM_API //In order to allow for low-latency: //We receive all available packets without timeout. //This call can timeout under regular operation... - size_t num_samps = _dev->get_device()->recv( - output_items, noutput_items, _metadata, - _type, uhd::device::RECV_MODE_FULL_BUFF, 0.0 + size_t num_samps = _rx_stream->recv( + output_items, noutput_items, _metadata, 0.0 ); //If receive resulted in a timeout condition: //We now receive a single packet with a large timeout. if (_metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){ + num_samps = _rx_stream->recv( + output_items, noutput_items, _metadata, 1.0, true/*one pkt*/ + ); + } + #else + size_t num_samps = _dev->get_device()->recv( + output_items, noutput_items, _metadata, + *_type, uhd::device::RECV_MODE_FULL_BUFF, 0.0 + ); + if (_metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){ num_samps = _dev->get_device()->recv( output_items, noutput_items, _metadata, - _type, uhd::device::RECV_MODE_ONE_PACKET, 1.0 + *_type, uhd::device::RECV_MODE_ONE_PACKET, 1.0 ); } + #endif //handle possible errors conditions switch(_metadata.error_code){ @@ -242,6 +364,10 @@ public: } bool start(void){ + #ifdef GR_UHD_USE_STREAM_API + _rx_stream = _dev->get_rx_stream(_stream_args); + _samps_per_packet = _rx_stream->get_max_num_samps(); + #endif //setup a stream command that starts streaming slightly in the future static const double reasonable_delay = 0.1; //order of magnitude over RTT uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); @@ -260,10 +386,17 @@ public: outputs.push_back(&buffs[i].front()); } while (true){ + #ifdef GR_UHD_USE_STREAM_API + const size_t bpi = uhd::convert::get_bytes_per_item(_stream_args.cpu_format); + const size_t num_samps = _rx_stream->recv( + outputs, nbytes/bpi, _metadata, 0.0 + ); + #else const size_t num_samps = _dev->get_device()->recv( - outputs, nbytes/_type.size, _metadata, - _type, uhd::device::RECV_MODE_FULL_BUFF, 0.0 + outputs, nbytes/_type->size, _metadata, + *_type, uhd::device::RECV_MODE_FULL_BUFF, 0.0 ); + #endif if (_metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break; } } @@ -278,7 +411,12 @@ public: private: uhd::usrp::multi_usrp::sptr _dev; - const uhd::io_type_t _type; + const uhd::stream_args_t _stream_args; + boost::shared_ptr<uhd::io_type_t> _type; + #ifdef GR_UHD_USE_STREAM_API + uhd::rx_streamer::sptr _rx_stream; + size_t _samps_per_packet; + #endif size_t _nchan; bool _stream_now, _tag_now; uhd::rx_metadata_t _metadata; @@ -294,7 +432,25 @@ boost::shared_ptr<uhd_usrp_source> uhd_make_usrp_source( const uhd::io_type_t &io_type, size_t num_channels ){ + //fill in the streamer args + uhd::stream_args_t stream_args; + switch(io_type.tid){ + case uhd::io_type_t::COMPLEX_FLOAT32: stream_args.cpu_format = "fc32"; break; + case uhd::io_type_t::COMPLEX_INT16: stream_args.cpu_format = "sc16"; break; + default: throw std::runtime_error("only complex float and shorts known to work"); + } + stream_args.otw_format = "sc16"; //only sc16 known to work + for (size_t chan = 0; chan < num_channels; chan++) + stream_args.channels.push_back(chan); //linear mapping + + return uhd_make_usrp_source(device_addr, stream_args); +} + +boost::shared_ptr<uhd_usrp_source> uhd_make_usrp_source( + const uhd::device_addr_t &device_addr, + const uhd::stream_args_t &stream_args +){ return boost::shared_ptr<uhd_usrp_source>( - new uhd_usrp_source_impl(device_addr, io_type, num_channels) + new uhd_usrp_source_impl(device_addr, stream_args) ); } diff --git a/gr-uhd/swig/__init__.py b/gr-uhd/swig/__init__.py index 7745b4b79..d098a7b8a 100644 --- a/gr-uhd/swig/__init__.py +++ b/gr-uhd/swig/__init__.py @@ -57,6 +57,20 @@ def _prepare_uhd_swig(): def __setitem__(self, key, val): self.set(key, val) setattr(uhd_swig, 'device_addr_t', device_addr_t) + #make the streamer args take **kwargs on init + class stream_args_t(uhd_swig.stream_args_t): + def __init__(self, *args, **kwargs): + super(stream_args_t, self).__init__(*args) + for key, val in kwargs.iteritems(): + #for some reason, i cant assign a list in the constructor + #but what i can do is append the elements individually + if key == 'channels': + for v in val: self.channels.append(v) + elif key == 'args': + self.args = device_addr_t(val) + else: setattr(self, key, val) + setattr(uhd_swig, 'stream_args_t', stream_args_t) + #handle general things on all uhd_swig attributes #Install the __str__ and __repr__ handlers if applicable #Create aliases for uhd swig attributes to avoid the "_t" @@ -88,9 +102,14 @@ def _prepare_uhd_swig(): (0, 'device_addr', device_addr), (1, 'io_type', io_type), ): - if len(args) > index: args[index] = cast(args[index]) - if kwargs.has_key(key): kwargs[key] = cast(kwargs[key]) - return old_constructor(*args, **kwargs) + try: + if len(args) > index: args[index] = cast(args[index]) + if kwargs.has_key(key): kwargs[key] = cast(kwargs[key]) + except: pass + #dont pass kwargs, it confuses swig, map into args list: + for key in ('device_addr', 'stream_args', 'io_type', 'num_channels'): + if kwargs.has_key(key): args.append(kwargs[key]) + return old_constructor(*args) return constructor_interceptor setattr(uhd_swig, attr, constructor_factory(getattr(uhd_swig, attr))) diff --git a/gr-uhd/swig/uhd_swig.i b/gr-uhd/swig/uhd_swig.i index 7e612907c..6ff9d9843 100644 --- a/gr-uhd/swig/uhd_swig.i +++ b/gr-uhd/swig/uhd_swig.i @@ -48,6 +48,8 @@ //////////////////////////////////////////////////////////////////////// %template(string_vector_t) std::vector<std::string>; +%template(size_vector_t) std::vector<size_t>; + %include <uhd/config.hpp> %include <uhd/utils/pimpl.hpp> |