diff options
46 files changed, 1092 insertions, 275 deletions
diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake index 540b97b93..0e1f40027 100644 --- a/cmake/Modules/GrMiscUtils.cmake +++ b/cmake/Modules/GrMiscUtils.cmake @@ -164,6 +164,7 @@ function(GR_LIBRARY_FOO target) POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 + COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install ) #and install the extra symlinks @@ -200,5 +201,10 @@ function(GR_GEN_TARGET_DEPS name var) if(ARGN) add_dependencies(${name} ${ARGN}) endif(ARGN) - set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) + + if(CMAKE_CROSSCOMPILING) + set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross + else() + set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) + endif() endfunction(GR_GEN_TARGET_DEPS) diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake index 4be583aa1..51d9203dd 100644 --- a/cmake/Modules/GrSwig.cmake +++ b/cmake/Modules/GrSwig.cmake @@ -38,10 +38,18 @@ include(GrPython) macro(GR_SWIG_MAKE name) set(ifiles ${ARGN}) + #append additional include directories + find_package(PythonLibs) + list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) + list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) + list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) + list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) + #determine include dependencies for swig file execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/get_swig_deps.py - "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}" + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_BINARY_DIR}/get_swig_deps.py + "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -61,9 +69,6 @@ macro(GR_SWIG_MAKE name) include_directories(${GR_SWIG_INCLUDE_DIRS}) list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file}) - find_package(PythonLibs) - include_directories(${PYTHON_INCLUDE_DIRS}) - #setup the swig flags with flags and include directories set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS}) foreach(dir ${GR_SWIG_INCLUDE_DIRS}) 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-howto-write-a-block-cmake/cmake/Modules/GrMiscUtils.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/GrMiscUtils.cmake index 540b97b93..0e1f40027 100644 --- a/gr-howto-write-a-block-cmake/cmake/Modules/GrMiscUtils.cmake +++ b/gr-howto-write-a-block-cmake/cmake/Modules/GrMiscUtils.cmake @@ -164,6 +164,7 @@ function(GR_LIBRARY_FOO target) POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 + COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install ) #and install the extra symlinks @@ -200,5 +201,10 @@ function(GR_GEN_TARGET_DEPS name var) if(ARGN) add_dependencies(${name} ${ARGN}) endif(ARGN) - set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) + + if(CMAKE_CROSSCOMPILING) + set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross + else() + set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) + endif() endfunction(GR_GEN_TARGET_DEPS) diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake index 4be583aa1..51d9203dd 100644 --- a/gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake +++ b/gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake @@ -38,10 +38,18 @@ include(GrPython) macro(GR_SWIG_MAKE name) set(ifiles ${ARGN}) + #append additional include directories + find_package(PythonLibs) + list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) + list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) + list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) + list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) + #determine include dependencies for swig file execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/get_swig_deps.py - "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}" + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_BINARY_DIR}/get_swig_deps.py + "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -61,9 +69,6 @@ macro(GR_SWIG_MAKE name) include_directories(${GR_SWIG_INCLUDE_DIRS}) list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file}) - find_package(PythonLibs) - include_directories(${PYTHON_INCLUDE_DIRS}) - #setup the swig flags with flags and include directories set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS}) foreach(dir ${GR_SWIG_INCLUDE_DIRS}) 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-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt index f60595ee6..2dc35e81c 100644 --- a/gr-qtgui/lib/CMakeLists.txt +++ b/gr-qtgui/lib/CMakeLists.txt @@ -73,6 +73,7 @@ include_directories(${QWT_INCLUDE_DIRS}) link_directories(${QWT_LIBRARY_DIRS}) include_directories(${PYTHON_INCLUDE_DIRS}) +include_directories(${PYTHON_INCLUDE_PATH}) #deprecated for dirs (cmake 2.6) ######################################################################## # Setup library diff --git a/gr-uhd/apps/uhd_fft.py b/gr-uhd/apps/uhd_fft.py index 7f529a528..c06a23036 100755 --- a/gr-uhd/apps/uhd_fft.py +++ b/gr-uhd/apps/uhd_fft.py @@ -74,9 +74,11 @@ 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): + self.u.set_subdev_spec(options.spec, 0) self.u.set_samp_rate(options.samp_rate) input_rate = self.u.get_samp_rate() @@ -119,10 +121,6 @@ class app_top_block(stdgui2.std_top_block): self.set_gain(options.gain) - # Set the subdevice spec - if(options.spec): - self.u.set_subdev_spec(options.spec, 0) - # Set the antenna if(options.antenna): self.u.set_antenna(options.antenna, 0) 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 4b7060460..27e9e8e01 100755 --- a/gr-uhd/apps/uhd_siggen.py +++ b/gr-uhd/apps/uhd_siggen.py @@ -92,15 +92,17 @@ 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 if(options.spec): self._u.set_subdev_spec(options.spec, 0) + # Set the gain on the usrp from options + if(options.gain): + self._u.set_gain(options.gain) + # Set the antenna if(options.antenna): self._u.set_antenna(options.antenna, 0) @@ -145,7 +147,7 @@ class top_block(gr.top_block, pubsub): def set_gain(self, gain): if gain is None: g = self[GAIN_RANGE_KEY] - gain = float(g[0]+g[1])/2 + gain = float(g.start()+g.stop())/2 if self._verbose: print "Using auto-calculated mid-point TX gain" self[GAIN_KEY] = gain @@ -158,7 +160,7 @@ class top_block(gr.top_block, pubsub): if target_freq is None: f = self[FREQ_RANGE_KEY] - target_freq = float(f[0]+f[1])/2.0 + target_freq = float(f.start()+f.stop())/2.0 if self._verbose: print "Using auto-calculated mid-point frequency" self[TX_FREQ_KEY] = target_freq 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> diff --git a/volk/CMakeLists.txt b/volk/CMakeLists.txt index 4b8fda059..fdde308ad 100644 --- a/volk/CMakeLists.txt +++ b/volk/CMakeLists.txt @@ -32,14 +32,32 @@ set(LIBVER 0.0.0) set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) #allows this to be a sub-project set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) #allows this to be a sub-project +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) #location for custom "Modules" + +######################################################################## +# Environment setup +######################################################################## +IF(NOT DEFINED BOOST_ROOT) + SET(BOOST_ROOT "") +ENDIF() +SET(BOOST_ROOT ${BOOST_ROOT} CACHE STRING "Modify search path for Boost components") + +#after caching user-defined value, make sure to add the install prefix +SET(BOOST_ROOT ${BOOST_ROOT}:${CMAKE_INSTALL_PREFIX}) + +IF(NOT DEFINED CROSSCOMPILE_MULTILIB) + SET(CROSSCOMPILE_MULTILIB "") +ENDIF() +SET(CROSSCOMPILE_MULTILIB ${CROSSCOMPILE_MULTILIB} CACHE STRING "Define \"true\" if you have and want to use multiple C development libs installed for cross compile") + ######################################################################## # Dependencies setup ######################################################################## -find_package(PythonInterp) -if(NOT PYTHONINTERP_FOUND) - message(FATAL_ERROR "Python interpreter required by the build system.") -endif(NOT PYTHONINTERP_FOUND) +find_package(PythonInterp REQUIRED PYTHON_EXECUTABLE) +find_package(Boost COMPONENTS unit_test_framework) +find_package(ORC) + ######################################################################## # Setup the package config file diff --git a/volk/cmake/FindORC.cmake b/volk/cmake/FindORC.cmake new file mode 100644 index 000000000..8d8c2d13e --- /dev/null +++ b/volk/cmake/FindORC.cmake @@ -0,0 +1,36 @@ +FIND_PACKAGE(PkgConfig) +PKG_CHECK_MODULES(PC_ORC orc-0.4) + + + + +FIND_PROGRAM(ORCC_EXECUTABLE orcc + HINTS ${PC_ORC_TOOLSDIR} + PATHS ${ORC_ROOT}/bin ${CMAKE_INSTALL_PREFIX}/bin) + +FIND_PATH(ORC_INCLUDE_DIR NAMES orc/orc.h + HINTS ${PC_ORC_INCLUDEDIR} + PATHS ${ORC_ROOT}/include/orc-0.4 ${CMAKE_INSTALL_PREFIX}/include/orc-0.4) + + +FIND_PATH(ORC_LIBRARY_DIR NAMES ${CMAKE_SHARED_LIBRARY_PREFIX}orc-0.4${CMAKE_SHARED_LIBRARY_SUFFIX} + HINTS ${PC_ORC_LIBDIR} + PATHS ${ORC_ROOT}/lib${LIB_SUFFIX} ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) + +FIND_LIBRARY(ORC_LIB orc-0.4 + HINTS ${PC_ORC_LIBRARY_DIRS} + PATHS ${ORC_ROOT}/lib${LIB_SUFFIX} ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) + +LIST(APPEND ORC_LIBRARY + ${ORC_LIB} +) + + +SET(ORC_INCLUDE_DIRS ${ORC_INCLUDE_DIR}) +SET(ORC_LIBRARIES ${ORC_LIBRARY}) +SET(ORC_LIBRARY_DIRS ${ORC_LIBRARY_DIR}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ORC "orc files" ORC_LIBRARY ORC_INCLUDE_DIR ORCC_EXECUTABLE) + +mark_as_advanced(ICE_INCLUDE_DIR ICE_LIBRARY ORCC_EXECUTABLE) diff --git a/volk/gen/archs.xml b/volk/gen/archs.xml index 960558b7c..effd90d33 100644 --- a/volk/gen/archs.xml +++ b/volk/gen/archs.xml @@ -1,8 +1,8 @@ <!-- archs appear in order of significance for blind, de-facto version ordering --> <grammar> -<arch name="generic" type="all"> - <flag>none</flag> +<arch name="generic" type="all"> <!-- name and type are both required--> + <flag>none</flag> <!-- flag is the only required field--> </arch> <arch name="altivec" type="powerpc"> @@ -11,7 +11,7 @@ </arch> <arch name="neon" type="arm"> - <flag>mfpu=neon -mfloat-abi=softfp -funsafe-math-optimizations</flag> + <flag>mfpu=neon,mfloat-abi=softfp,funsafe-math-optimizations</flag> <alignment>16</alignment> </arch> @@ -29,7 +29,6 @@ <val>1</val> <overrule>MD_SUBCPU</overrule> <overrule_val>x86</overrule_val> - <mutex>32</mutex> </arch> <arch name="3dnow" type="x86"> @@ -46,7 +45,7 @@ <op>0x80000001</op> <reg>d</reg> <shift>5</shift> - <flag>sse4.2</flag> + <flag>msse4.2</flag> <alignment>16</alignment> </arch> diff --git a/volk/gen/compilers.xml b/volk/gen/compilers.xml new file mode 100644 index 000000000..70c82e555 --- /dev/null +++ b/volk/gen/compilers.xml @@ -0,0 +1,18 @@ +<!-- compilers remap gcc-specific information from archs.xml to specific compiler cases--> +<grammar> + +<compiler name="MSVC"> + <remap name="mmmx">arch:SSE</remap> + <remap name="msse">arch:SSE</remap> + <remap name="msse2">arch:SSE2</remap> + <prefix>/</prefix> +</compiler> + +<compiler name="GNU"> + <prefix>-</prefix> +</compiler> + + + + +</grammar>
\ No newline at end of file diff --git a/volk/gen/make_cpuid_c.py b/volk/gen/make_cpuid_c.py index eb88dcd7f..7281f45a3 100644 --- a/volk/gen/make_cpuid_c.py +++ b/volk/gen/make_cpuid_c.py @@ -30,7 +30,11 @@ HEADER_TEMPL = """\ struct VOLK_CPU volk_cpu; -#if defined(__i386__) || (__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) +# define VOLK_CPU_x86 +#endif + +#if defined(VOLK_CPU_x86) //implement get cpuid for gcc compilers using a copy of cpuid.h #if defined(__GNUC__) @@ -40,32 +44,32 @@ struct VOLK_CPU volk_cpu; //implement get cpuid for MSVC compilers using __cpuid intrinsic #elif defined(_MSC_VER) #include <intrin.h> -#define cpuid(op, r) __cpuid(r, op) +#define cpuid_x86(op, r) __cpuid(r, op) #else #error "A get cpuid for volk is not available on this compiler..." #endif static inline unsigned int cpuid_eax(unsigned int op) { - unsigned int regs[4]; + int regs[4]; cpuid_x86 (op, regs); return regs[0]; } static inline unsigned int cpuid_ebx(unsigned int op) { - unsigned int regs[4]; + int regs[4]; cpuid_x86 (op, regs); return regs[1]; } static inline unsigned int cpuid_ecx(unsigned int op) { - unsigned int regs[4]; + int regs[4]; cpuid_x86 (op, regs); return regs[2]; } static inline unsigned int cpuid_edx(unsigned int op) { - unsigned int regs[4]; + int regs[4]; cpuid_x86 (op, regs); return regs[3]; } @@ -103,7 +107,7 @@ def make_cpuid_c(dom) : if no_test: tempstring = tempstring + """\ int i_can_has_%s () { -#if defined(__i386__) || (__x86_64__) +#if defined(VOLK_CPU_x86) return 1; #else return 0; @@ -115,7 +119,7 @@ int i_can_has_%s () { elif op == "1": tempstring = tempstring + """\ int i_can_has_%s () { -#if defined(__i386__) || (__x86_64__) +#if defined(VOLK_CPU_x86) unsigned int e%sx = cpuid_e%sx (%s); return ((e%sx >> %s) & 1) == %s; #else @@ -128,7 +132,7 @@ int i_can_has_%s () { elif op == "0x80000001": tempstring = tempstring + """\ int i_can_has_%s () { -#if defined(__i386__) || (__x86_64__) +#if defined(VOLK_CPU_x86) unsigned int extended_fct_count = cpuid_eax(0x80000000); if (extended_fct_count < 0x80000001) return %s^1; diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt index e18d13677..092c3ba0d 100644 --- a/volk/lib/CMakeLists.txt +++ b/volk/lib/CMakeLists.txt @@ -16,76 +16,141 @@ # ######################################################################## +# Setup the compiler name +######################################################################## +set(COMPILER_NAME ${CMAKE_C_COMPILER_ID}) +if(MSVC) #its not set otherwise + set(COMPILER_NAME MSVC) +endif() + +if(NOT DEFINED COMPILER_NAME) + message(FATAL_ERROR "COMPILER_NAME undefined. Volk build may not support this compiler.") +endif() + +######################################################################## # Parse the arches xml file: # Test each arch to see if the compiler supports the flag. # If the test passes append the arch to the available list. ######################################################################## -#extract the arch lines from the xml file using crazy python +#extract the compiler lines from the xml file using abusive python + + + execute_process( COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda a: '%s %s'%(a.attributes['name'].value,a.getElementsByTagName('flag')[0].firstChild.data),minidom.parse('${CMAKE_SOURCE_DIR}/gen/archs.xml').getElementsByTagName('arch')))" - OUTPUT_VARIABLE arch_lines OUTPUT_STRIP_TRAILING_WHITESPACE + "from xml.dom import minidom; print ';'.join(map(lambda b: ','.join([','.join([b.attributes['name'].value,item.attributes['name'].value,item.firstChild.data]) for item in b.getElementsByTagName('remap')]), minidom.parse('${CMAKE_SOURCE_DIR}/gen/compilers.xml').getElementsByTagName('compiler')))" + + OUTPUT_VARIABLE compiler_lines OUTPUT_STRIP_TRAILING_WHITESPACE ) -#get any mutually exclusive archs so we can exclude them -#this is really for compilers which can do both 32- and 64-bit compilations. +foreach(thing ${compiler_lines}) + string(REGEX REPLACE "," ";" thing_list ${thing}) + list(FIND thing_list ${COMPILER_NAME} check_val) + if(NOT ("${check_val}" STREQUAL "-1")) + string(REGEX REPLACE "${COMPILER_NAME}," ";" filter_string ${thing}) + endif() +endforeach() + + +#extract compiler prefixes from the xml file using abusive python execute_process( COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda a: '%s %s'%(a.parentNode.attributes['name'].value,a.firstChild.data),minidom.parse('${CMAKE_SOURCE_DIR}/gen/archs.xml').getElementsByTagName('mutex')))" - OUTPUT_VARIABLE mutex_lines OUTPUT_STRIP_TRAILING_WHITESPACE + "from xml.dom import minidom; print ';'.join(map(lambda b: ','.join([','.join([b.attributes['name'].value,item.firstChild.data]) for item in b.getElementsByTagName('prefix')]), minidom.parse('${CMAKE_SOURCE_DIR}/gen/compilers.xml').getElementsByTagName('compiler')))" + + OUTPUT_VARIABLE compiler_prefixes OUTPUT_STRIP_TRAILING_WHITESPACE ) -#This macro sets the ${arch}_flag variable, -#and handles special cases for MSVC arch flags. -macro(set_arch_flag name flag) - if(MSVC AND ${name} STREQUAL "mmx") - set(${name}_flag "/arch:SSE") #no /arch:MMX - elseif(MSVC AND ${name} STREQUAL "sse") - set(${name}_flag "/arch:SSE") - elseif(MSVC AND ${name} STREQUAL "sse2") - set(${name}_flag "/arch:SSE2") - else() - set(${name}_flag -${flag}) +foreach(thing ${compiler_prefixes}) + string(REGEX REPLACE "," ";" thing_list ${thing}) + list(FIND thing_list ${COMPILER_NAME} check_val) + if(NOT ("${check_val}" STREQUAL "-1")) + list(GET thing_list "1" prefix) endif() -endmacro(set_arch_flag) +endforeach() + + + + +#extract the arch lines from the xml file using abusive python +execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c + "from xml.dom import minidom; print ';'.join(map(lambda a: '%s %s %s %s'%(a.attributes['name'].value,a.getElementsByTagName('flag')[0].firstChild.data,a.getElementsByTagName('overrule')[0].firstChild.data,a.getElementsByTagName('overrule_val')[0].firstChild.data) if (len(a.getElementsByTagName('overrule'))) else '%s %s %s %s'%(a.attributes['name'].value,a.getElementsByTagName('flag')[0].firstChild.data,'no_overrule', 'no_overrule_val'), minidom.parse('${CMAKE_SOURCE_DIR}/gen/archs.xml').getElementsByTagName('arch')))" + + OUTPUT_VARIABLE arch_lines OUTPUT_STRIP_TRAILING_WHITESPACE +) + + + + +#set the various overrule values (see archs.xml) +#a lot of this is translating between automake and cmake +if(NOT "${CROSSCOMPILE_MULTILIB}" STREQUAL "true") + set(MD_SUBCPU ${CMAKE_HOST_SYSTEM_PROCESSOR}) +endif() +if(NOT "${ORC_FOUND}" STREQUAL "TRUE") + set(LV_HAVE_ORC "no") +endif() + + + -macro(handle_arch name flag) + +macro(compiler_filter name flag) + set(filtered_flag ${flag}) + foreach(thing ${filter_string}) + string(REGEX REPLACE "," ";" flagmap ${thing}) + list(GET flagmap "0" key) + list(GET flagmap "1" val) + string(REGEX MATCH "^${key}$" found ${flag}) + if("${found}" STREQUAL "${key}") + string(REGEX REPLACE "^${key}$" "${val}" filtered_flag ${flag}) + endif() + endforeach() + set(${name}_flag "${prefix}${filtered_flag}") +endmacro() + + + + + + + +macro(handle_arch name flag overrule overrule_val) + + #handle overrule + if("${${overrule}}" STREQUAL "${overrule_val}") + set(have_${name} FALSE) + message(STATUS "${name} overruled") #handle special case for none flag - if(${flag} STREQUAL "none") + elseif(${flag} STREQUAL "none") set(have_${name} TRUE) - - #otherwise test the flag against the compiler + #otherwise test the flag(s) against the compiler else() include(CheckCXXCompilerFlag) - set_arch_flag(${name} ${flag}) - CHECK_CXX_COMPILER_FLAG(${${name}_flag} have_${name}) + string(REGEX REPLACE "," ";" flag_list ${flag}) + set(have_${name} 1) + foreach(thing ${flag_list}) + compiler_filter(${name} ${thing}) + CHECK_CXX_COMPILER_FLAG(${${name}_flag} have_${thing}) + if(NOT (${have_${name}} AND ("${have_${thing}}" STREQUAL "1"))) + set(have_${name} 0) + endif() + endforeach() endif() if(have_${name}) list(APPEND available_arches ${name}) endif() -endmacro(handle_arch) -macro(remove_mutex name mutex) - if(have_${name}) - unset(have_${mutex}) - endif() - list(REMOVE_ITEM available_arches ${mutex}) -endmacro(remove_mutex) +endmacro(handle_arch) #create a list of available arches foreach(arch_line ${arch_lines}) - separate_arguments(args UNIX_COMMAND "${arch_line}") + string(REPLACE " " ";" args "${arch_line}") handle_arch(${args}) endforeach(arch_line) -#strip out mutex archs -foreach(mutex_line ${mutex_lines}) - separate_arguments(args UNIX_COMMAND "${mutex_line}") - remove_mutex(${args}) -endforeach(mutex_line) - message(STATUS "Available arches: ${available_arches}") ######################################################################## @@ -114,10 +179,12 @@ macro(handle_machine1 name) set(machine_flags "${machine_flags} ${${arch}_flag}") endforeach(arch) + string(REGEX REPLACE "^[ \t]+" "" machine_flags "${machine_flags}") + if(is_match) #this is a match, append the source and set its flags set(machine_source ${CMAKE_CURRENT_BINARY_DIR}/volk_machine_${name}.c) - set_source_files_properties(${machine_source} PROPERTIES COMPILE_FLAGS ${machine_flags}) + set_source_files_properties(${machine_source} PROPERTIES COMPILE_FLAGS "${machine_flags}") list(APPEND machine_sources ${machine_source}) list(APPEND machine_defs ${machine_def}) list(APPEND available_machines ${name}) @@ -138,7 +205,7 @@ endmacro(handle_machine) #setup the available machines foreach(machine_line ${machine_lines}) - separate_arguments(args UNIX_COMMAND "${machine_line}") + string(REPLACE " " ";" args "${machine_line}") handle_machine(${args}) endforeach(machine_line) @@ -168,20 +235,10 @@ file(GLOB xml_files ${CMAKE_SOURCE_DIR}/gen/*.xml) file(GLOB py_files ${CMAKE_SOURCE_DIR}/gen/*.py) file(GLOB h_files ${CMAKE_SOURCE_DIR}/include/volk/*.h) -#make sure we can use -B with python (introduced in 2.6) -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -B -c "" - OUTPUT_QUIET ERROR_QUIET - RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT -) -if(PYTHON_HAS_DASH_B_RESULT EQUAL 0) - set(PYTHON_DASH_B "-B") -endif() - add_custom_command( OUTPUT ${volk_gen_sources} DEPENDS ${xml_files} ${py_files} ${h_files} - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_SOURCE_DIR}/gen/volk_register.py ${CMAKE_BINARY_DIR} ) @@ -189,14 +246,12 @@ add_custom_command( ######################################################################## # Handle orc support ######################################################################## -find_package(PkgConfig) -if(PKG_CONFIG_FOUND) -PKG_CHECK_MODULES(ORC "orc-0.4 > 0.4.11") -endif(PKG_CONFIG_FOUND) -find_program(ORCC_EXECUTABLE orcc) -if(ORC_FOUND AND ORCC_EXECUTABLE) + + + +if(ORC_FOUND) #setup orc library usage include_directories(${ORC_INCLUDE_DIRS}) link_directories(${ORC_LIBRARY_DIRS}) @@ -225,16 +280,15 @@ endif() ######################################################################## # Setup the volk sources list and library ######################################################################## -if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) - #http://gcc.gnu.org/wiki/Visibility +if(NOT WIN32) add_definitions(-fvisibility=hidden) endif() include_directories( - ${CMAKE_BINARY_DIR}/include ${CMAKE_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} ) list(APPEND volk_sources @@ -254,11 +308,13 @@ if(MSVC) include_directories(${CMAKE_SOURCE_DIR}/msvc) #compile the sources as C++ due to the lack of complex.h under MSVC set_source_files_properties(${volk_sources} PROPERTIES LANGUAGE CXX) -endif(MSVC) +endif() #create the volk runtime library add_library(volk SHARED ${volk_sources}) -target_link_libraries(volk ${ORC_LIBRARIES}) +if(ORC_FOUND) + target_link_libraries(volk ${ORC_LIBRARIES}) +endif(ORC_FOUND) set_target_properties(volk PROPERTIES SOVERSION ${LIBVER}) set_target_properties(volk PROPERTIES DEFINE_SYMBOL "volk_EXPORTS") @@ -271,23 +327,24 @@ install(TARGETS volk ######################################################################## # Build the QA test application ######################################################################## -find_package(Boost COMPONENTS unit_test_framework) + if(Boost_FOUND) -set_source_files_properties( - ${CMAKE_CURRENT_SOURCE_DIR}/testqa.cc PROPERTIES - COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK;BOOST_TEST_MAIN" -) + set_source_files_properties( + ${CMAKE_CURRENT_SOURCE_DIR}/testqa.cc PROPERTIES + COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK;BOOST_TEST_MAIN" + ) -include_directories(${Boost_INCLUDE_DIRS}) -link_directories(${Boost_LIBRARY_DIRS}) + include_directories(${Boost_INCLUDE_DIRS}) + link_directories(${Boost_LIBRARY_DIRS}) -add_executable(test_all - ${CMAKE_CURRENT_SOURCE_DIR}/testqa.cc - ${CMAKE_CURRENT_SOURCE_DIR}/qa_utils.cc -) -target_link_libraries(test_all volk ${Boost_LIBRARIES}) -#ADD_TEST(qa_volk_test_all test_all) + add_executable(test_all + ${CMAKE_CURRENT_SOURCE_DIR}/testqa.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_utils.cc + ) + target_link_libraries(test_all volk ${Boost_LIBRARIES}) + add_test(qa_volk_test_all test_all) + +endif(Boost_FOUND) -endif() |